moved exprs into nodes with code position

This commit is contained in:
Moritz Gmeiner 2024-08-17 13:32:59 +02:00
commit a8290a4104
6 changed files with 155 additions and 49 deletions

View file

@ -4,14 +4,14 @@ open Error
open Expr
open Lexer
type parse_result = (expr, parser_error list) result
type expr_result = (expr, parser_error) result
type parse_result = (expr_node, parser_error list) result
type expr_result = (expr_node, parser_error) result
type state = { tokens : token list; errors_rev : parser_error list }
let is_at_end state = (List.hd !state.tokens).token_type == Eof
let append_error msg pos state =
let e = { pos; msg } in
let e = ParserError.make pos msg in
{ state with errors_rev = e :: state.errors_rev }
let advance state = state := { !state with tokens = List.tl !state.tokens }
@ -36,16 +36,8 @@ let matches state tts =
let cur_pos state = (peek state).pos
let collect_chain (state : state ref) (tts : token_type array)
(higher_prec : state ref -> expr_result) : ((expr * token) array, parser_error) result =
(* ([], state) *)
(* let out_list_rev = ref [] in
while (not (is_at_end state)) && matches state tts do
let token = next state in
let expr = higher_prec state in
out_list_rev := (expr, token) :: !out_list_rev
done;
Ok (Array.of_list (List.rev !out_list_rev)) *)
let rec collect_chain_rec (acc : (expr * token) list) =
(higher_prec : state ref -> expr_result) : ((expr_node * token) array, parser_error) result =
let rec collect_chain_rec (acc : (expr_node * token) list) =
if (not (is_at_end state)) && matches state tts then
let token = next state in
let* expr = higher_prec state in
@ -53,16 +45,26 @@ let collect_chain (state : state ref) (tts : token_type array)
collect_chain_rec acc
else Ok acc
in
(* match collect_chain_rec [] with Ok l -> Ok (Array.of_list (List.rev l)) | Error e -> Error e *)
collect_chain_rec [] |> Result.map (fun l -> Array.of_list (List.rev l))
let primary (state : state ref) : expr_result =
let pos = cur_pos state in
match (peek state).token_type with
| Number x -> Ok (make_number x)
| String s -> Ok (make_string s)
| True -> Ok (make_bool true)
| False -> Ok (make_bool false)
| Nil -> Ok (make_nil ())
| Number x ->
advance state;
Ok (make_number pos x)
| String s ->
advance state;
Ok (make_string pos s)
| True ->
advance state;
Ok (make_bool pos true)
| False ->
advance state;
Ok (make_bool pos false)
| Nil ->
advance state;
Ok (make_nil pos)
| tt ->
let msg = Printf.sprintf "Unexpected %s, expected valid expression" (show_token_type tt) in
let pos = (peek state).pos in
@ -72,7 +74,7 @@ let rec grouping (state : state ref) : expr_result =
if matches state [| LeftParen |] then (
advance state;
let* expr = expression state in
if advance_if state RightParen then Ok expr
if advance_if state RightParen then Ok expr (* expect a ) here *)
else
let pos = cur_pos state in
let tt = (peek state).token_type in
@ -83,6 +85,7 @@ let rec grouping (state : state ref) : expr_result =
and neg_not (state : state ref) : expr_result =
if matches state [| Bang; Minus |] then
let token = next state in
let pos = token.pos in
let* expr = neg_not state in
let op =
match token.token_type with
@ -90,7 +93,7 @@ and neg_not (state : state ref) : expr_result =
| Minus -> Neg
| _ -> assert false (* should only be here if tt is - ! *)
in
let expr = make_unary op expr in
let expr = make_unary pos op expr in
Ok expr
else grouping state
@ -98,13 +101,14 @@ and mul_or_div (state : state ref) : expr_result =
let* expr = neg_not state in
let* exprs_tokens = collect_chain state [| Star; Slash |] neg_not in
let f acc (expr, token) =
let pos = token.pos in
let op : binary_op =
match token.token_type with
| Star -> Mul
| Slash -> Div
| _ -> assert false (* should only be here if tt is * / *)
in
make_binary op acc expr
make_binary pos op acc expr
in
let expr = Array.fold_left f expr exprs_tokens in
Ok expr
@ -113,13 +117,14 @@ and sum_or_diff (state : state ref) : expr_result =
let* expr = mul_or_div state in
let* exprs_tokens = collect_chain state [| Plus; Minus |] mul_or_div in
let f acc (expr, token) =
let pos = token.pos in
let op : binary_op =
match token.token_type with
| Plus -> Plus
| Minus -> Minus
| _ -> assert false (* should only be here if tt is + - *)
in
make_binary op acc expr
make_binary pos op acc expr
in
let expr = Array.fold_left f expr exprs_tokens in
Ok expr
@ -131,6 +136,7 @@ and inequality (state : state ref) : expr_result =
collect_chain state [| Greater; GreaterEqual; Less; LessEqual |] sum_or_diff
in
let f acc (expr, token) =
let pos = token.pos in
let (op : binary_op) =
match token.token_type with
| Greater -> Greater
@ -139,7 +145,7 @@ and inequality (state : state ref) : expr_result =
| LessEqual -> LessEqual
| _ -> assert false (* should only be here if tt is > < >= <= *)
in
make_binary op acc expr
make_binary pos op acc expr
in
let expr = Array.fold_left f expr exprs_tokens in
Ok expr
@ -148,11 +154,12 @@ and equality (state : state ref) : expr_result =
let* expr = inequality state in
let* exprs_tokens = collect_chain state [| EqualEqual; BangEqual |] inequality in
let f acc (expr, token) =
let pos = token.pos in
match token.token_type with
| EqualEqual -> make_binary Equal acc expr
| EqualEqual -> make_binary pos Equal acc expr
| BangEqual ->
let expr = make_binary Equal acc expr in
make_unary Not expr
let expr = make_binary pos Equal acc expr in
make_unary pos Not expr
| _ -> assert false (* should only be here if tt is == != *)
in
let expr = Array.fold_left f expr exprs_tokens in
@ -170,7 +177,9 @@ let rec synchronise (state : state ref) =
let parse (tokens : token list) : parse_result =
let state = ref { tokens; errors_rev = [] } in
expression state |> Result.map_error (fun e -> [ e ])
let result = expression state |> Result.map_error (fun e -> [ e ]) in
assert (Result.is_error result || (peek state).token_type = Eof);
result
(* let expr = State.expression state in
let state =
if not (State.is_at_end state) then