SLR(1)語法分析


實驗目的

構造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;

}

  

截圖

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM