PegKit:以不同方式处理相同工作的语法语法

PegKit: Grammar syntax which handles same work in different ways

我正在编写一些使用 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处理

这里是 PEGKit 的创建者。

我认为这里的问题是领先的可选 is?。任何以这样的可选前缀开头,然后匹配与另一条规则相似或相同的规则(在本例中为 runtimeObject)都可能导致问题。

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

试试这个,我相信一切都会成功的:

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

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