Разбор вызова функции без аргумента в параметрах функции - FParsec - PullRequest
0 голосов
/ 31 декабря 2018

Я пытаюсь реализовать анализатор с помощью монадической комбинации синтаксического анализатора с использованием FParsec.Я также использую модуль отступа, но это не важно для текущей проблемы.

Поэтому я пытаюсь разобрать эту ветку моего маленького AST:

type Identifier = string

type Expression =
    ...
    | Call of Identifier * Expression list
    ...
type Program = Program of Expression list

У меня есть эта реализация:

// Identifier parser
let private identifier =
    many1Satisfy2L isLetter
        (fun c -> isLetter c || isDigit c) "identifier"

// Monadic parser
let call = parse {
        let! id = identifier
        let! parameters = sepBy parameter spaces1
        return Call(id, parameters)
    }

and expression =
    ... // <|>
    attempt call // <|>
    ...

parameter представляет все допустимые выражения в вызове функции в качестве параметра:

// All possible parameter
let parameter =
    attempt pint32 <|> // A number, for example.
    attempt (identifier |>> fun callid -> Call(callid, [])) <|>
    attempt (between (pstring "(") (pstring ")") call)

Как видите, есть два элемента синтаксического анализатора, которые используют "C / колл».Они соответствуют этому по порядку и, например:

add x 1  // Call the function `add` and passing it another call (`x`) and the simple literal `1`
add (add 8 2) 10 // Call the function `add` and passing it another call (`add 8 2`) and the simple literal `10`

И, конечно, эти элементы также могут быть переплетены:

add (add x 1) 7

Проблема, которую я, очевидно, не могу решитьв противном случае я не буду задавать вопрос, является ли сгенерированное дерево не похожим на ожидаемое:

add x 1 дает:

Success: Program [Call ("add",[Call ("x",[]); Literal (Int 1)])]

Другими словами, парсер выглядитидентифицировать следующие x в качестве аргументов x.

Однако второй способ работает.add (add 8 2) 10 дает:

Success: Program
  [Call
     ("add",[Call ("add",[Literal (Int 8); Literal (Int 2)]); Literal (Int 10)])]

Не могли бы вы поставить меня на путь?

1 Ответ

0 голосов
/ 31 декабря 2018

Для меня это выглядит следующим образом: x:

attempt (identifier |>> fun callid -> Call(callid, [])) <|>

Один идентификатор рассматривается как call.

Поэтому вас не удивляетget: [Call ("add",[Call ("x",[]); Literal (Int 1)])

Как вы думаете, это неправильно, каковы ожидаемые результаты для вас?Я бы ожидал, что это будет выражение разыменования идентификатора.

Также совет, вы, кажется, выбрали вариант вызова функций в стиле OCaml, например: f x y

Возможно, вам следует такжеперейти к стилю OCaml, в котором функция всегда принимает один аргумент и возвращает одно значение.

add x 1 будет затем проанализирован в нечто вроде: Apply (Apply (Identifier "add", Identifier "x"), Literal 1)

...