2012-02-08 37 views
6

Câu hỏi tương tự như this one, nhưng tôi muốn phân tích biểu thức bằng ứng dụng chức năng bằng cách sử dụng OperatorPrecedenceParser trong FParsec.Ứng dụng chức năng phân tích cú pháp với FParsec bằng OperatorPrecedenceParser?

Đây là AST tôi:

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

tôi đã đầu vào sau:

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

Và đây là mã phân tích cú pháp:

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

Vấn đề của tôi ở đây là các chức năng các đối số cũng là các biểu thức (chúng có thể bao gồm các toán tử, các biến vv) và tôi không biết cách mở rộngcủa mìnhtrình phân tích cú pháp để phân tích cú pháp danh sách đối số dưới dạng danh sách biểu thức. Tôi đã xây dựng một phân tích cú pháp ở đây, nhưng tôi không biết làm thế nào để kết hợp nó với phân tích cú pháp hiện tại của tôi:

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

Tôi hiện đang có đầu ra sau đây từ phân tích cú pháp của tôi:

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

Những gì tôi muốn là để có được những điều sau đây:

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

Trả lời

6

Bạn có thể phân tích danh sách đối số như là một biểu postfix tùy chọn của một định danh

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

và sau đó xác định expr như

let expr = (number |>> Float) <|> identWithOptArgs 
Các vấn đề liên quan