1

我正在编写一些使用PegKit的代码,但我遇到了一些我不确定如何解决的问题。我有一个看起来像这样的语法(简化):

expr = runtimeExpr | objectExpr;
runtimeExpr = is? runtimeObject;
objectExpr = runtimeObject keyPath;
runtimeObject = '[' string ']';
is = 'is';
keyPath = string;

我正在寻找以下结果:

[abc] -> runtime expr.
is [abc] -> runtime expr.
[abc].def -> object expr.

然而,正在发生的是生成的解析器代码如下所示:

if ([self predicts:STLOGEXPRESSIONPARSER_TOKEN_KIND_IS, 0]) {
    [self runtimeExpr_]; 
} else if ([self predicts:STLOGEXPRESSIONPARSER_TOKEN_KIND_OPEN_BRACKET, 0]) {
    [self objectExpr_]; 
}

有效的说,为了解析运行时表达式,它必须以'is'开头。这意味着它[abc]被作为对象 expr 传递。

所以我需要帮助的是理解如何在语法语法中表达这个逻辑:

  1. 如果字符串以“is”开头,后跟 runtimeObject,或者只是一个 runtimeObject,则将其作为 runtimeExpr 处理。

  2. 否则将其作为 objectExpr 处理。

4

1 回答 1

1

PEGKit的创建者在这里。

我相信这里的问题是领先的 optional is?。任何以这样的可选前缀开头的规则,然后匹配与另一个规则相似或相同的内容(runtimeObject在这种情况下)都可能导致问题。

但解决方案很简单。稍微重新排序一下。PEGKit 是确定性的,这意味着它将按照您在语法中指定的顺序尝试OR替代方案。因此,在这种情况下,只需将较长的替代规则 ( objectExpr)放在首位runtimeExprexpr规则之前)。

试试这个,我相信一切都会好起来的:

expr = objectExpr | runtimeExpr;
objectExpr = runtimeObject keyPath;
runtimeExpr = is runtimeObject | runtimeObject;
runtimeObject = '[' string ']';
is = 'is';
keyPath = string;

请注意我对exprruntimeExpr规则所做的更改。我怀疑只有更改为expr是解决此问题所必需的,但更改为runtimeExpr是无害的。实验应该告诉你runtimeExpr改变是否真的有必要。

于 2015-07-01T16:26:37.190 回答