【編譯原理實驗】LL(1)語法分析器


實驗內容

針對CP語言中簡單算術表達式文法G[E]:

E→TE’

E’→ATE’|ε

T→FT’

T’→MFT’|ε

F→(E) | i

A→+ | -

M→* | /

求解相應的FIRST、FOLLOW集,構造預測分析表,並編寫LL(1)語法分析程序,並給出測試句子的分析過程。

 

 實驗要求

(1)輸入:是詞法分析輸出的二元組序列,即任意簡單算術表達式經過專題1程序輸出后得到的結果。

(2)處理:基於分析表進行 LL(1)語法分析,判斷其是否符合文法。

(3)輸出:串是否合法。

 

 設計思路

先根據題意求解FIRST集、FOLLOW集和SELECT集,構造預測分析表(構造過程見下圖),並用string類型的二維數組存儲。

 

將上上篇詞法分析器的二元組輸出作為輸入讀入到二維字符數組中,再將每個二元組中的單詞提取出來存入string數組中(若這里的單詞為標識符,則將其替換為“i”),數組尾部加入輸入結束符“$”。構造一個空棧,將“$”和“E”壓入棧中,用變量p指向輸入的單詞,當棧頂元素不為“$”時,取出棧頂元素X,重復進行如下操作:

(1)若X和p指向的單詞相同,彈出X,p指向下一個單詞。

(2)否則,若預測分析表中X和p指向單詞對應的位置非空,則彈出X,將相應的產生式右部倒序壓入棧中。

(3)否則,記錄錯誤,並嘗試跳過當前字符繼續向下分析。

 

執行完后,若沒有錯誤的標記,則輸入串合法,否則不合法。

 

 程序結構

(1)主要數據結構:

二維字符數組:用於接受輸入的二元組。

一維string數組:用於存儲提取出的單詞。

二維string數組:用於存儲預測分析表。

棧:用於中間過程分析。

 

(2)函數定義:

string M(string X,string a):返回分析表中X和a對應的產生式。

void travel_st(stack<string> str):遍歷當前棧中的元素。

int main():主程序。

 

(3)算法流程:

 

 

 實驗代碼

#include<bits/stdc++.h>
using namespace std;
char ch[100][20];
string a[100];
int p=0;
string travel="";
int flag=0;
string fenxibiao[8][9]={" ","i","+","-","*","/","(",")","$",
                        "E","E->TE'"," "," "," "," ","E->TE'"," "," ",
                        "E'"," ","E'->ATE'","E'->ATE'"," "," "," ","E'->#","E'->#",
                        "T","T->FT'"," "," "," "," ","T->FT'"," "," ",
                        "T'"," ","T'->#","T'->#","T'->MFT'","T'->MFT'"," ","T'->#","T'->#",
                        "F","F->i"," "," "," "," ","F->(E)"," "," ",
                        "A"," ","A->+","A->-"," "," "," "," "," ",
                        "M"," "," "," ","M->*","M->/"," "," "," "};
                        
string M(string X,string a)
{
    int i,j;
    for(i=0;i<8;i++)
    {
        if(X==fenxibiao[i][0]) break;
    }
    for(j=0;j<9;j++)
    {
        if(a==fenxibiao[0][j]) break;
    }
    if(i>=8||j>=9) return " ";
    return fenxibiao[i][j];
}

void travel_st(stack<string> str)//遍歷棧 
{
    travel="";
    while(!str.empty())
    {
        travel+=str.top();
        str.pop();
    }
}

int main()
{
    FILE *fp;
    fp=fopen("result2.txt","r");
    if(fp==NULL)
    {
        cout<<"Open Error";
        exit(1);
    }
    int len=0;
    while(fscanf(fp,"%s",ch[len])!=EOF) len++;
    fclose(fp);
    
    for(int i=0;i<len;i++)//輸入轉換 
    {
        string temp="";
        int j=1;
        for(;ch[i][j]!=',';j++)
        {
            temp+=ch[i][j];
        }
        a[i]=temp;
        string code="";
        for(j++;ch[i][j]!='>';j++)
        {
            code+=ch[i][j];
        }
        if(code=="28") a[i]="i";
    }
    a[len]="$";
    stack<string> st;
    st.push("$");st.push("E");
    string zhan="",shuru="",shuchu="";
    cout<<setiosflags(ios::right)   //設置右對齊輸出,空格在前
        <<setw(20)<<""<<setw(20)<<"輸入"<<setw(20)<<"輸出"<<endl; 
    for(int i=p;i<=len;i++)
    {
        shuru+=a[i];
    }
    cout<<setiosflags(ios::right)   //設置右對齊輸出,空格在前
        <<setw(20)<<"E$"<<setw(20)<<shuru<<setw(20)<<" "<<endl; 
    string X=st.top();
    while(X!="$")
    {
        zhan="",shuru="",shuchu="";
        if(X==a[p])//將X彈出 
        {
            st.pop();
            p++; 
        }
        else if(M(X,a[p])!=" ")
        {
            st.pop();
            string temp=M(X,a[p]);
            int l=temp.length();
            if(temp[l-1]!='#')
            {
                for(int i=l-1;temp[i]!='>';i--)
                {
                string temp1="";
                if(temp[i]=='\'')
                {
                    temp1+=temp[i-1];
                    temp1+=temp[i];
                    i--;
                }
                else 
                {
                    temp1+=temp[i];
                }
                st.push(temp1);
                }
            }
            
            shuchu=temp;
        }
        else 
        {
            shuchu="錯誤,跳過"; 
            if(a[p].length()>1)
            {
                string::iterator it=a[p].begin();
                a[p].erase(it);
            }
            else p++;
            flag=1;
        }
        travel_st(st);
        zhan=travel;
        shuru="";
        for(int i=p;i<=len;i++)
        {
            shuru+=a[i];
        }
        cout<<setiosflags(ios::right)  
        <<setw(20)<<zhan<<setw(20)<<shuru<<setw(20)<<shuchu<<endl;
        X=st.top(); 
    } 
    
    if(flag==0) cout<<"句子合法"<<endl;
    else cout<<"句子不合法"<<endl;
     
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM