FParsec用括号解析表达式

时间:2016-06-01 18:23:22

标签: parsing compilation f# functional-programming fparsec

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

1 个答案:

答案 0 :(得分:1)

“{true和false”或“true”之类的输入会发生pline适用,pexpression尝试应用betweenParentheses exprParserLogic。这成功并解析“(真与假)”。因此,由于解析成功,它永远不会尝试第二个选项exprParserLogic,只返回plinepline然后应用eof,但失败是因为输入中仍保留“或true”。

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