【编译原理】自下而上语法分析-LR分析方法总结

总览

LR分析方法的关键是识别出句柄(最左直接短语),根据不同的寻找句柄的方法,就得到了不同的规范归约方法。下面四种依次递进,前者为后者基础。
这四种方法的区别就在于产生式归约(上面说的识别句柄)的条件
首先是最简单的LR(0)文法,只要项目集中出现了归约项目,那么对后面所有字符都采取归约操作,所以可以看到LR(0)分析表某些状态整行都是一样的rx.(r for reduce, 归约)
在这里插入图片描述
如果所有项目集中,都不存在 移进-归约冲突 和 归约-归约冲突,那么就说这个文法是LR(0)的。


如果存在这两种冲突,就使用SLR方法,对所有的归约项目来说,只有遇到该项目的FOLLOW集中的元素时才进行归约。如,对于一个项目集
I = { X -> α·bβ, A -> α·, B -> α· }
第一个是移进项目,第二三是归约项目,存在归-归冲突,如果下一输入符号是b,还存在移-归冲突。SLR的解决方法是,考察归约项左部符号的FOLLOW集, 只有当下一输入符号是对应项目的FOLLOW集中元素时,才决定进行归约。这时,为了避免移-归冲突和归-归冲突,需要保证不同归约项的FOLLOW集和移进项目等待的符号(·后面的终结符)交集为空。就上面说的那个项目集而言,b可以认为是移进项目X -> α·bβ移进信号, FOLLOW(A) FOLLOW(B)分别是归约项目A -> α·, B -> α·归约信号。可以看到,归约项目不再是整行都是归约,而是某几个符号(对应FOLLOW集)才是归约操作,如:
在这里插入图片描述
在同一行内,归约信号对应归约操作,移进信号对应移进操作,如:
在这里插入图片描述
如果给定文法的SLR分析表中不存在有冲突的动作(移进信号和归约信号交集为空),那么该文法称为SLR文法。

如P113的例子,SLR方法同样有问题,即移进信号和归约信号的交集不为空的情况。SLR方法将归约项目的FOLLOW集合作为归约信号,实际上扩大了范围。归约信号必然在FOLLOW集合中,但是FOLLOW集中元素不全是归约信号。此时用到了下面的LR(1)方法。


首先需要知道,LR(1)项的定义,求LR(1)项的等价项。余下的过程同上。由于LR(1)项目很多,所以进一步使用LALR方法对某些状态进行合并。具体内容在后面。


LR(0)分析法

最为简单,是后面几个的基础。
首先明确,分析法的

  • 目标:构造分析表(包括后几种分析法)
  • 已有信息:给定的文法(如P105文法5.8)
  • 所用算法:将文法转为项目;构造项目的闭包;构造拓广文法的LR(0)项目集规范族(参考构造算法P107);根据规范族生成分析表
    这里介绍构造闭包、构造项目集规范族的算法

构造项目集规范组

  1. 根据文法,写出该文法的所有项目(参考P104-P105)
  2. 将等价的项目放到一起,作为一个项目集规范组(参考P105)。如 S -> a·A,意思是我已经得到了符号串a, 下面我期待的是A。根据文法中A的产生式,期待A也就等价于期待A所能得到的产生式。假定有产生式 A -> γ, 那么 S -> a·A等价的项目就包括 A -> ·γ。当然,如果γ开始符号还是非终结符号,还要继续上述过程。总之就是,如果·后面是非终结符,就要把这个非终结符的所有产生式前面加上·添加到这个项目集中。重复这个过程,直到项目集不再增大。(参考P107)

构造项目集规范族

P107下面构造算法。
在这里插入图片描述

规范族生成分析表

前面已经得到的项目集规范族。给每个项目集编号,将箭头表示的关系转化为表格即可。
例如:
在这里插入图片描述
项目集已经编号,箭头上带有符号,表示前后的转换过程。
ACTION表对应的都是终结符;GOTO都是非终结符。
ACTION表中,s for shift, 转换;r for reduce, 归约
在这里插入图片描述
GOTO表中数字意思是状态,和状态列数字一致;
ACTION表中s后面的数字表示状态;r后面的数字是下面产生式的编号,表示用这个编号对应的产生式进行归约。
在这里插入图片描述

SLR分析法

LR(1)分析法

在这里插入图片描述
在这里插入图片描述
按照同样的过程,构造LR(1)项目集,构造DFA,构造分析表。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注意上面LR(1)项目集闭包算法中红字部分,for (FIRST(βa)中的每个符号)β是非终结符
B后面的那一项,可以为空
在这里插入图片描述
在这里插入图片描述
试着将P115的例5.13做一下,得到项目集规范组和分析表。注意,在求项目的等价项目时要小心。
在这里插入图片描述

LALR分析法

观察LR(1)分析法得到的项目集状态族可以看到,I8 I9, I4 I7, I3 I6除了展望符,前面的产生式是一样的。把这样的状态集称为同心状态集。由于LR(1)方法得到的状态太多,LALR方法尝试对同心状态集进行合并。
合并同心项目集可能会带来两个问题:
1.产生归约-归约冲突
在这里插入图片描述
这里状态I6 I9是同心项目集。当下一个符号是d时,对I6来说,将栈顶的c归约为A;对I9来说,将栈顶的c归约为B。下一个符号是e时同理。这样就产生了归约-归约冲突。不过,合并同心状态集不会产生移进-归约冲突。 因为合并的是展望符,而展望符只在归约时起作用,在移进时不起作用。

2.推迟错误的发现
会推迟错误的发现,但最终还是会发现错误。
LALR分析法可能会作多余的归约动作,但绝不会作错误的移进操作。

LALR方法的特点:

  • 形式上与LR(1)相同
  • 大小上与LR(0)/SLR相当
  • 分析能力介于SLR和LR(1)二者之间
    SLR < LALR(1) < LR(1)
    因为推迟了某些错误的发现,因此弱于LR(1);同时LALR对归约信号的划分比SLR更细致,因此又强于SLR。
  • 合并后的展望符集合仍为FOLLOW集的子集
  • 30
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
由于你没有提供文法,我这里以一个简单的算术表达式文法为例: ``` E -> E + T E -> E - T E -> T T -> T * F T -> T / F T -> F F -> ( E ) F -> num ``` LR分析需要先构建LR(1)自动机,然后进行分析。下面是该文法的LR(1)自动机(省略了一些状态和转换): ``` state 0: E -> . E + T E -> . E - T E -> . T T -> . T * F T -> . T / F T -> . F F -> . ( E ) F -> . num ... state 1: E -> E . + T E -> E . - T ... state 2: E -> T . ... state 3: T -> T . * F T -> T . / F ... state 4: T -> F . ... state 5: F -> ( . E ) ... state 6: F -> num . ... ``` 接下来,我们可以通过栈的方式对输入的字符串进行语法分析。具体步骤如下: 1. 将起始状态(0)和结束符号$入栈。 2. 读入输入字符串的第一个符号,并将其入栈。 3. 从状态栈顶取出状态,从符号栈顶取出符号。 4. 如果符号是终结符号,则比较该符号和输入字符串当前位置的符号是否相同。如果相同,则将输入字符串的下一个符号入栈,否则出错并结束分析。 5. 如果符号是非终结符,则查找该符号和输入字符串当前位置的符号对应的转移状态,并将该状态入栈。 6. 如果栈顶符号是$,并且输入字符串已经全部读入,则分析成功,结束分析。 7. 如果栈为空,但输入字符串还没有全部读入,则分析失败,结束分析。 8. 重复步骤3-7,直到分析成功或失败。 通过以上步骤,我们可以完成对该文法的语法分析

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值