fnished first draft of expression parser

This commit is contained in:
Moritz Gmeiner 2024-08-14 12:36:36 +02:00
commit f14677b6f5

View file

@ -22,6 +22,18 @@ module State = struct
let advance_if state tt = let advance_if state tt =
if (peek state).token_type == tt then (true, advance state) else (false, state) if (peek state).token_type == tt then (true, advance state) else (false, state)
let consume state tt =
if (peek state).token_type == tt then advance state
else
let state =
append_error
(Printf.sprintf "Unexpected %s, expected %s"
(show_token_type (peek state).token_type)
(show_token_type tt))
(peek state).pos state
in
state
let matches state tts = let matches state tts =
let f = ( == ) (peek state).token_type in let f = ( == ) (peek state).token_type in
Array.fold_left (fun acc tt -> acc || f tt) false tts Array.fold_left (fun acc tt -> acc || f tt) false tts
@ -40,10 +52,27 @@ module State = struct
(Array.of_list (List.rev !out_list_rev), !state_ref) (Array.of_list (List.rev !out_list_rev), !state_ref)
let primary (state : state) : expr * state = let primary (state : state) : expr * state =
let token, state = next state in match (peek state).token_type with
(make_string @@ show_token_type token.token_type, state) | Number x -> (make_number x, advance state)
| String s -> (make_string s, advance state)
| True -> (make_bool true, advance state)
| False -> (make_bool false, advance state)
| Nil -> (make_nil (), advance state)
| tt ->
( make_nil (),
append_error
(Printf.sprintf "Unexpected %s, expected valid expression" (show_token_type tt))
(peek state).pos state )
let rec neg_not (state : state) : expr * state = let rec grouping (state : state) : expr * state =
if matches state [| LeftParen |] then
let state = advance state in
let expr, state = expression state in
let state = consume state RightParen in
(expr, state)
else primary state
and neg_not (state : state) : expr * state =
if matches state [| Bang; Minus |] then if matches state [| Bang; Minus |] then
let token, state = next state in let token, state = next state in
let expr, state = neg_not state in let expr, state = neg_not state in
@ -55,9 +84,9 @@ module State = struct
in in
let expr = make_unary op expr in let expr = make_unary op expr in
(expr, state) (expr, state)
else primary state else grouping state
let mul_or_div (state : state) : expr * state = and mul_or_div (state : state) : expr * state =
let expr, state = neg_not state in let expr, state = neg_not state in
let exprs_tokens, state = collect_chain state [| Star; Slash |] neg_not in let exprs_tokens, state = collect_chain state [| Star; Slash |] neg_not in
let f acc (expr, token) = let f acc (expr, token) =
@ -72,7 +101,7 @@ module State = struct
let expr = Array.fold_left f expr exprs_tokens in let expr = Array.fold_left f expr exprs_tokens in
(expr, state) (expr, state)
let sum_or_diff (state : state) : expr * state = and sum_or_diff (state : state) : expr * state =
let expr, state = mul_or_div state in let expr, state = mul_or_div state in
let exprs_tokens, state = collect_chain state [| Plus; Minus |] mul_or_div in let exprs_tokens, state = collect_chain state [| Plus; Minus |] mul_or_div in
let f acc (expr, token) = let f acc (expr, token) =
@ -87,7 +116,7 @@ module State = struct
let expr = Array.fold_left f expr exprs_tokens in let expr = Array.fold_left f expr exprs_tokens in
(expr, state) (expr, state)
let inequality (state : state) : expr * state = and inequality (state : state) : expr * state =
(* TODO: maybe rework to only have Less and Greater as ops; performance? *) (* TODO: maybe rework to only have Less and Greater as ops; performance? *)
let expr, state = sum_or_diff state in let expr, state = sum_or_diff state in
let exprs_tokens, state = let exprs_tokens, state =
@ -107,7 +136,7 @@ module State = struct
let expr = Array.fold_left f expr exprs_tokens in let expr = Array.fold_left f expr exprs_tokens in
(expr, state) (expr, state)
let equality (state : state) : expr * state = and equality (state : state) : expr * state =
let expr, state = inequality state in let expr, state = inequality state in
let exprs_tokens, state = collect_chain state [| EqualEqual; BangEqual |] inequality in let exprs_tokens, state = collect_chain state [| EqualEqual; BangEqual |] inequality in
let f acc (expr, token) = let f acc (expr, token) =
@ -121,7 +150,7 @@ module State = struct
let expr = Array.fold_left f expr exprs_tokens in let expr = Array.fold_left f expr exprs_tokens in
(expr, state) (expr, state)
let expression (state : state) : expr * state = equality state and expression (state : state) : expr * state = equality state
end end
let parse (tokens : token list) : parse_result = let parse (tokens : token list) : parse_result =