【实验目的】
构造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] = { ' ' };
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] = ' ';
break;
}
if (singleChar == '
')
{
Grammar[i][j] = ' ';
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] = ' ';
i++;
j = 1;
continue;
}
Grammar[i][j] = singleChar;
if (singleChar >= 'A'&&singleChar <= 'Z'){
count = 0;
while (VN[count] != singleChar&&VN[count] != ' ')
{
count++;
}
if (VN[count] == ' ')
{
vnNum = count + 1;
if (singleChar == 'S')
{
j++;
continue;
}
VN[count] = singleChar;
vnNum = count + 1;
}
}
else
{
count = 0;
while (VT[count] != singleChar&&VT[count] != ' ')
{
count++;
}
if (VT[count] == ' ')
{
VT[count] = singleChar;
vtNum = count + 1;
}
}
j++;
}
printf("输入的文法:
");
for (k = 0; k <= i; k++)
{
j = 0;
while (Grammar[k][j] != ' ')
{
if (j == 1)
{
printf("_>");
}
printf("%c", Grammar[k][j]);
j++;
}
printf("
");
}
count = 0;
printf("VT:");
while (VT[count] != ' ')
{
printf("%3c", VT[count]);
count++;
}
VT[count] = '#';
vtNum = count + 1;
printf("%3c", VT[count]);
printf("
VN:");
count = 0;
while (VN[count] != ' ')
{
printf("%3c", VN[count]);
count++;
}
printf("
");
// printf("
%d %d
", 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] != ' ')
{
j++;
}
VNum[i]=j;
//printf("%3d", VNum[i]);
}
printf("
");
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 ", count);
while (p != state.top + 1)
{
stateNum = *p;
printf("%d", stateNum);
p++;
}
printf(" ");
while (q != symbol.top + 1)
{
symbolNum = *q;
printf("%c", symbolNum);
q++;
}
printf(" ");
j = i;
jj = 0;
while (jj < j)
{
printf(" ");
jj++;
}
while (Input[j] != ' ')
{
printf("%c", Input[j]);
j++;
}
printf(" ");
if (sign == 1)
{
printf(" S%d %d
", action, gt);
}
if (sign == 2)
{
printf(" r%d %d
", action, gt);
}
if (sign == 3)
{
printf("tacc %d
", gt);
}
if (sign == 0) printf(" 0 0
");
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] != ' ')
{
if (Input[i] >= 'A'&&Input[i] <= 'Z')
{
printf("输入的不是有效的表达式!");
return 0;
}
i++;
}
i = 0;
printf("步骤 状态栈 符号栈 输入串 ACTION GOTO
");
while (Input[i] != ' ')
{
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;
}
截图:
