语法分析程序.docx
- 文档编号:10214660
- 上传时间:2023-02-09
- 格式:DOCX
- 页数:43
- 大小:393.15KB
语法分析程序.docx
《语法分析程序.docx》由会员分享,可在线阅读,更多相关《语法分析程序.docx(43页珍藏版)》请在冰豆网上搜索。
语法分析程序
HUNANUNIVERSITY
编译原理
实验报告
题目:
语法分析器的实现
学生姓名:
杨玉茹
学生学号:
201508010325
专业班级:
计科1503
上课老师:
杨晓波
一、实验目的
(一)学习已有编译器的经典语法分析源程序。
(二)通过本次实验,加深对语法分析的理解,学会编制语法分析器。
二、实验任务
(一)阅读已有编译器的经典语法分析源程序,并测试语法分析器的输出。
(二)用C或JAVA语言编写一门语言的语法分析器。
三、实验内容
(一)学习经典的语法分析器(2学时)
(1)选择一个编译器,如:
TINY或PL/0,其它编译器也可(需自备源代码)。
(2)通过将定义语言的语法规则的BNF文法改写成EBNF文法,以利于递归下降分析算法。
(3)阅读语法分析源程序,加上你自己的理解。
尤其要求对相关函数与重要变量的作用与功能进行稍微详细的描述。
若能加上学习心得则更好。
TINY语言请参考《编译原理及实践》第3.7节;PL/0语言请参考相关实现文档。
对TINY语言要特别注意抽象语法树的定义与应用。
对PL/0语言要特别注意各种符号表的处理。
(4)测试语法分析器。
对TINY语言要求输出测试程序的字符形式的抽象语法树。
(手工或编程)画出图形形式的抽象语法树。
对PL/0语言要求给出测试程序的各种符号表的内容。
TINY语言:
测试用例一:
sample.tny。
测试用例二:
用TINY语言自编一个程序计算任意两个正整数的最大公约数与最大公倍数。
PL/0语言:
测试用例一~三:
test.pls,test2.pls,a1.pls。
(二)实现一门语言的语法分析器(6学时)
(1)语言确定:
C-语言,其定义在《编译原理及实践》附录A中。
也可选择其它语言,不过要有该语言的详细定义(可仿照C-语言)。
一旦选定,不能更改,因为要在以后继续实现编译器的其它部分。
鼓励自己定义一门语言。
(2)完成C-语言的BNF文法到EBNF文法的转换。
通过这一转换,消除左递归,提取左公因子,将文法改写为LL
(1)文法,以适用于自顶向下的语法分析。
规划需要将哪些非终结符写成递归下降函数。
(3)为每一个将要写成递归下降函数的非终结符,如:
变量声明、函数声明、语句序列、语句、表达式等,定义其抽象语法子树的形式结构,然后定义C-语言的语法树的数据结构。
(4)仿照前面学习的语法分析器,编写选定语言的语法分析器。
(5)准备2~3个测试用例,测试并解释程序的运行结果。
四、系统设计
(1)实验设计思路分析:
思路:
主函数里面的执行步骤:
(由于我所使用的绘图软件不能导出图片,因此只能通过截屏)
(2)代码分析
A.声明产生式Pronode:
包括三部分,产生式左边、产生式的推导符号、产生式右边
B.每次声明一个产生式以后需要对产生式进行初始化;
C.输入一个含有产生式的文件txt以后,需要对文件进行读取,因此这里使用了ReadPro函数进行读取;读取的方式主要是运用库函数fsanf以输入流的方式进行读取;分三段进行读取,产生式的左边、终结推介符号、右边;
D.打印txt文件里面含有的产生式PrintPro;
E.对产生式里面的终结符号和非终结符号分别用SetUnTerminate和SetTerminate进行存储到UnTerminate和Terminate两个数组当中去;用bool数flag对表里面的内容进行标记,如果已经含有了,就不需要再进行存储了;如果没有标记过,就加入表中去;
F.获得产生式的First集合以及Follow集合;
First集合的求解方法:
如果右边的第一个字符是一个终结符号,那么直接加入到First集合当中去;
如果右边的第一个字符是非终结符号,若对于产生式右边的一切非终结符,均可推出ε,则将ε加进FIRST集,
将产生式右边能推出空字符的非终结符的Frist集中不含ε的终结符加入到该非终结符的Fisrt集;
产生式右边不能推出空字符的非终结符的Frist集加入到该非终结符的Fisrt集;
变量说明:
boolIsNull(charc):
非终结符能否产生空字符
boolIsTerminate(charc):
判断是否为终结符号
voidAddChar(charchArray[],charc):
将非终结符的所有first值加入First集
voidAddCharToChar(charchArray[],charotherArray[]):
将非终结符的所有first集加入First集
voidAddCharToChar(charchArray[],charotherArray[]):
将非终结符的所有first集加入First集
voidAddFollow(charfollow[],charc);将非终结符的所有follow值加入Follow集
Follow集合的求解方法:
将$放进Follow(S)集合当中去,其中S是开始符号;
如果存在一个产生式A->aCB,那么FOLLOW(B)中除了$之外的所有符号都在FOOLOW(B)当中了;
如果存在一个产生式A->aB,或者存在产生式A->aCB且FIRST(B)包含空,那么FOLLOW(A)中的所有的符号都在FOLLOW(B)中;
G.根据给出的First集合和Follow集合选择出对应的输入的符号对应的产生式SetSelect;
步骤:
扫描每一个产生式,求出Select集合
如果产生式的右边第一字符为终结符,则将其加入select集
如果产生式的右边字符为ε,则应将左边字符的follow集加入select集
产生式右边的第一个字符为非终结符,则逐个分析:
若α=X1X2…Xnα′,其中Xi∈VN,1≤i≤n;若ε∈FIRST(X1),则将FIRST(X2)中的一切非ε的终结符加进FIRST(α),FIRST(α)则应加入select集;以此类推
处理像E->ABaβ的产生式的情况,若α=X1X2…Xnα′,其中Xi∈VN,1≤i≤n;若对于一切1≤i≤n,ε∈FIRST(Xi),则将follow(α)加入select集合;
相关代码(由于代码太长了,只截取了一部分的代码):
H.构造分析表SetSheet,根据我们已经求出来的FIRST集合和FOLLOW集合,构造出预测分析表:
I.输入我所需要分析的字符串voidInputSym();
J.万事具备只欠东风,此时所有的事情已经准备好了,那么就只需要一一的进行分析;voidScan()函数就将字符串的分析过程体现出来了,当然这个分析过程包含了以下几个重要的部分:
存储符号的栈:
包括栈底和栈顶,以及栈的大小
存储剩余符号的队列:
队列里面包含了两个结构,一个是数据,一个是指向下一个数据的指针;
预测分析表:
也就是我们刚刚构造出来的分析表SetSheet;
每一步操作所运用到的产生式PrintSheet(introw,intcol):
F分析的过程:
将#压入栈中,Push(SymStack,'#');
开始符号入栈,Push(SymStack,UnTerminate[0]);
读入第一个符号:
a=GetSym(Remain);
查看是否和输入符号的第一个符号对应,如果没有的话,就继续在栈中进行左递推;
如果对应了就将此符号出队列,然后再进行左递推;
五、实验测试
我的pro.txt文件里面的产生式为:
打印出的产生式与我的产生式是一样的:
得出的分析表:
对i*i进行预测分析时执行的步骤:
六、实验心得
a)实验问题:
1)程序读不到我的pro.txt文件
刚开始的时候,我写了一个读取txt文件里面的产生式的文件,可以每次我输入文件名以后,程序也不报任何的错误或者信息,也没有显示不能读取,我检查了半天我的程序,最后发现是我最后在txt文件里面末尾少写了一个#。
b)实验心得:
由于有了之前几次实验的基础,所以这次在理解题意的时候变得相对的简单一点了,不过这次实验明显比前几次都难,涉及到的步骤程序太多了,因此思绪很容易乱。
不过由于之前我已经把LL的方法透彻的理解过了,所以相对要好一些,过程中遇到了不少的麻烦,所以部分的代码借鉴了网上的。
LL
(1)分析器是自顶向下的一个最重要的分析,所以这是我们这学期该重点掌握的内容,所以做实验的过程也加强了我对这个算法的理解。
七、附录(源代码及注释)
代码附在文件夹里面
HUNANUNIVERSITY
编译原理
实验报告
题目:
LL
(1)分析
学生姓名:
杨玉茹
学生学号:
201508010325
专业班级:
计科1503
上课老师:
杨晓波、陈浩
二、实验目的
学习和掌握LL
(1)文法的判定和LL
(1)分析方法。
二、实验任务
(1)存储文法的LL
(1)分析表;
(2)根据LL
(1)分析表判断文法是否LL
(1)文法;
(3)实现LL
(1)分析过程。
三、实验内容
(1)确定LL
(1)分析表的文件存储格式。
要求为3个以上测试文法准备好相应LL
(1)分析表的存储文件。
(2)根据LL
(1)分析表判断文法是否LL
(1)文法。
看每个表项是否最多只有一条候选式,如是该文法是LL
(1)文法。
(3)实现LL
(1)分析过程。
当
(2)判断出该文法是LL
(1)文法时,要求给出3个以上输入串的LL
(1)分析过程,并判断输入串是否该文法的合法句子。
四、系统设计
(1)实验设计思路分析:
思路:
主函数里面的执行步骤:
(由于我所使用的绘图软件不能导出图片,因此只能通过截屏)
●实验的主线是
求First集合和Follow集合->构造分析表->判断文法是否是LL文法->实现LL
(1)的分析过程
(2)前期准备工作(变量的声明、结构的构造)
A.声明产生式Pronode:
包括三部分,产生式左边、产生式的推导符号、产生式右边
B.每次声明一个产生式以后需要对产生式进行初始化;
C.输入一个含有产生式的文件txt以后,需要对文件进行读取,因此这里使用了ReadPro函数进行读取;读取的方式主要是运用库函数fsanf以输入流的方式进行读取;分三段进行读取,产生式的左边、终结推介符号、右边;
D.打印txt文件里面含有的产生式PrintPro;
E.对产生式里面的终结符号和非终结符号分别用SetUnTerminate和SetTerminate进行存储到UnTerminate和Terminate两个数组当中去;用bool数flag对表里面的内容进行标记,如果已经含有了,就不需要再进行存储了;如果没有标记过,就加入表中去;
(3)求First集合和Follow集合
A..获得产生式的First集合以及Follow集合;
First集合的求解方法:
如果右边的第一个字符是一个终结符号,那么直接加入到First集合当中去;
如果右边的第一个字符是非终结符号,若对于产生式右边的一切非终结符,均可推出ε,则将ε加进FIRST集,
将产生式右边能推出空字符的非终结符的Frist集中不含ε的终结符加入到该非终结符的Fisrt集;
产生式右边不能推出空字符的非终结符的Frist集加入到该非终结符的Fisrt集;
变量说明:
boolIsNull(charc):
非终结符能否产生空字符
boolIsTerminate(charc):
判断是否为终结符号
voidAddChar(charchArray[],charc):
将非终结符的所有first值加入First集
voidAddCharToChar(charchArray[],charotherArray[]):
将非终结符的所有first集加入First集
voidAddCharToChar(charchArray[],charotherArray[]):
将非终结符的所有first集加入First集
voidAddFollow(charfollow[],charc);将非终结符的所有follow值加入Follow集
B.Follow集合的求解方法:
将$放进Follow(S)集合当中去,其中S是开始符号;
如果存在一个产生式A->aCB,那么FOLLOW(B)中除了$之外的所有符号都在FOOLOW(B)当中了;
如果存在一个产生式A->aB,或者存在产生式A->aCB且FIRST(B)包含空,那么FOLLOW(A)中的所有的符号都在FOLLOW(B)中;
(4)构造分析表
A..根据给出的First集合和Follow集合选择出对应的输入的符号对应的产生式SetSelect;
步骤:
扫描每一个产生式,求出Select集合
如果产生式的右边第一字符为终结符,则将其加入select集
如果产生式的右边字符为ε,则应将左边字符的follow集加入select集
产生式右边的第一个字符为非终结符,则逐个分析:
若α=X1X2…Xnα′,其中Xi∈VN,1≤i≤n;若ε∈FIRST(X1),则将FIRST(X2)中的一切非ε的终结符加进FIRST(α),FIRST(α)则应加入select集;以此类推
处理像E->ABaβ的产生式的情况,若α=X1X2…Xnα′,其中Xi∈VN,1≤i≤n;若对于一切1≤i≤n,ε∈FIRST(Xi),则将follow(α)加入select集合;
相关代码(由于代码太长了,只截取了一部分的代码):
B.构造分析表SetSheet,根据我们已经求出来的FIRST集合和FOLLOW集合,构造出预测分析表:
(4)判断文法是否是LL文法
A.判断的依据是,看每个表项是否最多只有一条候选式,如是该文法是LL
(1)文法。
B.inta[20][20]={0},就是用来记录每一个表项的候选式的数目的;如果a[row][col]>2或者a[row][col]==2,那么这个文法就不是LL文法了;
C.代码实现
(5)LL
(1)文法分析过程
A.输入我所需要分析的字符串voidInputSym();
B.万事具备只欠东风,此时所有的事情已经准备好了,那么就只需要一一的进行分析;voidScan()函数就将字符串的分析过程体现出来了,当然这个分析过程包含了以下几个重要的部分:
存储符号的栈:
包括栈底和栈顶,以及栈的大小
存储剩余符号的队列:
队列里面包含了两个结构,一个是数据,一个是指向下一个数据的指针;
预测分析表:
也就是我们刚刚构造出来的分析表SetSheet;
每一步操作所运用到的产生式PrintSheet(introw,intcol):
C.分析的过程:
将#压入栈中,Push(SymStack,'#');
开始符号入栈,Push(SymStack,UnTerminate[0]);
读入第一个符号:
a=GetSym(Remain);
查看是否和输入符号的第一个符号对应,如果没有的话,就继续在栈中进行左递推;
如果对应了就将此符号出队列,然后再进行左递推;
D.Scan代码实现
由于代码太长,我就只展示了部分代码,具体可看具体文件中的代码;
分析过程中查找一个输入符号串中的一个输入符号,那么就可以直接在对应的预测分析表中查找对应的非终结符号对应的终结符号的产生式,查找到了,就将非终结符号从栈中弹出,将产生式里面右边的部分,放入栈中,再在看是否有输入的符号,如果没有,那么就继续查找;如果找到,就将找到的符号弹出栈中,并且查找下一个输入符号;
D.分析过程的格式
五、实验测试
我的pro.txt文件里面的产生式为:
打印出的产生式与我的产生式是一样的:
得出的分析表:
对i*i+i-i进行预测分析时执行的步骤:
八、实验心得
a)实验问题:
1)程序读不到我的pro.txt文件
刚开始的时候,我写了一个读取txt文件里面的产生式的文件,可以每次我输入文件名以后,程序也不报任何的错误或者信息,也没有显示不能读取,我检查了半天我的程序,最后发现是我最后在txt文件里面末尾少写了一个#。
2)检测是否是LL文法
在检测的时候,我按照如果表项里面有两个候选式子,那么就得出它不是LL文法,然后我在打印表的函数里面添加了一个检测每一个表项右边部分输出了几次,结果检测出来,本来一个LL文法检测出来说不是LL文法,因此我很纳闷。
终于反复检测了几遍,我发现我忽略了一个问题,就是那个我检测的那个函数应该放在for循环以外。
b)实验心得:
由于有了之前几次实验的基础,所以这次在理解题意的时候变得相对的简单一点了,不过这次实验明显比前几次都难,涉及到的步骤程序太多了,因此思绪很容易乱。
不过由于之前我已经把LL的方法透彻的理解过了,所以相对要好一些,过程中遇到了不少的麻烦,所以部分的代码借鉴了网上的。
LL
(1)分析器是自顶向下的一个最重要的分析,所以这是我们这学期该重点掌握的内容,所以做实验的过程也加强了我对这个算法的理解。
而且本次实验内容和第四次实验内容很相似,所以写起来就很容易,大部分就借鉴了前几次的内容,所以完成的时间就比较快了。
九、附录(源代码及注释)
代码附在文件夹里面
HUNANUNIVERSITY
编译原理
实验报告
题目:
LL
(1)分析
学生姓名:
杨玉茹
学生学号:
201508010325
专业班级:
计科1503
上课老师:
杨晓波、陈浩
三、实验目的
学习和掌握FIRST集合、FOLLOW集合的计算,LL
(1)分析表的构造方法。
二、实验任务
(1)存储文法;
(1)计算给定文法所有非终结符的FIRST集合;
(2)计算给定文法所有非终结符的FOLLOW集合;
(3)构造该文法的LL
(1)文法的分析表并按实验九的文法格式存储;
(4)结合实验九,完成完整的LL
(1)分析过程。
三、实验内容
(6)确定文法的文件存储格式,存储文法的非终结符集合、开始符号、终结符集合和产生式规则集合。
要求为3个以上测试文法准备好相应的存储文件。
(7)计算给定文法所有非终结符的FIRST集合。
(8)计算给定文法所有非终结符的FOLLOW集合;
(9)构造该文法的LL
(1)文法的分析表并按实验九的文法格式存储;
(10)结合实验九,完成完整的LL
(1)分析过程。
四、系统设计
(1)实验设计思路分析:
(感觉实验十和实验九的实验内容是差不多的呀,所以我的实验报告和前面几个没有太大区别)
思路:
主函数里面的执行步骤:
(由于我所使用的绘图软件不能导出图片,因此只能通过截屏)
●实验的主线是
求First集合和Follow集合->构造分析表->判断文法是否是LL文法->实现LL
(1)的分析过程
(2)前期准备工作(变量的声明、结构的构造)
A.声明产生式Pronode:
包括三部分,产生式左边、产生式的推导符号、产生式右边
B.每次声明一个产生式以后需要对产生式进行初始化;
C.输入一个含有产生式的文件txt以后,需要对文件进行读取,因此这里使用了ReadPro函数进行读取;读取的方式主要是运用库函数fsanf以输入流的方式进行读取;分三段进行读取,产生式的左边、终结推介符号、右边;
D.打印txt文件里面含有的产生式PrintPro;
E.对产生式里面的终结符号和非终结符号分别用SetUnTerminate和SetTerminate进行存储到UnTerminate和Terminate两个数组当中去;用bool数flag对表里面的内容进行标记,如果已经含有了,就不需要再进行存储了;如果没有标记过,就加入表中去;
(3)求First集合和Follow集合
A..获得产生式的First集合以及Follow集合;
First集合的求解方法:
如果右边的第一个字符是一个终结符号,那么直接加入到First集合当中去;
如果右边的第一个字符是非终结符号,若对于产生式右边的一切非终结符,均可推出ε,则将ε加进FIRST集,
将产生式右边能推出空字符的非终结符的Frist集中不含ε的终结符加入到该非终结符的Fisrt集;
产生式右边不能推出空字符的非终结符的Frist集加入到该非终结符的Fisrt集;
变量说明:
boolIsNull(charc):
非终结符能否产生空字符
boolIsTerminate(charc):
判断是否为终结符号
voidAddChar(charchArray[],charc):
将非终结符的所有first值加入First集
voidAddCharToChar(charchArray[],charotherArray[]):
将非终结符的所有first集加入First集
voidAddCharToChar(charchArray[],charotherArray[]):
将非终结符的所有first集加入First集
voidAddFollow(charfollow[],charc);将非终结符的所有follow值加入Follow集
B.Follow集合的求解方法:
将$放进Follow(S)集合当中去,其中S是开始符号;
如果存在一个产生式A->aCB,那么FOLLOW(B)中除了$之外的所有符号都在FOOLOW(B)当中了;
如果存在一个产生式A->aB,或者存在产生式A->aCB且FIRST(B)包含空,那么FOLLOW(A)中的所有的符号都在FOLLOW(B)中;
(4)构造分析表
A..根据给出的First集合和Follow集合选择出对应的输入的符号对应的产生式SetSelect;
步骤:
扫描每一个产生式,求出Select集合
如果产生式的右边第一字符为终结符,则将其加入select集
如果产生式的右边字符为ε,则应将左边字符的follow集加入select集
产生式右边的第一个字符为非终结符,则逐个分析:
若α=X1X2…Xnα′,其中Xi∈VN,1≤i≤n;若ε∈FIRST(X1),则将FIRST(X2)中的一切非ε的终结符加进FIRST(α),FIRST(α)则应加入select集;以此类推
处理像E->ABaβ的产生式的情况,若α=X1X2…Xnα′,其中Xi∈VN,1≤i≤n;若对于一切1≤i≤n,ε∈FIRST(Xi),则将follow(α)加入select集合;
相关代码(由于代码太长了,只截取了一部分的代码):
B.构造分析表SetSheet,根据我们已经求出来的FIRST集合和FOLLOW集合,构造出预测分析表:
(11)判断文法是否是LL文法
E.判断的依据是,看每个表项是否最多只有一条候选式,如是该文法是LL
(1)文法。
F.inta[20][20]={0},就是用来记录每一个表项的候选式的数目的;如果a[row][col]>2或者a[row][col]==2,那么这个文法就不是LL文法了;
G.代码实现
(12)LL
(1)文法分析过程
A.输入我所需要分析的字符串voidInputS
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语法分析 程序