#include <iostream> #include <vector> #include <string> #include <sstream> #include <stack> #include <queue> #include <cmath> #include <fstream> #define END ";" #define COL 17 #define ROW 22 #define ACCEPT "ac" using namespace std; //注意事项: //1.只支持单个变量的声明 //2.支持的变量类型为 char int float void,或者调用addType函数添加自己定义的类型 //3.如果变量类型为函数,函数的形参不能省略(注意这与C语言的声明不同),否则会造成错误 //4.函数返回类型为数组,或者声明函数数组,虽然可以分析,但C语言里不允许如此定义的 class Token { public: typedef double Value; typedef string Property; string name; Value sync; Property property; Token():sync(0.0){} Token(const string &s):name(s),property(s),sync(0.0) {} Token(const char* s):name(s),property(s),sync(0.0) {} friend bool operator ==(const Token& t1,const Token& t2); }; bool operator ==(const Token& t1,const Token& t2) { return t1.name==t2.name; } class LRpda//定义LL语法分析下推自动机 { typedef vector<Token> Engender;//定义产生式 typedef int State; typedef string Action; typedef struct eexpr//定义表达式 { Token uToken; Engender engender; }eExpr; public: LRpda(); bool in_propertys(Token::Property pro,vector<Token::Property> &pVec); bool is_unTerminateToken(const Token& token);//判断是否为非终结符 bool is_TerminateToken(const Token& token);//判断是否为终结符 bool StringToEngender(const char *exprtmp,Engender &engender); bool is_delim(char ch); bool is_letter(char ch); bool is_num(const string& str); bool is_id(const string& str); double get_digit(char *&exprtmp); void get_propertys(const char* str,vector<Token::Property> &pVec); Token::Property get_property(const string& str); void addExpr(const Token& token,const Engender& engender);//添加产生式 void addExpr(const Token& token,const string& engender); void addType(const string type); Action ACTION(const State state,const Token& ttoken); Action GOTO(const State state,const Token& utoken); bool Execute(const char * exprtmp);//执行PDA private: State start; //开始符号 Token end; //结束符号 vector<Token::Property> uTokens;//非终结符号集 vector<Token::Property> tTokens;//终结符号集 vector<Token::Property> TYPE;//终结符号集 vector<string> Error; vector<eExpr> eExprs;//表达式集合 stack<State> sStack; stack<Token> tStack; stack<string> dStack; unsigned int uTokenCount;//非终结符号数量 unsigned int tTokenCount;//终结符号数量 string matrix[ROW][COL];//LR语法分析表 }; LRpda::LRpda() { //type id num * ( ) [ ] , ; string copymatrix[ROW][COL]={ {"s2","e0","e0","e0","e0","e0","e0","e0","e0","e0","1","-1","-1","-1","-1"}, {"e0","e0","e0","e0","e0","e0","e0","e0","e0","ac","-1","-1","-1","-1","-1"}, {"e0","s20","e0","s18","s15","e0","e0","e0","e0","e0","-1","3","-1","-1","-1"}, {"r7","e0","r7","r7","s9","r1","r7","r7","r1","r1","-1","-1","4","-1","-1"}, {"r12","e0","r12","r12","r12","r12","s6","r12","r12","r12","-1","-1","-1","-1","5"}, {"r4","r4","r4","r4","r4","r4","r4","r4","r4","r4","-1","-1","-1","-1","-1"}, {"e0","e0","s21","e0","e0","s10","e0","e0","e0","e0","-1","-1","-1","-1","-1"}, {"r12","r12","r12","r12","r12","r12","s6","r12","r12","r12","-1","-1","-1","-1","8"}, {"r11","r11","r11","r11","r11","r11","r11","r11","r11","r11","-1","-1","-1","-1","-1"}, {"s2","r10","r10","r10","r10","r10","r10","r10","r10","r10","12","-1","-1","10","-1"}, {"e0","e0","e0","e0","e0","s11","e0","e0","e0","e0","-1","-1","-1","-1","-1"}, {"r6","r6","r6","r6","r6","r6","r6","r6","r6","r6","-1","-1","-1","-1","-1"}, {"r8","r8","r8","r8","r8","r8","r8","r8","s13","r8","-1","-1","-1","-1","-1"}, {"s2","e0","e0","e0","e0","e0","e0","e0","e0","e0","12","-1","-1","14","-1"}, {"r9","r9","r9","r9","r9","r9","r9","r9","r9","r9","-1","-1","-1","-1","-1"}, {"e0","s20","e0","s18","s15","e0","e0","e0","e0","e0","-1","16","-1","-1","-1"}, {"r7","r7","r7","r7","s9","s17","r7","r7","r7","r7","-1","-1","4","-1","-1"}, {"r2","r2","r2","r2","r2","r2","r2","r2","r2","r2","-1","-1","-1","-1","-1"}, {"e0","s20","e0","s18","s15","e0","e0","e0","e0","e0","-1","19","-1","-1","-1"}, {"r7","r7","r7","r7","s9","r3","r7","r7","r3","r3","-1","-1","4","-1","-1"}, {"r5","r5","r5","r5","r5","r5","r5","r5","r5","r5","-1","-1","-1","-1","-1"}, {"e0","e0","e0","e0","e0","e0","e0","s7","e0","e0","-1","-1","-1","-1","-1"} }; Token tTmp; string sTmp; int i,j; for(i=0;i<ROW;++i) for(j=0;j<COL;++j) matrix[i][j]=copymatrix[i][j]; get_propertys("type id num * ( ) [ ] , ;",tTokens); get_propertys("E D F L C",uTokens); get_propertys("int float char void",TYPE); uTokenCount=uTokens.size(); tTokenCount=tTokens.size(); start=0; end=END; addExpr("E'","E ;"); //0 addExpr("E","T D"); //1 addExpr("D","( D )"); //2 addExpr("D","* D"); //3 addExpr("D","D F C"); //4 addExpr("D","id"); //4 addExpr("F","( L )"); //5 addExpr("F",""); //6 addExpr("L","E"); //7 addExpr("L","E , L"); //8 addExpr("L",""); //9 addExpr("C","[ num ] C"); //9 addExpr("C",""); //9 Error.push_back("语法错误!"); } void LRpda::get_propertys(const char* str,vector<Token::Property> &pVec) { stringstream ss(str); string sTmp; while( ss>>sTmp) pVec.push_back(sTmp); } bool LRpda::in_propertys(Token::Property pro,vector<Token::Property> &pVec) { int i,size=pVec.size(); for(i=0;i<size;++i) { if(pVec[i]==pro) return true; } return false; } Token::Property LRpda::get_property(const string& str) { if(in_propertys(str,TYPE)) return "type"; else if(is_num(str)) return "num"; else if(is_id(str)) return "id"; else if(str==")") return ")"; else if(str=="(") return "("; else if(str=="[") return "["; else if(str=="]") return "]"; else if(str==",") return ","; else if(str=="*") return "*"; else if(str==END) return END; else return ""; } bool LRpda::is_num(const string& str) { int state=0; char ch; bool flag=1; const char *exprtmp=str.c_str(); while((ch=*exprtmp)!=0 && flag) { switch(state) { case 0: if(ch>='1' && ch<='9') state=1; else flag=0; break; case 2: if(isdigit(ch)) state=1; else flag=0; break; default: break; } ++exprtmp; } if(flag==1 && (state==1)) return true; return false; } bool LRpda::is_letter(char ch) { ch|=0x20; if((ch>='a' && ch<='z')||ch=='_') return true; return false; } bool LRpda::is_id(const string &str) { int state=0; char ch; bool flag=1; const char *exprtmp=str.c_str(); while((ch=*exprtmp)!=0 && flag) { switch(state) { case 0: if(is_letter(ch)) state=1; else flag=0; break; case 1: if(is_letter(ch)||isdigit(ch)) state=1; else flag=0; break; default: break; } ++exprtmp; } if(flag==1 && state==1) return true; return false; } bool LRpda::is_delim(char ch) { return (ch==' '||ch=='/n' ||ch=='/t'); } bool LRpda::StringToEngender(const char *expr,Engender &engender) { string sTmp; char ch; Token token; int flag=1; while((ch=*expr)!='/0') { if(ch=='(' || ch==')' ||ch=='[' ||ch==']' ||ch==',' ||ch=='*' ||ch==';' ) { if(sTmp.size()!=0) { token.name=sTmp; token.property=get_property(sTmp); if(token.property=="") { cout<<"未知字符 "<<token.name<<endl; return 0; } sTmp.clear(); engender.push_back(token); } ++expr; sTmp.push_back(ch); flag=1; } else if(is_delim(ch)) { if(sTmp.size()!=0) { token.name=sTmp; token.property=get_property(sTmp); if(token.property=="") { cout<<"未知字符 "<<token.name<<endl; return 0; } sTmp.clear(); engender.push_back(token); } ++expr; } else if(flag) { if(sTmp.size()!=0) { token.name=sTmp; token.property=get_property(sTmp); if(token.property=="") { cout<<"未知字符 "<<token.name<<endl; return 0; } sTmp.clear(); engender.push_back(token); } ++expr; sTmp.push_back(ch); flag=0; } else { sTmp.push_back(ch); ++expr; } } if(sTmp.size()!=0) { token.name=sTmp; token.property=get_property(sTmp); if(token.property=="") { cout<<"未知字符 "<<token.name<<endl; return 0; } engender.push_back(token); } return 1; } bool LRpda::Execute(const char * exprtmp) { State state; Action action,actiontmp; Token token,token1,token2,token3,token4,token0; Engender expr; int index=0,enlen,cur; string sTmp; int expr_len=0; string suffix; int para_num=0; char sbuf[128]={0}; string explain; if(StringToEngender(exprtmp,expr)==0) { return 0; } expr_len=expr.size(); state=start; token=expr[index++]; sStack.push(state); while(1) { if(state==9) { explain=explain+"函数,函数形参( "; } if(state==6) { suffix=token.name+"维数组,数组元素的类型为"; explain=explain+suffix; } action=ACTION(state,token); if(action[0]=='e') { actiontmp=action.substr(1,action.size()); state=atoi(actiontmp.c_str()); cout<<Error[state]<<endl; return 0; } else if(action[0]=='s') { actiontmp=action.substr(1,action.size()); state=atoi(actiontmp.c_str()); sStack.push(state); tStack.push(token); if(index >=expr_len) { cout<<"缺少终结符!"<<endl; return 0; } token=expr[index++]; } else if(action[0]=='r') { actiontmp=action.substr(1,action.size()); cur=atoi(actiontmp.c_str()); switch(cur) { case 1: token2=tStack.top(); tStack.pop(); token1=tStack.top(); tStack.pop(); token0.name=token1.name+token2.name; tStack.push(token0); suffix=token1.name; explain=explain+suffix+";"; break; case 3: token2=tStack.top(); tStack.pop(); token1=tStack.top(); tStack.pop(); token0.name=token1.name+token2.name; tStack.push(token0); suffix="指针,指针指向的类型为"; explain=explain+suffix; break; case 4: token3=tStack.top(); tStack.pop(); token2=tStack.top(); tStack.pop(); token1=tStack.top(); tStack.pop(); token0.name=token1.name+token2.name+token3.name; tStack.push(token0); break; case 6: token3=tStack.top(); tStack.pop(); token2=tStack.top(); tStack.pop(); token1=tStack.top(); tStack.pop(); token0.name=token1.name+token2.name+token3.name; tStack.push(token0); sprintf(sbuf,")形参数为 %d , 函数返回类型为 ",para_num); para_num=0; suffix=sbuf; explain=explain+suffix; break; case 2: case 9: token3=tStack.top(); tStack.pop(); token2=tStack.top(); tStack.pop(); token1=tStack.top(); tStack.pop(); token0.name=token1.name+token2.name+token3.name; tStack.push(token0); ++para_num; break; case 11: token4=tStack.top(); tStack.pop(); token3=tStack.top(); tStack.pop(); token2=tStack.top(); tStack.pop(); token1=tStack.top(); tStack.pop(); token0.name=token1.name+token2.name+token3.name+token4.name; tStack.push(token0); break; case 7: case 12: tStack.push(""); break; case 10: para_num=0; tStack.push(""); break; case 5: suffix="变量名为"+tStack.top().name+",变量的类型为"; explain=explain+suffix; break; case 8: para_num=1; break; default:break; } enlen=eExprs[cur].engender.size(); while(enlen) { sStack.pop(); --enlen; } state=sStack.top(); action=GOTO(state,eExprs[cur].uToken); state=atoi(action.c_str()); if(state==-1) { cout<<"状态出错!"<<endl;; return 0; } sStack.push(state); token0=tStack.top(); } else if(action==ACCEPT) { system("cls"); cout<<"分析完毕!"<<endl; cout<<"********************************************************************************"<<endl; cout<<exprtmp<<" --> "<<explain<<endl; cout<<"********************************************************************************/n"<<endl; return 1; } else { cout<<"分析未完成!"<<endl; return 0; } } } void LRpda::addExpr(const Token& token,const string& engender) { stringstream enStream(engender); Token tTmp; eExpr eTmp; string sTmp; eTmp.uToken=token; while(enStream>>sTmp) { tTmp.name=sTmp; tTmp.property=sTmp; eTmp.engender.push_back(tTmp); } eExprs.push_back(eTmp); } void LRpda::addType(const string type) { TYPE.push_back(type); } LRpda::Action LRpda::ACTION(const State state,const Token& ttoken) { int j; for(j=0;j<tTokenCount;++j) if(tTokens[j]==ttoken.property) break; if(j>=tTokenCount) return "e0"; return matrix[state][j]; } LRpda::Action LRpda::GOTO(const State state,const Token& utoken) { int j; for(j=0;j<uTokenCount;++j) if(uTokens[j]==utoken.property) break; if(j>=uTokenCount) return "e0"; return matrix[state][tTokenCount+j]; } void menu(void) { LRpda lrpda; string expr; while(1) { cout<<"请输入表达式(直接按回车退出): "<<endl; getline(cin,expr); if(expr.size()==0) { cout<<"谢谢使用,再见!"<<endl; return; } lrpda.Execute(expr.c_str()); expr.clear(); } } int main(void) { menu(); getchar(); return 0; }