I'm trying to write a simple Lisp parser with OCaml Opal:
This is my AST:
type atom = Num of int | Ident of string [@@deriving show]
type sexp = Atom of atom | ListSexp of sexp list [@@deriving show]
And this is the parser:
open Opal
open Ast
let integer = many1 digit => implode % int_of_string => fun n -> Atom (Num n)
let ident = many alpha_num => implode => fun i -> Atom (Ident i)
let parens = between (token "(") (token ")")
let atom = integer <|> ident
let expr = parens (sep_by atom space)
let parse_expr input =
match parse expr input with
| Some ans -> List.iter (fun a -> Printf.printf "%s" (show_sexp a)) ans
| None -> print_endline "ERROR!"
This works ok when I try to parse Parser.parse_expr (LazyStream.of_string "(5 3 abc)")
However, the next thing I tried is to parse S-Expressions recursively by naively modifying my expr function to:
let rec expr = parens (sep_by (atom <|> expr) space)
And this produces an error:
8 | let rec expr = parens (sep_by (atom <|> expr) space)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This expression has type char input -> (sexp list * char input) option
but an expression was expected of type
char input -> (sexp * char input) option
Type sexp list is not compatible with type sexp
This seems ok since atom function returns char input -> (sexp * char input) option while expr function returns char input -> (sexp list * char input) option.
But I'm not sure how can to fix this. Ideas?
Atomvalues for numbers and identifiers, but then you returnsexp listdirectly, which is not of typesexplet expr = parens (sep_by atom space) => fun l -> ListSexp l. I tried, but how to apply the function recursively on this? I got: ` 8 | let rec expr = parens (sep_by (atom <|> expr) space) => fun l -> ListSexp l ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: This kind of expression is not allowed as right-hand side oflet rec'errorlet rec expr input = (parens (sep_by (expr <|> atom) space) => fun l -> ListSexp l) inputcompiles and parses expressions recursively. You can make that an answer.