语法分析
- 格式:docx
- 大小:236.52 KB
- 文档页数:26
编译原理实验二·语法分析
一、 实验目的
通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。同时增强编写和调试程序的能力。
二、 实验内容及要求
对某特定语言A ,构造其语法规则。该语言的语法单位如下:
实现识别该语言的语法分析器, 可以选用:细化的递归下降程序,或者预测分析程序等。
按语法单位出现的顺序,返回识别出的语法单位序列
出现的语法错误,可以指出错误位置,及错误原因。
出现的标识符存放在标识符表,整型常数存放在常数表
三、 实验过程
1、 文法描述
语言A的文法的描述如下:
程序P的文法:
P program ID;
语句S文法:
S SA | SD | SW | SC | SIF
赋值语句的文法:
SA ID := E | ID := NUM 定义语句的文法:
SD var int ID D’
D’ ,ID D’|ε
循环语句的文法:
SW while B do S
判断语句的文法:
SIF if B then S | if B then S else S
复合语句的文法:
SC begin S C’
C’ ;S C’| ;end
布尔表达式B的文法:
B TB′
B′ and TB′|ε
T FT′
T′ or FT′|ε
F not F |(B)| E rop E | E
rop > | < | >= | <= | <> | =
算术表达式E的文法(此中的T、T’和F与上面不同):
E TE'
E' + TE' | ε
T FT'
T' * FT' | ε
F (E) | I
注:ID与NUM的文法与语法分析器中的定义相同。
2、 单词种别定义
A语言中的单词符号及其对应的种别编码如下表所示:
单词符号 种别编码 单词符号 种别编码
program 1 + 16
begin 2 * 17
end 3 ( 18
var 4 ) 19
int 5 , 20
and 6 . 21
or 7 := 22
not 8 ; 23
if 9 > 24
then 10 < 25 else 11 = 26
while 12 >= 27
do 13 <= 28
标识符 14 <> 29
整型常量 15 - 30
3、 运行环境
本次实验采用win-tc进行代码的编写和编译及运行
程序的运行环境为windows
4、 关键算法描述
本程序采用细化的递归下降程序进行描述,所用到的主要函数有:
main() //主函数,程序的入口
P() //程序P文法判定函数
S(int i) //语句S文法实现程序,i表示递归层数,下同
SA(int i) //赋值语句文法实现程序
SD(int i) //定义语句文法实现程序
SW(int i) //循环语句文法实现语句
SIF(int i) //判断语句文法实现语句
SC(int i) //复合语句文法实现判断语句
E() //算数表达式
B() //布尔表达式
errProc(int type) //出错处理语句,参数type表示错误类型,此函数与词法分析中的出错函数相同,是在原函数的基础上添加新的错误类型
struct binary *lexicalAnalyze() //词法分析主函数,本程序通过此函数实现了与词法分析程序的连接
语句S的程序流程图如下所示:
开始
判断当前单词符号
当前为if
关键字 调用SIF()函数 是
否
当前为begin
关键字 调用SC()函数 是 否
当前为while
关键字 调用SW()函数 是
主函数main()程序流程图如下所示:
否
当前为var
关键字 调用SD()函数 是
否
当前为分号 调用SD()函数 是
否
结束
开始
程序的初始化操作:将文件的内容读入内存;保留字、标识符、常数和错误表初始化;ch指针初始化
调用程序P(),返回result
Result为1 是 到达数据末尾
否
出错处理 调用函数S() 否 是
结束
其他的文法分析函数SA()、SD()、SW()、SIF()、SC()、E()、B()和P()按照文法的产生式就可以得到具体的代码了。
在lexicalAnalyze()函数的调用过程中,用到了词法分析的函数,通过这个函数作为接口将词法与语法分析很好地结合在了一起。
5、 测试报告
语法分析功能检测:
测试用的A语言代码如下:
代码执行后在控制台中输出如下:
报错功能检测:
将原A语言加入如下图的语法错误:
(图中画圈处为加入的语法错误)
代码执行结果如下所示:
(矩形方框为表示错误检测的表现)
经检验,本程序的语法分析功能和报错功能均可以正确执行。
四、 实验总结
1、 实验体会
通过本次实验,我进一步巩固了学习的编译原理的知识,同时更加熟练地掌握了各种矩形的文法,对词法分析器的工作原理有了进一步的认识,自上而下的分析程序的思想进一步巩固,增强了编程技巧。
刚完成的时候,程序可以完成语法分析,但由于使用了递归调用,所以先出现的语法句型反而在后面显示,后来增加了以一种数据结构,将分析过程中出现的矩形记录在链表中,最后进行分析与显示。通过这个过程,我认识到,在编程的过程中,要充分利用各种数据结构帮助解决问题,可以大大增加编程效率。
2、 存在不足及改进思路
1、 当遇到错误的时候,直接寻找下一个的分号的位置,可能会错过一些关键字,从而对结构进行误判。
改进思路:当遇到错误的时候,可以寻找下一个关键字或分号。
2、 若语句缺少while或if关键字,将对整个结构都不能正确分析
改进思路:增加S()函数的判断条件,将if 或while 的缺失作为一种错误类型。
附:程序源代码(C语言)
注:仅语法分析的部分
主函数:
main(int argc,char ** argv)
{
int nLen;
char *pchBuf;
struct showitem *tempitem;
int tempi,curi;
FILE *pf = fopen(argv[1],"r");
FILE *pf1 = fopen(argv[2],"w");
itable = (struct identifier*)malloc(sizeof(struct identifier));
ctable = (struct constant*)malloc(sizeof(struct constant));
etable = (struct err*)malloc(sizeof(struct err));
shead = (struct showitem*)malloc(sizeof(struct showitem));
itable->index = 0;
ctable->index = 0;
itail = itable;
ctail = ctable;
etail = etable;
stail = shead;
itable->next = NULL;
ctable->next = NULL;
etable->next = NULL;
shead->next = NULL;
fseek(pf, 0, SEEK_END);
nLen = ftell(pf);
rewind(pf);
pchBuf = (char*) malloc(sizeof(char)*nLen+1);
nLen = fread(pchBuf, sizeof(char), nLen, pf);
pchBuf[nLen] = '\0';
ch = pchBuf;
fclose(pf);
curBinary = lexicalAnalyze();
if(P() == 1){
while(curBinary->type != 21)
S(0);
}
stail = shead->next;