我正在尝试解析 F# 类型语法。我开始编写 [F] Parsec 语法并遇到问题,因此我将语法简化为:
type ::= identifier | type -> type
identifier ::= [A-Za-z0-9.`]+
在遇到 FParsec 问题后,我转而使用 Parsec,因为我有一整章专门解释它。我的这个语法的代码是
typeP = choice [identP, arrowP]
identP = do
id <- many1 (digit <|> letter <|> char '.' <|> char '`')
-- more complicated code here later
return id
arrowP = do
domain <- typeP
string "->"
range <- typeP
return $ "("++domain++" -> "++range++")"
run = parse (do t <- typeP
eof
return t) "F# type syntax"
问题是 Parsec 默认不回溯,所以
> run "int"
Right "int"
-- works!
> run "int->int"
Left "F# type syntax"
unexpected "-"
expecting digit, letter, ".", "`" or end of input
-- doesn't work!
我尝试的第一件事是重新排序 typeP:
typeP = choice [arrowP, identP]
但这只是堆栈溢出,因为语法是左递归的——typeP 永远不会尝试identP
,因为它会arrowP
一遍又一遍地尝试。接下来我在各个地方进行了尝试try
,例如:
typeP = choice [try identP, arrowP]
但是我所做的一切似乎都没有改变(1)堆栈溢出或(2)在标识符后面不识别“->”的基本行为。
对于任何成功编写 Parsec 语法的人来说,我的错误可能是显而易见的。有人可以指出吗?