一、实验目的及要求
1.1 目的
加深对语法分析器工作过程的理解;加强对算符优先分析法实现语法分析程序的掌握;能够采用一种编程语言实现简单的语法分析程序;能够使用自己编写的分析程序对简单的程序段进行语法翻译。
1.2 要求
对语法规则有明确的定义
编写的分析程序能够对实验一的结果进行正确的语法分析
对于遇到的语法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成语法分析过程
软件、硬件环境:code::blocks 10.05,win10系统
二、实验步骤
2.1 实验步骤
定义目标语言的语法规则
求解预测分析方法需要的符号集和分析表
输入将要进行分析的句子
根据预测分析的方法进行语法分析,直到源程序结束
对遇到的语法错误做出错误处理
2.2 文法定义
E->E*T
F->T
T->(E)
T->i
2.3 求出FIRSTVT和LASTVT
FIRSTVT LASTVT
E * ( i * ) i
T ( i ) i
2.4 画出算符优先分析表
* ( ) i #
* > < > < >
( < < = < >
) > >
i > > >
# < < < =
三、实验内容
# include<stdlib.h>
# include<stdio.h>
# include<string.h>
# include<iostream>
# define SIZE 128
char priority[6][6]={{0},{'>','>','<','<','>','>'},{'>','>','$','$','>','>'},{'<','<','<','<','=','$'},
{'>','>','$','$','>','>'},{'<','<','<','<','$','='}};
char input[SIZE];
char remain[SIZE];
char AnalyseStack[SIZE];
int testchar(char x),k;
void remainString();
int testchar(char x){
int m;
if(x=='+') m=0;
if(x=='*') m=1;
if(x=='i') m=2;
if(x=='(') m=3;
if(x==')') m=4;
if(x=='#') m=5;
return m;
}
void analyse(){
int i,j,f,z,z1,n,n1,z2,n2;
int count=0;
char a;
char p,Q,p1,p2;
f=strlen(input);
for(i=0;i<=f;i++) {
a=input[i];
if(i==0) remainString();
if(AnalyseStack[k]=='+'||AnalyseStack[k]=='*'||AnalyseStack[k]=='i'
||AnalyseStack[k]=='('||AnalyseStack[k]==')'||AnalyseStack[k]=='#')
j=k;
else j=k-1;
z=testchar(AnalyseStack[j]);
if(a=='+'||a=='*'||a=='i'||a=='('||a==')'||a=='#') n=testchar(a);
else //如果句子含有不是终结符集合里的其它字符,不合法
printf("错误!该句子不是该文法的合法句子!\n"); break;
p=priority[z][n];
if(p=='$'){
printf("错误!该句子不是该文法的合法句子!\n"); return;
}
if(p=='>'){
for( ; ; ){
Q=AnalyseStack[j];
if(AnalyseStack[j-1]=='+'||AnalyseStack[j-1]=='*'||AnalyseStack[j-1]=='i'
||AnalyseStack[j-1]=='('||AnalyseStack[j-1]==')'||AnalyseStack[j-1]=='#')
j=j-1;
else j=j-2;
z1=testchar(AnalyseStack[j]);
n1=testchar(Q);
p1=priority[z1][n1];
if(p1=='<') {
count++;
printf("(%d) %s\t%10c\t%5c%17s\t 归约\n",count,AnalyseStack,p,a,remain);
k=j+1; i--;
AnalyseStack[k]='N'; int r,r1;
r=strlen(AnalyseStack);
for(r1=k+1;r1<r;r1++)
AnalyseStack[r1]='\0';
break;
}
else continue;
}
}
else{
if(p=='<'){
count++;
printf("(%d) %s\t%10c\t%5c%17s\t 移进\n",count,AnalyseStack,p,a,remain);
k=k+1;
AnalyseStack[k]=a;
remainString();
}
else{
if(p=='='){
z2=testchar(AnalyseStack[j]);
n2=testchar('#'); p2=priority[z2][n2];
if(p2=='='){
count++;
printf("(%d) %s\t%10c\t%5c%17s\t 接受\n",count,AnalyseStack,p,a,remain);
printf("该句子是该文法的合法句子。\n");
break;
}
else{
count++;
printf("(%d) %s\t%10c\t%5c%17s\t 移进\n",count,AnalyseStack,p,a,remain);
k=k+1;
AnalyseStack[k]=a; remainString();
}
}
else
printf("错误!该句子不是该文法的合法句子!\n"); break;
}
}
}
}
void remainString(){
int i,j; i=strlen(remain);
for(j=0;j<i;j++) remain[j]=remain[j+1];
remain[i-1]='\0';
}
int main(){
printf("请输入要进行分析的句子(以#号结束输入):\n");
gets(input); k=0;
printf("步骤 栈 优先关系 当前符号 剩余输入串 移进或归约\n");
AnalyseStack[k]='#'; AnalyseStack[k+1]='\0';
int length,i; length=strlen(input);
for(i=0;i<length;i++) remain[i]=input[i];
remain[i]='\0'; analyse();
return 0;
}
四、实验结果
4.1 运行截图
五、实验总结
本次实验基本完成了实验题目的要求,定义了一个文法,求出了每一个非终结符的VT集和LASTVT集,画出了算符优先关系表,并判定出给定的文法是否是算符优先文法。当给定一个 句子时,能够判定是否是文法中的句子,并能够将分析过程打印出来。
这个实验最大的收获,不仅仅使我更进一步的了解到了算符优先算法是一个省略了所有单非终结符产生式对应的归约步骤,其分析效率是很高的,同时,通过此次实验让我的处理问题的能力,思考问题的角度都得到了很大的提高,从词法分析到语法分析再到语义分析,基本走完了编译器的大致流程,这对我理解编译的过程和具体的实现都是有极大的帮助的。