2015-07-01 35 views
1

我正在研究一些使用PegKit的代码,我碰到了一些我不确定如何弄清楚的东西。我有一个语法看起来像这样(简化):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传递。

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

  1. 如果字符串用“是”开始,然后是runtimeObject,或者仅仅是一个runtimeObject,然后将其作为runtimeExpr进行处理。

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

回答

1

PEGKit的创建者在这里。

我相信这里的问题是领先的可选is?。任何以这种可选前缀开头的规则,然后再匹配与其他规则类似或相同的东西(本例中为runtimeObject)可能会导致问题。

但是解决方案很简单。只需重新排序一下。 PEGKit是确定性这意味着它将按照您在语法中指定的顺序尝试备选项。因此,在这种情况下,只需将延长的替代规则(objectExpr第一个(在expr规则中的runtimeExpr之前)。

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

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

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

+0

啊。我在文法的其他部分使用了确定性方面。我刚刚运行了运行库,因为我认为首先检查它是个更好的主意。我最终以一种不同的方式解决了这个问题。我意识到我的语法需要'运行时'上的不同代码,而不是'运行时...'。所以我能够改变事物。不过,我喜欢你的建议,我认为这可能会让我简化整体语法。谢谢托德。 – drekka

+0

P.S>作为一般性问题。从解析中使用返回令牌数组还是使用回调作为令牌解析是更好的主意?目前,我几乎忽略了返回的标记数组,并使用回调来生成弹出和处理令牌。 – drekka

+1

如果我理解正确,后者(回调)是最好的方法。 –

相关问题