编译原理学习笔记5(语义分析)

4 语义分析

4.1 语义分析介绍
  • 通常是以自下而上语法分析为基础。语义分析把分析树中的每个结点都看作一个对象,并规定它们的属性,设置方法需要根据要完成的语义任务而定,如表达式求值时,属性就是结点的值。
  • 想直接翻译整棵树是不可能做到的,但是我们可以发现树中的二层子树都对应着一个产生式,而产生式的个数是有限的,所以可以从这上面找思路。
  • 语法制导翻译的基本思想是:对每个产生式规定一种语义动作,并在归约/推导时触发,从而完成相应的语义分析。两个关键点是:1)语义分析的时机;2)语义分析的动作。
  • 以表达式求值为例:在归约时,可以拿到一个算符结点和两个操作数结点,可以根据不同的算符来设置对操作数结点中值的计算,并生成新的结点作为父结点,令算符和操作数作为其孩子结点,设置属性为根据算符计算后的值,即可完成一次归约并求值,重复自底向上归约的过程,最终在根节点的属性就能得到整个表达式的结果。
4.2 中间代码
  • 中间代码需要便于语义制导翻译,并且与机器指令的结构相近,便于目标代码生成。因此,中间代码的主要形式有树,后缀式,三地址码等。
  • 1)这种形式,实质上就是语法树,一个典型的例子就是数据库语言中的查询树;2)后缀式,又称逆波兰表示,是为了方便表达式求值的,典型特征是操作数在前,操作符紧跟在后。常见的考题是由中缀表达式(对应树的中序遍历)生成后缀表达式(对应树的后序遍历)。3)三地址码,是指由不超过三个地址组成的一个运算,形式上与赋值语句很类似。可以有多种表现形式,如三元式,四元式。其中,三元式的表示为(op, arg1, arg2),如x=a+b*c,可以用三元式表示成:(*, b, c), (+, a, (1)), (=, x, (2)),最大的缺点是一旦在三元式表中确认了位置(如上述的(1),(2)这种形式),就无法再改变,这给优化工作带来了困难。四元式在三元式基础上,增加了一个结果项,表示为(op, arg1, arg2, result),result就类似于临时变量。同样地,x=a+b*c可以表示为(*, b, c, T1), (+, a, T1, T2), (=, x, T2, T3),就解决了三元式的问题。
4.3 符号表
  • 符号表是连接声明和引用的桥梁,一个名字在声明时,相关信息被写入符号表,在引用时,再根据信息执行相应的操作。符号表的一个条目包含名字和属性,本质上就是语法树的点集。

知识补充

之前消除文法的二义性时,应该如何改写文法,从而规定文法的优先级和结合性?
首先举例:对于运算法则,优先级 加法<乘法<括号,那么文法就可以规定成如下所示:

  • A -> A + B | B
  • B -> B * C | C
  • C -> (A) | num
    这样就确定了乘法与加法的优先级和结合性,下面讲讲如何理解。

原理:观察文法发现,其实就是分级,通过新增加一个非终结符,来让高优先级的算符在整个递归链中下移一级,即越接近开始符号的优先级越低。这种下移,体现在树中也是下移一层,这就限制了在建树时,会先建立出较低优先级的式子,从而避免了一个句子出现多棵分析树的情况,也就消除了二义性。然后归约时,由于是自底向上,所以就会先计算靠下的式子,也就保证了优先级。对于结合性,加法和乘法都具有左结合性,即从左到右计算,A -> A + B中A在+的左边,则规定了+具有左结合性,若改成A -> B + A,则+具有右结合性。归约时考虑的是最左句柄,即左边会先被归约,就变相规定了左边优先级较高。
总结:优先级相同时,靠左先被归约;优先级不同时,靠下先被归约。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值