编译原理课程设计报告词法分析器.docx
《编译原理课程设计报告词法分析器.docx》由会员分享,可在线阅读,更多相关《编译原理课程设计报告词法分析器.docx(31页珍藏版)》请在冰豆网上搜索。
编译原理课程设计报告词法分析器
编译原理课程设计报告
目录
一、目的和要求3
二、运行平台3
三、结构设计说明:
3
1、概述3
2、各功能模块描述4
四、主要成分描述5
1.符号表5
2.运行时存储组织和管理5
3.语法分析方法6
4.中间代码表示6
五、测试用例7
①测试+=的用例为:
7
②测试-=的用例为:
9
③测试FORDONWTO的用例为:
2
④测试FORTODO的用例为:
10
⑤测试++的用例为:
11
⑥测试—的用例为:
11
⑦测试CHAR的用例为:
14
⑧测试不等号用例为:
14
⑨测试ELSE用例为:
14
六、开发过程和完成情况16
1.总述16
2.具体添加的代码17
七、学习体会26
八、关于这次课程设计的自我评价:
27
1、自我评分:
27
2、下面说一下我这次做这次PL0的收获:
27
一、目的和要求
基本内容:
(1)增加单词:
保留字ELSE,FOR,TO,DOWNTO;运算符+=,-=,++,--
(2)修改单词:
不等号#改为<>
(3)增加条件语句的ELSE子句
(4)扩充赋值运算:
+=和-=
(5)扩充语句(Pascal的FOR语句):
①FOR<变量>:
=<表达式>TO<表达式>DO<语句>
②FOR<变量>:
=<表达式>DOWNTO<表达式>DO<语句>
其中,语句①的循环变量的步长为1,
语句②的循环变量的步长为-1。
选做内容:
(1)增加运算:
++和--。
(2)增加类型:
①字符类型;②实数类型。
(3)扩充函数:
①有返回值和返回语句;②有参数函数。
(4)增加一维数组类型(可增加指令)。
二、运行平台
编译器实现工具和运行平台程序用C++语言编写,在C++Builder平台下运行。
三、结构设计说明:
1、概述
PL/0语言是Pascal语言的一个子集,这里分析的PL/0的编译程序包括了对PL/0语言源程序进行分析处理、编译生成类PCODE代码,并在虚拟机上解释运行生成的类PCODE代码的功能。
PL/0语言编译程序采用以语法分析为核心、一遍扫描的编译方法。
词法分析和代码生成作为独立的子程序供语法分析程序调用。
语法分析的同时,提供了出错报告和出错恢复的功能。
在源程序没有错误编译通过的情况下,调用类PCODE解释程序解释执行生成的类PCODE代码。
PL/0的编译过程采用一趟扫描方式,以语法分析为核心,词法分析程序和代码生成程序都作为一个独立的过程,当语法分析需要读入单词时就调用词法分析程序,而当语法分析正确需生成相应的目标代码时,则调用代码生成程序。
此外,用表格管理程序建立变量、常量和过程标识符的说明与引用之间的信息联系。
用出错处理程序对词法和语法分析遇到的错误给出在源程序中出错的位置和错误性质。
当源程序编译正确时,PL/0编译程序自动调用解释执行程序,对目标代码进行解释执行,并按用户程序的要求输入数据和输出运行结果。
2、各功能模块描述
①.词法分析
词法分析是编译的第一个阶段,它的主要任务是从左向右逐个字符地对源程序进行扫描,产生一个个单词序列用于语法分析。
PL/0词法分析程序GETSYM的功能是为语法分析提供单词用的,是语法分析的基础,把输入的字符串形式的源程序分割成一个个单词符号。
经过词法分析程序分析出来的单词,对语言固有的单词只给出类别存放在全程变量SYM中,而对用户定义的单词(标识符或常数)既给出类别又给值,其类别放在SYM中,值放在全程变量ID或全程变量NUM中,全部单词种类由编译程序定义的纯量类型SYMBOL给出,称为语法词汇表。
词法分析器的分析过程:
调用GETSYM时,它通过GETCH过程从源程序中获得一个字符。
如果这个字符是字母,则继续获取字符或数字,最终可以拼成一个单词,查保留字表,如果查到为保留字,则把SYM变量赋成相应的保留字类型值;如果没有查到,则这个单词应是一个用户自定义的标识符(可能是变量名、常量名或是过程的名字),把SYM置为IDENT,把这个单词存入ID变量。
查保留字表时使用了二分法查找以提高效率。
如果Getch获得的字符是数字,则继续用Getch获取数字,并把它们拼成一个整数或实数,然后把SYM置为INTEGER,并把拼成的数值放入NUM变量。
如果识别出其它合法的符号(比如:
赋值号、大于号、小于等于号等),则把SYM则成相应的类型。
如果遇到不合法的字符,把SYM置成NUL。
词法分析程序GETSYM将完成下列任务:
(1)滤空格
(2)识别保留字(3)识别标识符
(4)拼数(5)拼复合词(6)输出源程序
②.语法分析
PL/0编译程序的语法分析采用了自顶向下的递归的子程序法。
语法分析同时也根据程序的语义生成相应三元代码,并提供了出错处理的机制。
语法分析主要由分程序分析过程(BLOCK)、常量定义分析过程(ConstDeclaration)、变量定义分析过程(Vardeclaration)、语句分析过程(Statement)、表达式处理过程(Expression)、项处理过程(Term)、因子处理过程(Factor)和条件处理过程(Condition)构成。
这些过程在结构上构成一个嵌套的层次结构。
除此之外,还有出错报告过程(Error)、代码生成过程(Gen)、测试单词合法性及出错恢复过程(Test)、登录名字表过程(Enter)、查询名字表函数(Position)以及列出类PCODE代码过程(Listcode)作过语法分析的辅助过程。
由PL/0的语法图可知:
一个完整的PL/0程序是由分程序和句号构成的。
因此,本编译程序在运行的时候,通过主程序中调用分程序处理过程block来分析分程序部分(分程序分析过程中还可能会递归调用block过程),然后,判断最后读入的符号是否为句号。
如果是句号且分程序分析中未出错,则是一个合法的PL/0程序,可以运行生成的代码,否则就说明源PL/0程序是不合法的,输出出错提示即可。
③.语义分析
PL/0的语义分析主要进行以下检查:
(1)是否存在标识符先引用未声明的情况;
(2)是否存在己声明的标识符的错误引用;
(3)是否存在一般标识符的多重声明。
④.语法错误处理
PL/0编译程序对语法错误的处理采用两种办法:
(1)对于一些易于校正的错误,如丢了逗号、分号等,指出出错的位置,加以校正,继续进行分析。
(2)对于难于校正的错误,给出错误的位置与性质,跳过后面一些单词,直到下一个可以进行正常语法分析的语法单位。
⑤.解释执行
这个过程模拟了一台可以运行类PCODE指令的栈式计算机。
解释程序过程中的base函数的功能,就是用于沿着静态链,向前查找相差指定层数的局部数据段基址。
这在使用sto、lod等访问局部变量的指令中会经常用到。
类PCODE代码解释执行的部分通过循环和简单的case判断不同的指令,做出相应的动作。
当遇到主程序中的返回指令时,指令指针会指到0位置,把这样一个条件作为终至循环的条件,保证程序运行可以正常的结束。
生产目标代码后,程序调用Interpret程序解释执行,程序定义的一个数据区S,三个寄存器T栈顶寄存器,B基址寄存器和P程序地址寄存器用于运行程序。
四、主要成分描述
1.符号表
在编译过程中常用到的表格包括常量表、变量表(标识符表)、保留字表、数组表和过程信息表等。
统称为符号表,又称为单词属性字表;符号表可以用来收集符号属性、是上下文语义的合法性检查的依据、也作为目标代码生成阶段地址分配的依据。
从编译系统的造表过程来区分,符号表可分为静态表(是事先构造好表,编译程序需要使用时直接查找。
如:
保留字、标准函数名表等)和动态表(编译程序在编译过程中根据需要构造的表。
如:
标识符表、符号表、循环表、数组信息表和过程表等)。
符号表在编译过程的重要作用主要表现在两个方面:
辅助语义的正确性和检查辅助目标代码的生成。
符号表有若干个表项组成,每个表项有单词的名字域和属性域两部分。
符号表应包括符号的所有属性,这样可以有助于编译程序的语义检查和生成可运行的目标代码,其主要内容包括:
符号的名字、符号的类型、地址码、符号的类型、地址码、数组的维数、下标的类型或过程参数等等。
符号表的组织可分为符号表的总统组织、符号表项的排列、关键字域的组织、其它域的组织和下推链组织;符号表的管理包括符号表的初始化、符号的登录、符号的查找、符号表中分程序结构层次分管理。
2.运行时存储组织和管理
程序运行时的存储区常常划分成:
目标区、静态数据区、栈区和堆区。
数据空间的使用和管理方法分成三种:
静态存储分配、栈式动态存储分配和堆式动态存储分配。
在简单栈式存储分配的实现中常常使用两个指针指示栈最顶端的数据区,一个是SP(总是指向现行过程活动记录的起点),另一个是TOP(始终指向已占用的栈顶单元),嵌套过程语言的栈式实现只是增加了非局部变量的存取,其方法有在过程活动记录中增设存取链和在每进入一个过程后,在建立它的活动记录的同时建立一张嵌套层次显示表display。
在分程序结构的存储管理中要注意分清楚各过程体的活动记录和SP及TOP指针的始末位置。
在过程调用过程中有可能有参数的传递,其路径有:
传值,传地址,传名及宏扩展等。
3.语法分析方法
语法分析是编译程序的核心部分。
语法分析的作用是识别由词法分析给出的单词符号序列是否是给的文法的正确句子(程序),目前语法分析常用的方法由自顶向下分析和自底向上分析两大类。
自顶向下分析包括确定分析和不确定分析,自底向上分析包括算符优先分析和LR分析。
自顶向下的不确定分析方法是带回溯的分析方法,实际上是一种穷举的试探方法,因此效率低。
代价高。
确定的自顶向下分析方法,是从文法的开始符号出发,考虑如何根据当前的输入符号(单词符号)惟一地确定选用哪个产生式替换相应非终结符以往下推导,或如何构造一棵相应的语法树。
确定的自顶向下分析方法只适合于LL
(1)文法,一个文法需经过计算它的FIRST、FOLLOW、SELECT集合来判断其是否为LL
(1)文法,有些文法也可以通过踢去左公因子和消除左递归来转换成LL
(1)文法。
确定的自顶向下分析方法有递归子程序法(对应文法中每个非终结符编写一个递归过程)和预测分析方法(由预测分析程序、先进后出栈和预测分析表组成)。
简单优先分析法的基本思想是对一个文法按一定原则求出该文法所有符号即包括终结符和非终结符之间的优先关系,按照这种关系确定归约过程中的句柄,它的归约过程实际上是一种规范归约;其关键是构造优先关系表的构造。
自底向上分析法的关键问题是在分析过程中如何确定句柄,LR分析法正是给出一种能根据当前分析栈中的符号串(通常以状态表示)和向右顺序查看输入串的k个(k>=0)符号就可惟一确定分析器的动作是移进还是归约和用哪个产生式归约,因而也就能惟一地确定句柄。
LR分析法的归约过程是规范推导的逆过程,所以LR分析过程是一种规范归约过程。
一个LR分析器是由总控程序、分析表或分析函数和分析栈三部分组成的,LR分析过程主要是对文法的产生式进行排序、计算各非终结符的FIRST和FOLLOW集、构造文法关于LR(k)的项目集族(若有冲突的话要用相关的办法解决)、根据项目集族构造相应的LR(k)分析表、对输入的字符串进行分析,看是属于接受态还是出错。
4.中间代码表示
中间代码长见的形式有逆波兰记号(后缀式)、三元式、四元式和树形表示。
逆波兰记号式最简单的一种中间代码表示形式,这种表示法将运算对象写在前面,把运算符号写在后面,其最大的优点是易于计算机处理表达式。
利用一个栈,自左至右扫描算术表达式(后缀表示)。
每碰到运算对象,就把它推进栈;碰到运算符,若该运算符是二目的,则对栈顶部的两个运算对象实施该运算,并将运算结构代替这两个运算对象而进栈。
若是一目运算符