得到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;//记录匹配成功的token int 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; else BackToken(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; else BackToken(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; } else return true; } bool MatchFidMore() { if (ReadToken(g_pf)->type == "$comma") { if (MatchFormList()) return true; else BackToken(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; } } else BackToken(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; else BackToken(g_pf); else BackToken(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; } } else BackToken(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; else BackToken(g_pf); if (ReadToken(g_pf)->type == "$=") return true; else BackToken(g_pf); return false; } bool MatchAddOp() { if (ReadToken(g_pf)->type == "$+") return true; else BackToken(g_pf); if (ReadToken(g_pf)->type == "$-") return true; else BackToken(g_pf); return false; } bool MatchMultOp() { if (ReadToken(g_pf)->type == "$*") return true; else BackToken(g_pf); if (ReadToken(g_pf)->type == "$/") return true; else BackToken(g_pf); return false; } int main(int argc, char **argv) { //设置源文件名 string filename; if (argc >= 2) filename = argv[1]; else filename = "snl.txt"; //打开*.token g_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,否则返回false bool re = MatchProgram(); //最多匹配结果 while (result.size() < max_read_num) { ReadToken(g_pf);//读入一个token } //关闭文件*.token fclose(g_pf); //打开文件*.result FILE * pfile = fopen((filename+".result").c_str(), "w+"); //打印result中除最后一个token之外的所有token for (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()); } //关闭文件*.result fclose(pfile); //暂停 system("pause"); }
程序运行结果打印到屏幕,并写入到*.result文件
语法分析阶段完成,如果要写编译器,后面还需要有语义分析,中间代码生成等等。
原文地址:http://blog.csdn.net/kyt511/article/details/46490927