parsing - FParsec only parses expr between parentheses -


i coding parser (for learning pourpuses).

i want parse constructions like

let myvar 40 plus 2 

and

let myvar (40 plus 2) 

with no problems... parser not "understand" former. sees 40 , thinks "well, it's literal numeric 40".

when put parentheses, parser works great.

i having hard time understand why.

parser:

type value =     | boolean of bool     | numeric of float     | string of string  type arithmetic = sum | sub | mul | div | pow  type logic = , | or | equal | notequal | greater | smaller  type identifier =     | identifier of string  type expression =     | literal of value     | arithmetic of expression * arithmetic * expression     | negative of expression     | negation of expression     | logic of expression * logic * expression     | variable of identifier  type statement =     | assignment of identifier * expression     | print of expression     | read of identifier  let private ws = spaces  let private str s = pstring s .>> ws  let private pnumeric =     pfloat     .>> ws     |>> fun n -> literal (numeric n)  let private pboolean =     choice [         (stringreturn "true" (literal (boolean true)))         (stringreturn "false" (literal (boolean false)))     ]     .>> ws  let private pstringliteral =     choice [         between (pstring "\"") (pstring "\"") (manychars (satisfy (fun c -> c <> '"')))         between (pstring "'") (pstring "'") (manychars (satisfy (fun c -> c <> ''')))     ]     |>> fun s -> literal (string s)  let private pidentifier =     many1satisfy2l isletter (fun c -> isletter c || isdigit c) "identifier"     |>> fun s -> identifier s  let private betweenparentheses p =     between (str "(") (str ")") p  let private pvalue =     choice [         pnumeric         pboolean     ]  let private prefixoperator (p: operatorprecedenceparser<_,_,_>) op prec map =     p.addoperator(prefixoperator (op, ws, prec, true, map))  let private infixoperator (p: operatorprecedenceparser<_,_,_>) op prec map =     p.addoperator(infixoperator (op, ws, prec, associativity.left, map))  let private oppnegation = new operatorprecedenceparser<_,_,_>() let private opplogic = new operatorprecedenceparser<_,_,_>() let private opparithmetic = new operatorprecedenceparser<_,_,_>() let private oppnegative = new operatorprecedenceparser<_,_,_>()  prefixoperator oppnegation "not" 1 (fun x -> negation x) infixoperator opplogic "is" 1 (fun x y -> logic (x, equal, y)) infixoperator opplogic "isnt" 1 (fun x y -> logic (x, notequal, y)) infixoperator opplogic "and" 2 (fun x y -> logic (x, and, y)) infixoperator opplogic "or" 3 (fun x y -> logic (x, or, y)) prefixoperator oppnegative "-" 1 (fun x -> negative x) infixoperator opparithmetic ">" 1 (fun x y -> logic (x, greater, y)) infixoperator opparithmetic "<" 1 (fun x y -> logic (x, smaller, y)) infixoperator opparithmetic "is" 2 (fun x y -> logic (x, equal, y)) infixoperator opparithmetic "isnt" 2 (fun x y -> logic (x, notequal, y)) infixoperator opparithmetic "plus" 3 (fun x y -> arithmetic (x, sum, y)) infixoperator opparithmetic "minus" 3 (fun x y -> arithmetic (x, sub, y)) infixoperator opparithmetic "times" 4 (fun x y -> arithmetic (x, mul, y)) infixoperator opparithmetic "divided by" 4 (fun x y -> arithmetic (x, div, y)) infixoperator opparithmetic "power" 5 (fun x y -> arithmetic (x, pow, y))  let private negationexprparser = oppnegation.expressionparser let private logicexprparser = opplogic.expressionparser let private arithmeticexprparser = opparithmetic.expressionparser let private negativeexprparser = oppnegative.expressionparser  oppnegation.termparser <- choice [     betweenparentheses negationexprparser     pboolean ]  opplogic.termparser <- choice [     betweenparentheses logicexprparser     pboolean ]  oppnegative.termparser <- choice [     betweenparentheses negativeexprparser     pnumeric ]  opparithmetic.termparser <- choice [     betweenparentheses arithmeticexprparser     pnumeric ]  let private pexpression =     choice [         attempt <| pstringliteral         attempt <| negationexprparser         attempt <| logicexprparser         attempt <| negativeexprparser         attempt <| arithmeticexprparser         attempt <| (pidentifier |>> fun id -> variable id)     ]  let private passignment =     pipe2 (str "let" .>> ws >>. pidentifier) (ws >>. str "be" >>. ws >>. pexpression) (fun id exp -> assignment (id, exp))  let private pprint =     str "print"     >>. pexpression     |>> fun exp -> print exp  let private pread =     str "read"     >>. pidentifier     |>> fun id -> read id  let private pstatement =     choice [         passignment         pprint         pread     ]  let private pline =     skipmany (satisfy (fun c -> c = '\n' || c = ' '))     >>. pstatement     .>> ws  let private pcode =     many pline  let generateast code =     match run pcode code     | success (ast, _, _) -> sprintf "%a" ast     | failure (msg, _, _) -> msg 

usage:

[<entrypoint>] let main argv =     printfn "%s\n" (generateast "let b 5 plus 7")      // [assignment (identifier "b",literal (numeric 5.0))]      printfn "%s\n" (generateast "let b (5 plus 7)")     // [assignment     //    (identifier "b",arithmetic (literal (numeric 5.0),sum,literal (numeric 7.0)))]      0 

take @ fparsec - tracing parser

if add recommended fparsec tracing function top of code

let (<!>) (p: parser<_,_>) label : parser<_,_> =     fun stream ->         printfn "%a: entering %s" stream.position label         let reply = p stream         printfn "%a: leaving %s (%a)" stream.position label reply.status         reply 

then modify parsers use trace function

let private pnumeric =     (pfloat     .>> ws     |>> fun n -> literal (numeric n)) <!> "pnumeric"  let private pboolean =     (choice [         (stringreturn "true" (literal (boolean true)))         (stringreturn "false" (literal (boolean false)))     ]     .>> ws) <!> "pboolean"  let private pstringliteral =     (choice [         between (pstring "\"") (pstring "\"") (manychars (satisfy (fun c -> c <> '"')))         between (pstring "'") (pstring "'") (manychars (satisfy (fun c -> c <> ''')))     ]     |>> fun s -> literal (string s))  <!> "pstringliteral"  let private pidentifier =     (many1satisfy2l isletter (fun c -> isletter c || isdigit c) "identifier"     |>> fun s -> identifier s) <!> "pidentifier"  let private betweenparentheses p =     (between (str "(") (str ")") p) <!> "betweenparentheses"  let private pvalue =     (choice [         pnumeric         pboolean     ]) <!> "pvalue"  let private negationexprparser = oppnegation.expressionparser <!> "negationexprparser" let private logicexprparser = opplogic.expressionparser <!> "logicexprparser" let private arithmeticexprparser = opparithmetic.expressionparser <!> "arithmeticexprparser" let private negativeexprparser = oppnegative.expressionparser <!> "negativeexprparser "  let private pexpression =     choice [         attempt <| pstringliteral         attempt <| negationexprparser         attempt <| logicexprparser         attempt <| negativeexprparser         attempt <| arithmeticexprparser         attempt <| (pidentifier |>> fun id -> variable id)     ]  <!> "pexpression"  let private passignment =     pipe2 (str "let" .>> ws >>. pidentifier) (ws >>. str "be" >>. ws >>. pexpression) (fun id exp -> assignment (id, exp))  <!> "passignment"  let private pprint =     (str "print"     >>. pexpression     |>> fun exp -> print exp)  <!> "pprint"  let private pread =     (str "read"     >>. pidentifier     |>> fun id -> read id)  <!> "pread"  let private pstatement =     (choice [         passignment         pprint         pread     ])   <!> "pstatement"  let private pline =     (skipmany (satisfy (fun c -> c = '\n' || c = ' '))     >>. pstatement     .>> ws)   <!> "pline"  let private pcode =     many pline  <!> "pcode" 

and run code get

(ln: 1, col: 1): entering pcode (ln: 1, col: 1): entering pline (ln: 1, col: 1): entering pstatement (ln: 1, col: 1): entering passignment (ln: 1, col: 5): entering pidentifier (ln: 1, col: 6): leaving pidentifier (ok) (ln: 1, col: 10): entering pexpression (ln: 1, col: 10): entering pstringliteral (ln: 1, col: 10): leaving pstringliteral (error) (ln: 1, col: 10): entering negationexprparser (ln: 1, col: 10): entering betweenparentheses (ln: 1, col: 10): leaving betweenparentheses (error) (ln: 1, col: 10): entering pboolean (ln: 1, col: 10): leaving pboolean (error) (ln: 1, col: 10): leaving negationexprparser (error) (ln: 1, col: 10): entering logicexprparser (ln: 1, col: 10): entering betweenparentheses (ln: 1, col: 10): leaving betweenparentheses (error) (ln: 1, col: 10): entering pboolean (ln: 1, col: 10): leaving pboolean (error) (ln: 1, col: 10): leaving logicexprparser (error) (ln: 1, col: 10): entering negativeexprparser (ln: 1, col: 10): entering betweenparentheses (ln: 1, col: 10): leaving betweenparentheses (error) (ln: 1, col: 10): entering pnumeric (ln: 1, col: 12): leaving pnumeric (ok) (ln: 1, col: 12): leaving negativeexprparser (ok) (ln: 1, col: 12): leaving pexpression (ok) (ln: 1, col: 12): leaving passignment (ok) (ln: 1, col: 12): leaving pstatement (ok) (ln: 1, col: 12): leaving pline (ok) (ln: 1, col: 12): entering pline (ln: 1, col: 12): entering pstatement (ln: 1, col: 12): entering passignment (ln: 1, col: 12): leaving passignment (error) (ln: 1, col: 12): entering pprint (ln: 1, col: 12): leaving pprint (error) (ln: 1, col: 12): entering pread (ln: 1, col: 12): leaving pread (error) (ln: 1, col: 12): leaving pstatement (error) (ln: 1, col: 12): leaving pline (error) (ln: 1, col: 12): leaving pcode (ok) [assignment (identifier "b",literal (numeric 5.0))]  (ln: 1, col: 1): entering pcode (ln: 1, col: 1): entering pline (ln: 1, col: 1): entering pstatement (ln: 1, col: 1): entering passignment (ln: 1, col: 5): entering pidentifier (ln: 1, col: 6): leaving pidentifier (ok) (ln: 1, col: 10): entering pexpression (ln: 1, col: 10): entering pstringliteral (ln: 1, col: 10): leaving pstringliteral (error) (ln: 1, col: 10): entering negationexprparser (ln: 1, col: 10): entering betweenparentheses (ln: 1, col: 11): entering negationexprparser (ln: 1, col: 11): entering betweenparentheses (ln: 1, col: 11): leaving betweenparentheses (error) (ln: 1, col: 11): entering pboolean (ln: 1, col: 11): leaving pboolean (error) (ln: 1, col: 11): leaving negationexprparser (error) (ln: 1, col: 11): leaving betweenparentheses (error) (ln: 1, col: 11): leaving negationexprparser (error) (ln: 1, col: 10): entering logicexprparser (ln: 1, col: 10): entering betweenparentheses (ln: 1, col: 11): entering logicexprparser (ln: 1, col: 11): entering betweenparentheses (ln: 1, col: 11): leaving betweenparentheses (error) (ln: 1, col: 11): entering pboolean (ln: 1, col: 11): leaving pboolean (error) (ln: 1, col: 11): leaving logicexprparser (error) (ln: 1, col: 11): leaving betweenparentheses (error) (ln: 1, col: 11): leaving logicexprparser (error) (ln: 1, col: 10): entering negativeexprparser (ln: 1, col: 10): entering betweenparentheses (ln: 1, col: 11): entering negativeexprparser (ln: 1, col: 11): entering betweenparentheses (ln: 1, col: 11): leaving betweenparentheses (error) (ln: 1, col: 11): entering pnumeric (ln: 1, col: 13): leaving pnumeric (ok) (ln: 1, col: 13): leaving negativeexprparser (ok) (ln: 1, col: 13): leaving betweenparentheses (error) (ln: 1, col: 13): leaving negativeexprparser (error) (ln: 1, col: 10): entering arithmeticexprparser (ln: 1, col: 10): entering betweenparentheses (ln: 1, col: 11): entering arithmeticexprparser (ln: 1, col: 11): entering betweenparentheses (ln: 1, col: 11): leaving betweenparentheses (error) (ln: 1, col: 11): entering pnumeric (ln: 1, col: 13): leaving pnumeric (ok) (ln: 1, col: 18): entering betweenparentheses (ln: 1, col: 18): leaving betweenparentheses (error) (ln: 1, col: 18): entering pnumeric (ln: 1, col: 19): leaving pnumeric (ok) (ln: 1, col: 19): leaving arithmeticexprparser (ok) (ln: 1, col: 20): leaving betweenparentheses (ok) (ln: 1, col: 20): leaving arithmeticexprparser (ok) (ln: 1, col: 20): leaving pexpression (ok) (ln: 1, col: 20): leaving passignment (ok) (ln: 1, col: 20): leaving pstatement (ok) (ln: 1, col: 20): leaving pline (ok) (ln: 1, col: 20): entering pline (ln: 1, col: 20): entering pstatement (ln: 1, col: 20): entering passignment (ln: 1, col: 20): leaving passignment (error) (ln: 1, col: 20): entering pprint (ln: 1, col: 20): leaving pprint (error) (ln: 1, col: 20): entering pread (ln: 1, col: 20): leaving pread (error) (ln: 1, col: 20): leaving pstatement (error) (ln: 1, col: 20): leaving pline (error) (ln: 1, col: 20): leaving pcode (ok) [assignment    (identifier "b",arithmetic (literal (numeric 5.0),sum,literal (numeric 7.0)))] 

this should figure out problem, more importantly how solve future problems fparsec.


Popular posts from this blog

php - How should I create my API for mobile applications (Needs Authentication) -

5 Reasons to Blog Anonymously (and 5 Reasons Not To)

Google AdWords and AdSense - A Dynamic Small Business Marketing Duo