Разбор функции приложения с помощью FParsec с использованием OperatorPrecedenceParser? - PullRequest
7 голосов
/ 08 февраля 2012

Вопрос похож на этот , но я хочу проанализировать выражение с помощью функции приложения, используя 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"]))

1 Ответ

6 голосов
/ 08 февраля 2012

Вы можете проанализировать список аргументов как необязательное постфиксное выражение идентификатора

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