编译原理课设 词法分析自下而上语法分析程序生成中间代码Word文档格式.docx
《编译原理课设 词法分析自下而上语法分析程序生成中间代码Word文档格式.docx》由会员分享,可在线阅读,更多相关《编译原理课设 词法分析自下而上语法分析程序生成中间代码Word文档格式.docx(66页珍藏版)》请在冰豆网上搜索。
涉及词法分析、自下而上语法分析程序的实现:
SLR
(1)分析器的实现以及生成中间代码。
1.4.3、具体要求
根据LR分析算法构造SLR
(1)分析程序,并完成语法分析动作(当需要一个单词时,调用词法分析程序获取),同时完成语义分析生成四元式输出。
要求程序具有通用性,改变文法时只需改变程序的数据初值,无需改变程序主体;
要求完成一条说明语句、一条算数表达式和赋值语句的翻译,生成中间代码。
变量说明语句的文法及相应的语义子程序:
.att表示数据类型属性,fill函数表示将单词id及其类别属性填写符号表。
(0)S→D;
{acc}
(1)D→intid{fill(id,int);
D.att=int;
}
(2)D→floatid{fill(id,float);
D.att=float;
(3)D→D
(1),id{fill(id,D
(1).att);
D.att=D
(1).att;
算数表达式和赋值语句的文法及相应的语义子程序。
(1)A→id=E;
{p=lookup(id.name);
emit(E.PALCE,,p);
}
(2)E→E
(1)+T{E.PALCE=newtemp();
emit(+,E
(1).PALCE,T.PALCE,E.PALCE)}
(3)E→T{E.PALCE=T.PALCE;
}
(4)T→T
(1)*F{T.PALCE=newtemp();
emit(+,T
(1).PALCE,F.PALCE,T.PALCE)}
(5)T→F{T.PALCE=F.PALCE;
(6)F→(E){F.PALCE=E.PALCE;
(7)F→id{P=LOOKUP(id.name);
F.PALCE=P;
(8)F→num{P=LOOKUP(num.value)
F.PALCE=P;
构造其用于SLR
(1)分析的识别活前缀的DFA以及action表和goto表。
然后编程实现。
(关于词法分析部分只需识别出与此文法相关的单词即可(+,*,(,),id,=))。
1.4.4、程序设计提示
(1)分析栈设计时可以用一个栈完成,也可以设计三个栈:
一个符号栈,一个状态栈,一个语义栈,则归约时,则需要在符号栈中退掉n个符号,在状态栈中退掉n个符号(n为产生式符号个数),语义栈中退掉n个符号对应的语义;
(2)终结符表和非终结符表的组织和预测分析程序中相同(将符号对应到一个数字,表示在分析表中对应的下标)。
(3)action表中的错误处理:
简化的错误处理:
当查找action表出现空白时,则当前单词无法移进和规约,可简单的认为当前单词为多余的单词,则抛弃当前单词,读下一单词继续分析。
1.4.5、测试数据
源文件中数据:
intarea,r;
r=1;
area=r*r+r;
程序要求输出二元式序列、符号表、语法分析过程、四元式序列。
1.4.6、程序扩展要求
第2章程序总体设计
第3章程序详细设计与实现
3.1、词法分析
首先定义结构体
typedefstruct//状态栈
{
intdata[max];
inttop;
}seqstack1;
typedefstruct//符号栈
stringdata[max];
inttop;
}seqstack2;
structreserveedword//保留字表结构
stringword;
charvalue;
}reserveedword1[maxsize];
structidentifer//标识符表结构
charidentiname[15];
charidentitype[15];
intaddress;
}identifer1[maxsize];
structconstant//常量表结构
stringconstantname;
stringvalue;
intconstantaddress;
}constant1[maxsize];
词法分析主要函数结构:
voidInitscanner()//该函数用于用C语言当中常见的关键字初始化保留表
voidIsalpha(chars)//用于判断读入的字符是不是字母
voidIsnumber(chars)//用于判断读入的字符是不是数字
voidIsother(chars)//判断除数字与字母之外的其他字符
voidLexscan()//用于循环从程序中读入字符并判断应调用那个判断函数字符
voidOutput(inti,intj,charss[15])//输出二元式
本模块程序的伪代码如下:
打开文件
infile.open("
input.txt"
ios:
:
in);
if(!
infile)
{
cerr<
<
"
读取的文件打开失败!
endl;
exit
(1);
}
初始化保留字表
Initscanner();
循环读入从文件当中
Scanner()
while(ch!
='
#'
)
在该函数中判断应该调用的判断函数
Lexscan()
{
infile.get(ch);
if(((ch>
A'
)&
&
(ch<
Z'
))||((ch>
a'
z'
)))
Isalpha(ch){Output};
elseif((ch>
0'
9'
))
Isnumber(ch){Output};
else
Isother(ch){Output};
关闭文件
infile.close();
词法分析器中从源文件读出一个单词,判断其类型是关键字、标识符还是普通符号,根据其类型为结构体各项赋值,并将其传给语法分析函数。
3.2、语法分析
由于说明语句与算术表达式和赋值语句所使用的是不同的文法,所以两者的ACTION表和GOTO表也不一样,本次课设采用二维数组存放ACTION表和GOTO表信息,其中移进用大于0的数表示,归约用小于0的数表示,成功用100表示(acc),其他处用0表示,查表时遇到相应的数进行相应的操作。
其中,归约部分需要根据其产生式的信息进行,所以程序中有如下定义:
stringv1[8]={"
int"
"
float"
;
id"
#"
D"
S"
};
//存放说明文法当中的字符
stringv2[13]={"
="
num"
+"
*"
("
)"
F"
A"
E"
T"
//存放算本文法当中的字符
根据状态转换图(DFA)构造SLR
(1)分析表:
其中说明文法和算术文法分别构造,同时在每个表当中既有action表又有goto表
intanalysis_table1[10][8]={3,4,0,0,0,0,2,1,
0,0,0,0,0,100,0,0,
0,0,5,6,0,0,0,0,
0,0,0,0,7,0,0,0,
0,0,0,0,8,0,0,0,
0,0,0,0,0,-1,0,0,
0,0,0,0,9,0,0,0,
0,0,-2,-2,0,0,0,0,
0,0,-3,-3,0,0,0,0,
0,0,-4,-4,0,0,0,0};
intanalysis_table2[17][13]={0,2,0,0,0,0,0,0,0,0,1,0,0,
100,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,3,0,0,0,0,0,0,0,0,0,0,
0,9,0,8,0,0,0,7,0,6,0,4,5,
0,0,0,0,10,11,0,0,0,0,0,0,0,
0,0,0,0,-3,-3,12,0,-3,0,0,0,0,
0,0,0,0,-5,-5,-5,0,-5,0,0,0,0,
0,9,0,8,0,0,0,7,0,6,0,13,5,
0,0,0,0,-8,-8,-8,0,-8,0,0,0,0,
0,0,0,0,-7,-7,-7,0,-7,0,0,0,0,
-1,0,0,0,0,0,0,0,0,0,0,0,0,
0,9,0,8,0,0,0,7,0,6,0,0,14,
0,9,0,8,0,0,0,7,0,15,0,0,0,
0,0,0,0,0,11,0,0,16,0,0,0,0,
0,0,0,0,-2,-2,12,0,-2,0,0,0,0,
0,0,0,0,-4,-4,-4,0,-4,0,0,0,0,
0,0,0,0,-6,-6,-6,0,-6,0,0,0,0};
语法分析当中各个函数说明及伪代码:
voidaction1(inti,strings)//通过词法分析传过来的值判断移进动作三个栈(状态栈,符号栈,语义栈)应该读入哪些值。
voidaction2(inti,strings)//同action1只是表示算术文法
intaddress(stringm[],inti,stringx)//获得在分析表中的列下标
voidgoto1(inti,strings)//通过判断栈中的元素,来判断用那个产生式来进行规约
voidgoto2(inti,strings)//同goto1
voidslr1()//对说明文法进行语法分析
voidslr1()//对算术文法进行语法分析
伪代码如下:
先判断是说明文法还是算术文法
If(说明文法)
Slr1()
push_seq1(s1,0);
push_seq2(s2,"
);
push_seq2(s3,"
_"
while
(1)
{
j=address(v1,8,get1);
top_seq1(s1,top);
j=analysis_table1[top][j];
if(j<
0)
if(j==-1)
用S->
D;
归约
elseif(j==-2)
用D->
intid归约
elseif(j==-3)
floatid归约"
elseif(j==-4)
D,id归约"
elseif(j>
action1(top,get1);
else
Slr2()
push_seq1(s1,0);
push_seq2(s3,"
while
(1)
j=address(v2,13,get1);
j=analysis_table2[top][j];
if(j>
action2(top,get1);
elseif(j<
if(j==-1)
用A->
id=E;
归约"
用E->
E+T归约"
T归约"
elseif(j==-4)
用T->
T*F归约"
elseif(j==-5)
F归约"
elseif(j==-6)
用F->
(E)归约"
elseif(j==-7)
id归约"
elseif(j==-8)
num归约"
}
3.3、语义分析
一个程序经过词法分析,语法分析之后,表明该院程序在书写上是正确的,但是未对程序的内部逻辑语义进行分析,接下来是进行语义分析。
语义分析当中各个函数说明:
voidprint(strings[])//打印四元式
str1,stringstr2,stringstr3,stringstr4)//产生四元式
stringnewtemp()//产生一个新的临时变量
3.4、程序实现结果图
图3-4语义分析结果图
图3-5二元式
图3-6符号表
图3-7四元式
附录
#include<
iostream>
fstream>
usingnamespacestd;
#definemaxsize50
#definemax30
ifstreaminfile;
charch;
intm,n,kk=0,addr=0,t=1;
stringget1;
stringin[maxsize];
stringins[maxsize];
strings[4];
intcount=0;
stringE="
E1="
T="
T1="
F="
stringword;
charidentiname[15];
charidentitype[15];
intaddress;
stringvalue;
intconstantaddress;
voidInitscanner();
voidLexscan();
voidIsalpha(char);
voidIsnumber(char);
voidIsother(char);
voidOutput(int,int,char*);
voidScanner();
voidchange(charc[],stringstr)
intlen=str.length();
for(intnum=0;
num<
len;
num++)
c[num]=str[num];
c[len]='
\0'
seqstack1*init_seqstack1()
seqstack1*s;
s=newseqstack1;
if(!
s)
cout<
空间不足!
returnNULL;
else
s->
top=-1;
returns;
intempty_seq1(seqstack1*s)
if(s->
top==-1)
return1;
return0;
intpush_seq1(seqstack1*s,intx)
top==max-1)
else
s->
top++;
data[s->
top]=x;
intpop_seq1(seqstack1*s,int*x)
if(empty_seq1(s))
*x=s->
top];
top--;
voidtop_seq1(seqstack1*s,int&
e)
占空!
e=s->
seqstack2*init_seqstack2()
seqstack2*s;
s=newseqstack2;
intempty_seq2(seqstack2*s)
intpush_seq2(seqstack2*s,stringx)
intpop_seq2(seqstack2*s,string*x)
if(empty_seq2(s))
voidout_seq1(seqstack1*s)
for(inti=0;
i<
=s->
top;
i++)
printf("
%d"
s->
data[i]);
voidout_seq2(seqstack2*s)
charch[15];
change(ch,s->
%s"
ch);
seqstack1*s1=init_seqstack1();
seqstack2*s2=init_seqstack2();
seqstack2*s3=init_seqstack2();
voidpop(intn)
intm;
strings;
n;
pop_seq1(s1,&
m);
pop_seq2(s2,&
s);
pop_seq2(s3,&
intscreamp(chara[15],stringb)
inti=0,j=0;
while(a[i]!
b[i]!
if(a[i]==b[i])
i++;
j++;
return0;
if(a[i]==b[i])
intscreamp1(stringa,stringb)