【實驗目的】
構造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;
}
截圖:

