rhanqtlnuse

4.7 更强大的 LR 语法分析器

4.7.5

对于某个产生式 \(B \rightarrow \gamma\cdot\delta\)

  • 自发生成:如果 \(GOTO(CLOSURE(\{[A \rightarrow \alpha\cdot\beta, a]\}), X)\) 中包含 \([B \rightarrow \gamma\cdot\delta, b]\),其中 \(b \ne a\),则称 lookahead \(b\) 是对于 \(B \rightarrow \gamma\cdot\delta\) 自发生成的
  • 传播:如果 \(GOTO(CLOSURE(\{[A \rightarrow \alpha\cdot\beta, b]\}), X)\) 中包含 \([B \rightarrow \gamma \cdot \delta, b]\),则称 lookahead \(b\) 是由 \(A \rightarrow \alpha\cdot\beta\) 传播到 \(B \rightarrow \gamma\cdot\delta\)

可以看到,\(J\) 中的产生式一定有如下的形式:\(B \rightarrow \gamma\cdot X \delta\)

有了上面关于自发生成和传播的定义,可以很自然地得到确定 lookahead 的算法(详见龙书 4.7.5 算法 4.62)

4.7.6 LR 语法分析表的压缩

  • 压缩动作表

    • 原理:动作表(ACTION)中通常有很多相同的行
    • 第一种做法
      • 为每个状态创建指向一维数组的指针,为每个(符号,动作)对列表创建一个一维数组(同时每个终结符分配一个编号),有相同动作的状态指向相同的(符号,动作)对列表
      • 以图 4-37(英文版 Figure 4.37)中的动作表为例,图示:
      • 类似于 Java 中引用变量和对象的关系:一个引用变量引用一个对象,一个对象可以被多个引用变量所指向(在 Java 中引用变量可以不指向任何对象,即引用变量为 null;同时,一个对象也可以不被任何引用变量所指向。但是在动作表中,状态一定有其对应的动作,动作也一定会有对应的状态集)
    • 第二种做法
      • 在第一种的基础上再次压缩,将一维数组替换为(终结符,动作)的列表(链表),将最频繁的动作放在列表结尾,符号为“any”,同时将 error 条目替换为规约动作
      • 以图 4-37(英文版 Figure 4.37)中的动作表为例,图示:
      • 类似于 switch-case 或路由器配置中的 ACL(Access Control List,访问控制列表)
      • 以状态 0、4、6、7 对应的动作为例,switch-case 类比:
        switch (symbol) {
            case id:
                id 对应的动作;
                break;
            case (:
                ( 对应的动作;
                break;
            default:
                any 对应的动作;
                break;
        }
        
  • 压缩 GOTO 表

    • 与压缩 ACTION 表类似
    • 为每个非终结符 A 构造一个数对的列表,(当前状态,下一状态)表示 GOTO[当前状态, A] = 下一状态
    • 进一步压缩:将每个报错条目替换为该列表中最常用的非报错条目,当前状态设置为“any”

疑问

4.7.5

  • 为什么产生式 \(S\' \rightarrow S\) 一定与 \(\$\) 相关联(attache)?
    • 或者说,为什么 \(\$\) 对于 \(S\' \rightarrow S\) 是自发生成的?

参考

[1] 《编译原理》

分类:

技术点:

相关文章:

  • 2021-07-03
  • 2021-12-28
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-11-08
猜你喜欢
  • 2022-12-23
  • 2021-10-08
  • 2022-12-23
  • 2021-09-30
  • 2021-07-22
  • 2022-12-23
  • 2021-06-05
相关资源
相似解决方案