【编译原理实验】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