Packages

A simple Lisp interpreter implemented in Gleam. Features a REPL, basic Lisp functionality including arithmetic operations, list manipulation, conditionals, and variable definitions.

Current section

Files

Jump to
glisp src glisp@parser.erl
Raw

src/glisp@parser.erl

-module(glisp@parser).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([parse/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC("// Parses a list of tokens into an abstract syntax tree expression.\n").
-file("src/glisp/parser.gleam", 32).
-spec is_digit(binary()) -> boolean().
is_digit(Token) ->
gleam@result:is_ok(gleam_stdlib:parse_int(Token)).
-file("src/glisp/parser.gleam", 36).
-spec as_int_or(binary(), integer()) -> integer().
as_int_or(Token, Ex) ->
gleam@result:unwrap(gleam_stdlib:parse_int(Token), Ex).
-file("src/glisp/parser.gleam", 56).
-spec flip(list(glisp@ast:expr())) -> list(glisp@ast:expr()).
flip(Arr) ->
lists:reverse(Arr).
-file("src/glisp/parser.gleam", 60).
-spec parse_list(list(glisp@ast:expr()), list(binary())) -> {ok,
{glisp@ast:expr(), list(binary())}} |
{error, binary()}.
parse_list(Acc, Tokens) ->
case Tokens of
[] ->
{error, <<"Unclosed list"/utf8>>};
[Head | Rest] ->
case Head of
<<")"/utf8>> ->
{ok, {{list, flip(Acc)}, Rest}};
<<"("/utf8>> ->
case parse_list([], Rest) of
{ok, {Inner_expr, Remaining}} ->
parse_list([Inner_expr | Acc], Remaining);
{error, Msg} ->
{error, Msg}
end;
_ ->
case parse_tokens([Head]) of
{ok, {Item, _}} ->
parse_list([Item | Acc], Rest);
{error, Msg@1} ->
{error, Msg@1}
end
end
end.
-file("src/glisp/parser.gleam", 40).
-spec parse_tokens(list(binary())) -> {ok, {glisp@ast:expr(), list(binary())}} |
{error, binary()}.
parse_tokens(Tokens) ->
case Tokens of
[] ->
{error, <<"Unexpected EOF"/utf8>>};
[Head | Rest] ->
case Head of
<<"("/utf8>> ->
parse_list([], Rest);
<<")"/utf8>> ->
{error, <<"Unexpected ')'"/utf8>>};
_ ->
case is_digit(Head) of
true ->
{ok, {{number, as_int_or(Head, 0)}, Rest}};
false ->
{ok, {{atom, Head}, Rest}}
end
end
end.
-file("src/glisp/parser.gleam", 24).
?DOC(
" This function takes a list of string tokens and attempts to parse them\n"
" into a structured expression according to a simple Lisp-like syntax.\n"
" It can recognize atoms, numbers, and nested lists.\n"
"\n"
" ## Examples\n"
"\n"
" ```\n"
" parse([\"(\", \"hello\", \"world\", \")\"])\n"
" // -> Ok(List([Atom(\"hello\"), Atom(\"world\")]))\n"
"\n"
" parse([\"42\"])\n"
" // -> Ok(Number(42))\n"
"\n"
" parse([\"missing_paren\", \"(\"])\n"
" // -> Error(\"Unclosed list\")\n"
" ```\n"
).
-spec parse(list(binary())) -> {ok, glisp@ast:expr()} | {error, binary()}.
parse(Tokens) ->
case parse_tokens(Tokens) of
{ok, {Expr, []}} ->
{ok, Expr};
{ok, {_, _}} ->
{error, <<"Unexpected tokens after valid expression"/utf8>>};
{error, Msg} ->
{error, Msg}
end.