我正在研究一些使用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_];
}
有效的说,为了解析运行时expr,它必须以'is'开头。这意味着[abc]
将作为对象expr传递。
所以我需要帮助的是理解如何在语法语法中表达这个逻辑:
如果字符串以'is'开头,后跟runtimeObject,或者只是runtimeObject,则将其作为runtimeExpr处理。
否则将其作为objectExpr。
答案 0 :(得分:1)
PEGKit的创作者。
我认为这里的问题是领先的可选is?
。任何以这样的可选前缀开头的规则,然后匹配与其他规则相似或相同的内容(在这种情况下为runtimeObject
)可能会导致问题。
但解决方案很简单。只需重新排序一下。 PEGKit 确定性,这意味着它将按照您在语法中指定的顺序尝试 OR 替代方案。因此,在这种情况下,只需在objectExpr
规则中放置更长备用规则(runtimeExpr
)优先(expr
之前)。< / p>
试试这个,我相信一切都会成功:
expr = objectExpr | runtimeExpr;
objectExpr = runtimeObject keyPath;
runtimeExpr = is runtimeObject | runtimeObject;
runtimeObject = '[' string ']';
is = 'is';
keyPath = string;
请注意我对expr
和runtimeExpr
规则所做的更改。我怀疑只有expr
的更改才能解决这个问题,但对runtimeExpr
的更改是无害的。实验应该告诉您实际上是否需要runtimeExpr
更改。