编译原理试验指导Word格式.docx
- 文档编号:21380544
- 上传时间:2023-01-30
- 格式:DOCX
- 页数:11
- 大小:82.81KB
编译原理试验指导Word格式.docx
《编译原理试验指导Word格式.docx》由会员分享,可在线阅读,更多相关《编译原理试验指导Word格式.docx(11页珍藏版)》请在冰豆网上搜索。
b=a+20;
}
请对以上代码利用词法分析程序分析并得到相应的二元组。
3、实验分析
在本次实验中是对一个简化的c语言程序进行分析,它的单词符号有:
●标识符:
字母打头,后接字母数字,识别出的标识符用ID标记。
●保留字(它是标识符的子集):
if,else,for,while,do,int,write,read,识别出的保留字直接用该保
留字标记。
●无符号整数:
由数字组成,用NUM标记。
●分界符:
+、-、*、/、(、)、;
、,>
、<
、{、}、!
等单分界符,直接用单分界符标记。
>
=、<
=、!
=、==等双字符分界符,直接用双分界符标记。
●注释符:
用/*….*/括起
为了从源程序字符流中正确识别出各类单词符号,相邻的标识符、整数或保留字之间至少要用一个空格分开。
此语言的各类单词符号的正则文法规则如下:
<
identifier>
∷=<
letter>
|ID<
digit>
number>
|<
<
∷=a|b|…|z|A|B|…|Z
∷=1|2|…|9|0
singleword>
∷=+|-|*|/|=|(|)|{|}|:
|,|;
|<|>|!
doubleword>
∷=>=|<=|!
=|==
commend_first>
∷=/*
commend_last>
∷=*/
图1单词符号的状态图
根据状态图,分析相应动作就可以构造出词法分析程序的算法流程图,如下图所示,在程序开始时,首先读入一个字符,若为空字符,则继续读,直到读进一个非空字符,读进的字符有如下6种情况,要进行不同的处理。
(1)字母。
继续读,直到遇见空格、分界符、文件尾或非字母数字字符。
组合标记符,查保留字表。
若为保留字,输出相应单词记号;
若不是,输出标记符的单词记号及单词值(标识符)。
(2)数字。
继续读,直到遇见空格、或非数字字符出现或文件尾。
输出无符号整数的单词记号及数字串。
(3)=、<
、>
、!
。
读入下一个字符,判断是否为双字符分界符,若是,组成双字符分界符,输出相应单词记号及双分界符;
若不是,输出单分界符记号。
(4)非=、<
、/等与双分界符首字符不同的单分界字符。
输出相应单词记号及单分界符。
(5)/。
读入下一个字符。
若不是“*”,输出/的单词记号;
若是“*”,进行注释处理。
词法分析不输出“/*”,并要跳过整个注释内容直到遇到“*/”为止,然后返回开始状态,继续识别下一个单词符号。
(6)非法字符。
如果读进的字符不属于上面任意情况,则说明词法分析程序从源程序读入了一个不合法的字符,即该字符不属于程序语言所定义的所有单词符号首字符集合。
词法分析程序在遇到不合法字符时要进行错误处理,报告错误信息,跳过这个字符,然后转入开始状态,继续识别下一个单词符号。
图2词法分析程序流程图
4、实验步骤
(1)启动VisualC++系统,新建一个工程;
(2)新建一个源程序文件;
(3)编译,调试该程序;
(4)运行该程序,输入测试数据,观察输出数据;
(5)分析实验结果。
实验二LL1语法分析
(1)一切LL
(1)文法;
含有直接左递归但可以转化为LL
(1)文法的文法;
含有间接左递归但可以转化为LL
(1)文法的文法
(2)计算出文法的First()Follow()
(3)构造相应文法的预测分析表
(4)对某个输入句子进行分析
LL
(1)文法是一类可以进行确定的自顶向下语法分析的文法。
就是要求描述语言的文法是无左递归的和无回溯的。
根据LL
(1)文法的定义,对于同一非终结符A的任意两个产生式A:
=a和A:
=b,都要满足:
SELECT(A:
=a)∩SELECT(A:
=b)=Ø
(1)文法的左递归
当一个文法是左递归文法时,采用自顶向下分析法会使分析过程进入无穷循环之中。
所以采用自顶向下语法分析需要消除文法的左递归性。
文法的左递归是指若文法中对任一非终结符A有推导AA…,则称该文法是左递归的。
左递归又可以分为直接左递归和间接左递归。
●直接左递归
若文法中的某一产生式形如A→Aα,α∈V*,则称该文法是直接左递归的。
消除直接左递归的方法:
设有产生式是关于非终结符A的直接左递归:
A→Aα|β(α,β∈V*,且β不以A开头)
对A引入一个新的非终结符A′,把上式改写为:
A→βA′
A′→αA′|ε
●间接左递归
若文法中存在某一非终结符A,使得AA…至少需要两步推导,则称该文法是间接左递归的。
消除间接左递归的方法:
【方法一】采用代入法把间接左递归变成直接左递归。
【方法二】直接改写文法:
设有文法G10[S]:
S→Aα|β⑴
A→Sγ⑵
因为SAαSγα,所以S是一个间接递归的非终结符。
为了消除这种间接左递归,将⑵式代入⑴式,即可得到与原文法等价的文法(可以证明):
S→Sγα|β⑶
⑶式是直接左递归的,可以采用前面介绍的消除直接左递归的方法,对文法进行改写后可得文法:
S→βS′
S′→γαS′|ε
1计算first集合
(1)若X∈VT,则First(X)={X}
(2)若X∈VN,且有产生式X→a…,a∈VT则First(X)={X}
(3)若X∈VN,且有产生式X→ε,则First(X)={X}
(4)若X,Y1,Y2,…,Yn都∈VN,而由产生式X→Y1Y2…Yn。
当Y1,Y2,…,Yi-1都能推导出ε时,(其中1≤i≤n),则First(Y1)-{ε},First(Y2)-{ε},…,First(Yi)都包含在First(X)中
(5)当(4)中所有Yi都能推导出ε,(i=1,2,…,n),则First(X)=First(Y1)∪First(Y2)∪…First(Yn)∪{ε}
反复使用上述步骤直到每个符合的First集合不再增大为止。
2计算Follow集
对文法中的每个A∈VN,计算Follw(A):
(1)设S为文法的开始符合,把{#}加入Follow(S)中;
(2)若A→αBβ是一个产生式,则把First(β)的非空元素加入Follow(B)中,如果β能推导出ε,则把Follow(A)也加入(B)中;
(3)反复使用以上步骤直到每个非终结符号的Follow集不再增大为止。
3预测分析方法
预测分析方法是自顶向下分析的另一种方法,一个预测分析器是由三个部分组成:
预测分析程序;
先进后出栈;
预测分析表。
预测分析程序的框图如下:
实验三语义及代码生成
理解并掌握语义分析的基本概念,基本方法;
掌握代码优化与目标生成的基本原理与技术实现;
编写类C语言编译程序的目标代码生成的程序,调试成功后,以给出的程序段为测试数据,并按一定格式显示结果。
2、实验内容和分析
与实验二的语法规则相比,只有部分规则需要添加动作符号,下面我们列出添加了动作符号的规则。
(1)<
declaration_stat>
↓vartablep,datap->
intID↑n@name-def↓n,t;
动作解释:
vartablep指出符号表的最后一个记录的下一个位置,即第一个空白记录位置。
每当有一个记录加入符号表,该值加1;
datap表示已经分配的地址空间,它开始时为0,每声明一个变量,该值则根据变量类型累加,如整型加2,实型加4等等。
@name-def↓n,t的动作:
查询符号表,从vartablep所指的前一个位置起往回查直到第一个记录,若没有,将标识符名n及类型1、datap的值填入符号表vartablep所指的位置,然后vartablep加1,datap根据类型t增加;
若有,报告错误:
变量重复定义。
(2)<
expression>
:
=ID↑n@LOOK↓n↑d@ASSIGN=<
bool_expr>
@STO↓d|<
(3)<
=<
additive_expr>
|<
additive_expr>
@GT
@LES
additive_expr>
@GE
@LE
==<
@EQ
!
@NOTEQ
(4)<
additive_expr>
term>
{(+<
term>
@ADD|-<
项>
@SUB)}
(5)<
factor>
{(*<
factor>
@MULT|/<
@DIV)}
(6)<
=(<
expression>
)|ID↑n@LOOK↓n↑d@LOAD↓d|NUM↑i@LOADI↓i
(2)、(3)、(4)、(5)、(6)规则中的动作符号解释如下:
@LOOK↓n↑d:
查符号表n,给出变量地址d;
没有,变量没定义
@ASSIGN:
超前读一个符号,如果是'
='
,则表示进入赋值表达式,如果不是'
,则选择<
比较表达式>
,然后还要将超前读的这个符号退回。
@STO↓d:
输出指令代码STOd,且codep++(因产生了指令,所以指令记数加1)
@LOADI↓i:
输出指令代码LOADIi,且codep++
@LOAD↓d:
输出指令代码LOADd,且codep++
@GT、@ADD等:
输出后的指令代码GT、ADD等
(7)<
if_stat>
=if(<
)@BRF↑label1<
statement>
@BR↑label2
@SETlabel↓label1[else<
statement>
]@SETlabel↓label2
其中动作符号的含义如下
@BRF↑label1:
输出BRFlabel1,codep++
@BR↑label2:
输出BRlabel2,codep++
@SETlabel↓label1:
设置标号label1
@SETlabel↓label2:
设置标号label2
(8)<
while_stat>
=while@SETlabel↑label1(<
)@BRF↑label2
@BR↓label1@SETlabel↓label2
动作解释如下:
@SETlabel↑label1:
设置标号label1
@BRF↑label2:
输出BRFlabel2,codep++
@BR↓label1:
输出BRlabel1,codep++
@SETlabel↓label2:
(9)<
for_stat>
=for(<
@SETlabel↑label1<
@BRF↑label2@BR↑label3;
@SETlabel↑label4<
@BR↓label1)
@SETlabel↓label3<
@BR↓label4@SETlabel↓label2
@BRF↑label2:
@BR↑label3:
输出BRlabel3,codep++
@SETlabel↓label4:
设置标号label4
@BR↑label1:
@SETlabel↓label3:
设置标号label3
@BR↑label4:
输出BRlabel4,codep++
设置标号label2
(10)<
write_stat>
=write<
@OUT;
@OUT:
输出OUT
(11)<
read_stat>
=readID↑nLOOK↓n↑d@IN↓d;
@LOOK↓n↑d:
@IN:
输出IN
@STI↓d:
输出指令代码STId
抽象机常用汇编指令如下:
LOADD将D中的内容加载到操作数栈
LOADI常量将常量压入操作数栈
LOAD(D)将变量地址D压入操作数栈
STOD将操作数栈栈顶单元内容存入D
ADD将次栈顶单元与栈顶单元内容相加,和置于栈顶
SUB将栈顶单元减去次栈顶单元内容,差置于栈顶
MULT将次栈顶单元与栈顶单元内容相乘,积置于栈顶
DIV将栈顶单元除次栈顶单元内容,商置于栈顶(分母为栈)
BRlab无条件转移到lab
BRFlab检查栈顶单元逻辑值,若为假(0)则转移到lab
EQ将栈顶两单元做等于比较,并将结果真或假(1或0)置于栈顶
NOTEQ将栈顶两单元做不等于比较,并将结果真或假(1或0)置于栈顶
GT次栈顶大于栈顶操作数,则栈顶置1,否则置0
LES次栈顶小于栈顶操作数,则栈顶置1,否则置0
GE次栈顶大于等于栈顶操作数,则栈顶置1,否则置0
LE次栈顶小于等于栈顶操作数,则栈顶置1,否则置0
AND将栈顶两单元做逻辑与运算,并将结果真或假(1或0)置于栈顶
OR将栈顶两单元做逻辑或运算,并将结果真或假(1或0)置于栈顶
NOT将栈顶的逻辑值取反
构造语义和代码生成程序,然后对测试程序进行分析
测试程序
inta;
intb;
reada;
writea;
if(a==10)b=1;
elseb=2;
writeb;
while(a<
=6)b=3;
b=0;
for(a=0;
a<
5;
a=a+1)b=4;
在本实验中仍采用递归下降分析法,根据实验二中的语法分析,用上面给出的各语句程序替换语法分析对应的同名函数程序,即可将语法分析改为语义分析和代码生成程序。
为了简化起见,在类C编译程序中没有进行复杂的错误处理。
在语法和语义分析中,一旦遇到语法或语义错误,则停止编译,立即返回,并报告发生的错误。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 试验 指导