FParsec 解析带括号的表达式

FParsec parse expressions with parentheses

我正在编写我的第一个解析器。它在 F# 中,我正在使用 FParsec。

我的解析器解析了 true and false(true and false or true)true(((true and false or true))) 等内容,这是正确的。

但是当它像(true and false) or true时它不解析。当文本中间有括号时失败。

我该如何解决?

示例代码:

let private infixOperator (opp: OperatorPrecedenceParser<_,_,_>) op prec map =
    opp.AddOperator(InfixOperator (op, ws, prec, Associativity.Left, map))

let private oppLogic = new OperatorPrecedenceParser<_,_,_>()

infixOperator oppLogic "is" 1 (fun x y -> Comparison (x, Equal, y))
infixOperator oppLogic "isnt" 1 (fun x y -> Comparison (x, NotEqual, y))
infixOperator oppLogic "or" 2 (fun x y -> Logic (x, Or, y))
infixOperator oppLogic "and" 3 (fun x y -> Logic (x, And, y))

let private exprParserLogic = oppLogic.ExpressionParser

let private betweenParentheses p =
    between (str "(") (str ")") p

oppLogic.TermParser <- choice [
    betweenParentheses exprParserLogic
    pboolean
]

let pexpression =
    choice [
        attempt <| betweenParentheses exprParserLogic
        exprParserLogic
    ]

let private pline =
    ws
    >>. pexpression
    .>> eof

对于“(true and false)或 true”这样的输入,发生的情况是 pline 适用,pexpression 尝试应用 betweenParentheses exprParserLogic。这会成功并解析“(true and false)”。因此,由于解析成功,它永远不会尝试第二个选项 exprParserLogic,而只是 returns 到 plinepline 然后应用 eof,它失败了,因为 "or true" 仍然留在输入中。

由于 betweenParentheses exprParserLogic 已经是运算符解析器的术语解析器的一部分,您没有理由尝试在它自己的规则中解析它。您可以只让 pline 调用 exprParserLogic 并完全删除 pexpression(或定义 let pexpression = oppLogic.ExpressionParser 并删除 exprParserLogic)。这将正确解析“(true and false) or true”。