本关任务:编写一个程序实现自下而上语法分析,利用SLR(1)分析算法实现。
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#define size 20
//状态个数
#define size_s 10
//终结符个数
#define size_a 5
//非终结符个数
#define size_g 2
//文法规则条数
#define size_ge 5
#define MAXSIZE 3
typedef struct Ge
{
char head;
char gen[4];
}Generate;
typedef struct A
{
int st[size_a];
int re[size_a];
}Action;
typedef struct G
{
char head[size_g];
int gt[size_g];
}GOTO;
int status[size]; //状态栈
int sta_Index; //状态栈栈顶
char symbol[size]; //符号栈
int sym_Index; //符号栈栈顶
char expression[size]; //输入串
int exp_Index; //输入串最后下标
int exp_top; //输入串开始下标
int step; //步骤
int IsAccept = 0; //0 不接受,1表示接受
Generate gene[size_ge +1]; //文法
Action act[size_s]; //action表
GOTO go[size_s]; //goto表
void GOTOTable(int sta, char symb);
void Syntax(void)//输出文法
{
printf("-------SLR(1) Analysis Program -------- \n");
printf(" (1)S -> Sb\n (2)S -> bAa\n (3)A -> aSc\n (4)A -> aSb\n (5)A -> a\n ");
printf("-----------------------------------------\n");
}
void InputExpression(void)//输入表达式,以#结束
{
char ch;
printf("请输入分析串,以'#'结束:");
exp_Index = 0;
do
{
scanf("%c",&ch);
if ((ch!='a') &&(ch!='b') &&(ch!='c')&&(ch!='#'))
{
printf("fail");
getchar();
exit(0);
}
expression[exp_Index++]=ch;
}while(ch!='#');
getchar();
}
void Initlize(void)//将文法、action表、goto表初始化
{
gene[1].head = 'S';
strcpy(gene[1].gen,"Sb");
gene[2].head = 'S';
strcpy(gene[2].gen,"bAa");
gene[3].head = 'A';
strcpy(gene[3].gen,"aSc");
gene[4].head = 'A';
strcpy(gene[4].gen,"aSb");
gene[5].head = 'A';
strcpy(gene[5].gen,"a");
act[0].st[1] = 2;
act[1].st[1] = 3; //E -> E + T\n (1)E -> T\n (2)T -> T*F\n (3)T -> F\n (4)F -> (E)\n (5)F ->i\n");
// act[1].st[5] = 10;
act[2].st[0] = 5;
act[3].re[1] = 1;
act[3].re[2] = 1;
act[3].re[3] = 1;
act[4].st[0] = 6;
act[5].re[0] = 5;
act[5].st[1] = 2;
act[6].re[1] = 2;
act[6].re[2] = 2;
act[6].re[3] = 2;
act[7].st[1] = 9;
act[7].st[2] = 8;
act[8].re[0] = 3;
act[9].re[0] = 4;
act[9].re[1] = 1;
act[9].re[2] = 1;
act[9].re[3] = 1;
go[0].head[0] = 'S';
go[0].gt[0] = 1;
go[2].head[1] = 'A';
go[2].gt[1] = 4;
go[5].head[0] = 'S';
go[5].gt[0] = 7;
sta_Index = 0; //状态栈栈顶
status[sta_Index] = 0; //状态栈
step = 1; //步骤
sym_Index = 0; //符号栈栈顶
symbol[sym_Index] = '#'; //符号栈
IsAccept = 0; //是否被接受
exp_top = 0; //表达式下标
}
void Reduce(int sta, char symb,int col)
//归约,若句柄有n个字符,则状态栈和符号栈都需要出栈n个
{
int i = 0;
for(i = 0; i < strlen(gene[act[sta].re[col]].gen); i++)
{
symbol[sym_Index--] = '\0';
}
symbol[++sym_Index] = gene[act[sta].re[col]].head;
for(i = 0; i < strlen(gene[act[sta].re[col]].gen) ; i++)
{
status[sta_Index - i] = '\0';
}
sta_Index -= i;
GOTOTable(status[sta_Index], symbol[sym_Index]);
}
void ActionTable(int sta, char symb,int col)
//对应LR分析表,
{
if(sta == 1 && col == 3)
{
printf("accept\n");
IsAccept = 1;
return;
}
if(act[sta].st[col] != 0)
{
status[++sta_Index] = act[sta].st[col];
symbol[++sym_Index] = symb;
exp_top ++;
}
else if(act[sta].re[col] != 0)
{
Reduce(sta, symb, col);
}
else
{
getchar();
exit(1);
}
}
void GOTOTable(int sta, char symb)
{
int i = 0;
for(i = 0; i < size_s; i++)
{
if(go[sta].head[i] == symb)
{
status[++sta_Index] = go[sta].gt[i];
return;
}
}
}
void Launch(void)//语法分析
{
int s = status[sta_Index];
char exp = expression[exp_top];
char sym = symbol[sym_Index];
while(IsAccept != 1)
{
s = status[sta_Index];
exp = expression[exp_top];
sym = symbol[sym_Index];
switch(exp)
{
case 'a':
ActionTable(s, exp, 0);
break;
case 'b':
ActionTable(s, exp, 1);
break;
case 'c':
ActionTable(s, exp, 2);
break;
case '#':
ActionTable(s, exp, 3);
break;
}
}
}
int main()
{
Syntax();//输出文法
InputExpression();//输入表达式
//初始化文法数组gene[]、action表中:act[].st[]为状态, act[].re[]为规则
//goto表go[].head[]为表头, go[].gt[]为转移状态
Initlize();
Launch();//语法分析
return 1;
}
因为编译器的不同,某些输入和输出代码会出bug,需要读者自行修改一下,(我用的是DEVC++)另外代码是直接从DEV上复制过来的,进行了一点修改,也可能导致代码报错无法通过,这也需要读者自行修改一下,总体来说代码没有太大的毛病,只需要稍微修改一下就可以啦!