Reputation: 1942
I'm coding my first parser. It's in F# and I'm using with FParsec.
My parser parses things like true and false
, (true and false or true)
, true
, (((true and false or true)))
etc, which is correct.
But it doesn't parses when it's like (true and false) or true
. It fails when there are parentheses in the middle of the text.
How can I solve it?
Sample code:
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
Upvotes: 2
Views: 383
Reputation: 370455
What happens for an input like "(true and false) or true" is that pline
applies, which pexpression
tries to apply betweenParentheses exprParserLogic
. This succeeds and parses "(true and false)". So since the parse was successful, it never tries the second option exprParserLogic
and simply returns to pline
. pline
then applies eof
, which fails because "or true" is still left in the input.
Since betweenParentheses exprParserLogic
is already part of the operator parser's term parser, there's no reason for you to try to parse it in its own rule. You can just have pline
invoke exprParserLogic
and remove pexpression
altogether (or define let pexpression = oppLogic.ExpressionParser
and remove exprParserLogic
). This will correctly parse "(true and false) or true".
Upvotes: 1