当前位置

网站首页> 程序设计 > 开源项目 > 程序开发 > 浏览文章

[译] 自顶向下解析和自底向上解析的区别

作者:小梦 来源: 网络 时间: 2024-02-17 阅读:

原文

The difference between top-down parsing and bottom-up parsing
http://qntm.org/top


给定一套形式化文法和这套文法生成的字符串
parsing (解析)就是分析出字符串产生的过程

对于上下文无关文法, 生成过程以 parse tree 的形式出现
我买开始前, 先要知道 parse tree 的两件事:
根节点, 字符衍生出来的初始的符号
叶节点, 字符串按照顺序的所有字符
我们所不知道的是两者之间的节点和分支

比如对于字符串 acddf, 我们已经知道的是

    S   /|\   ???| | | | |a c d d f

这篇文章作为例子的文法:

  • S → xyz | aBC

  • B → c | cd

  • C → eg | df

自底向上解析

这个方案和拼图没有本质差别
我们从 parse tree 的底部开始, 从单个的字符开始
随后是有规则将字符尽自己所能拼接成更大的 token
字符串最终的结果, 一切都应该被结合到一个单个巨大的 S
而且 S 应该是我们剩下的唯一的内容
如果不是, 那么就需要回溯尝试用别的办法尝试合并出 token

在自底向上解析中,一般会维护一个 stack
也就是已经读取的所有的字符和 token
每一个步骤, 一个新的字符会被插图到 stack 顶部
然后尽可能地结合字符并归纳为更大的 token

例子

字符串是 acddf

步骤
  • ε 无法归纳

  • a 无法归纳

  • ac 可以被归纳, 如下:

  • 归纳 acaB

    • aB 无法归纳

    • aBd 无法归纳

    • aBdd 无法归纳

    • aBddf 可以被归纳, 如下:

    • 归纳 aBddfaBdC

      • aBdC 无法归纳

      • 字符串完. Stack 为 aBdC, 非 S. 失败! 需要回溯.

    • aBddf 无法归纳

  • ac 无法归纳

  • acd 可以被归纳, 如下:

  • 归纳 acdaB

    • aB 无法归纳

    • aBd 无法归纳

    • aBdf 可以被归纳, 如下:

    • 归纳 aBdfaBC

      • aBC 可以被归纳, 如下:

      • 归纳 aBCS

        • 字符串完. Stack 为 S. 成功!

Parse trees
|a| |a c  B| |a c  B| | |a c d  B| | | |a c d d  B| | | | |a c d d f  B   C| | | |\a c d d f| |a c| | |a c d    B|  /|a c d    B|  /| |a c d d    B|  /| | |a c d d f    B C|  /| |\a c d d f    S   /|\  / | | /  B C|  /| |\a c d d f

例子 2

如果所有符合都失败, 那么字符串无法被解析

字符串为 acdg

步骤
  • ε 无法归纳

  • a 无法归纳

  • ac 可以被归纳, 如下:

  • 归纳 acaB

    • aB 无法归纳

    • aBd 无法归纳

    • aBdg 无法归纳

    • 字符串完. Stack 为 aBdg, 非 S. 失败! 需要回溯.

  • ac 无法归纳

  • acd 可以被归纳, 如下:

  • 归纳 acdaB

    • aB 无法归纳

    • aBg 无法归纳

    • 字符串完. Stack 为 aBg, 非 S. 失败! 需要回溯.

  • acd 无法归纳

  • acdg 无法归纳

  • 字符串完. Stack 为 acdg, 非 S. 没有可用的回溯. 失败!

Parse trees
|a| |a c  B| |a c  B| | |a c d  B| | | |a c d g| |a c| | |a c d    B|  /|a c d    B|  /| |a c d g| | |a c d| | | |a c d g

自顶向下解析

这套方案中设想字符串匹配 S 并查看这个假设的内部逻辑提示
比如当字符串匹配 S 逻辑上按时或者
(1) 字符串匹配 xyz 或 (2) 字符串匹配 aBC
当知道 (1) 不对, 那么 (2) 必须是对的, 而 (2) 内部有更深的逻辑提示
这些必须逐个检查以验证基本的假设

例子

字符串是 acddf

步骤
  • 断言 1: acddf 匹配 S

    • 断言 2: acddf 匹配 xyz:

    • 断言 为否. 尝试其他.

    • 断言 2: acddf 匹配 aBC, 即 cddf 匹配 BC:

      • 断言 3: cddf 匹配 cC, 即 ddf 匹配 C:

        • 断言 4: ddf 匹配 eg:

        • 否.

        • 断言 4: ddf 匹配 df:

        • 否.

      • 断言 3 为否. 尝试其他.

      • 断言 3: cddf 匹配 cdC, 即 df 匹配 C:

        • 断言 4: df 匹配 eg:

        • 否.

        • 断言 4: df 匹配 df:

        • 断言 4 为真.

      • 断言 3 为真.

    • 断言 2 为真.

  • 断言 1 为真. 成功!

Parse trees
    S    |    S   /|\  a B C    | |    S   /|\  a B C    | |    c    S   /|\  a B C   /| |  c d    S   /|\  a B C   /| |\  c d d f

例子 2

如果, 试验了所有逻辑线索, 依然无法验证基本假设("字符串匹配 S")
那么字符串无法被解析

字符串为 acdg

步骤
  • 断言 1: acdg 匹配 S:

    • 断言 2: acdg 匹配 xyz:

    • 否.

    • 断言 2: acdg 匹配 aBC, 即 cdg 匹配 BC:

      • 断言 3: cdg 匹配 cC, 即 dg 匹配 C:

        • 断言 4: dg 匹配 eg:

        • 否.

        • 断言 4: dg 匹配 df:

        • 否.

      • 否.

      • 断言 3: cdg 匹配 cdC, 即 g 匹配 C:

        • 断言 4: g 匹配 eg:

        • 否.

        • 断言 4: g 匹配 df:

        • 否.

      • 否.

    • 否.

  • 断言 1 为否. 失败!

Parse trees
    S    |    S   /|\  a B C    | |    S   /|\  a B C    | |    c    S   /|\  a B C   /| |  c d

为什么做递归是自顶向下解析器的一个问题

如果规则是做递归, 比如这样的内容

  • S → Sb

可以注意到算法的行为是:

步骤

  • 断言 1: acddf 匹配 S:

    • 断言 2: acddf 匹配 Sb:

      • 断言 3: acddf 匹配 Sbb:

        • 断言 4: acddf 匹配 Sbbb:

          • ...无穷无尽

Parse trees

  S  |  S  |\  S b  |  S  |\  S b  |\  S b  |  S  |\  S b  |\  S b  |\  S b  |...

热点阅读

网友最爱