编译原理实验手册

编译原理实验手册

一、实验目的

编译原理是一门实践性很强的课程,但由于课时所限,只能在课堂上讲授一些通用的原理和方法。而为了真正学好这门课程,必须自己动手构造出一个编译器,才能对书里讲到的原理、方法和技术有较全面的体会,才能对学生以后的程序设计和解决实际问题的能力有所帮助。

实际的编译程序是十分复杂的,有时由多达十几万条指令组成。为此,编译原理的实践教学,采用简化编译过程的办法,选择最关键的三个环节──词法分析、语法分析、语义分析和中间代码产生,每个环节作为一个实践课题,逐步深入,扩展功能,直至得到一个简单实用的编译器。本实验不涉及到优化。

二、实验内容

任何一个实用的高级语言,其语法都比较复杂,如选其作为源语言,很难实践全过程。故本试验将定义一个简化的语言──PASCAL语言的一个子集作为源语言,分三个课题、一步步地构造出它的编译程序。所有试验项目前后贯穿这一条主线进行。本实验共进行6周,每周3学时,共18学时。本实验主要包括以下三个课题:

1.  词法分析:以源程序为输入,输出单词符号流;

2.  语法分析:以源语言的文法为依据,调用词法分析器,使用递归下降分析法或算符优先分析法或LR(1)分析法,构造能识别源语言各种语法结构的语法分析器;

3.  语义分析和中间代码产生:使用语法制导翻译技术,对源语言程序进行简单的翻译,输出四元式序列。

在本节的第三部分给出了PASCAL语言两个子集的文法,对这些文法稍加变换,即可获得用于语法分析的LL(1)文法或LR(1)文法。学生可以直接选择一个作为编译器的源语言,也可以对这些文法进行改造,以获得能力更为强大的源语言。学生也可以自己设计源语言,来完成这些题目;唯一的要求是源语言必须包含三种基本的程序设计结构(顺序、选择、循环)和至少两种不同的数据类型。

本实验要求:

·        所有的输入输出均采用文件形式。

·        独立完成。

·        语言不限,开发工具不限;但必须有可运行的程序和规范的注释。

三、PASCAL语言子集的文法

由于Pascal语言结构严谨,层次清晰,语法与C语言接近,也便于理解,因此本实验抽取Pascal语言的一个子集,稍加改造,作为源语言,姑且命名为LittleP。一个LittleP程序由一系列全局数据声明和一个主程序体组成。所有数据采用静态存储分配,没有I/O,只支持一种基本数据类型:无符号整数。

1.  LittleP的文法:

 

〈程序〉→〈程序首部〉〈程序体〉

〈程序首部〉→ program〈程序名〉
  〈程序体〉→〈变量声明〉〈复合语句〉

 

〈变量声明〉→var〈变量定义列表〉|〈空〉

<变量定义列表> → 〈变量定义〉〈变量定义列表〉|〈变量定义〉

〈变量定义〉→〈变量名列表〉: <类型>

<变量名列表> → 〈变量名〉|〈变量名〉,〈变量名列表〉

<类型> →  integer

 

〈复合语句〉→begin〈语句块〉end

〈语句块〉→〈语句〉|〈语句〉 〈语句块〉

〈语句〉→〈赋值语句〉|〈条件语句〉|〈循环语句〉|〈复合语句〉|〈空〉

 

〈赋值语句〉→〈左部〉:=〈右部〉

〈左部〉→〈变量名〉

〈右部〉→〈算术表达式〉

 

〈条件语句〉→ if〈关系表达式〉then〈语句〉else〈语句〉

 

〈循环语句〉→ while〈关系表达式〉do〈语句〉

 

<关系表达式> →〈算术表达式〉〈关系运算符〉〈算术表达式〉

<算术表达式> → 〈项〉| 〈算术表达式〉〈加运算符〉〈项〉

<项> → 〈因子〉| 〈项〉〈乘运算符〉〈因子〉

〈因子〉→〈变量名〉|(〈算术表达式〉) |〈整数〉

 

〈程序名〉→〈标识符〉

〈变量名〉→〈标识符〉

〈标识符〉→〈字母〉|〈标识符〉〈字母〉|〈标识符〉〈数字〉

 

〈整数〉→〈数字〉|〈整数〉〈数字〉

〈关系运算符〉→ < | <= || >= | > | <>

〈加运算符〉→ +| -  

〈乘运算符〉→ *| /  

〈字母〉→ a|b||x|y|z

〈数字〉→ 1|2|3|4|5|6|7|8|9|0

 

2.在此基础上加以扩充,可得功能较强的一个 LittleP 语言的超集:LittleP+。该语言引入了实数、一维数组和过程、函数的定义,参数传递采用传值方式。另外,加入了I/O支持,编译器提供两个系统函数:read()和write()。

 

〈程序〉→〈程序首部〉〈程序体〉

〈程序首部〉→ program〈程序名〉
  〈程序体〉→〈变量声明〉<分程序声明>〈复合语句〉

 

〈变量声明〉→var〈变量定义列表〉|〈空〉

<变量定义列表> → 〈变量定义〉〈变量定义列表〉|〈变量定义〉

〈变量定义〉→〈变量名列表〉: <类型>

<变量名列表> → 〈变量名〉|〈变量名〉,〈变量名列表〉

 

 <类型> → <基本类型>|<数组>

<基本类型> → integer | real

<数组> →array [〈下界〉..〈上界〉] of <基本类型>

<下界> →<整数>

<上界> →<整数>

 

<分程序声明> → 〈分程序〉 〈分程序声明〉|〈空〉

〈分程序〉→〈分程序首部〉〈变量声明〉〈复合语句〉

〈分程序首部〉→ procedure〈过程名〉( <形参列表> );

| function〈函数名〉( <形参列表> ) : <基本类型>

<形参列表> → 〈形参定义〉 ,〈形参列表〉|〈形参定义〉|〈空〉

〈形参定义〉→〈变量名列表〉: <基本类型>

 

〈复合语句〉→begin〈语句块〉end

〈语句块〉→〈语句〉|〈语句〉〈语句块〉

〈语句〉→〈赋值语句〉|〈条件语句〉|〈循环语句〉

|〈过程调用语句〉|〈复合语句〉|〈读写语句〉|〈空〉

 

〈赋值语句〉→〈左部〉:=〈右部〉

〈左部〉→〈变量名〉|〈变量名〉[ 算术表达式 ]

〈右部〉→〈算术表达式〉

 

〈条件语句〉→ if〈关系表达式〉then〈语句〉else〈语句〉

 

〈循环语句〉→ while〈关系表达式〉do〈语句〉

 

〈过程调用语句〉→〈过程名〉( <实参列表> )
                      
|〈函数名〉( <实参列表> )

<实参列表> → 〈算术表达式〉| 〈算术表达式〉,〈实参列表〉|〈空〉

 

〈读写语句〉→ read ( <变量名列表> ) |write (<实参列表> )

 

<关系表达式> →〈算术表达式〉〈关系运算符〉〈算术表达式〉

<算术表达式> → 〈项〉| 〈算术表达式〉〈加运算符〉〈项〉

<项> → 〈因子〉| 〈项〉〈乘运算符〉〈因子〉

〈因子〉→〈变量名〉|(〈算术表达式〉)|〈函数名〉(<实参列表>)

           |〈变量名〉[ 算术表达式 ] |〈整数〉|〈实数〉

 

〈程序名〉→〈标识符〉

〈变量名〉→〈标识符〉

〈过程名〉→〈标识符〉

〈函数名〉→〈标识符〉

〈标识符〉→〈字母〉|〈标识符〉〈字母〉|〈标识符〉〈数字〉

 

〈整数〉→〈数字〉|〈整数〉〈数字〉

〈实数〉→〈整数〉 . 〈整数〉

〈关系运算符〉→ < | <= || >= | > | <>

〈加运算符〉→ +| -  

〈乘运算符〉→ *| div | mod  

〈字母〉→ a|b||x|y|z|A|B||X|Y|Z

〈数字〉→ 1|2|3|4|5|6|7|8|9|0

 

3.对源程序语法的其他说明:

a)  出现在{ }里的所有字符作为注释跳过。

b)  各单词符号之间的空格可有可无,但关键字和标识符必须分隔开来。

c)  过程没有返回值,只能出现在过程调用语句中;函数有且只有1个返回值,只能出现在算术表达式中或作为赋值语句的右部。函数返回值通过函数名带回,因此在函数体内必须给函数名赋值。

d)  标识符的长度不得超过8个字符。

e)  关键字保留,包括read和write。

四、实验要求:

每个课题完成后写出实验报告。实验报告应该包括:

·        程序设计时考虑的算法和主要的数据结构;

·        可执行的程序

·        至少2个测试用例,包括:

§  至少1个合法的源程序及其运行结果;

§  至少1个非法的源程序及其错误报告。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值