编译原理表驱动的语法分析程序
代码按照教材上的说明编写。不明白可以参考教材相应内容。由于本人是自学的,不是软件相关专业的学生,所以不排除代码有错误。以下代码中的quDongTable中的数值表示的是语法表达式的序号,顺序按照前三行注释中的顺序来。\x00表示E=TG;\x01表示G=+TG……;\xff表示出错。本代码测试环境是VS2015和Qt5.9,经过简单的测试可以正确检测表达式是否有误。
#include "qstring.h" #include "qstack.h" // E = TG // G = +TG | -TG | 空 // T = (E) | id //--------------------------------------------------------------------------------------- // + - ( ) id # // E TG TG // G +TG -TG 空 空 // T (E) id //--------------------------------------------------------------------------------------- const static char* quDongTable[] = { "\xff\xff\x00\xff\x00\xff", "\x01\x02\xff\x03\xff\x03", "\xff\xff\x04\xff\x05\xff", }; enum TokenType { TOKEN_NONE, STRING_NUMBER, STRING_PLUS, STRING_MINUS, STRING_L, /* 左括号 */ STRING_R, /* 右括号 */ STRING_END_TAG, }; struct Token { TokenType type; float value; QString str; }; #define NT_E 0 #define NT_T 1 #define NT_G 2 #define NT_NUMBER 3 #define NT_PLUS 4 #define NT_MINUS 5 #define NT_L 6 #define NT_R 7 #define NT_END_TAG 8 int indexOfNonterminator(int nt) { switch (nt) { case NT_E: return 0; case NT_G: return 1; case NT_T: return 2; default: Q_ASSERT(0); break; } return -1; } int indexOfToken(const Token& token) { switch (token.type) { case STRING_PLUS: return 0; case STRING_MINUS: return 1; case STRING_L: return 2; case STRING_R: return 3; case STRING_NUMBER: return 4; case STRING_END_TAG: return 5; default: Q_ASSERT(0); break; } return -1; } bool checkSyntax(const QVector<Token>& tokens) { QStack<int> nonterminators; nonterminators.push(NT_END_TAG); nonterminators.push(NT_E); int i = 0; while (i < tokens.size()) { int stop = nonterminators.pop(); Token peek = tokens[i]; if ((stop == NT_PLUS && peek.type == STRING_PLUS) || (stop == NT_MINUS && peek.type == STRING_MINUS) || (stop == NT_L && peek.type == STRING_L) || (stop == NT_R && peek.type == STRING_R) || (stop == NT_NUMBER && peek.type == STRING_NUMBER) || (stop == NT_END_TAG && peek.type == STRING_END_TAG)) { i++; continue; } else if (stop == NT_E || stop == NT_G || stop == NT_T) { int row = indexOfNonterminator(stop); int col = indexOfToken(peek); int index = quDongTable[row][col]; if (index >= 0) /* != 0xff */ { switch (index) { case 0: nonterminators.push(NT_G); nonterminators.push(NT_T); break; case 1: nonterminators.push(NT_G); nonterminators.push(NT_T); nonterminators.push(NT_PLUS); break; case 2: nonterminators.push(NT_G); nonterminators.push(NT_T); nonterminators.push(NT_MINUS); break; case 3: break; case 4: nonterminators.push(NT_R); nonterminators.push(NT_E); nonterminators.push(NT_L); break; case 5: nonterminators.push(NT_NUMBER); break; } continue; } } break; /* error. */ } bool good = (nonterminators.empty() && i == tokens.size()); return good; } bool test() { QVector<Token> tokens; tokens.push_back({ STRING_NUMBER, 32.5f, "32.5" }); tokens.push_back({ STRING_PLUS, 0, "+" }); tokens.push_back({ STRING_L, 0, "(" }); tokens.push_back({ STRING_L, 0, "(" }); tokens.push_back({ STRING_NUMBER, 0.32f, "0.32" }); tokens.push_back({ STRING_R, 0, ")" }); tokens.push_back({ STRING_MINUS, 0, "-" }); tokens.push_back({ STRING_NUMBER, 33.5f, "33.5" }); tokens.push_back({ STRING_R, 0, ")" }); tokens.push_back({ STRING_END_TAG, 0, "#" }); bool good = checkSyntax(tokens); return good; }
附教材相关内容的图片: