diff --git a/lib/parser.ml b/lib/parser.ml index 59da51a..10dbb90 100644 --- a/lib/parser.ml +++ b/lib/parser.ml @@ -24,9 +24,9 @@ module State = struct let matches state tts = 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 = (* ([], state) *) let state_ref = ref state in @@ -39,59 +39,61 @@ module State = struct done; (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 (make_string @@ show_token_type token.token_type, state) - let sum_or_diff (state : state) : expr * state = - let expr, state = mul_or_div state in - (* if (not (is_at_end state)) && matches state [ Plus; Minus ] then - let token, state = next state in - let expr2, state = sum_or_diff 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 expr2 in - (expr, state) - else (expr, state) *) - (* turn expr and state to refs for the loop *) - (* Printf.printf "expr: %s\n\n" (show_expr expr); - let expr_ref, state_ref = (ref expr, ref state) in - while (not (is_at_end !state_ref)) && matches !state_ref [ Plus; Minus ] do - 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 rec neg_not (state : state) : expr * state = + if matches state [| Bang; Minus |] then + let token, state = next state in + let expr, state = neg_not state in + let op = + match token.token_type with + | Bang -> Not + | Minus -> Neg + | _ -> assert false (* should only be here if tt is - ! *) + in + let expr = make_unary op expr in + (expr, state) + else primary state + + let mul_or_div (state : state) : expr * state = + let expr, state = neg_not state in + let exprs_tokens, state = collect_chain state [| Star; Slash |] neg_not in let f acc (expr, token) = 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 make_binary op acc expr in let expr = Array.fold_left f expr exprs_tokens in (expr, state) - let rec inequality (state : state) : expr * state = + let sum_or_diff (state : state) : expr * state = + let expr, state = mul_or_div state in + let exprs_tokens, state = collect_chain state [| Plus; Minus |] mul_or_div in + let f acc (expr, token) = + 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? *) let expr, state = sum_or_diff state in - if (not (is_at_end state)) && matches state [ Greater; GreaterEqual; Less; LessEqual ] then - let token, state = next state in - let expr2, state = inequality state in - (* TODO: maybe rework to only have Less and Greater as ops; performance? *) + let exprs_tokens, state = + collect_chain state [| Greater; GreaterEqual; Less; LessEqual |] sum_or_diff + in + let f acc (expr, token) = let (op : binary_op) = match token.token_type with | Greater -> Greater @@ -100,25 +102,24 @@ module State = struct | LessEqual -> LessEqual | _ -> assert false (* should only be here if tt is > < >= <= *) in - let expr = make_binary op expr expr2 in - (expr, state) - else (expr, state) + make_binary op acc expr + in + let expr = Array.fold_left f expr exprs_tokens in + (expr, state) - let rec equality (state : state) : expr * state = + let equality (state : state) : expr * state = let expr, state = inequality state in - if matches state [ EqualEqual; BangEqual ] then - let token, state = next state in - let expr2, state = equality state in - let expr = - match token.token_type with - | EqualEqual -> make_binary Equal expr expr2 - | BangEqual -> - let expr = make_binary Equal expr expr2 in - make_unary Not expr - | _ -> assert false (* should only be here if tt is == != *) - in - (expr, state) - else (expr, state) + let exprs_tokens, state = collect_chain state [| EqualEqual; BangEqual |] inequality in + let f acc (expr, token) = + match token.token_type with + | EqualEqual -> make_binary Equal acc expr + | BangEqual -> + let expr = make_binary Equal acc expr in + make_unary Not expr + | _ -> assert false (* should only be here if tt is == != *) + in + let expr = Array.fold_left f expr exprs_tokens in + (expr, state) let expression (state : state) : expr * state = equality state end