2012-02-08 11 views
6

La pregunta es similar a this one, pero quiero analizar una expresión con la aplicación de función usando OperatorPrecedenceParser en FParsec.Aplicación de función de análisis con FParsec utilizando OperatorPrecedenceParser?

Aquí es mi AST:

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

Tengo el siguiente entrada:

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

Y aquí está el código de programa de análisis:

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))) 

Mi problema aquí es que la función los argumentos también son expresiones (pueden incluir operadores, variables, etc.) y no sé cómo extender mi expr analizador para analizar la lista de argumentos como una lista de expresiones. Construí un analizador aquí, pero no sé cómo combinar con mi analizador existente:

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

que actualmente tiene la siguiente salida de mi programa de análisis:

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

Lo que yo quiero es obtenemos lo siguiente:

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

Respuesta

6

Usted ha podido analizar la lista de argumentos como una expresión de sufijo opcional de un identificador

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)) 

y luego definir expr como

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