编译原理实验全集Word格式.docx
《编译原理实验全集Word格式.docx》由会员分享,可在线阅读,更多相关《编译原理实验全集Word格式.docx(22页珍藏版)》请在冰豆网上搜索。
实验1、2要求独立完成。
实验3、实验4的实现代码(VC++工程)均已调试成功,打包在目录中(lab3,lab4)。
希望认真学习的同学多看看。
由于时间关系,许多地方还没来得及做好,本手册的内容可能比较繁琐。
欢迎大家提出问题和意见。
时间比较紧的同学也请关注每个实验末尾的实验报告要求。
期末实验占10分。
实验1词法分析
1.1.目的
构造词法分析器,熟悉编译程序词法分析过程。
掌握LEX自动生成工具的使用。
1.2.内容
从本实验开始,用C语言实现一个编译系统。
词法分析是其第一步。
采用Lex工具自动生成大大简化了其中的内容。
因此本实验的重心并不在如何操作,而是在于怎样编写Lex源程序。
而要编写Lex源程序,首先要定义源语言,即该编译系统所实现的语言。
这里作为例子,我们以C++为基础,采用其部分单词,因此不妨将我们定义的这种语言称之为MiniC++。
1.3.知识
Lex是一个词法分析器的自动构造工具。
相关资料较多。
1.4.步骤
1、在编写LEX源程序前,首先要定义一种高级语言。
找出其中所有单词。
并进行编码。
高级语言可以是已经存在的一种语言,如,C,Pascal,Basic。
也可以是自己构造的一种语言。
当然,考虑到后续实现的难度,可以简化许多内容。
如不考虑数组,不考虑For循环等。
将定义好的单词编码用一个表表达出来。
如我们这里的MiniC++的单词定义如下:
保留字
内部编码
运算符号
其他符号
内部编码
if
1
+
8
(
19
else
2
-
9
)
20
while
3
*
10
;
21
cout
4
/
11
{
22
cin
5
**
12
}
23
>
(输入)
6
==
13
=
24
<
(输出)
7
14
数字
25
15
标识符
26
16
27
17
var
28
18
说明:
(1)由于只允许数字,所以不作变量类型。
所有类型都是var。
(2)单词编码无任何约束,只要方便可行。
要知道,我们构造的是一个独立的自包含的系统。
所有的东西都是我们自己定义的。
而编码只是便于机器内部识别。
只要后面的语法分析,语义分析都按这个编码即可。
2、将flex.rar展开在一个目录中,如E:
\flex。
3、根据上述单词编码编写LEX源程序。
LEX源程序是纯文本文件,任何文本编辑器均具备这一功能(如用记事本打开即可)。
保存时文件名任取。
这里假设命名为LexDemo.txt。
为后续操作简便,将该文件保存在E:
\flex子目录中。
4、编译LEX源程序。
生成lexyy.c。
5、使用C语言环境打开lexyy.c。
编译运行,最终生成lexyy.exe。
根据我们现有的情况,可以使用三种方案,任选其一。
(建议使用命令行工具,实际上更简单。
)
(1)使用VC建立一个工程(Project),将lexyy.c加入到该工程。
实际上,最好拷贝lexyy.c到相应的目录。
然后编译,产生的lexyy.exe文件在该工程目录下的Debug子目录中。
(2)使用VC的命令行工具。
格式为:
VC的安装路径>
\bin\CLlexyy.c
如:
VC安装在D:
\”ProgramFiles”下。
则命令为:
D:
\"
ProgramFiles"
MicrosoftVisualStudio"
\VC98\Bin\CLlexyy.c
(3)使用TC命令行工具。
<
TC的安装路径>
\bin\TCClexyy.c
\TC20\bin\TCClexyy.c
6、写一段该语言测试代码进行测试。
如:
While(i<
2)
{Cout<
10;
}
则输出序列为:
3,0
19,0
15,0
……
7、根据单词编码序列对照上面的表进行验证。
(1)每个单词对应一对数,第一个数为其编码。
第二个数为该单词的附加属性。
如无该属性则置0。
(2)如单词为标识符,其属性应该为符号表的入口地址。
但考虑到学词法分析时,还不熟悉符号表的机制,因而暂时也置0
1.5.问题及解答
1、涉及到命令行操作,考虑到仍有许多同学对DOS命令不熟悉。
希望自行加强。
2、如采用VisualC++编译,则先要建一个工程,将lexyy.c加入。
3、如果采用TC编译,则建议用TCC命令行工具。
4、由于LEX只能处理单字节的字符,请在LEX源程序中千万不要用中文注释。
保存时一定要看清楚类型,必须是ANSI类型。
1.6.实验报告要求
1、目的
2、内容
(1)单词及编码定义(设计一种高级语言(或子集)的单词其编码,见前面的表)
(2)部分LEX代码
(3)测试(写出两个测试句子:
所有单词正确,含有错误单词的句子)
3、总结(心得)
实验2自顶向下的语法分析
2.1.目的
在词法分析的基础上,熟悉自顶向下的语法分析方法。
体验递归程序的特点。
实现界面和业务逻辑代码分离。
实现异种平台的访问。
培养初步的软件架构的观念。
培养软件设计及编程能力。
2.2.知识
2.2.1终结符、非终结符及产生式
所有的组成最终句子的单词即为终结符。
非终结符代表的是我们观念上的语法范畴。
如主语。
谓语,名词等。
在高级语言中,语法范畴包括程序、说明语句、可执行语句、IF结构、关系表达式、算术表达式等等。
2.2.2语法及语义分析
语法分析只要求验证某个句子是否符合某个文法。
关注的是结构。
而语义关注的是句子的含义。
计算机本身无生命,无所谓真正地理解句子的含义。
我们所期望的计算机执行相应的语义是指:
当计算机程序扫描到某个句子后,所执行的操作恰好符合这个句子所表达的意思。
如扫描到一个“3+2”这样一个字符串。
自动地把结果5算出来。
而在语法分析中,所作的仅仅是判别这个句子的结构是否合法。
并不执行计算。
2.2.3FIRST集与FOLLOW集
所谓FIRST集,本质上就是第一个可能出现的符号构成的集合。
这个是可以由产生式本身得到的。
因为任何句子都是由该文法的产生式推出来的。
2.2.4关于递归下降子程序的编写
规则(请注意规则和下面的颜色对应关系):
(1)文法中的每个非终结符对应一个过程(函数)。
(2)若某个非终结符有多个产生式候选,则根据当前输入符是否在某个候选的Select集选择。
每个候选对应一个if分支。
(3)选择好候选之后,对产生式候选的右部的符号由左到右依次处理。
1若为终结符。
则将该符号和当前输入符号进行判等操作。
若相等,继续。
否则转③
2若为非终结符,则调用该非终结符所对应的过程。
3若当前扫描的符号为当前候选的第一个符号,且当前产生式有ε候选.则不作出错处理。
否则均出错处理。
例1:
S(S)|a
charstr[];
…//待检查的串
intip;
//扫描指针
voidS(){//只有一个非终结符S
if(str[ip]==’(‘){//处理S(S)候选
ip++;
S();
if(str[ip]==’)’)ip++;
elseerror();
elseif(str[ip]==’a’){//处理Sa候选
ip++;
}else//对应第1符号
error();
//但无ε候选项,必须出错。
例2:
S(S)|ε
if(str[ip]==’(‘){
//不是第1个符号,出错。
elseif(str[ip]==’a’){
}//不作出错处理。
需要注意的是,本例比较的是字符。
而本实验中用的是符号(单词)编码,是经过词法分析后的编码。
也就是后面定义的token数组相当于本例的str。
这点变通能力希望大家有。
关于这三条规则的具体运用,可看模板代码。
实现了两个非终结符,其余的需要同学们自己去实现。
2.3.
内容
2.3.1.文法的设计
本实验的目标是实现一个文本计算器的语法检验。
要实现实数的加、减、乘、除、乘方几种运算。
这几种运算构成了三种优先级。
因此文法的表达和课堂上不一样。
根据需要设计所有的非终结符。
可以以产生式为核心。
在设计的过程中逐步引入非终结符。
E>
→<
L>
A>
→+<
→-<
→ε
->
M>
B>
*<
/<
N>
C>
→**<
→“(“<
“)”//此括号非彼括号,故用引号括起来。
→$num//经过词法分析,数字被认为是终结符。
→ε
非终结符定义
符号
定义
算术表达式
消除左递归的算术子表达式
优先级为3的子项
消除左递归且优先级为3的子项
优先级为2的子项
消除左递归且优先级为2的子项
优先级为1的子项
优先级的编号越小,其运算(归约)的次序先。
2.3.2.基于LEX自动构造器地词法分析程序的重构(任选)
对于大型编译系统而言,往往存在多遍扫描的可能性。
将词法分析程序构造成独立的过程有很大的好处。
但对于我们这个小型的文本计算器而言。
将词法分析构造成依附于语法分析的子过程可能更加合理。
因此我们需要对词法分析程序进行重构。
本实验只要求实现表达式的求值。
因此,只需要使用原来集合的部分单词。
对词法分析程序进行重构,使之成为语法分析程序的子程序。
通过全局变量的方式加工数据,输入表达式串,输出编码及属性序列,分别存放在两个全局的整型数组中。
因此需要作如下变更:
(1)单词的编码在语法分析和词法分析中都需要,因而同一集中在一个头文件token.h中。
以后,无论是词法、语法、语义分析,均用这套编码。
以下是部分语句:
#ifndefTOKEN
/*终结符定义*/
#define$add20/*+*/
#d