2016-06-01 9 views
1

Ich kodiere meinen ersten Parser. Es ist in F # und ich verwende mit FParsec.FParsec analysiert Ausdrücke mit Klammern

Mein Parser parst Dinge wie true and false, (true and false or true), true, (((true and false or true))) etc, was richtig ist.

Aber es analysiert nicht, wenn es wie (true and false) or true ist. Es schlägt fehl, wenn in der Mitte des Textes Klammern stehen.

Wie kann ich es lösen?

Beispielcode:

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 

Antwort

1

Was für eine Eingabe wie "(wahr und falsch) oder true" passiert ist, dass pline gilt, die pexpression versucht betweenParentheses exprParserLogic anzuwenden. Dies gelingt und analysiert "(wahr und falsch)". Da die Analyse erfolgreich war, versucht sie nie die zweite Option exprParserLogic und kehrt einfach zu pline zurück. pline gilt dann eof, was fehlschlägt, weil noch "oder wahr" in der Eingabe übrig ist.

Da betweenParentheses exprParserLogic bereits Teil des Parsers des Operator-Parsers ist, gibt es keinen Grund für Sie, es in seiner eigenen Regel zu analysieren. Sie können einfach pline aufrufen exprParserLogic und entfernen pexpression insgesamt (oder definieren let pexpression = oppLogic.ExpressionParser und entfernen exprParserLogic). Dies wird korrekt "(wahr und falsch) oder wahr" analysieren.

+0

Sie sind angenehm richtig. – Gabriel

Verwandte Themen