目的:熟练掌握自下而上的语法分析方法,并能用程序实现。
要求:
1. 使用如下文法:
E ® E+T | T
T ® T*F | F
F ® (E) | id
2. 对于任意给定的输入串(词法记号流)进行语法分析,要求采用LR分析器来完成。手工构造LR分析表,利用移进-归约分析算法(P71 图3.12)输出(P72 表3.8)对应的动作部分。如:
输入:id*+id/(id+id)#
输出:移进
按 F->id归约
移进
error
……
3. 要有一定的错误处理功能。即对错误能提示,并且能在一定程度上忽略尽量少的记号来进行接下来的分析。
例如:
从状态0开始的记号流为:bm
将b移进之后,栈里的情况应该为: 0 b 2
此时查表发现 action[2,m]=error
输出打印:error
把A和状态1相继压入栈,用户指针后移到FOLLOW(A)对应的元素继续分析。
把LR分析表画出来之后,代码写出来应该不难。我使用map和vector的组合来储存LR分析表的信息,这样代码可能短一些。对于输入串,自定义push函数可以将输入串倒置(注意是将终结符的顺序倒置,而不是字符的简单倒置),这样便于使用栈。
代码量100行出头相对小巧些,所以如果代码中有什么问题,欢迎大家留言!
#include<iostream>
#include<map>
#include<cstring>
#include<vector>
using namespace std;
vector<string> zhan;
static string getT(string s1,string s2){//LR分析表
map<string,map<string,string>> m;
map<string,string>n0={{"id","s5"},{"(","s4"},{"E","1"},{"T","2"},{"F","3"}},
n1={{"+","s6"},{"#","acc"}},
n2={{"*","s7"},{"+","r3"},{"#","r3"},{")","r3"}},
n3={{"+","r5"},{"*","r5"},{"#","r5"},{")","r5"}} ,
n4={{"(","s4"},{"id","s5"},{"E","8"},{"T","2"},{"F","3"}},
n5={{"+","r7"},{"*","r7"},{"#","r7"},{")","r7"}},
n6={{"(","s4"},{"id","s5"},{"T","9"},{"F","3"}},
n7={{"(","s4"},{"id","s5"},{"F","10"}},
n8={{"+","s6"},{")","s11"}},
n9={{"+","r2"},{"#","r2"},{")","r2"}},
n10={{"+","r4"},{"*","r4"},{"#","r4"},{")","r4"}},
n11={{"+","r6"},{"*","r6"},{"#","r6"},{")","r6"}};
m["0"]=n0;
m["1"]=n1;
m["2"]=n2;
m["3"]=n3;
m["4"]=n4;
m["5"]=n5;
m["6"]=n6;
m["7"]=n7;
m["8"]=n8;
m["9"]=n9;
m["10"]=n10;
m["11"]=n11;
string s=m[s1][s2];
if(s.length()==0){
cout<<"error"<<endl;
return "error";
}else
return m[s1][s2];
}
static vector<string> getL(string num){//归约的依据
map<string,vector<string>> m;
vector<string>v2={"E","E","+","T"};
vector<string>v3={"E","T"};
vector<string>v4={"T","T","*","F"};
vector<string>v5={"T","F"};
vector<string>v6={"F","(","E",")"};
vector<string>v7={"F","id"};
m["2"]=v2;
m["3"]=v3;
m["4"]=v4;
m["5"]=v5;
m["6"]=v6;
m["7"]=v7;
return m[num];
}
vector<string> push(string a){
vector<string> v;
string s="";
v.push_back("#");
for(int i=a.length()-1;i>=0;i--){
char w=a.at(i);
s+=w;
if(s==" "||s=="#"){
s="";
continue;
}
else if(s=="*"||s=="("||s==")"||s=="+"){
v.push_back(s);
}else if(s=="d"){
v.push_back("id");
i--;
}
s="";
}
return v;
}
int main(){
int count=0;
vector<string>v=push("id * * id + id#");
zhan.push_back("#");
zhan.push_back("0");
while(count<20){
count++;
string get=getT(zhan.back(),v.back());
string state="";
state+=get.at(0);
string num=get.substr(1);
if(state=="s")
{
cout<<"移进"<<endl;
zhan.push_back(v.back());
zhan.push_back(num);
v.pop_back();
}else if(state=="r"){
vector<string>list=getL(num);
cout<<"按照"<<list[0]<<"->";
for(int i=1;i<list.size();i++) {
cout<<list[i];
}
cout<<"进行归约"<<endl;
while(list.size()>1){
zhan.pop_back();//抛掉数字
zhan.pop_back();
list.pop_back();
}
string pre=zhan.back();
zhan.push_back(list.back());
string go=getT(pre,zhan.back());
zhan.push_back(go) ;
}
else if(state=="a"){
cout<<"接受"<<endl;
break;
}else if(state=="e"){
zhan.pop_back();
zhan.pop_back();
}
state="";
}
}
如果不好理解的话,下面有注释版本的,运行一下,可以把我个人的思路和代码逻辑都可以清晰地打印出来。
#include<iostream>
#include<map>
#include<cstring>
#include<vector>
using namespace std;
vector<string> zhan;
static string getT(string s1,string s2){
map<string,map<string,string>> m;
map<string,string>n0={{"id","s5"},{"(","s4"},{"E","1"},{"T","2"},{"F","3"}},
n1={{"+","s6"},{"#","acc"}},
n2={{"*","s7"},{"+","r3"},{"#","r3"},{")","r3"}},
n3={{"+","r5"},{"*","r5"},{"#","r5"},{")","r5"}} ,
n4={{"(","s4"},{"id","s5"},{"E","8"},{"T","2"},{"F","3"}},
n5={{"+","r7"},{"*","r7"},{"#","r7"},{")","r7"}},
n6={{"(","s4"},{"id","s5"},{"T","9"},{"F","3"}},
n7={{"(","s4"},{"id","s5"},{"F","10"}},
n8={{"+","s6"},{")","s11"}},
n9={{"+","r2"},{"#","r2"},{")","r2"}},
n10={{"+","r4"},{"*","r4"},{"#","r4"},{")","r4"}},
n11={{"+","r6"},{"*","r6"},{"#","r6"},{")","r6"}};
m["0"]=n0;
m["1"]=n1;
m["2"]=n2;
m["3"]=n3;
m["4"]=n4;
m["5"]=n5;
m["6"]=n6;
m["7"]=n7;
m["8"]=n8;
m["9"]=n9;
m["10"]=n10;
m["11"]=n11;
string s=m[s1][s2];
if(s.length()==0){
return "error";
}else
return m[s1][s2];
}
static vector<string> getL(string num){
map<string,vector<string>> m;
vector<string>v2={"E","E","+","T"};
vector<string>v3={"E","T"};
vector<string>v4={"T","T","*","F"};
vector<string>v5={"T","F"};
vector<string>v6={"F","(","E",")"};
vector<string>v7={"F","id"};
m["2"]=v2;
m["3"]=v3;
m["4"]=v4;
m["5"]=v5;
m["6"]=v6;
m["7"]=v7;
return m[num];
}
void dis(vector<string> &v);
vector<string> push(string a){
vector<string> v;
string s="";
v.push_back("#");
for(int i=a.length()-1;i>=0;i--){
char w=a.at(i);
s+=w;
if(s==" "||s=="#"){
s="";
continue;
}
else if(s=="*"||s=="("||s==")"||s=="+"){
v.push_back(s);
}else if(s=="d"){
v.push_back("id");
i--;
}
s="";
}
dis(v);
return v;
}
void dis(vector<string> &v){
cout<<"此时:"<<endl;
for(int i=0;i<v.size();i++){
cout<<v[i]<<" ";
}
cout<<endl;
}
int main(){
int count=0;
vector<string>v=push("id * * id + id#");
zhan.push_back("#");
zhan.push_back("0");
while(count<20){
count++;
cout<<"使用两个key:"<<zhan.back()<<"和"<<v.back()<<endl;
string get=getT(zhan.back(),v.back());
cout<<"查表得到"<<get<<endl;
string state="";
state+=get.at(0);
string num=get.substr(1);
cout<<"分解为"<<state<<"和"<<num<<endl;
if(state=="s")
{
cout<<"移进"<<endl;
zhan.push_back(v.back());
zhan.push_back(num);
cout<<"装入"<<v.back()<<"和"<<num<<endl;
v.pop_back();
dis(zhan);
}else if(state=="r"){
vector<string>list=getL(num);
cout<<"按照"<<list[0]<<"->";
for(int i=1;i<list.size();i++) {
cout<<list[i];
}
cout<<"进行归约"<<endl;
while(list.size()>1){
zhan.pop_back();//抛掉数字
cout<<"约去"<<zhan.back()<<"和"<<list.back()<<endl;
zhan.pop_back();
list.pop_back();
}
cout<<"装入"<<list.back()<<endl;
string pre=zhan.back();
zhan.push_back(list.back());
string go=getT(pre,zhan.back());
cout<<"再次查表得到goto表项,并装入"<<go<<endl;
zhan.push_back(go) ;
dis(zhan);
}
else if(state=="a"){
dis(zhan);
cout<<"接受"<<endl;
break;
}else if(state=="e"){
zhan.pop_back();
zhan.pop_back();
dis(zhan);
}
state="";
}
}