最近在做编译原理的实验,有一个实验是LL(1)语法分析设计。LL(1)语法分析主要有一下几个步骤:1、给定文法构造FIRST集、SELECT集与FOLLOW集。2、构造文法预测分析表。3、进行语法分析,构造语法分析过程表。因为这个实验我是和同学合写的,大佬同学构造出了FIRST集、SELECT集与FOLLOW集,而我在已有文法预测表的情况下完成了语法分析。
首先给定文法G[S]:
S->aH
H->aMd
H->d
M->Ab
M->@ //@为空串
A->aM
A->e
对此文法手动构造文法预测分析表
a
string table[6][6]={
{"","a","d","b","e","#"},
{"S","aH","","","",""},
{"H","aMd","d","","",""},
{"M","Ab","@","@","Ab",""},
{"A","aM","","","e",""},
{"","","","","",""}
};
在此分析中用到了两个栈:
stack<char> s1;///分析栈
stack<char> s2;///剩余输入串
在分析栈中首先push一个#和文法开始符,分析栈栈顶元素与剩余输入串栈顶元素相遇查找文法预测分析表进行分析,匹配或者选择相应产生式。在这里我写了一个CharToNumber函数进行终结符和非终结符在文法预测分析表的映射,返回数组下标。
int CharToNumber(char c)
{
switch(c)
{
case 'a':return 1;
case 'S':return 1;break;
case 'd':return 2;
case 'H':return 2;break;
case 'b':return 3;
case 'M':return 3;break;
case 'e':return 4;
case 'A':return 4;break;
case '#':return 5;break;
}
return 0;
}
然后进行循环分析
while(++x)
{
if(s1.top()=='#'&&s2.top()=='#'||table[CharToNumber(s1.top())][CharToNumber(s2.top())]!="")
{
name=table[CharToNumber(s1.top())][CharToNumber(s2.top())];
reverse(name.begin(),name.end());
p=name;
if(s1.top()=='#'&&s2.top()=='#')
{
ss="接受";
cout<<x<<"t";
toStr2();
cout<<"t";
toStr1();
cout<<"tt"<<ss<<endl;
flag=true;
break;
}
else if(s1.top()==s2.top()&&s1.top()!='#'&&s2.top()!='#')
{
ss="匹配";
cout<<x<<"t";
toStr1();
cout<<"t";
toStr2();
cout<<"tt"<<s1.top()<<ss<<endl;
s1.pop();
s2.pop();
}
else
{
reverse(name.begin(),name.end());
ss=name;
p=s1.top();
cout<<x<<"t";
toStr1();
cout<<"t";
toStr2();
cout<<"tt"<<s1.top()<<"->"<<ss<<endl;
for(int i=0;i<p.size();i++)
s1.pop();
for(int i=name.length()-1;i>=0;i--)
{
s1.push(name[i]);
if(s1.top()=='@')
s1.pop();
}
}
}
else
{
ss="分析错误";
cout<<x<<"t";
toStr1();
cout<<"t";
toStr2();
cout<<"tt"<<ss<<endl;
break;
}
}
语法分析判断: