编译原理-语法分析(自底向上)

文章目录

  • 核心问题
  • 概念
    • 句柄
    • LR(k) 与LR文法
    • 自底向上分析概述
    • LR(0) 项目自动机
      • LR(0) 项
      • 增广
      • 构造自动机--项集,项集闭包,项集投影
      • 内核项 与 非内核项
      • 构造自动机--GOTO函数
      • 移入规约冲突
    • SLR
    • LR(1)
    • LALR(1)
    • LALR分析器与LR分析器
  • 子问题
    • 构造自动机--完整算法,实例
    • 计算展望符集
    • LR(1)项目自动机的构造
    • LALR(1)项目自动机的构造
    • 消除LR文法二义性
    • 语法错误的处理

自顶向下解决该使用哪条产生式进行推导的问题
自底向上解决什么时候该移入,什么时候该规约的问题

核心问题

  • 什么时候移入,什么时候规约

通过action表执行相应的移入规约动作

  • 如何解决移入规约冲突

通过向前看一个字符,这个字符可以是非终结符的follow集,也可以是产生式的展望集

  • LR(0),SLR(1),LR(1),LALR(1)的关系

见 概念->LALR分析器与LR分析器

概念

句柄

“句柄”: “正确的待规约对象”,即它能保证被归约后一定还保持着最右句型

  • 短语,简单短语

编译原理-语法分析(自底向上)_第1张图片

  1. 一个短语,满足:被规约后,整个句子仍然保持最右句型。2.一个句型简单短语可能有多个,称最左简单短语为句柄
  • rm: 最右推导
  • 规范句型(最右句型):通过最右推导或最左规约得到的句型
  • 规范前缀:一个规范句型的前缀,且前缀后面不包括非终结符,如:
    编译原理-语法分析(自底向上)_第2张图片
  • 规范活前缀
    就是在栈中可能出现的前缀。
    满足:
    在这里插入图片描述
    如:
    编译原理-语法分析(自底向上)_第3张图片
    活前缀又分两种类型:归态活前缀、非归态(移入)活前缀

LR(k) 与LR文法

LR(k)

  • L 表示最左扫描,R表示反向构造出最右推导,k 表示最多向前看 k 个符号

LR文法:

  • 某一CFG能够构造一张分析表,使得表中每一元素至多只有一种 明确动作,则称改文法为LR文法
  • 并非所有CFG都是LR文法,但对于多数程序设计语言,一般 都可以用LR文法描述;和LL(1)相比,LR分析适应的文法范围要 广一些

不同的LR方法对CFG的要求不一样, 能够分析的CFG多少也不一 样, L R ( 0 ) ⊆ S L R ( 1 ) ⊆ L A L R ( 1 ) ⊆ L R ( 1 ) LR(0) \subseteq SLR(1) \subseteq LALR(1) \subseteq LR(1) LR(0)SLR(1)LALR(1)LR(1)

LR(0)文法

已知LR0 是CFG G的LR(0)自动机 。如果LR0的任意一个状态都不存在冲突(归约-归约冲突、移入-归约 冲突), 则G称为LR(0)文法;

自底向上分析概述

编译原理-语法分析(自底向上)_第4张图片
例:
编译原理-语法分析(自底向上)_第5张图片

LR(0) 项目自动机

LR(0) 项

编译原理-语法分析(自底向上)_第6张图片
编译原理-语法分析(自底向上)_第7张图片
编译原理-语法分析(自底向上)_第8张图片

增广

在这里插入图片描述
当规约到S‘ 时结束

构造自动机–项集,项集闭包,项集投影

编译原理-语法分析(自底向上)_第9张图片
编译原理-语法分析(自底向上)_第10张图片
编译原理-语法分析(自底向上)_第11张图片
编译原理-语法分析(自底向上)_第12张图片

内核项 与 非内核项

编译原理-语法分析(自底向上)_第13张图片

构造自动机–GOTO函数

编译原理-语法分析(自底向上)_第14张图片

移入规约冲突

编译原理-语法分析(自底向上)_第15张图片
编译原理-语法分析(自底向上)_第16张图片

SLR

向前看一个输入符号来选择分析动作

对于可规约项目 B ⟶ β ⋅ B\longrightarrow \beta\cdot Bβ 如果 a ∉ f o l l o w ( B ) a\notin follow(B) a/follow(B), 那么当读头是a时,不应该规约此项目。由此可解决一些 S-R 和 RR 冲突

如果能将LR(0)自动机中的所有冲突消除掉,则该文法称为SLR(1) 文法 , 否则称为非SLR(1)文法。

LR(1)

SLR中在向前看的时候,只考虑了非终结符的follow,而没有根据具体的产生式分析。
LR(1)做出了如下改进

  • 给每个LR(0)项目添加展望信息,即添加句柄之后可能跟的终结符, 因为这些终结符确实是规范句型中跟在句柄之后的
  • 不要看Follow集,而是要看展望符(First集)
    编译原理-语法分析(自底向上)_第17张图片
    且投影操作对展望符集没有影响。

如果对于任意一个状态s和任意的一个终极符a, A1(s,a)只有一个唯 一的动作, 则文法G称为LR(1) 文法

LALR(1)

LR(1)为消除冲突,引入太多的状态; 有些状态含有完全相同的LR(0)项目部分,只有展望符部分是不同 的;

  • LR(1)项目的心:如果( A ⟶ α ⋅ β A\longrightarrow \alpha \cdot \beta Aαβ, ss) 是一个LR(1)项目,则其中的 LR(0)项目部分称为它的心;
  • LR(1)自动机状态的心:一个状态所含有的所有LR(1)项目的心;
  • 同心状态:如果两个LR(1)状态具有相同的心,则称这两个状态为 同心状态

合并文法G的LR(1)自动机中的同心状态,得到的自动机称为 LALR(1)自动机
若这个得到的LALR(1)自动机没有冲突,则称文法G是LALR(1)文 法

构造LALR(1)自动机两种思路:

  • 先构造LR(1), 再合并(不现实)
  • 能用LR(0)自动机构造LALR(1)自动机

LALR(1)与LR(1),LR(0)

  • G的LALR(1)项目跟LR(1)项目形式相同;
  • LALR(1)自动机中每个状态S中各个项目的展望符集是把LR(1)自 动机中所有和S同心的状态的对应项目的展望符集合合并后得到的;
  • 如果每个LALR(1)的状态都用该状态的心(LR(0)项目)替换,则 LALR(1)自动机和它的LR(0)自动机相同;
  • G的LALR(1) 自动机的状态数同LR(0)自动机的状态数相同;

LALR分析器与LR分析器

分析能力

  • 如果是正确的输入串
    • LALR和LR分析器执行完全相同的移入和归约动作序列,只是栈中的状态名字 有所不同
  • 如果是错误的输入串
    • 则LALR分析器可能会比LR分析器晚一点报错,定位一样,能力一样
    • LALR分析器不会在LR分析器报错后再移入任何符号,但是可能会继续执行一 些归约

状态数:

  • 对LR(1)项集规范族中所谓的同心项集进行合并,从而使得分析表既保持了 LR(1)项中向前看符号的信息,又使状态数减少到与SLR分析表的一样多
  • LR(1) > LALR(1) = SLR(1) = LR(0)

展望符的确定:

  • LR(0)没有展望符;
  • SLR(1)取follow集;
  • LR(1)取不同位置的follow集
  • LALR(1)取同心项的展望符的并集;

分析能力: LR(1)  LALR(1)  SLR(1)  LR(0)

编译原理-语法分析(自底向上)_第18张图片

子问题

构造自动机–完整算法,实例

编译原理-语法分析(自底向上)_第19张图片
编译原理-语法分析(自底向上)_第20张图片
编译原理-语法分析(自底向上)_第21张图片

  • 注意goto表和action表的区别:在使用自动机的时候,实际只用到了action表,goto表在分析action表的规约动作的时候会用到。

编译原理-语法分析(自底向上)_第22张图片

计算展望符集

编译原理-语法分析(自底向上)_第23张图片

LR(1)项目自动机的构造

LALR(1)项目自动机的构造

通过LR(0)构造

  • step1:构造LR(0)
  • step2:计算展望符集
    编译原理-语法分析(自底向上)_第24张图片

消除LR文法二义性

二义性文法都不是LR的

  • 之前消除通过改造文法消除二义性,还可以通过改造LR分析表来消除二义性

例:
E ⟶ E + E ∣ E ∗ E ∣ ( E ) ∣ i d E\longrightarrow E+E|E*E|(E)|id EE+EEE(E)id
编译原理-语法分析(自底向上)_第25张图片
设定优先级如下:*的优先级大于+,且+是左结合的,则有

  • 下一个符号为+时,我们应该将E+E归约为E
  • 下一个符号为*时,我们应该移入*,期待移入下一个符号
    编译原理-语法分析(自底向上)_第26张图片

语法错误的处理

编译原理-语法分析(自底向上)_第27张图片

你可能感兴趣的:(编译原理)