2

我正在编写我的第一个解析器。它在 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
4

1 回答 1

1

像“(真假)或真”这样的输入会发生什么情况pline,它会pexpression尝试应用betweenParentheses exprParserLogic。这成功并解析“(真假)”。因此,由于解析成功,它永远不会尝试第二个选项,而是exprParserLogic简单地返回pline. pline然后 apply eof,失败,因为“或真”仍然留在输入中。

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

于 2016-06-01T19:21:24.100 回答