实验三自下而上语法分析及语义分析
一、实验目的:
通过本实验掌握LR分析器的构造过程,并根据语法制导翻译,掌握属性文法的自下而上计算的过程。
二、实验学时:
4学时。
三、实验内容
根据给出的简单表达式的语法构成规则(见五),编制LR分析程序,要求能对用给定的语法规则书写的源程序进行语法分析和语义分析。
对于正确的表达式,给出表达式的值。
对于错误的表达式,给出出错位置。
四、实验方法
采用LR分析法。
首先给出S-属性文法的定义(为简便起见,每个文法符号只设置一个综合属性,即该文法符号所代表的表达式的值。
属性文法的定义可参照书137页表),并将其改造成用LR分析实现时的语义分析动作(可参照书145页表)。
接下来给出LR分析表。
然后程序的具体实现:
LR分析表可用二维数组(或其他)实现。
添加一个val栈作为语义分析实现的工具。
编写总控程序,实现语法分析和语义分析的过程。
注:对于整数的识别可以借助实验1。
五、文法定义
简单的表达式文法如下:
E->E+T|E-T|T
T->T*F|T/F|F
F->(E)|i
上式中, i 为整数。
六、处理程序例
例1: 正确源程序例:
23+(45+4)* 40分析结果应为:正确的表达式。
其值为:1983
例2: 错误源程序例:
5+(56+)-24
分析结果应为:错误的表达式:出错位置为)
附录:源程序
#include <>
#include""
#include <iostream>
using namespace std;
#define R 30
#define C 20
typedef struct elem
{
char e[4];
}Elem; ;
for(i=0;i<row;i++)
{
printf("请输入%d号状态所对应的各列的元素,空白的地方用s代替\n",i);
for(j=0;j<colno;j++)
{
scanf("%s",mid);
if(strcmp(mid,"s")==0||strcmp(mid,"S")==0)
strcpy(LR[i+1][j].e," ");
else
strcpy(LR[i+1][j].e,mid);
}
}
}
void output_LR(int row,int colno)
{
int i,j;
printf("**********************************************************\n");
printf("* LR分析表如下: *\n");
printf("**********************************************************\n");
printf("\n");
printf(" ");
for(j=0;j<colno;j++)
printf("%s ",LR[0][j].e);
printf("\n");
for(i=1;i<=row;i++)
{
printf("%d ",i-1);
for(j=0;j<colno;j++)
printf("%s ",LR[i][j].e);
printf("\n");
}
printf("\n");
}
int SignNum(char ch)==0)
return i;
return -1;
}
int CharChangeNum(char* ch);
if(strcmp(mid," ")==0)
{ printf("不能规约\n"); return -2; }
if(strcmp(mid,"acc")==0||strcmp(mid,"ACC")==0)
{ printf("规约成功\n"); return -1; }
out[i+1].order=i+2;
if(mid[0]=='s'||mid[0]=='S')
{
s_num=CharChangeNum(mid+1);tate[j]=out[i].state[j];
out[i+1].state[stateTop]=s_num;
out[i+1].state[++stateTop]=-1; ign,out[i].sign);
out[i+1].sign[signTop]=out[i].input[0];
out[i+1].sign[++signTop]='\0'; rasen," "); nput,out[i].input+1); tate[j]=out[i].state[j];
j=SignNum(gra[0]);
out[i+1].state[stateTop]=CharChangeNum(LR[out[i+1].state[stateTop-1]+1][
j].e);
out[i+1].state[++stateTop]=-1; ign,out[i].sign);
out[i+1].sign[signTop]=gra[0];
out[i+1].sign[++signTop]='\0'; rasen,gra);
nput,out[i].input); rder);
while(out[i].state[j]!=-1)
printf("%d",out[i].state[j++]);
printf(" %s %s %s\n",out[i].sign,out[i].grasen,out[i].input)
;
}
}
int OutControl()rder=1; tate[0]=0;
stateTop=1; out[0].state[stateTop]=-1; ign,"#");
signTop=1; rasen," "); nput,Sentence); nput,"#");
strcpy(out[0].explen,"0和#进栈"); nput[0]);
tate[stateTop-1],s_num,i)!=1)
break;
i++;
}
return i;
}
main()
{
int r;
printf("**********************************************************\n");
printf("* 函数的输入: 文法的产生式,文法句型的一个句子,LR分析
表 *\n");
printf("* 函数的输出: LR分析器的工作过程与说明 *\n");
printf("**********************************************************\n");
printf("请输入LR分析表中终结符与非终结符的总个数\n");
scanf("%d",&colno);
printf("请输入LR分析表中状态的总个数\n");
scanf("%d",&row);
input_LR(row,colno);
output_LR(row,colno);
input_GramSent();
r=OutControl(); //r为输出结果的行数 OutputResult(r);
}
七、实验小结
这个程序是从网上下载下来的,根据这个实验要求做了些更改,但是总是出现溢出错误,只能运行到LR分析表的部分(如截图),没有找到解决问题的办法。