Parsing function application with FParsec using OperatorPrecedenceParser?

谁都会走 提交于 2019-12-10 04:19:22

问题


The question is similar to this one, but I want to parse an expression with function application using the OperatorPrecedenceParser in FParsec.

Here is my AST:

type Expression =
  | Float of float
  | Variable of VarIdentifier
  | BinaryOperation of Operator * Expression * Expression
  | FunctionCall of VarIdentifier (*fun name*) * Expression list (*arguments*)

I have the following input:

board→create_obstacle(4, 4, 450, 0, fric)

And here is the parser code:

let expr = (number |>> Float) <|> (ident |>> Variable)
let parenexpr = between (str_ws "(") (str_ws ")") expr

let opp = new OperatorPrecedenceParser<_,_,_>()

opp.TermParser <- expr <|> parenexpr

opp.AddOperator(InfixOperator("→", ws, 
  10, Associativity.Right, 
  fun left right -> BinaryOperation(Arrow, left, right)))

My problem here is that the function arguments are expressions as well (they can include operators, variables etc) and I don't know how to extend my expr parser to parse the argument list as a list of expression. I built a parser here, but I don't know how to combine it with my existing parser:

let primitive = expr <|> parenexpr
let argList = sepBy primitive (str_ws ",")
let fcall = tuple2 ident (between (str_ws "(") (str_ws ")") argList)

I currently have the following output from my parser:

Success: Expression (BinaryOperation 
     (Arrow,Variable "board",Variable "create_obstacle"))

What I want is to get the following:

 Success: Expression 
      (BinaryOperation 
            (Arrow,
                Variable "board",
                Function (VarIdentifier "create_obstacle",
                          [Float 4, Float 4, Float 450, Float 0, Variable "fric"]))

回答1:


You could parse the argument list as an optional postfix expression of an identifier

let argListInParens = between (str_ws "(") (str_ws ")") argList
let identWithOptArgs = 
    pipe2 ident (opt argListInParens) 
          (fun id optArgs -> match optArgs with
                             | Some args -> FunctionCall(id, args)
                             | None -> Variable(id))

and then define expr like

let expr = (number |>> Float) <|> identWithOptArgs


来源:https://stackoverflow.com/questions/9197687/parsing-function-application-with-fparsec-using-operatorprecedenceparser

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!