关于算法:在令牌流中解析上下文无关语言

Parsing context-free languages in a stream of tokens

问题

给定具有任意规则和标记流的上下文无关文法,如何有效识别匹配文法的流片段?

例子:

语法

1
2
3
S -> ASB | AB
A -> a
B -> b

(所以本质上,多个 as 后跟相同数量的 bs)

溪流:

1
aabaaabbc...

预期结果:

  • 从位置 1 开始匹配:ab
  • 从位置 4 开始匹配:aabb
  • 当然,关键是"有效地"。没有测试太多绝望的候选人太久。我对我的数据唯一了解的是,尽管语法是任意的,但实际上匹配序列会相对较短(<20 个终端),而流本身会很长(>10000 个终端)。

    理想情况下,我还想要一个语法树,但这并不是很重要,因为一旦识别出片段,我就可以在它上面运行一个普通的解析器来获取树。

    我应该从哪里开始?哪种类型的解析器可以适应这种类型的工作?


    "任意语法"让我建议你看看 wberry 的评论。

    这些语法有多复杂?是否有人工干预步骤?

    我会尝试的。如果我修改了您的示例语法:

    1
    2
    3
    S -> ASB | AB
    A -> a
    B -> b

    包括:

    1
    2
    S' -> S | GS' | S'GS' | S'G
    G -> sigma*

    所以 G = 垃圾和 S' 是许多 S 片段之间有垃圾(我可能对我的生产规则粗心。你明白了),我认为我们可以解决你的问题。您只需要一个在 G 之前匹配其他规则的解析器。您可能需要根据解析器修改这些生产规则。我几乎保证会根据解析器进行规则排序更改。由于大多数解析器库将词法分析与解析分开,因此您可能需要一个包罗万象的词位,然后修改 G 以包含所有可能的词位。根据您的具体情况,这可能不会比仅在流中的每个位置开始每次尝试更好(效率方面)。

    但是...假设我的生产规则是固定的(为了正确性和解析器的特殊风格),这不仅应该匹配流中的片段,而且应该为您提供整个流的解析树。您只对以 S 类型的节点为根的子树感兴趣。