(1)总体要求:
1)根据文法手工或程序方式构造预测分析表;
2)采用程序方式构造预测分析表时,需计算First()和Follow()集合,有一定难度;
3)根据预测分析表,设计并实现预测分析总控程序,完成自上而下的语法分析器。
(2)文法的定义(可以选择此文法,也可以自己选择其他文法)
(3)给出当输入串为:(i1+i2)*(i3+i4)的分析过程。(输出分析过程中的栈,输入串和利用的产生式等信息)
int a;//当前正在读的字符的下标
char VT[7] = {'+','*','(',')','i','#'};//终结符号
int length_vt = 6;//终结符号的个数
char VN[6] = {'E','M','T','N','F' };//非终结符号用M代替了E' 用N代替了T’
int length_vn = 5;//非终结符号的个数
string equation[8] = { "TM","+TM","","FN","*FN","","(E)","i" };//产生式表
stack<char> sta;//分析栈
bool flag = false;//判断分析是否结束
string str;//存放用户输入的字符串
string used;//所使用的产生式
string table[5][6] = {
{"error","error","TM","error","TM","error" },
{"+TM","error","error","","error",""},
{"error","error","FN","error","FN","error"} ,
{"","*FN","error","","error",""} ,
{"error","error","(E)","error","i","error"} };//预测分析表
bool is_vn()//判断是否为非终结符
{
if ((sta.top() >= 'A')&& (sta.top() <= 'Z'))
return true;
else
return false;
}
void init()//做初始化
{
sta.push('#');
sta.push('E');//将'#'和起始符号先入栈
str = str + '#';//将输入串最后加一个‘#’结束符。
a = 0;
}
void analyse()//对一个字符的分析情况
{
string s;//所使用的的产生式
if(is_vn()==false)//判断是否为非终结符
{
if (str[a] == '#'&&(sta.top()=='#'))
{
cout << "分析成功..." << endl;
flag = true;
return;
}
else if (sta.top() == str[a])//如果栈顶元素和当前字符一致,则读入下一个字符,且栈顶元素出栈
{
s = s +str[a]+ "匹配";
used = s;
// cout << "当前栈顶元素" << sta.top() << "当前字符" << str[a] << endl;
a++;
sta.pop();
return;
}
else
{
flag = true;//已经判断出了该句子不属于此文法,所以分析结束
cout << "该句子不属于该文法" << endl;
return;
}
}
else {
for (int i = 0; i < length_vn; i++)//查表判断
{
if (sta.top() == VN[i])
{
for (int j = 0; j < length_vt; j++)
{
if (VT[j] == str[a])
{
if (table[i][j] == "error")
{
cout << "预测分析表没有对应的产生式" << endl;
flag = true;//已经判断出了该句子不属于此文法,所以分析结束
return;
}
else if (table[i][j] == "")
{
// cout << "出栈:" << sta.top() << endl;
s = s + VN[i];
s = s + "->空";
used = s;//将使用的产生式放入used
sta.pop();
return;
}
else//将当前栈顶出栈,将预测分析表对应的产生式右部进栈
{
sta.pop();
for (int z= table[i][j].length()-1; z >=0 ; z--)
{
sta.push(table[i][j][z]);
}
s=s+ VN[i]+"->"+ table[i][j];
used = s;
return;
}
}
}
cout << "error:这个输入串中的字符不属于该文法" << endl;
flag = true;
return;
}
}
cout << "error:该栈顶的符号不属于该文法" << endl;
flag = true;
return;
}
}
string printstack()//顺序输出栈中的符号
{
string s;//存放栈中的符号
string sf;//栈中的元素的反序
int num = sta.size();
for (int i = 0; i < num; i++)//把sta栈的内容给s
{
sf=sf+sta.top();
sta.pop();
}
for (int i = num-1; i >=0; i--)//反序
{
s = s + sf[i];
}
for (int i = 0; i < num; i++)//恢复sta
{
sta.push(s[i]);
}
return s;
}
string getstr()//返回输入串
{
string s;
for (int i = a; i < str.length(); i++)
{
s=s+str[i];
}
return s;
}
int main()
{
cout << "请输入一个字符串:" << endl;
cin>>str;
init();
int step = 0;
cout << setw(25) << setiosflags(ios::left) << "步骤" << setw(25) <<"符号栈" << setw(25) << "输入串"<< setw(25) << "所用产生式" << endl;
while(flag==false)
{
cout << setw(25) << setiosflags(ios::left) << step << setw(25)<<printstack()<< setw(25)<<getstr()<<setw(25)<< used<<endl;
analyse();
step++;
}
return 0;
}