语法分析GUET编译原理课设,当时找了很多资料,网上的资料乱七八糟,花了哥哥我好久时间。致谢:代码的算法有参考书本其他博主的,表示感谢,同时也更正他们的了一些微小错误和不合理地方。这里,我用书本的例子数据作为测试。
西北工业大学出版社《编译原理》蒋立源 第3版第157页代码中的约定:
用 0 表示空用102表示移进 s2用 53 表示规约 r3#include <iostream>#include<stdio.h>#include<stdlib.h>using namespace std;//0为空白//102表示S2//51表示r1int actionTable[12][6] = { 102,0,0,0,0,0, 0,0,0,0,0,-1, 0,104,0,0,0,0, 0,0,105,0,0,0, 0,0,53,0,0,0, 0,107,0,108,0,0, 0,0,0,0,109,0, 0,0,52,0,0,0, 0,0,110,0,55,0, 0,0,0,0,0,51, 0,0,0,108,0,0, 0,0,0,0,54,0};int gotoTable[12][3] = { 1,0,0,0,0,0, 0,3,0,0,0,0, 0,0,0,0,0,6, 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,11,0,0,0};//语法表,存储读取的文法char Grammar[20][10] = { '\0' };char vtArray[10], vnArray[10];//action表横坐标数组:用于定位,查表char actionAxis[6] = { 'b', 'd', 't', 's', 'e', '#' };//goto表横坐标数组:用于定位,查表char gotoAxis[3] = { 'B', 'D', 'S' };//非终结符数量,终结符数量,状态数量int vnNumber, vtNumber, stateNumber = 12;int LR[10];int grammarNum;typedef struct { char * base; char * top;}SymbolStack;typedef struct { int * base; int * top;}StateStack;StateStack state;SymbolStack symbol;//扫描文法文件,得到文法//左部符号存储在第一列,即 Grammar[i][0]int scanGrammar() { FILE * fp = fopen("slr.txt", "r"); FILE * tp; char ch, nextCh; int i = 0, j = 0, k, count; while (!feof(fp)) { fscanf(fp, "%c", &ch); //文件结束标志 if (ch == '?') { Grammar[i][j] = '\0'; break; } if (ch == '\n') { Grammar[i][j] = '\0'; //转移到下一行第一列 i++; j = 0; continue; } if (ch == '-') { tp = fp; fscanf(tp, "%c", &nextCh); if (nextCh == '>') { fp = tp; continue; } } if (ch == '|') { Grammar[i + 1][0] = Grammar[i][0]; Grammar[i][j] = '\0'; i++; j = 1; continue; } Grammar[i][j] = ch; if (ch >= 'A' && ch <= 'Z') { count = 0; while (vnArray[count] != ch && vnArray[count] != '\0') { count++; } if (vnArray[count] == '\0') { vnNumber = count + 1; //拓广文法的开始符W if (ch == 'W') { j++; continue; } vnArray[count] = ch; vnNumber = count + 1; } } else { count = 0; while (vtArray[count] != ch && vtArray[count] != '\0') { count++; } if (vtArray[count] == '\0') { vtArray[count] = ch; vtNumber = count + 1; } } j++; } cout << "输入的文法:" << endl; for (k = 0; k <= i; k++) { j = 0; while (Grammar[k][j] != '\0') { if (j == 1) { printf("->"); } printf("%c", Grammar[k][j]); j++; } cout << endl; } count = 0; cout << endl << "vn:" << endl; while (vtArray[count] != '\0') { printf("%3c", vtArray[count]); count++; } vtArray[count] = '#'; vtNumber = count + 1; printf("%3c", vtArray[count]); cout << endl << "vn:" << endl; count = 0; while (vnArray[count] != '\0') { printf("%3c", vnArray[count]); count++; } cout << endl; fclose(fp); grammarNum = i + 1; return i;}//计算LR(0)项目长度,决定了:规约时符号栈和状态栈的出栈次数int getLRLength() { int i, j; for (i = 0; i < grammarNum; i++) { j = 1; while (Grammar[i][j] != '\0') { j++; } //产生式 i 的长度为 j LR[i] = j; } return 0;}//创建栈void createStack() { state.base = (int *)malloc(100 * sizeof(int)); if (!state.base) exit(1); state.top = state.base; *state.top = 0; symbol.base = (char *)malloc(100 * sizeof(char)); if (!symbol.base) exit(1); symbol.top = symbol.base; *symbol.top = '#';}//查 Action 表int getActionValue(int stateTop, char ch) { int i, j; //查找 //更改 i 为 stateTop /*for (i = 0; i < stateNumber; i++) { if (stateTop == i) { break; } }*/ //查找横坐标数组actionAxis,定位 for (j = 0; j < vtNumber; j++) { if (ch == actionAxis[j]) break; } return actionTable[stateTop][j];}//查 Goto 表int getGotoValue(int stateTop, char inputChar) { int i, j; for (j = 0; j < vnNumber; j++) { if (inputChar == gotoAxis[j]) break; } if (gotoTable[stateTop][j] == 0) { //cout << "Error" << endl; } return gotoTable[stateTop][j];}//输出信息int printInfo(int count, int i, char chars[], int actionValue) { int * p = state.base, stateNum; int j, jj; char * q = symbol.base, symbolNum; printf("%d\t", count); while (p != state.top + 1) { stateNum = *p; printf("%d", stateNum); p++; } printf("\t"); while (q != symbol.top + 1) { symbolNum = *q; printf("%c", symbolNum); q++; } printf("\t"); j = i; jj = 0; while (jj < j) { printf(" "); jj++; } while (chars[j] != '\0') { printf("%c", chars[j]); j++; } if (actionValue > 100) { cout << "\t\ts" << actionValue - 100 << "\t" << actionValue - 100 << endl; } //如果是规约,把预留下一状态给规约程序输出,在此不清除下一状态为多少 else if (actionValue > 50) { cout << "\t\tr" << actionValue - 50 << "\t"; } else if (actionValue == -1) { cout << "\t\tacc" << "\n\n可以识别的输入串\n" << endl; } else { return 0; } return 1;}//规约 -- 根据编号为 i 的产生式进行规约//规约的结果是一个非终结符号,即 Grammar[i][0]int redution(int i) { int * p, stateNum, gotoValue, LRLength; LRLength = LR[i] - 1; while (LRLength != 0) { state.top--; symbol.top--; LRLength--; } int temp = *state.top; state.top++; *state.top = getGotoValue(temp, Grammar[i][0]); symbol.top++; *symbol.top = Grammar[i][0]; stateNum = *state.top; if (*state.top == 0) { return *state.top; } return *state.top;}//扫描输入字符串int scanChars() { char chars[20] = { 'b', 'd', 't', 's', 'e','#' }; int i = 0, stepCount = 1; int actionValue, nextActionValue; int stateTop, gotoValue; //scanf("%s", &chars); cout << "步骤\t状态\t栈中\t余留符号 分析动作 下一状态" << endl; while (chars[i] != '\0') { stateTop = *state.top; //向前查看一个符号,查action表 actionValue = getActionValue(stateTop, chars[i]); //如果是移进,就可以输出下一状态 //如果是规约,则等到规约完毕再输出下一状态,因为现在不可知 printInfo(stepCount, i, chars, actionValue); //数组(表格)的值 if (actionValue == 0) { cout <<endl<< "不合法的字符串!" << endl; break; } //acc 接受 if (actionValue == -1) { stepCount++; return 1; } //s 移进 if (actionValue >= 100) { actionValue = actionValue - 100; state.top++; *state.top = actionValue; symbol.top++; *symbol.top = chars[i]; i++; stepCount++; } //r 规约 if (actionValue >= 50 && actionValue < 100) { actionValue = actionValue - 50; gotoValue = redution(actionValue); //规约完毕后,输出下一状态 cout << gotoValue << endl; stepCount++; } } return 0;}int main() { scanGrammar(); getLRLength(); createStack(); scanChars(); system("pause"); return 0;}文法 slr.txt问号结尾
...