我有一个简单的语法,大部分都有效,但在一个地方报告错误,我认为不应该,因为它可以使用回溯来解决。
这是有问题的部分。
command: object message_chain;
object: ID;
message_chain: unary_message_chain keyword_message?
| binary_message_chain keyword_message?
| keyword_message;
unary_message_chain: unary_message+;
binary_message_chain: binary_message+;
unary_message: ID;
binary_message: BINARY_OPERATOR object;
keyword_message: (ID ':' object)+;
这是简化版本,对象更复杂(它可能是其他命令,原始值等的结果,但该部分工作正常)。问题出在message_chain
,第一种选择。对于像obj unary1 unary2
这样的输入,它可以正常工作,但是像obj unary1 unary2 keyword1:obj2
这样的输入是将keyword1
作为一元消息进行匹配,并在到达:
时失败。我认为这种情况解析器会回溯并认为存在:
并认识到这是关键字消息。
如果我将关键字消息设为非可选,它可以正常工作,但我需要关键字消息是可选的。
Parser在第二个备选(binary_message)和第三个备选(只是keyword_message)中找到关键字消息。所以这样的结果会产生很好的结果:1 + 2 + 3 Keyword1:Value
我错过了什么?在选项中将回溯设置为true,并且在其他情况下,它在同一语法中工作正常。
感谢。
答案 0 :(得分:1)
这不是PEG式回溯的情况,因为失败时只返回到未完成的推导中的决策点。对于输入obj unary1 unary2 keyword1:obj2
,使用单个标记预测,keyword1
可以使用unary_message_chain
。失败可能不会发生在keyword_message
之前,接下来要尝试的是message_chain的第二个替代方法,即binary_message_chain
,因此错过了正确的解析。
然而,由于此语法是LL(2),因此应该可以扩展前瞻以避免在keyword1
内使用unary_message_chain
。您是否尝试过明确设置k=2
,而无需回溯?