【问题标题】:How does backtracking work in peg.js (with example)?回溯如何在 peg.js 中工作(示例)?
【发布时间】:2014-09-06 13:11:04
【问题描述】:

我已经定义了以下最小的 Peg.js 语法:

start  =  "A1" / "A123"

你可以试试in the sandbox

我本来希望匹配“A1”和“A123”(根据我对回溯如何工作的概念)。但事实并非如此:语法识别“A1”但不识别“A123”。

注意:我不是在寻找相关问题How to transform a simple grammar into something which works in PEG.js (expected "a" but "a" found) 中的“颠倒您的术语顺序”的建议。相反,我希望了解我所看到的行为,以及为什么 Peg.js 的回溯不适用于这种情况。有关为什么颠倒我的术语顺序没有帮助的解释,请参阅下面更现实的示例。


举一个更现实的例子,考虑单位解析。语法应该识别带有可选前缀的公制单位(如“m”、“mol”),如“mm”、“mmol”,以及非公制单位,如“yr”、“week”或“mo”。

以下 Peg.js 语法无法识别“mol”,因为它在使用“mo”时会出错,并且不会回溯。 (更改术语的顺序无济于事;或者更确切地说,会导致以牺牲“mol”或“mmol”为代价来识别“mo”。)

start  =  nonmetric / metric / prefix metric
metric = "mol" / "l" / "m" / "g"
nonmetric = "yr" / "mo" / "week" / "day" / "hour"
prefix = "m" / "k" / "c"

我可以在 Antlr 中成功地做类似的事情:

grammar units;
start  :  nonmetric | metric | prefix metric;
metric : 'mol' | 'l' | 'm' | 'g';
nonmetric : 'yr' | 'mo' | 'week' | 'day' | 'hour';
prefix : 'm' | 'k' | 'c';

【问题讨论】:

  • 感谢您在尝试学习来自 Antlr 的 Peg.js 时为这个问题提供了很好的示例。它真的帮助我理解了我的语法到底出了什么问题。

标签: node.js grammar peg pegjs


【解决方案1】:

问题在于回溯的概念。 PEG 解析器不会像其他递归下降解析器或 Prolog 那样回溯。相反,当面临选择时,PEG 解析器将尝试所有选项,直到成功。一旦成功,无论如何调用规则,它都会提交。

来自Wikipedia article

然而,与上下文无关文法和正则表达式不同的是, 这些操作员总是表现得很贪婪,消耗的输入与 可能且永不回头。

您在复杂情况下的要求与this question 中的要求相同。到目前为止的答案是是的:您必须调整 PEG 语法中的规则,以确保总是首先匹配最长的选项,即使结果是有点难看的语法。

调整 PEG 语法的一种方法是使用前瞻(这是前瞻在 PEG 中出现的主要原因之一):

start  =  nonmetric / metric / prefix metric
metric = "mol" / "l" / !"mo" "m" / "g"
nonmetric = "yr" / !"mol" "mo" / "week" / "day" / "hour"
prefix = !("mol"/"mo") "m" / "k" / "c"

【讨论】:

【解决方案2】:

这是设计使然。您可以指定正确的顺序或将用于匹配的规则。

引用原文white paper

当然,这些工具不会让语言语法设计变得简单。在 不必确定是否有两种可能的选择 CFG 是模棱两可的,PEG 为语言设计者提供了类似的 确定“/”表达式中是否有两个备选方案的挑战 可以在不影响语言的情况下重新排序。这个问题是 通常是显而易见的,但有时不是,而且通常是不确定的。 然而,与发现 CFG 中的歧义一样,我们希望 寻找自动算法来识别订单敏感性或 在常见情况下保守的不敏感。

在这个简单的例子中,PEG.js 可能会更聪明一些,并且可以识别您指定的规则是不明确的。可能值得ask作者。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-16
    相关资源
    最近更新 更多