语义分析器
- 内容
学习经典的语义分析器
(1)选择一个编译器,如:TINY或PL/0,其它编译器也可(需自备源代码)。
(2)阅读语义分析源程序,加上你自己的理解。尤其要求对相关函数与重要变量的作用与功能进行稍微详细的描述。若能加上学习心得则更好。TINY语言请参考《编译原理及实践》第6.5节;PL/0语言请参考相关实现文档。
(3)理解符号表的定义(栏目设置)与基于抽象语法树的类型检查/推论的实现方法(树遍历)。
(4)测试语义分析器。对TINY语言要求输出测试程序的符号表与测试结果。对PL/0语言要求给出测试程序的各种符号表的内容。
TINY语言:
测试用例一:sample.tny。
测试用例二:用TINY语言自编一个程序计算任意两个正整数的最大公约数与最大公倍数。
PL/0语言:
测试用例一~三:test.pls,test2.pls,a1.pls。
实现一门语言的语义分析器
(1)语言确定:C-语言,其定义在《编译原理及实践》附录A中。也可选择其它语言,不过要有该语言的详细定义(可仿照C-语言)。一旦选定,不能更改,因为要在以后继续实现编译器的其它部分。鼓励自己定义一门语言。
(2)完成C-语言的符号表的定义设计。规划类型检查/推论的实现方法。
(3)仿照前面学习的语义分析器,编写选定语言的语义分析器。
(4)准备2~3个测试用例,测试并解释程序的运行结果。
- 实验目的
- 学习已有编译器的经典语义分析源程序。
- 通过本次实验,加深对语义分析的理解,学会编制语义分析器。
- 实验任务
- 阅读已有编译器的经典语义分析源程序,并测试语义分析器的输出。
- 用C或JAVA语言编写一门语言的语义分析器。
- 学习TINY的语义分析器
首先看main函数中,语义分析的入口,我们可以看到,一共有两个主要的函数
buildSymtab(syntaxTree); typeCheck(syntaxTree);
然后我们先看第一个
buildSymtab(syntaxTree);
traverse函数是一种通用的递归语法树遍历例程:它将preProc按顺序应用于postorder中的preProc,将postProc应用于t所指向的树
首先是这个函数:
主要的是st_insert函数:
我们来仔细分析一下:
首先是一个哈希函数,让我们看一下这个哈希函数:
传进来的参数是节点的名字字符串,设置一个temp向左移4位,然后从0开始取每个字符,然后除以211取余,赋值给temp,重复直到字符串中所有的字符都处理过。这样就可以将字符串映射到哈希表上了。
这是哈希表的结构体:
总结起来就是:
st_insert这个函数将ID字符串按照哈希映射映射到哈希表中,如果表中已有该字符出阿奴,则将该ID的行号存到哈希表中该字符的行号链表的末尾;如果表中还没有该ID的字符串,则映射到哈希表中,如果映射到的位置已经被占了,就向后移一位。
还有一个比较重要的函数就是st_lookup函数: