Я пытаюсь реализовать анализатор с помощью монадической комбинации синтаксического анализатора с использованием 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)])]
Не могли бы вы поставить меня на путь?