我想解析构造为a is x or y or z or b is z or w
的表达式,因此基本上我在语法上具有相同的分隔符来表示不同的规则。
我已经成功使用Antlr解析了此类表达式,因为它可以很好地回溯。但是现在我想用FParsec解析它,而且我不希望内部解析器不贪心。我当前的解析器如下所示:
let variable = // matches a,b,c,...
// variables ::= variable { "or" variable }+ ;
let variables =
variable .>>? keyword "or" .>>.? (sepBy1 variable (keyword "or"))
let operation =
variable .>>? keyword "is" .>>.? variables
// expression ::= operation { "or" operation }+ ;
let expression =
operation .>>? keyword "or" .>>.? (sepBy1 variable (keyword "or"))
在我的示例中,变量解析器消耗x or y or z or b
,而整个过程在is
处失败。这意味着我需要使variables
解析器的贪婪程度降低,或使其正确回溯。
我找到了一个similar question,他们在其中制作了sepBy1
的回溯版本,但是仍然不能解决我的问题。我想那是因为我想回溯到嵌套的解析器。
那么使FParsec接受我的输入的正确方法是什么?
答案 0 :(得分:1)
除了我在评论中提到的将or
的含义之一转换为|
之外,还可以如下使用notFollowedBy (keyword "is")
:
let variables =
variable .>>? keyword "or" .>>.? (sepBy1 (variable .>> (notFollowedBy (keyword "is"))) (keyword "or"))
我不太热衷于此解决方案,因为它不易推广。除了is
之外,还有其他关键字可以出现在变量之后吗?例如,您是否有类似b matches x or y
之类的语法?如果是这样,那么您需要编写类似(notFollowedBy ((keyword "is") <|> (keyword "matches")))
的内容,它很快就会变得复杂。但是只要关键字is
是唯一一个无法解析的关键字,那么使用(notFollowedBy (keyword "is"))
可能是最好的选择。