implemented parsing up to neg/not

This commit is contained in:
Moritz Gmeiner 2024-08-12 18:28:21 +02:00
commit 3bd18634d5

View file

@ -24,9 +24,9 @@ module State = struct
let matches state tts = let matches state tts =
let f = ( == ) (peek state).token_type in let f = ( == ) (peek state).token_type in
List.fold_left (fun acc tt -> acc || f tt) false tts Array.fold_left (fun acc tt -> acc || f tt) false tts
let collect_chain (state : state) (tts : token_type list) higher_prec : let collect_chain (state : state) (tts : token_type array) higher_prec :
(expr * token) array * state = (expr * token) array * state =
(* ([], state) *) (* ([], state) *)
let state_ref = ref state in let state_ref = ref state in
@ -39,59 +39,61 @@ module State = struct
done; done;
(Array.of_list (List.rev !out_list_rev), !state_ref) (Array.of_list (List.rev !out_list_rev), !state_ref)
let mul_or_div (state : state) : expr * state = let primary (state : state) : expr * state =
let token, state = next state in let token, state = next state in
(make_string @@ show_token_type token.token_type, state) (make_string @@ show_token_type token.token_type, state)
let sum_or_diff (state : state) : expr * state = let rec neg_not (state : state) : expr * state =
let expr, state = mul_or_div state in if matches state [| Bang; Minus |] then
(* if (not (is_at_end state)) && matches state [ Plus; Minus ] then
let token, state = next state in let token, state = next state in
let expr2, state = sum_or_diff state in let expr, state = neg_not state in
let (op : binary_op) = let op =
match token.token_type with match token.token_type with
| Plus -> Plus | Bang -> Not
| Minus -> Minus | Minus -> Neg
| _ -> assert false (* should only be here if tt is + - *) | _ -> assert false (* should only be here if tt is - ! *)
in in
let expr = make_binary op expr expr2 in let expr = make_unary op expr in
(expr, state) (expr, state)
else (expr, state) *) else primary state
(* turn expr and state to refs for the loop *)
(* Printf.printf "expr: %s\n\n" (show_expr expr); let mul_or_div (state : state) : expr * state =
let expr_ref, state_ref = (ref expr, ref state) in let expr, state = neg_not state in
while (not (is_at_end !state_ref)) && matches !state_ref [ Plus; Minus ] do let exprs_tokens, state = collect_chain state [| Star; Slash |] neg_not in
let token, state = next !state_ref in
let expr2, state = mul_or_div state in
let (op : binary_op) =
match token.token_type with
| Plus -> Plus
| Minus -> Minus
| _ -> assert false (* should only be here if tt is + - *)
in
let expr = make_binary op !expr_ref expr2 in
(* (expr_ref, state_ref) := (expr, state) *)
Printf.printf "expr: %s\n\n" (show_expr expr);
expr_ref := expr;
state_ref := state
done;
(!expr_ref, !state_ref) *)
let exprs_tokens, state = collect_chain state [ Plus; Minus ] mul_or_div in
let f acc (expr, token) = let f acc (expr, token) =
let op : binary_op = let op : binary_op =
match token.token_type with Plus -> Plus | Minus -> Minus | _ -> assert false match token.token_type with
| Star -> Mul
| Slash -> Div
| _ -> assert false (* should only be here if tt is * / *)
in in
make_binary op acc expr make_binary op acc expr
in in
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 rec inequality (state : state) : expr * state = let sum_or_diff (state : state) : expr * state =
let expr, state = sum_or_diff state in let expr, state = mul_or_div state in
if (not (is_at_end state)) && matches state [ Greater; GreaterEqual; Less; LessEqual ] then let exprs_tokens, state = collect_chain state [| Plus; Minus |] mul_or_div in
let token, state = next state in let f acc (expr, token) =
let expr2, state = inequality state 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
in
let expr = Array.fold_left f expr exprs_tokens in
(expr, state)
let 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 exprs_tokens, state =
collect_chain state [| Greater; GreaterEqual; Less; LessEqual |] sum_or_diff
in
let f acc (expr, token) =
let (op : binary_op) = let (op : binary_op) =
match token.token_type with match token.token_type with
| Greater -> Greater | Greater -> Greater
@ -100,25 +102,24 @@ module State = struct
| LessEqual -> LessEqual | LessEqual -> LessEqual
| _ -> assert false (* should only be here if tt is > < >= <= *) | _ -> assert false (* should only be here if tt is > < >= <= *)
in in
let expr = make_binary op expr expr2 in make_binary op acc expr
in
let expr = Array.fold_left f expr exprs_tokens in
(expr, state) (expr, state)
else (expr, state)
let rec equality (state : state) : expr * state = let equality (state : state) : expr * state =
let expr, state = inequality state in let expr, state = inequality state in
if matches state [ EqualEqual; BangEqual ] then let exprs_tokens, state = collect_chain state [| EqualEqual; BangEqual |] inequality in
let token, state = next state in let f acc (expr, token) =
let expr2, state = equality state in
let expr =
match token.token_type with match token.token_type with
| EqualEqual -> make_binary Equal expr expr2 | EqualEqual -> make_binary Equal acc expr
| BangEqual -> | BangEqual ->
let expr = make_binary Equal expr expr2 in let expr = make_binary Equal acc expr in
make_unary Not expr make_unary Not expr
| _ -> assert false (* should only be here if tt is == != *) | _ -> assert false (* should only be here if tt is == != *)
in in
let expr = Array.fold_left f expr exprs_tokens in
(expr, state) (expr, state)
else (expr, state)
let expression (state : state) : expr * state = equality state let expression (state : state) : expr * state = equality state
end end