Я работаю над созданием интерпретатора Lisp в OCaml. Я, естественно, начал с фронтенда. Пока что у меня есть алгоритм разбора S-выражения, который работает большую часть времени. Для обоих простых S-выражений, таких как (a b)
и ((a b) (c d))
, моя функция ast_as_str
показывает, что структура выходного списка неверна. Я задокументировал это ниже. После бесчисленных вариантов parse
ничего не работает. Есть ли у кого-то из специалистов по написанию парсеров в OCaml предложение о том, как я могу исправить свой код?
type s_expression = Nil | Atom of string | Pair of s_expression * s_expression
let rec parse tokens =
match tokens with
| [] -> Nil
| token :: rest ->
match token with
| "(" -> parse rest
| ")" -> Pair(Nil, parse rest)
| atom -> Pair(Atom atom, parse rest)
let rec ast_as_str ast =
match ast with
| Nil -> "nil"
| Atom a -> Printf.sprintf "%s" a
| Pair(a, b) -> Printf.sprintf "(%s %s)" (ast_as_str a) (ast_as_str b);;
let check_output test = print_endline (ast_as_str (parse test));;
(*
Input:
(a b)
Output:
(a (b (nil nil)))
Almost correct...
*)
check_output ["("; "a"; "b"; ")"];;
(*
Input:
((w x) (y z))
Output:
(w (x (nil (y (z (nil (nil nil)))))))
Incorrect.
*)
check_output ["("; "("; "w"; "x"; ")"; "("; "y"; "z"; ")"; ")"]