2012-02-08 69 views
6

該問題與this one類似,但我想用功能應用程序使用OperatorPrecedenceParserFParsec中解析表達式。使用OperatorPrecedenceParser使用FParsec解析函數應用程序?

這裏是我的AST:

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

我有以下輸入:

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

這裏是解析器代碼:

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

我這裏的問題是,函數參數也是表達式(它們可以包括運算符,變量等),我不知道如何擴展我的expr解析器將參數列表解析爲表達式列表。我建了一個解析器在這裏,但我不知道如何將它與我現有的解析器結合:

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

我現在有從我的解析器的輸出如下:

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

我想是得到如下:

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

回答

6

你可以解析參數列表作爲標識符的可選後綴表達式

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

然後定義expr

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