一、实验目的:
利用C语言编制递归下降分析程序,并对简单语言进行语法分析。
编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。
二、实验原理
每个非终结符都对应一个子程序。
该子程序根据下一个输入符号(SELECT集)来确定按照哪一个产生式进行处理,再根据该产生式的右端:
- 每遇到一个终结符,则判断当前读入的单词是否与该终结符相匹配,若匹配,再读取下一个单词继续分析;不匹配,则进行出错处理
- 每遇到一个非终结符,则调用相应的子程序
三、实验要求说明
输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”,并指出语法错误的类型及位置。
例如:
输入begin a:=9;x:=2*3;b:=a+x end #
输出success
输入x:=a+b*c end #
输出‘end' error
四、实验步骤
1.待分析的语言的语法(参考P90)
2.将其改为文法表示,至少包含
–语句
–条件
–表达式
3. 消除其左递归
4. 提取公共左因子
5. SELECT集计算
6. LL(1)文法判断
7. 递归下降分析程序
#include <iostream> #include <ext/hash_map> #include <string.h> #include<map> using std::map; using namespace __gnu_cxx; using namespace std; map<string, string> m; string str="begin if a>9 then a:=4 end #"; vector<string> str_list; vector<string> strnum; int select=0; int kk=0; void test(); void E(); void E1(); void T(); void T1(); void F(); void lrparser(); void yucu(); void statement(); void condition(); void expression(); void term(); void factor(); void test(){ select++; cout<<select<<" "<<strnum[select]<<endl; } void init(){ m["begin"]="1"; m["if"]="2"; m["then"]="3"; m["while"]="4"; m["do"]="5"; m["end"]="6"; m["+"]="13"; m["-"]="14"; m["*"]="15"; m["/"]="16"; m[":"]="17"; m[":="]="18"; m["<"]="20"; m["<="]="21"; m["<>"]="22"; m[">"]="23"; m[">="]="24"; m["="]="25"; m[";"]="26"; m["("]="27"; m[")"]="28"; m["#"]="0"; } //字符串切割函数 vector<string> split(const string& str, const string& delim) { vector<string> res; if("" == str) return res; //先将要切割的字符串从string类型转换为char*类型 char * strs = new char[str.length() + 1] ; strcpy(strs, str.c_str()); char * d = new char[delim.length() + 1]; strcpy(d, delim.c_str()); char *p = strtok(strs, d); while(p) { string s = p; //分割得到的字符串转换为string类型 res.push_back(s); //存入结果数组 p = strtok(NULL, d); } return res; } //辨别字符串是否为纯数字 bool AllisNum(string str) { for (int i = 0; i < str.size(); i++) { int tmp = (int)str[i]; if (tmp >= 48 && tmp <= 57) { continue; } else { return false; } } return true; } void scanner() { int chock=0; int row=1; init(); //string str="begin a/*:=bc/:()d>=eas;dasd"; // string str; // string s; // cout<<"请输入字符串:"<<endl; // do{ // getline(cin,s); // str+=s; // if(str[str.size()-1]=='#'){ // break; // } // str+=" "; // }while(1); //插入空格 for(int i=0;i<str.size();i++){ switch(str[i]){ case '+': str.insert(i," "); i++; str.insert(i+1," "); break; case '-': str.insert(i," "); i++; str.insert(i+1," "); break; case '*': str.insert(i," "); i++; str.insert(i+1," "); break; /**/ case '/': if(str[i+1]=='*'){ for(int k=i;k<str.size();k++){ if(str[k]=='/' && str[k-1]=='*'){ cout<<"成功进入"<<endl; str.erase(i,k-i+1); str.insert(i," "); chock=1; break; } } if(chock==0){ chock=0; cout<<"注释方式错误不完整,错误位置第"<<row<<"行"<<endl ; exit(0); } } else{ str.insert(i," "); i++; str.insert(i+1," "); } break; case ':': str.insert(i," "); if(str[i+2]=='=')i=i+2;else i++; str.insert(i+1," "); break; case '<': str.insert(i," "); if(str[i+2]=='=' || str[i+2]=='>')i=i+2;else i++; str.insert(i+1," "); break; case '>': str.insert(i," "); if(str[i+2]=='=')i=i+2;else i++; str.insert(i+1," "); break; case '=': str.insert(i," "); i++; str.insert(i+1," "); break; case ';': str.insert(i," "); i++; str.insert(i+1," "); break; case '(': str.insert(i," "); i++; str.insert(i+1," "); break; case ')': str.insert(i," "); i++; str.insert(i+1," "); break; case '#': str.insert(i," "); i++; str.insert(i+1," "); break; case ' ': str.insert(i," "); i++; row++; str.insert(i+1," "); break; } } for(int i=0;i<str.size();i++){ cout<<str[i]; } cout<<endl; //切割空格 str_list=split(str," "); //输出对应序列 for(int i = 0; i < str_list.size(); i++) { if (m.find(str_list[i]) != m.end()){ cout<<" < "<<str_list[i] <<","<<m[str_list[i]]<<" >"<<endl; strnum.push_back(m[str_list[i]]); } else if(AllisNum(str_list[i])){ cout<<" < "<<str_list[i] <<","<<11<<" >"<<endl; strnum.push_back("11"); } else { cout<<" < "<<str_list[i] <<","<<10<<" >"<<endl; strnum.push_back("10"); } } for(int i = 0; i < strnum.size(); i++){ cout<<strnum[i]<<" "; } } //void E(){ // if(select==strnum.size())return; // T(); // E1(); //} // //void E1(){ // if(select==strnum.size())return; // if(strnum[select]=="13"){ // select++; // T(); // E1(); // } // else if(strnum[select]=="0" || strnum[select]=="28"){ // // } // else cout<<"error : "<<select; // //} // //void T(){ // if(select==strnum.size())return; // F(); // T1(); //} // //void T1(){ // if(select==strnum.size())return; // if(strnum[select]=="15"){ // select++; // F(); // T1(); // } // else if(strnum[select]=="0" || strnum[select]=="13" || strnum[select]=="28"){ // // } // else cout<<"error : "<<select; // //} // //void F(){ // if(select==strnum.size())return; // if(strnum[select]=="27"){ // select++; // E(); // if(strnum[select]=="28"){} // else cout<<"error : "<<select; // } // else if(strnum[select]=="10"){ // select++; // } // else cout<<"error : "<<select; //} //程序,判断是否以begin开始,end #结束 void lrparser(){ if (strnum[select]=="1") { //begin test(); yucu(); if (strnum[select]=="6") { //end test(); if (strnum[select]=="0" && kk==0){ printf("success "); } } else { printf("error,lose 'end' ! "); kk=1; exit(0); } } else { printf("error,lose 'begin' ! "); kk=1; exit(0); } return; } //语句串 void yucu() { statement(); while(strnum[select]=="26") { test(); statement(); } return; } //语句 void statement(){ if (strnum[select]=="10") { //为标识符 test(); if (strnum[select]=="18") { //为 := test(); expression(); } else { printf("error!"); kk=1; exit(0); } } else if(strnum[select]=="2"){ //为if test(); condition(); if(strnum[select]=="3"){ test(); statement(); } else{ printf("error,lose 'then' ! "); kk=1; exit(0); } } else { printf("error!"); kk=1; exit(0); } return; } //条件 void condition(){ expression(); if(strnum[select]=="25"||strnum[select]=="0"||strnum[select]=="20"||strnum[select]=="21"||strnum[select]=="23"||strnum[select]=="24"){ test(); } else{ printf("error! "); kk=1; exit(0); } expression(); return; } //表达式 void expression(){ term(); while(strnum[select]=="13" || strnum[select]=="14") { test(); term(); } return; } //项 void term(){ factor(); while(strnum[select]=="15" || strnum[select]=="16") { test(); factor(); } return; } //因子 void factor(){ if(strnum[select]=="10" || strnum[select]=="11"){ test(); //为标识符或整常数时,读下一个单词符号 } else if(strnum[select]=="27") { test(); expression(); if(strnum[select]=="28"){ test(); } else { printf(" ')' 错误 "); kk=1; exit(0); } } else { cout<<select<<" asdsada"<<endl; printf("表达式错误 "); kk=1; exit(0); } return; } int main(){ scanner(); cout<<endl; lrparser(); }
测试