语法制导四元式算术表达式生成器.docx
《语法制导四元式算术表达式生成器.docx》由会员分享,可在线阅读,更多相关《语法制导四元式算术表达式生成器.docx(16页珍藏版)》请在冰点文库上搜索。
语法制导四元式算术表达式生成器
辽宁师范大学计算机与信息技术学院
综合性实验报告
课程名称:
编译技术
实验题目:
语法制导四元式(算术表达式)生成器
学生姓名:
专业:
计算机科学与技术
学号:
实验日期:
2015.06.05
【实验目的】
1.理解语法分析器原理、语法制导翻译的过程实质。
2.学会将语法分析所识别的语法成分变换为中间代码形式中的逆波兰记号形式的语义分析方法,编程实现在对一个算术表达式进行语法分析过程的基础上进行语义分析。
【实验内容】
1.输入算术表达式源语言形式,输出语法分析过程(输入流变化过程)和四元式序列。
2.对于一个给定的算术表达式,首先通过词法分析过程识别出各类语法成分输出至文件中,然后采用预测分析的方法对其进行分析和语法检查,并给出具体的分析过程,包括分析步骤、分析栈、剩余符号以及所用的产生式。
在此基础上,向文法中插入语义动作,在语法分析过程中遇到语义动作就做相应的翻译工作,最终将结果(算术表达式的逆波兰式)输出到源文件中。
【实验过程】
一、判断文法是否为LL
(1)文法
(1)E->E+E
(2)E->E*E
(3)E->i|-E
由于此文法含左递归,消除左递归,确定算法优先次序,使文法变为:
(1)E->TG
(2)G->+TG|^
(3)T->FS
(4)S->*FS|^
(5)F->i|-E
1.可推出^的非终结符表为:
E
G
T
S
F
否
是
否
是
否
2.各非终结符的FIRST集合如下:
FIRST(E)={(,i}
ﻩFIRST(G)={+,∅}
FIRST(T)={(,i}
FIRST(S)={*, ∅}
ﻩFIRST(F)={(,i}
ﻩ
3.各非终结符的FOLLOW集合为:
ﻩFOLLOW(E)={),#}
FOLLOW(G)={),#}
ﻩFOLLOW(T)={+,),#}
ﻩFOLLOW(S)={+,),#}
FOLLOW(F)={*,+,),#}
4.各产生式的SELECT集合为:
ﻩSELECT(E->TG)={(,i}
SELECT(G->+TG)={+}
ﻩSELECT(G->^)={),#}
ﻩSELECT(T->FS)={(,i}
ﻩSELECT(S->*FS)={*}
SELECT(S->^)={+,),#}
SELECT(F->-E)={(}
SELECT(F->i)={i}
5.因为:
SELECT(G->+TG)∩SELECT(G->∅)={+}∩{),#}=∅
SELECT(S->*FS)∩SELECT(S->∅) ={*}∩{+,),#} =∅
SELECT(F->-E)∩SELECT(F->i)={i}∩{(}=∅
所以文法是LL
(1)文法。
二、构造预测分析表
i
+
*
(
)
-
#
E
TG
TG
-E
G
+TG
^
^
T
FS
FS
S
∅
*FS
^
^
F
i
(E)
三、程序开始
1.预测试的算术表达式:
4+(-4.67e-10)*(-7.89)+5#
ﻩ 分析后:
i+(-i)*(-i)+i#写入文件中。
边分析边编织逆波兰式,用数组stack1存放。
1.存入9个文法产生式:
E->TG
E2->-E
G->+TG
G2->^
T->FS
S->*FS
S2->^
F->i
F2->(E)
2.存入预测分析表格(如二)
3.利用 终结符数组:
vt;非终结符数组:
vn;预测分析表table;分析栈stack;等等,对待分析串str2进行分析,并将分许过程存入op.txt中。
具体代码如下:
#include
#include<malloc.h>
#include<string.h>
#include
charstr2[20]={0};ﻩﻩ//存放识别后的字符串“i+(-i)*(-i)+i#”
FILE*op;ﻩﻩ//存储算术表达式的文件“a+(-4.67e-10)*(-7.89)+b#”
FILE*fp;ﻩﻩﻩ//存储分析过程的文件
charvt[7]={'i','+','*','(',')','-','#'}; //终结符
char vn[5]={'E','G','T','S','F'};ﻩ//非终结符
typedefstructtype{//产生式类型定义
ﻩcharleft; //非终结符
ﻩcharright[5];ﻩ//产生式右边字符
}type;
typeE,E1,G,G1,T,S,S1,F,F1;ﻩ//8个产生式
typetable[7][7];ﻩﻩﻩﻩ//预分析表
char stack[30]={0};ﻩﻩ//分析栈
charstack1[30]={0};ﻩ//存储逆波兰式的
int s=-1,st=0;ﻩﻩﻩ//s->栈顶,st->当前需分析字符
voidanaly1(charstr1[]){ﻩﻩ//分析=>i+(-i)*(-i)+i#
ﻩint i=0,j=0,p=0,q=0;
chars[30]={0};ﻩﻩ//辅助堆栈
while(str1[i]!
='#'){
switch(str1[i]){
case'a':
str2[j++]='i';stack1[q++]='a'; break;
ﻩﻩcase'b':
str2[j++]='i';
ﻩﻩ stack1[q++]=s[p-2];
ﻩstack1[q++]=s[--p];s[p--]='\0';s[p]='\0';
ﻩ stack1[q++]='b';
ﻩbreak;
ﻩcase '+':
s[p++]='+';ﻩstr2[j++]='+';break;
ﻩﻩcase'*':
stack1[q++]=s[--p];
ﻩs[p]='\0';
ﻩﻩstr2[j++]='*';
ﻩﻩﻩs[p++]='*';
ﻩﻩﻩbreak;
ﻩﻩcase'(':
str2[j++]='(';break;
ﻩcase ')':
stack1[q++]=s[--p];s[p]='\0';
ﻩﻩ stack1[q++]='b';
ﻩﻩstr2[j++]=')';break;
ﻩcase '-':
s[p++]='@';
ﻩﻩﻩﻩif(str2[j-1]=='i')break;
ﻩﻩﻩelseﻩstr2[j++]='-';
ﻩbreak;
case '.':
stack1[q++]='.';
ﻩif(str2[j-1]=='i')break;
ﻩelse str2[j++]='i';
ﻩﻩbreak;
ﻩﻩcase'0':
stack1[q++]='0';
ﻩﻩif(str2[j-1]=='i')break;
ﻩﻩelse str2[j++]='i';ﻩﻩﻩ
ﻩﻩbreak;
ﻩcase'1':
stack1[q++]='1';
ﻩﻩﻩif(str2[j-1]=='i')break;
ﻩﻩﻩﻩelsestr2[j++]='i';ﻩﻩﻩﻩ
ﻩﻩﻩﻩ break;
ﻩﻩcase'2':
stack1[q++]='2';
ﻩﻩﻩif(str2[j-1]=='i')break;
ﻩﻩﻩﻩﻩ else str2[j++]='i';
ﻩﻩ
ﻩﻩbreak;
ﻩcase'3':
ﻩstack1[q++]='3';
ﻩﻩif(str2[j-1]=='i')break;
ﻩﻩelsestr2[j++]='i';ﻩ
ﻩﻩ break;
ﻩcase'4':
stack1[q++]='4';
ﻩﻩﻩif(str2[j-1]=='i')break;
ﻩelsestr2[j++]='i';
ﻩﻩﻩbreak;
ﻩﻩcase'5':
ﻩstack1[q++]='5';
ﻩﻩﻩﻩif(str2[j-1]=='i')break;
ﻩﻩelsestr2[j++]='i';ﻩﻩﻩ
ﻩﻩﻩbreak;
ﻩcase'6':
stack1[q++]='6';
ﻩﻩﻩif(str2[j-1]=='i')break;
ﻩﻩﻩelsestr2[j++]='i';ﻩﻩﻩ
ﻩﻩﻩbreak;ﻩ
case'7':
stack1[q++]='7';
ﻩif(str2[j-1]=='i')break;
ﻩﻩﻩ elsestr2[j++]='i';ﻩﻩﻩ
ﻩﻩﻩﻩﻩbreak;
ﻩﻩcase'8':
stack1[q++]='8';
ﻩﻩﻩﻩif(str2[j-1]=='i')break;
ﻩﻩ elsestr2[j++]='i';ﻩ
ﻩﻩﻩ break;
ﻩcase'9':
ﻩ stack1[q++]='9';
ﻩﻩif(str2[j-1]=='i')break;
ﻩﻩﻩ elsestr2[j++]='i';ﻩﻩ
ﻩﻩbreak;
case'e':
stack1[q++]=s[--p];s[p]='\0';
ﻩﻩif(str2[j-1]=='i'){
ﻩﻩ s[p++]='e';ﻩ
ﻩﻩﻩbreak;
ﻩﻩ}
ﻩﻩelsestr2[j++]='i';
ﻩﻩﻩbreak;
ﻩ}
ﻩi++;
ﻩ}
ﻩstack1[q++]=s[--p];s[p]='\0';
ﻩstr2[j]='#';
}
voidstore(){ﻩ//将8个产生式存入
printf("产生式:
\n");
E.left='E';
ﻩstrcpy(E.right,"TG");
ﻩprintf("%c->%s\n",E.left,E.right);
E1.left='E';
strcpy(E1.right,"-E");
ﻩprintf("%c->%s\n",E1.left,E1.right);
ﻩG.left='G';
ﻩstrcpy(G.right,"+TG");
ﻩprintf("%c->%s\n",G.left,G.right);
ﻩG1.left='G';
ﻩstrcpy(G1.right,"^");
ﻩprintf("%c->%s\n",G1.left,G1.right);
T.left='T';
strcpy(T.right,"FS");
printf("%c->%s\n",T.left,T.right);
ﻩS.left='S';
strcpy(S.right,"*FS");
ﻩprintf("%c->%s\n",S.left,S.right);
S1.left='S';
ﻩstrcpy(S1.right,"^");
ﻩprintf("%c->%s\n",S1.left,S1.right);
F.left='F';
ﻩstrcpy(F.right,"i");
printf("%c->%s\n",F.left,F.right);
ﻩF1.left='F';
strcpy(F1.right,"(E)");
printf("%c->%s\n\n",F1.left,F1.right);
}
intlength(char a[]){ﻩ//求数组长度
inti,l=0;
ﻩfor(i=0;i<5;i++)
ﻩﻩif(a[i]!
='\0') l++;
ﻩreturnl;
}
voidtables(){ﻩﻩ//建立分析表
int i,j;
for(i=0;i<=4;i++)ﻩﻩ//初始化分析表
ﻩﻩfor(j=0;j<=6;j++)
table[i][j].left='N';ﻩ//表内所有left置‘N’
table[0][5]=E1;table[0][0]=table[0][3]=E;ﻩ//存入文法
ﻩtable[1][1]=G;table[1][4]=table[1][6]=G1;
ﻩtable[2][0]=T;table[2][3]=T;
ﻩtable[3][2]=S;table[3][1]=table[3][4]=table[3][6]=S1;
ﻩtable[4][0]=F;table[4][3]=F1;
printf("表达式文法的预测分析表:
\n");
printf(" \t");
for(i=0;i<7;i++) printf("%c\t",vt[i]);
printf("\n");
for(i=0;i<5;i++){
ﻩﻩprintf("%c\t",vn[i]);
for(j=0;j<7;j++)
ﻩﻩprintf("%s\t",table[i][j].right);
ﻩﻩﻩprintf("\n");
ﻩﻩ}
printf("\n");
}
void write(charstr[]){ﻩ//将字符串写入文件fp
ﻩfputs(str,fp);
}
voidfun(inth,intl){ﻩﻩ//将推导所用产生式倒序存入分析栈中
inti=length(table[h][l].right)-1;ﻩ
ﻩs--;
ﻩfor(i; i>-1;i--)
stack[++s]=table[h][l].right[i];//产生式逆序入栈
if(stack[s]=='^')
ﻩﻩstack[s--]='\0';
ﻩfputc(table[h][l].left,fp);
write("->");
write(table[h][l].right);
write("\n");
}
voidprint(intn){//写入文件
ﻩfprintf(fp,"%d\t\t",n++);ﻩ//步骤
fprintf(fp,"%s\t\t",stack);ﻩ//分析栈
fprintf(fp,"%s\t\t",str2);ﻩﻩ//剩余输入串
}
voidanaly2(){
ﻩinti,j,n=0,finish=0,h,l;
ﻩchar X,a;
ﻩstore();//产生式
ﻩtables();//预测分析表格
write("********************分析如下********************\n");
write("步骤\t\t分析栈\t\t剩余字符\t\t所用产生式\n");
stack[++s]='#';ﻩ//#入栈
stack[++s]='E';ﻩ//E入栈
ﻩa=str2[st];ﻩ//当前剩余串最左字符
while(s>-1){
ﻩX=stack[s];ﻩ//栈顶字符
ﻩprint(++n);
for(i=0;i<5;i++){
ﻩif(X==vn[i]){ﻩ//栈顶为非终结符时E G TS F
ﻩh=i;ﻩﻩﻩ//行号
ﻩﻩﻩfor(j=0;j<7;j++){
ﻩﻩﻩif(a==vt[j]){
ﻩﻩﻩl=j;ﻩﻩ//列号
ﻩﻩbreak;
ﻩﻩﻩ}
ﻩ}ﻩﻩﻩﻩﻩﻩﻩ
ﻩif(table[h][j].left!
='N'){//不空时
ﻩfun(h,l);
ﻩ}
ﻩﻩ}
ﻩﻩ}
ﻩfor(i=0;i<7;i++){ﻩ//栈顶为终结符时i +* ()-#
ﻩif(X==vt[i]){
ﻩstack[s--]='\0';
ﻩstr2[st++]='';
ﻩa=str2[st];ﻩ//当前剩余串最左字符
ﻩfputc(X,fp);
ﻩﻩﻩif(X=='#')ﻩwrite("接受\n");
elsewrite("匹配\n");
ﻩ}
ﻩ}
ﻩ}
}
voidmain(){
ﻩcharstr1[300]={0};ﻩﻩ//预分析算术表达式a+(-4.67e-10)*(-7.89)+b#
charh[]="\n";
fp=fopen("H:
fp.txt","r");
ﻩfgets(str1,300,fp);//fgets读取一行fgetc读取一个字符fread想要的长度
fclose(fp);
ﻩanaly1(str1);
ﻩfp=fopen("H:
fp.txt","a");//不会覆盖原数据
ﻩfwrite(h,sizeof(h),1,fp);//换行
ﻩfwrite(stack1,sizeof(stack1),1,fp);//写入逆波兰式
ﻩfclose(fp);
ﻩprintf("分析得到的符号串:
%s\n\n",str2);
op=fopen("H:
op.txt","w");
fputs(str2,fp);ﻩ//写入i+(-i)*(-i)+i#
ﻩwrite("\n");
ﻩanaly2();
fclose(op);
}
四、运行结果截屏:
源文件:
屏幕输出:
分析过程:
运行后的源文件:
【实验结果分析】