2012-02-08 6 views
6

La domanda è simile a this one, ma voglio analizzare un'espressione con l'applicazione funzione utilizzando OperatorPrecedenceParser in FParsec.Applicazione della funzione di analisi con FParsec utilizzando OperatorPrecedenceParser?

Ecco il mio AST:

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

Ho il seguente testo:

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

Ed ecco il codice parser:

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

Il mio problema qui è che la funzione gli argomenti sono anche espressioni (possono includere operatori, variabili ecc.) e non so come estendere il mio expr parser per analizzare l'elenco degli argomenti come un elenco di espressioni. Ho costruito un parser qui, ma non so come combinare con il mio parser esistente:

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

ho attualmente il seguente output dal mio parser:

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

Quello che voglio è quello di ottenere i seguenti:

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

risposta

6

Si potrebbe analizzare la lista di argomenti come espressione postfix facoltativa di un identificatore

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

e quindi definire come expr

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