一、实验目的
构造LR(1)分析程序,利用它进行语法分析,判断给出的符号串是否为该文法识别的句子,了解LR(K)分析方法是严格的从左向右扫描,和自底向上的语法分析方法。
二、实验题目
1、对下列文法,用LR(1)分析法对任意输入的符号串进行分析:
(0)E->S
(1)S->BB
(2)B->aB
(3)B->b
2、LR(1)分析表为:
(0)E->S
(1)S->BB
(2)B->aB
(3)B->b
状态 | ACTION | GOTO | ||||
a | b | # | S | B | ||
S0 | S3 | S4 | 1 | 2 | ||
S1 | acc | |||||
S2 | S6 | S7 | 5 | |||
S3 | S3 | S4 | 8 | |||
S4 | r3 | r3 | ||||
S5 | r1 | |||||
S6 | S6 | S7 | 9 | |||
S7 | r3 | |||||
S8 | r2 | r2 | ||||
S9 | r2 |
(1)若输入baba#,则输出为:
步骤 状态栈 符号栈 输入串 ACTION GOTO
1 0 # baba# S4
2 04 #b aba# r3 2
3 02 #B aba# S6
4 026 #Ba ba# S7
5 0267 #Bab a# error
(2)若输入bb#,则输出为:
步骤 状态栈 符号栈 输入串 ACTION GOTO
1 0 # bb# S4
2 04 #b b# r3 2
3 02 #B b# S7
4 027 #Bb # r3 5
5 025 #BB # r1 1
6 01 #S # acc
三、算法流程图
四、完整程序
#include<stdio.h>
#include<string.h>
//ACTION表
char* action[10][3] = { "S3#","S4#",NULL,
NULL,NULL,"acc",
"S6#","S7#",NULL,
"S3#","S4#",NULL,
"r3#","r3#",NULL,
NULL,NULL,"r1#",
"S6#","S7#",NULL,
NULL,NULL,"r3#",
"r2#","r2#",NULL,
NULL,NULL,"r2#" };
//GOTO表
int goto1[10][2] = { 1,2,
0,0,
0,5,
0,8,
0,0,
0,0,
0,9,
0,0,
0,0,
0,0};
char vt[3] = { 'a','b','#' }; /*存放终结符*/
char vn[2] = { 'S','B' }; /*存放非终结符*/
char* LR[4] = { "E->S#","S->BB#","B->aB#","B->b#" }; //从第四位开始存放产生式
/*输出状态栈、输出符号栈、输出输入串*/
int a[10];//状态表内容
char b[10], c[10], c1;
int top1, top2, top3, top, m, n;
int main() {
int g, h, i, j, k, l, p, y, z, count;
char x, copy[10], copy1[10];//copy1[]为产生式数组
top1 = 0; top2 = 0; top3 = 0; top = 0;
a[0] = 0;
y = a[0];
b[0] = '#';
count = 0;
z = 0;
printf("input:\n");
do {
scanf_s("%c", &c1);
c[top3] = c1;
top3 = top3 + 1;
} while (c1 != '#');
printf("步骤\tS状态\t\tX符号\t\t输入串\t\tACTION\t\tGOTO\n");
do
{
y = z; m = 0; n = 0; /*y,z指向状态栈栈顶*/
g = top; j = 0; k = 0;
x = c[top];
count++; printf("%d\t", count);
while (m <= top1) /*输出状态栈*/
{
printf("%d", a[m]); m = m + 1;
} printf("\t\t");
while (n <= top2) /*输出符号栈*/
{
printf("%c", b[n]); n = n + 1;
} printf("\t\t");
while (g <= top3) /*输出输入串*/
{
printf("%c", c[g]); g = g + 1;
}
printf("\t\t");
//查action表
if (x == 'a')j = 0;
if (x == 'b')j = 1;
if (x == '#')j = 2;
if (action[y][j] == NULL)
{
printf("error\n");
return 0;
}
else
strcpy(copy, action[y][j]);
//处理移进
if (copy[0] == 'S')
{
z = copy[1] - '0';
top1 = top1 + 1;
top2 = top2 + 1;
a[top1] = z;
b[top2] = x;
top = top + 1; i = 0;
while (copy[i] != '#')
{
printf("%c", copy[i]); i++;
} printf("\n");
}
//处理归约
if (copy[0] == 'r')
{
i = 0;
while (copy[i] != '#')
{
printf("%c", copy[i]); i++;
}
h = copy[1] - '0';
strcpy(copy1, LR[h]);
if (copy1[0] == 'S')k = 0;
if (copy1[0] == 'B')k = 1;
l = strlen(LR[h]) - 4;//得到产生式右部的长度
top1 = top1 - l + 1;
top2 = top2 - l + 1;
y = a[top1 - 1];
p = goto1[y][k];
if (p == 0) {
printf("error\n");
return 0;
}
else
{
a[top1] = p;
b[top2] = copy1[0];
z = p;
printf("\t\t");
printf("%d\n", p);
}
}
} while (action[y][j] != action[1][2]);
printf("acc!\n");
return 0;
}
五、运行结果截图
1、输入字符串abaa#错误,错误原因为输入串为空:
2、输入字符串babb#错误,出错原因为查表为空:
3、输入字符串bab#正确: