// 首先,感谢孙同学的Java版代码,让我有了参考
// 下面上C++代码,文件操作部分自行改写即可
#include <iostream>
#include <fstream>
#include <cstring>
#include <stack>
// #include <stdexcept>
using namespace std;
char p_relation[][2] = { {'P','b'}, {'D','i'}, {'A','e'}, {'A',';'},
{'S','i'}, {'E','i'}, {'E','('}, {'E','n'},
{'B','e'}, {'B',';'}, {'B','+'}, {'B','-'},
{'B',')'}, {'T','i'}, {'T','('}, {'T','n'},
{'C','e'}, {'C',';'}, {'C','+'}, {'C','-'},
{'C','*'}, {'C','/'}, {'C',')'}, {'F','i'},
{'F','('}, {'F','n'} };
/*
string p_relation[] = { "Pb","Di","Ae","A;","Si","Ei","E(","En","Be",
"B;","B+","B-","B)","Ti","T(","Tn","Ce","C;",
"C+","C-","C*","C/","C)","Fi","F(","Fn" };
*/
string p_content[][2] = { {"P","bDe"}, {"D","SA"} ,{"A","@"} ,{"A",";SA"},
{"S","i=E"}, {"E","TB"} ,{"E","TB"} ,{"E","TB"},
{"B","@"}, {"B","@"} ,{"B","+TB"} ,{"B","-TB"},
{"B","@"}, {"T","FC"} ,{"T","FC"} ,{"T","FC"},
{"C","@"}, {"C","@"} ,{"C","@"} ,{"C","@"},
{"C","*FC"}, {"C","/FC"} ,{"C","@"} ,{"F","i"},
{"F","(E)"}, {"F","n"} };
int production_length = 26;
char symbol_table[] = { '=','+','-','*','/','(',')',';'};
string str = "";
char start_ch = ' ';
char top_ch = ' ';
stack<char> st;
void readFile()
{
fstream f;
char sf[255] = "C:\\Users\\admin_Li\\Desktop\\outfile.txt";
f.open(sf,ios::in);
if(!f) { cout<<"源文件打开失败!"; exit(1); }
f>>str;
f.close();
}
bool isProduction(char a, char b)
{
bool fit_flag = false;
for(int i = 0; i < production_length; i++)
{
if((p_relation[i][0] == a) && (p_relation[i][1] == b))
{
fit_flag = true;
break;
}
}
return fit_flag;
}
void analyse()
{
str += "#";
bool success_flag = false;
int next = 1, num = 1;
// 符号栈: s,剩余输入串: rest_str,产生式: production_str
string s = "", rest_str = str, production_str = "";
st.push('#'); st.push('P');
s += "#"; s += "P";
start_ch = str.at(0);
cout<<num<<"\t"<<s<<"\t\t"<<rest_str<<endl;
num++;
while(!success_flag)
{
top_ch = st.top();
st.pop();
s = s.substr(0, s.length()-1);
// 处理终结符
if((top_ch>='a' && top_ch<='z') || top_ch == symbol_table[0] ||
top_ch == symbol_table[1] || top_ch == symbol_table[2] ||
top_ch == symbol_table[3] || top_ch == symbol_table[4] ||
top_ch == symbol_table[5] || top_ch == symbol_table[6] ||
top_ch == symbol_table[7])
{
if(top_ch == start_ch)
{
start_ch = str.at(next);
rest_str = str.substr(next, str.length()-1);
next++;
cout<<num<<"\t"<<s<<"\t\t"<<rest_str<<"\t\t"<<production_str<<endl;
num++;
}
else
{
cout<<"error1"<<endl; // 未处理
return ;
}
}
// 处理非终结符
else if(isProduction(top_ch, start_ch))
{
// 判断为产生式编号
int i;
for(i = 0; i < production_length; i++)
{
if((p_relation[i][0] == top_ch) && (p_relation[i][1] == start_ch))
break;
}
production_str = p_content[i][0] + "->" + p_content[i][1];
for(int j = p_content[i][1].length()-1; j >= 0; j--)
{
if(p_content[i][1].at(j) != '@')
{
st.push(p_content[i][1].at(j));
s += p_content[i][1].at(j);
}
}
cout<<num<<"\t"<<s<<"\t\t"<<rest_str<<"\t\t"<<production_str<<endl;
num++;
}
// 处理结束符号: #
else if(top_ch == '#')
{
if(top_ch == start_ch)
success_flag = true;
else
{
cout<<"error2"<<endl; // 未处理
return ;
}
}
}
cout<<"------------------------"<<endl;
cout<<"语法分析成功(自顶向下)"<<endl;
}
int main()
{
readFile();
analyse();
return 0;
}
运行结果: