日记大全

日记大全 > 句子大全

编译器入门(语义分析)

句子大全 2012-08-26 22:54:45
相关推荐

语义分析,是语法分析与中间代码生成之间的过渡步骤,是基于抽象语法树AST的进一步分析,主要是3个方面:

1,类型检查和自动类型转换,

对抽象语法树的每一个节点的输入进行类型检查。

在类型不一致时添加自动类型转换(type cast),必要时给出warnning信息。

无法自动类型转换的,给出error信息。

确定该节点的输出结果类型,用于父节点的类型分析,依次递归。

2,常量表达式的计算,

常量表达式的结果在这里提前算出来,用一个常数代替,减少后续环节的运算量,提高生成的目标代码的效率。

例如,int sec = 60 * 60,

替换为,int sec = 3600,

这样在生成机器码的时候就不需要使用乘法指令,直接一个mov指令把常数3600

赋值给sec就行了。

3,运算符重载和函数重载,

已经完成了类型检查的情况下,在这里是可以确定具体选择哪一个重载函数的,把它转换为对重载函数的调用。

例如有个Mat矩阵类,该类有几个加法运算的重载函数,那么在这里就可以确定输入参数是不是含有矩阵,是2个矩阵相加还是矩阵加上一个常数,etc.

把这个加法运算符,转化为对Mat类的对应函数的调用。

虚函数调用是没法在这里确定的,因为基类指针的具体子类类型是动态的,只能运行时查询它的虚函数表获得实际调用的函数。

语义分析,是递归遍历AST树,并对它的节点进行分析。

从语义分析开始,后续的所有分析都是以AST树的节点为基础的,不同的阶段使用的分析函数不同而已。

所以,我们可以这么设计AST节点的数据结构:

struct ast_node_s

{

int type; 节点类型

struct ast_node_s* parent; 父节点

struct ast_node_s** childs; 子节点列表

int nb_childs; 子节点个数

uint32_t flags;

各种标示,例如常量、常量字面值等等

} ;

父节点和子节点列表,是构成整个AST树的基础。

运算符的优先级,也是体现在生成语法树时,谁是子节点,谁是父节点,子节点的优先级更高。

节点类型,就是节点的语义,标示着该用哪个函数去处理当前节点。

在语义分析阶段,和三地址码生成阶段,选择的处理函数是不同的。

当然,不同类型的节点,选择的处理函数也是不同。

我们可以根据当前的分析阶段和节点类型,去相应的函数表里查询对应的函数,并调用它。

过了语法分析之后,终于不再有那种互相交织着的递归调用了,不那么拧巴了:(

以后都是对语法树的遍历,或者三地址序列的遍历。

阅读剩余内容
网友评论
相关内容
拓展阅读
最近更新