SNL文法的递归下降语法分析器

来源:互联网 发布:c语言bool是什么 编辑:程序博客网 时间:2024/05/21 11:02

得到token序列后,我们就可以采用递归下降法对其进行语法分析。如果没有语法错误,打印token序列,提示没有语法错误,否则,打印已经匹配的token,提示语法错误。(下面程序使用vs2013编译)


#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>#include <iostream>#include <string>#include <vector>using namespace std;//token结构体struct Token{Token(string str, int pos){this->type = str;this->pos = pos;}string type;int pos;};vector<string> IdTable;//全局变量,标示符表vector<int> NbTable;//全局变量,INTC值表FILE *g_pf;//全局变量,打开*.token的文件指针FILE *g_pf_log;//全局变量,日志文件*.log的文件指针vector<string> result;//记录匹配成功的tokenint max_read_num = 0;//最大匹配token数量//从文件中读入一个token,需要先打开*.token文件Token *ReadToken(FILE *pf){if (pf == NULL)exit(-1);char buf1[256] = { 0 };char buf2[256] = { 0 };int num = 0;if (!pf)return NULL;while (!feof(pf)){memset(buf1, 0, sizeof(buf1));memset(buf2, 0, sizeof(buf2));fgets(buf1, sizeof(buf1), pf);result.push_back(buf1);if (result.size() > max_read_num)//记录读入token数量最大值max_read_num = result.size();if (g_pf_log)fprintf(g_pf_log,"读入%s\n", buf1);sscanf(buf1, "(%[^,],%[^)]", buf1, buf2);if (buf2[0] == '"'){return new Token(buf1, -1);}else if (buf2[0] == '['){sscanf(buf2, "[%[0-9]", buf2);num = atoi(buf2);return new Token(buf1, num);}else{return NULL;}}return NULL;}//从文件流中回退一个token,需要先打开*.token文件void BackToken(FILE*pf){if (pf == NULL)exit(-1);string tmp = result[result.size() - 1];int i = tmp.size();while (i){ ungetc(tmp[--i], pf);}if (g_pf_log)fprintf(g_pf_log, "返回%s\n", result[result.size() - 1].c_str());result.erase(result.end() - 1);}//总程序bool MatchProgramHead();bool MatchDeclarePart();bool MatchProgramBody();bool MatchProgramName();bool MatchTypeDecpart();bool MatchVarDecpart();bool MatchProcDecpart();bool MatchTypeDec();bool MatchTypeDecList();bool MatchTypeDecMore();bool MatchTypeId();bool MatchTypeName();bool MatchBaseName();bool MatchStructureType();bool MatchArrayType();bool MatchLow();bool MatchTop();bool MatchRecType();bool MatchFieldDecList();bool MatchFieldDecMore();bool MatchIdList();bool MatchIdMore();//变量声明bool MatchVarDecpart();bool MatchVarDec();bool MatchVarDecList();bool MatchVarDecMore();bool MatchVarIdList();bool MatchVarIdMore();//过程声明bool MatchProcDecpart();bool MatchProcDec();bool MatchProcDecMore();bool MatchProcName();//参数声明bool MatchParamList();bool MatchParamDecList();bool MatchParamMore();bool MatchParam();bool MatchFormList();bool MatchFidMore();//过程中的声明bool MatchProcDecPart();//过程体bool MatchProcBody();bool MatchProgramBody();//语句序列bool MatchStmList();bool MatchStmMore();//语句bool MatchStm();bool MatchAssCall();bool MatchAssignmentRest();bool MatchConditionalStm();bool MatchLoopStm();bool MatchInputStm();bool MatchInvar();bool MatchOutputStm();bool MatchReturnStm();bool MatchCallStmRest();bool MatchActParamList();bool MatchActParamMore();bool MatchRelExp();bool MatchOtherRelE();bool MatchExp();bool MatchOtherTerm();bool MatchTerm();bool MatchOtherFactor();bool MatchFactor();bool MatchVariable();bool MatchVariMore();bool MatchFieldVar();bool MatchFieldVarMore();bool MatchCmpOp();bool MatchAddOp();bool MatchMultOp();bool MatchProgram(){if (!MatchProgramHead())return false;if (!MatchDeclarePart())return false;if (!MatchProgramBody())return false;if (ReadToken(g_pf)->type != "$."){BackToken(g_pf);return false;}return true;}bool MatchProgramHead(){if (ReadToken(g_pf)->type == "$program")return MatchProgramName();return false;}bool MatchProgramName(){if (ReadToken(g_pf)->type == "$id")return true;return false;}bool MatchDeclarePart(){if (!MatchTypeDecpart())return false;if (!MatchVarDecpart())return false;if (!MatchProcDecpart())return false;return true;}bool MatchTypeDecpart(){MatchTypeDec();return true;}bool MatchTypeDec(){if (ReadToken(g_pf)->type != "$type"){BackToken(g_pf);return false;}else{if (!MatchTypeDecList()){BackToken(g_pf);return false;}else{return true;}}}bool MatchTypeDecList(){if (!MatchTypeId())return false;if (ReadToken(g_pf)->type != "$="){BackToken(g_pf);return false;}if (!MatchTypeName()){BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$;"){BackToken(g_pf);BackToken(g_pf);return false;}return MatchTypeDecMore();}bool MatchTypeDecMore(){MatchTypeDecList();return true;}bool MatchTypeId(){if (ReadToken(g_pf)->type == "$id")return true;else{BackToken(g_pf);return false;}}bool MatchTypeName(){if (MatchBaseName())return true;if (MatchStructureType())return true;if (ReadToken(g_pf)->type == "$id")return true;else{BackToken(g_pf);return false;}return false;}bool MatchBaseName(){if (ReadToken(g_pf)->type == "$integer")return true;else{BackToken(g_pf);}if (ReadToken(g_pf)->type == "$char")return true;else{BackToken(g_pf);}return false;}bool MatchStructureType(){if (MatchArrayType())return true;if (MatchRecType())return true;return false;}bool MatchArrayType(){if (ReadToken(g_pf)->type != "$array"){BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$["){BackToken(g_pf);BackToken(g_pf);return false;}if (!MatchLow()){BackToken(g_pf);BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$."){BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$."){BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);return false;}if (!MatchTop()){BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$]"){BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$of"){BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);return false;}return MatchBaseName();}bool MatchLow(){if (ReadToken(g_pf)->type != "$INTC"){BackToken(g_pf);return false;}return true;}bool MatchTop(){if (ReadToken(g_pf)->type != "$INTC"){BackToken(g_pf);return false;}return true;}bool MatchRecType(){if (ReadToken(g_pf)->type != "$record"){BackToken(g_pf);return false;}if (!MatchFieldDecList()){BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$end"){BackToken(g_pf);BackToken(g_pf);return false;}return true;}bool MatchFieldDecList(){if (MatchBaseName())if (MatchIdList())if (ReadToken(g_pf)->type == "$;"){if (MatchFieldDecMore())return true;}else{BackToken(g_pf);}if (MatchArrayType())if (MatchIdList())if (ReadToken(g_pf)->type == "$;"){if (MatchFieldDecMore())return true;}else{BackToken(g_pf);}return false;}bool MatchFieldDecMore(){MatchFieldDecList();return true;}bool MatchIdList(){if (ReadToken(g_pf)->type != "$id"){BackToken(g_pf);return false;}return MatchIdMore();}bool MatchIdMore(){if (ReadToken(g_pf)->type == "$comma")if (MatchIdList()){return true;}else{BackToken(g_pf);}return true;}bool MatchVarDecpart(){MatchVarDec();return true;}bool MatchVarDec(){if (ReadToken(g_pf)->type != "$var"){BackToken(g_pf);return false;}if (MatchVarDecList())return true;else{BackToken(g_pf);return false;}}bool MatchVarDecList(){if (!MatchTypeName())return false;if (!MatchVarIdList())return false;if (ReadToken(g_pf)->type != "$;"){BackToken(g_pf);return false;}if (!MatchVarDecMore())return false;return true;}bool MatchVarDecMore(){MatchVarDecList();return true;}bool MatchVarIdList(){if (ReadToken(g_pf)->type != "$id"){BackToken(g_pf);return false;}if (!MatchVarIdMore())return false;return true;}bool MatchVarIdMore(){if (ReadToken(g_pf)->type == "$comma"){if (MatchVarIdList()){return true;}else{BackToken(g_pf);}}else{BackToken(g_pf);}return true;}//过程声明bool MatchProcDecpart(){MatchProcDec();return true;}bool MatchProcDec(){if (ReadToken(g_pf)->type != "$procedure"){BackToken(g_pf);return false;}if (!MatchProcName()){BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$("){BackToken(g_pf);BackToken(g_pf);return false;}if (!MatchParamList()){BackToken(g_pf);BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$)"){BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$;"){BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);return false;}if (!MatchProcDecPart()){BackToken(g_pf);return false;}if (!MatchProcBody()){BackToken(g_pf);return false;}if (!MatchProcDecMore()){BackToken(g_pf);return false;}return true;}bool MatchProcDecMore(){MatchProcDec();return true;}bool MatchProcName(){if (ReadToken(g_pf)->type != "$id"){BackToken(g_pf);return false;}return true;}//参数声明bool MatchParamList(){MatchParamDecList();return true;}bool MatchParamDecList(){if (!MatchParam())return false;if (!MatchParamMore())return false;return true;}bool MatchParamMore(){if (ReadToken(g_pf)->type == "$;"){if (MatchParamDecList())return true;elseBackToken(g_pf);}else{BackToken(g_pf);}return true;}bool MatchParam(){if (MatchTypeName())return MatchFormList();if (ReadToken(g_pf)->type == "$var"){if (MatchTypeName()){if (MatchFormList())return true;elseBackToken(g_pf);}else{BackToken(g_pf);}}else{BackToken(g_pf);}return false;}bool MatchFormList(){if (ReadToken(g_pf)->type != "$id"){BackToken(g_pf);return false;}if(!MatchFidMore()){BackToken(g_pf);return false;}elsereturn true;}bool MatchFidMore(){if (ReadToken(g_pf)->type == "$comma"){if (MatchFormList())return true;elseBackToken(g_pf);}else{BackToken(g_pf);}return true;}//过程中的声明bool MatchProcDecPart(){return MatchDeclarePart();}//过程体bool MatchProcBody(){return MatchProgramBody();}bool MatchProgramBody(){if (ReadToken(g_pf)->type != "$begin"){BackToken(g_pf);return false;}if (!MatchStmList()){BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$end"){BackToken(g_pf);BackToken(g_pf);return false;}return true;}//语句序列bool MatchStmList(){if (!MatchStm())return false;if (!MatchStmMore())return false;return true;}bool MatchStmMore(){if (ReadToken(g_pf)->type == "$;"){if (MatchStmList())return true;else{BackToken(g_pf);return false;}}elseBackToken(g_pf);return true;}//语句bool MatchStm(){if (MatchConditionalStm())return true;if (MatchLoopStm())return true;if (MatchInputStm())return true;if (MatchOutputStm())return true;if (MatchReturnStm())return true;if (ReadToken(g_pf)->type == "$id")if (MatchAssCall())return true;elseBackToken(g_pf);elseBackToken(g_pf);return false;}bool MatchAssCall(){if (MatchAssignmentRest())return true;if (MatchCallStmRest())return true;return false;}bool MatchAssignmentRest(){if (!MatchVariMore())return false;if (ReadToken(g_pf)->type == "$:="){if (!MatchExp()){BackToken(g_pf);return false;}else{return true;}}else{BackToken(g_pf);return false;}}bool MatchConditionalStm(){if (ReadToken(g_pf)->type != "$if"){BackToken(g_pf);return false;}if (!MatchRelExp()){BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$then"){BackToken(g_pf);BackToken(g_pf);return false;}if (!MatchStmList()){BackToken(g_pf);BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$else"){BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);return false;}if (!MatchStmList()){BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$fi"){BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);return false;}return true;}bool MatchLoopStm(){if (ReadToken(g_pf)->type != "$while"){BackToken(g_pf);return false;}if (!MatchRelExp()){BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$do"){BackToken(g_pf);BackToken(g_pf);return false;}if (!MatchStmList()){BackToken(g_pf);BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$endwh"){BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);return false;}return true;}bool MatchInputStm(){if (ReadToken(g_pf)->type != "$read"){BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$("){BackToken(g_pf);BackToken(g_pf);return false;}if (!MatchInvar()){BackToken(g_pf);BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$)"){BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);return false;}return true;}bool MatchInvar(){if (ReadToken(g_pf)->type != "$id"){BackToken(g_pf);return false;}return true;}bool MatchOutputStm(){if (ReadToken(g_pf)->type != "$write"){BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$("){BackToken(g_pf);BackToken(g_pf);return false;}if (!MatchExp()){BackToken(g_pf);BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$)"){BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);return false;}return true;}bool MatchReturnStm(){if (ReadToken(g_pf)->type != "$return"){BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$("){BackToken(g_pf);BackToken(g_pf);return false;}if (!MatchExp()){BackToken(g_pf);BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$)"){BackToken(g_pf);BackToken(g_pf);BackToken(g_pf);return false;}return true;}bool MatchCallStmRest(){if (ReadToken(g_pf)->type != "$("){BackToken(g_pf);return false;}if (!MatchActParamList()){BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$)"){BackToken(g_pf);BackToken(g_pf);return false;}return true;}bool MatchActParamList(){if (!MatchExp())return MatchActParamMore();return true;}bool MatchActParamMore(){if (ReadToken(g_pf)->type == "$;"){if (MatchActParamList())return true;else{BackToken(g_pf);return false;}}elseBackToken(g_pf);return true;}bool MatchRelExp(){if (!MatchExp())return false;if (!MatchOtherRelE())return false;return true;}bool MatchOtherRelE(){if (!MatchCmpOp())return false;if (!MatchExp())return false;return true;}bool MatchExp(){if (!MatchTerm())return false;if (!MatchOtherTerm())return false;return true;}bool MatchOtherTerm(){if (MatchAddOp())return MatchExp();return true;}bool MatchTerm(){if (!MatchFactor())return false;if (!MatchOtherFactor())return false;return true;}bool MatchOtherFactor(){if (MatchMultOp())return MatchTerm();return true;}bool MatchFactor(){if (ReadToken(g_pf)->type == "$("){if (MatchExp()){if(ReadToken(g_pf)->type == "$)")return true;else{BackToken(g_pf);BackToken(g_pf);return false;}}else{BackToken(g_pf);return false;}}else{BackToken(g_pf);}if (ReadToken(g_pf)->type == "$INTC")return true;else{BackToken(g_pf);}if (MatchVariable())return true;return false;}bool MatchVariable(){if (ReadToken(g_pf)->type != "$id"){BackToken(g_pf);return false;}return MatchVariMore();}bool MatchVariMore(){bool flag = true;if (ReadToken(g_pf)->type == "$["){if (MatchExp()){if (ReadToken(g_pf)->type == "$]"){return true;}else{BackToken(g_pf);BackToken(g_pf);return false;}}else{BackToken(g_pf);return false;}}else{BackToken(g_pf);}if (ReadToken(g_pf)->type == "$.")if (MatchFieldVar())return true;else{BackToken(g_pf);return false;}else{BackToken(g_pf);}return true;}bool MatchFieldVar(){if (ReadToken(g_pf)->type == "$id"){if (MatchFieldVarMore())return true;else{BackToken(g_pf);return false;}}else{BackToken(g_pf);return false;}}bool MatchFieldVarMore(){if (ReadToken(g_pf)->type == "$["){if (!MatchExp()){BackToken(g_pf);return false;}if (ReadToken(g_pf)->type != "$]"){BackToken(g_pf);return false;}}else{BackToken(g_pf);}return true;}bool MatchCmpOp(){if (ReadToken(g_pf)->type == "$<")return true;elseBackToken(g_pf);if (ReadToken(g_pf)->type == "$=")return true;elseBackToken(g_pf);return false;}bool MatchAddOp(){if (ReadToken(g_pf)->type == "$+")return true;elseBackToken(g_pf);if (ReadToken(g_pf)->type == "$-")return true;elseBackToken(g_pf);return false;}bool MatchMultOp(){if (ReadToken(g_pf)->type == "$*")return true;elseBackToken(g_pf);if (ReadToken(g_pf)->type == "$/")return true;elseBackToken(g_pf);return false;}int main(int argc, char **argv){//设置源文件名string filename;if (argc >= 2)filename = argv[1];elsefilename = "snl.txt";//打开*.tokeng_pf = fopen((filename+".token").c_str(), "r");//判断文件是否存在if (g_pf == NULL){printf("请先进行词法分析!\n");return -1;}//打开语法分析日志文件,语法分析程序调用过程中记录分析信息g_pf_log = fopen((filename + ".log").c_str(), "w+");//进行语法分析,没有语法错误返回true,否则返回falsebool re = MatchProgram();//最多匹配结果while (result.size() < max_read_num){ReadToken(g_pf);//读入一个token}//关闭文件*.tokenfclose(g_pf);//打开文件*.resultFILE * pfile = fopen((filename+".result").c_str(), "w+");//打印result中除最后一个token之外的所有tokenfor (auto iter = result.begin(); iter != result.end() - 1; ++iter){printf(" 已匹配%s", iter->c_str());fprintf(pfile, "已匹配%s", iter->c_str());}if (re)//没有语法错误{//打印最后一个单词printf(" 已匹配%s", (result.end()-1)->c_str());fprintf(pfile, "已匹配%s", (result.end()-1)->c_str());//打印提示成功信息printf("语法分析完成,没有语法错误!\n");fprintf(pfile, "语法分析完成,没有语法错误!\n");}else//存在语法错误{//打印错误信息printf(" 语法错误:单词不匹配%s", (result.end()-1)->c_str());fprintf(pfile, "语法错误:单词不匹配%s", (result.end()-1)->c_str());}//关闭文件*.resultfclose(pfile);//暂停system("pause");}

程序运行结果打印到屏幕,并写入到*.result文件



语法分析阶段完成,如果要写编译器,后面还需要有语义分析,中间代码生成等等。


0 0