【實驗目的】
構造LR分析程序,利用它進行語法分析,判斷給出的符號串是否為該文法識別的句子,了解LR(K)分析方法是嚴格的從左向右掃描,和自底向上的語法分析方法。
【實驗內容】
對下列文法,用SLR(1)分析法對任意輸入的符號串進行分析:
(1)S->E
(2)E->E+T
(3)E->T
(4)T->T*F
(5)T->F
(6)F->(E)
(7)F->i
【設計思想】
(1)總控程序,也可以稱為驅動程序。對所有的LR分析器總控程序都是相同的。
(2)分析表或分析函數,不同的文法分析表將不同,同一個文法采用的LR分析器不同時,分析表將不同,分析表又可以分為動作表(ACTION)和狀態轉換(GOTO)表兩個部分,它們都可用二維數組表示。
(3)分析棧,包括文法符號棧和相應的狀態棧,它們均是先進后出棧。
分析器的動作就是由棧頂狀態和當前輸入符號所決定。
u LR分析器由三個部分組成:
u 其中:SP為棧指針,S[i]為狀態棧,X[i]為文法符號棧。狀態轉換表用GOTO[i,X]=j表示,規定當棧頂狀態為i,遇到當前文法符號為X時應轉向狀態j,X為終結符或非終結符。
u ACTION[i,a]規定了棧頂狀態為i時遇到輸入符號a應執行。動作有四種可能:
(1)移進:
action[i,a]= Sj:狀態j移入到狀態棧,把a移入到文法符號棧,其中i,j表示狀態號。
(2)歸約:
action[i,a]=rk:當在棧頂形成句柄時,則歸約為相應的非終結符A,即文法中有A- B的產生式,若B的長度為R(即|B|=R),則從狀態棧和文法符號棧中自頂向下去掉R個符號,即棧指針SP減去R,並把A移入文法符號棧內,j=GOTO[i,A]移進狀態棧,其中i為修改指針后的棧頂狀態。
(3)接受acc:
當歸約到文法符號棧中只剩文法的開始符號S時,並且輸入符號串已結束即當前輸入符是'#',則為分析成功。
(4)報錯:
當遇到狀態棧頂為某一狀態下出現不該遇到的文法符號時,則報錯,說明輸入端不是該文法能接受的符號串。
【實驗要求】
1、編程時注意編程風格:空行的使用、注釋的使用、縮進的使用等。
2、如果遇到錯誤的表達式,應輸出錯誤提示信息。
3、程序輸入/輸出實例:
輸入一以#結束的符號串(包括+—*/()i#):在此位置輸入符號串
輸出過程如下:
步驟 狀態棧 符號棧 剩余輸入串 動 作
1 0 # i+i*i# 移進
代碼:
#include<stdio.h> #include<stdlib.h> int Action[12][6] ={105, 0, 0, 104, 0, 0, 0, 106, 0, 0, 0, -1, 0, 52, 107, 0, 52, 52, 0, 54, 54, 0, 54, 54, 105, 0, 0, 104, 0, 0, 0, 56, 56, 0, 56, 56, 105, 0, 0, 104, 0, 0, 105, 0, 0, 104, 0, 0, 0, 106, 0, 0, 111, 0, 0, 51, 107, 0, 51, 51, 0, 53, 53, 0, 53, 53, 0, 55, 55, 0, 55, 55 }; int Goto[12][3] ={1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 2, 3, 0, 0, 0, 0, 9, 3, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; char Grammar[20][10] = { '\0' }; char VT[10], VN[10]; char AVT[6] = { 'i', '+', '*', '(', ')', '#' }; char GVN[3] = { 'E', 'T', 'F' }; int vnNum, vtNum, stateNum = 12; int VNum[10]; int grammarNum; typedef struct{ char *base; char *top; }SymbolStack; typedef struct{ int *base; int *top; }StateStack; StateStack state; SymbolStack symbol; int ScanGrammar() { FILE *fp = fopen("D:\SLR文法.txt","r"); FILE *tp; char singleChar, nextChar; int i = 0, j = 0, k, count; while (!feof(fp)) { fscanf(fp, "%c", &singleChar); if (singleChar == '?') { Grammar[i][j] = '\0'; break; } if (singleChar == '\n') { Grammar[i][j] = '\0'; i++; j = 0; continue; } if (singleChar == '_') { tp = fp; fscanf(tp, "%c", &nextChar); if (nextChar == '>') { fp = tp; continue; } } if (singleChar == '|') { Grammar[i + 1][0] = Grammar[i][0]; Grammar[i][j] = '\0'; i++; j = 1; continue; } Grammar[i][j] = singleChar; if (singleChar >= 'A'&&singleChar <= 'Z'){ count = 0; while (VN[count] != singleChar&&VN[count] != '\0') { count++; } if (VN[count] == '\0') { vnNum = count + 1; if (singleChar == 'S') { j++; continue; } VN[count] = singleChar; vnNum = count + 1; } } else { count = 0; while (VT[count] != singleChar&&VT[count] != '\0') { count++; } if (VT[count] == '\0') { VT[count] = singleChar; vtNum = count + 1; } } j++; } printf("輸入的文法:\n"); for (k = 0; k <= i; k++) { j = 0; while (Grammar[k][j] != '\0') { if (j == 1) { printf("_>"); } printf("%c", Grammar[k][j]); j++; } printf("\n"); } count = 0; printf("VT:"); while (VT[count] != '\0') { printf("%3c", VT[count]); count++; } VT[count] = '#'; vtNum = count + 1; printf("%3c", VT[count]); printf("\nVN:"); count = 0; while (VN[count] != '\0') { printf("%3c", VN[count]); count++; } printf("\n"); // printf("\n%d %d\n", vtNum, vnNum); fclose(fp); grammarNum = i + 1; return i; } int vNumCount() { int i,j; for (i = 0; i < grammarNum; i++) { j = 1; while (Grammar[i][j] != '\0') { j++; } VNum[i]=j; //printf("%3d", VNum[i]); } printf("\n"); return 0; } void InitStack() { 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 = '#'; } int Judge(int stateTop, char inputChar) { int i,j; for (i = 0; i < stateNum; i++){ if (stateTop == i)break; } for (j = 0; j < vtNum; j++){ if (inputChar == AVT[j])break; } return Action[i][i]; } int GetGoto(int stateTop, char inputChar){ int i, j; for (i = 0; i < stateNum; i++){ if (stateTop == i) break; } for (j = 0; j < vnNum; j++) { if (inputChar == GVN[j]) break; } return Goto[i][j]; } int print(int count, int i, char Input[], int action, int gt, int sign) { 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 (Input[j] != '\0') { printf("%c", Input[j]); j++; } printf("\t"); if (sign == 1) { printf("\tS%d\t%d\n", action, gt); } if (sign == 2) { printf("\tr%d\t%d\n", action, gt); } if (sign == 3) { printf("tacc\t%d\n", gt); } if (sign == 0) printf("\t0\t0\n"); return 0; } int Pop(int action) { int *p, stateNumn, ssValue, i; state.top--; p = state.top; stateNum = *p; i = VNum[action] - 1; while (i != 0) { symbol.top--; i--; } symbol.top++; *symbol.top = Grammar[action][0]; ssValue=GetGoto(stateNum,Grammar[action][0]); if (ssValue == 0)return ssValue; state.top++; *state.top = ssValue; return ssValue; } int Reduction() { char Input[20]; int i = 0,count = 1; int ssValue, action; int stateTop, gt; int sign = -1; // 彩進1, 規約2, 接受3 scanf("%s", &Input); while (Input[i] != '\0') { if (Input[i] >= 'A'&&Input[i] <= 'Z') { printf("輸入的不是有效的表達式!"); return 0; } i++; } i = 0; printf("步驟\t狀態棧\t符號棧\t輸入串\t\tACTION\tGOTO\n"); while (Input[i] != '\0') { if (count == 1) { print(count, i, Input, 0, 0, 0); count++; } stateTop = *state.top; ssValue = Judge(stateTop, Input[i]); if (ssValue == 0) { state.top--; if (*symbol.top == '#') { printf("規約出錯!"); return 0; } continue; } if (ssValue == -1) { sign = 3; print(count, i, Input, ssValue, 0, sign); count++; return 1; } if (ssValue >= 100) { sign = 1; action = ssValue - 100; state.top++; *state.top = action; symbol.top++; *symbol.top = Input[i]; i++; print(count, i, Input, action, 0, sign); count++; } if (ssValue >= 50 && ssValue < 100) { sign = 2; action = ssValue - 50; gt = Pop(action); print(count, i, Input, action, gt, sign); count++; } } return 0; } int main() { ScanGrammar(); vNumCount(); InitStack(); Reduction(); return 0; }
截圖: