语义分析
:material-circle-edit-outline: 约 700 个字 :material-clock-time-two-outline: 预计阅读时间 2 分钟
[!NOTE]
- 左值表达式不支持数组
- 所有函数都是全局的,都在最外层的符号表
- 实验实现的函数式风格符号表和课本上的不一样,实验里进入新的作用域创建了空的符号表,而课本里是要包括之前表里的符号,如此只需要在同一张表里查找
- clandg可以看数组怎么填充
符号表
在符号表中:
- 对于一个变量,我们需要记录下它的名字、类型、维度(如果是数组的话)等信息。
- 对于函数,我们也需要在符号表中记录,方便在调用函数时查询符号,以及检查参数列表是否一致、返回值是否一致等。我们需要在符号表中记录下函数的名字、参数列表(包含多个变量符号)和返回值类型。
- 在 SysY 中,所有函数都是全局的,并且不能重载。
符号表的实现有两种风格:函数式风格和命令式风格。这里我们对两种风格进行一个简要的介绍。
函数式风格的方法在每次进入新的作用域时都需要申请一个新的符号表,而当离开该作用域时,就可以将该符号表销毁,相当于维护了一个符号表的 栈。
命令式风格的方法则不需要申请多个符号表,自始至终在单个符号表上进行动态维护。其中每一项对应的不是一个变量的定义,而是变量定义的 栈。每次进入新的作用域时,将一个新的符号表压入栈中,离开作用域时弹出。
那么我们怎么知道哪些元素是在该语句块下定义的呢?你可以在每次进入一个块时,将一个特殊的标记符压入栈中,而当你离开该块时,你只需要将栈顶的元素弹出直到遇到这个特殊的元素即可。
类型检查
所谓类型,就是一组值构成的集合,对于这组集合我们可以进行其专属的操作,例如整型的加减乘除,数组的访问等。当我们在某组值上尝试去执行其不支持的操作时,类型错误就产生了。而类型检查,就是检查我们对这些类型的操作有没有错误。
与打印语法树和符号表的建立一样,类型检查也是遍历语法树的过程。
对于有类型的语法树节点(如Exp节点),我们可以自然地将该节点的类型作为返回值,继续给父节点使用。