xsf72006 / Compiler-PL0

BUAA Course-Fundamentals of Compiling -PL0 Compiler

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

编译实践 - PL/0编译系统说明文档

文件说明

解压后,除了本说明文档外,文件夹source存放源代码,文件夹test存放测试样例及exe运行程序。

注:务必保证exe文件和所有测试文件在同一文件夹下。

测试样例说明

样例编号 样例信息
1 书例14.1 鸡兔同笼问题
2 书例14.2 求最大公约数和最小公倍数
3 书例14.3 打印素数表
4 个人设计错误样例
5 书14.7.2 错误样例
6 个人设计正确样例(测试else和else if)
7 个人设计正确样例(测试repeat...until)

编译系统编写思路

PL/0编译系统是一个编译-解释执行程序,整个编译过程分两个阶段进行。第一阶段先把PL/0源程序编译成假想计算机的目标(P-code指令)程序,第二阶段再对该目标程序进行解释执行,得到运行结果。

下面介绍一下该编译系统编写思路。


PL/0文法

  • <程序> ::= <分程序>.
  • <分程序> ::= [<常量说明部分>][变量说明部分>][<过程说明部分>]<语句>
  • <常量说明部分> ::= const<常量定义>{,<常量定义>};
  • <常量定义> ::= <标识符>=<无符号整数>
  • <无符号整数> ::= <数字>{<数字>}
  • <标识符> ::= <字母>{<字母>|<数字>}
  • <变量说明部分>::= var<标识符>{,<标识符>};
  • <过程说明部分> ::= <过程首部><分程序>{;<过程说明部分>};
  • <过程首部> ::= procedure<标识符>;
  • <语句> ::= <赋值语句>|<条件语句>|<当型循环语句>|<过程调用语句>|<读语句>|<写语句- >|<复合语句>|<重复语句>|<空>
  • <赋值语句> ::= <标识符>:=<表达式>
  • <表达式> ::= [+|-]<项>{<加法运算符><项>}
  • <项> ::= <因子>{<乘法运算符><因子>}
  • <因子> ::= <标识符>|<无符号整数>|'('<表达式>')‘
  • <加法运算符> ::= +|-
  • <乘法运算符> ::= *|/
  • <条件> ::= <表达式><关系运算符><表达式>|odd<表达式>
  • <关系运算符> ::= =|<>|<|<=|>|>=
  • <条件语句> ::= if<条件>then<语句>[else<语句>]
  • <当型循环语句> ::= while<条件>do<语句>
  • <过程调用语句> ::= call<标识符>
  • <复合语句> ::= begin<语句>{;<语句>}end
  • <重复语句> ::= repeat<语句>{;<语句>}until<条件>
  • <读语句> ::= read'('<标识符>{,<标识符>}')‘
  • <写语句> ::= write'('<标识符>{,<标识符>}')‘
  • <字母> ::= a|b|...|X|Y|Z
  • <数字> ::= 0|1|2|...|8|9

PL/0编译器

编译器结构

本编译系统采用 **C++**语 言编写。编译系统的编译器部分由词法分析、语法分析、语义分析及代码生成、符号表管理、错误处理五部分组成。整个编译器以语法分析程序为中心,调用词法分析程序识别单词,生成相应的代码,查询或填写相应的符号表项,在出错时调用错误处理程序,报告错误,同时跳过出错部分继续进行语法分析。

本编译系统有main.cpp, words.cpp, syntax.cpp, tab.cpp, error.cpp, pcode.cpp, interpret.cpp七个类,下面是类中主要函数的介绍:

函数介绍
函数 作用
getch 取字符
getsym 词法分析,读取一个单词
test 测试当前单词符号是否合法
block 分析程序处理
constdeclaration 常量定义处理
vardeclaration 变量定义处理
statement 语句部分分析处理
expressison 表达式分析处理
term 项分析处理
factor 因子分析处理
condition 条件分析处理
error 出错处理,打印出错代码和出错信息
enter 登录符号表
position 查找标识符在符号表中的位置
gen 生成P-code指令,送入目标程序区
listcode 列出P-code指令清单
base 通过静态链接求出数据区的基地址
interpret P-code解释执行程序
词法分析

词法分析函数getsym由语法分析程序调用,主要功能:

  • 跳过源程序中的空格;
  • 从源程序中识别出单词符号,并以枚举值的形式送入变量sym中;
  • 用变量ID存放标识符,用二分查找保留字表,识别保留字;
  • 如取来的单词为无符号整数,则将其转换为整数后存入变量num中。
语法分析

实际的语法分析工作,在进入分程序(block)以后可以分成两部分进行,首先是对说明部分的分析处理,这一部分主要调用函数constdeclarationvardeclarationblock;说明部分处理完后,对语句部分进行分析处理,即调用函数statement,以及之后递归调用statementexpressiontermfactorcondition等。

符号表管理

在符号表管理中,符号表的录入是通过调用enter函数实现的,符号表的查找是通过函数position实现的。

可以将符号表理解成一个表格,其中储存着名字(name)、种类(kind)、值(val)、层次(level)、和地址(adr)。特别的,size是需要分配的数据区空间,仅procedure使用。

目标代码生成

PL/0编译器在进行语法分析的同时通过gen函数生成了P-code代码,即一个计算机的目标代码。最后用listcode函数输出所有P-code.

指令含义见书P316.

Interpret函数可模拟解释执行P-code代码,它采用栈式动态存储分配方法来分配程序运行时所需的数据存储空间。

错误处理

错误处理中,PL/0编译器采用了test函数,参数s1为合法符号集合,s2为停止符号集合,n为错误编码。test函数主要负责两种功能:

  • 在每个语法分析子程序的入口处,检测下一个取来的符号是否为该语法成分的合法后继符号或停止符号。若不是,则报告出错,并跳读一段源程序,直至取来的符号属于该语法成分的合法后继符号或停止符号集合为止;
  • 测试当前读取的符号是否属于该语法成分的合法头符号集合。

下表为错误编码及出错信息:

错误编码 出错信息
01 应是=而不是:=
02 =后应为常数
03 标识符后应为=
04 const, var, procedure后应为标识符
05 漏掉逗号或分号
06 过程说明后的符号不争取
07 应为语句
08 程序体内语句部分后的符号不正确
09 应为语句
10 语句之间漏分号
11 标识符未说明
12 不可向常量或过程赋值
13 应为赋值运算符:=
14 call后应为标识符
15 不可调用常量或变量
16 应为then
17 应为分号或end
18 应为do
19 语句后的符号不正确
20 应为关系运算符
21 表达式内不可有
22 漏右括号
23 因子后不可为此符号
24 表达式不能以此符号开始
25 缺少分号
26 缺少until
30 这个数太大
32 嵌套层数过多
40 应为左括号

感谢阅读这份说明文档。

About

BUAA Course-Fundamentals of Compiling -PL0 Compiler

License:GNU General Public License v2.0


Languages

Language:C++ 91.0%Language:C 9.0%