mirror of
https://github.com/MorizzG/MLox.git
synced 2025-12-06 04:22:41 +00:00
implemented break
This commit is contained in:
parent
3bc871d434
commit
e288a626fd
6 changed files with 84 additions and 72 deletions
|
|
@ -8,10 +8,18 @@ open Stmt
|
|||
type parse_result = (stmt_node list, parser_error list) result
|
||||
type stmt_result = (stmt_node, parser_error) result
|
||||
type expr_result = (expr_node, parser_error) result
|
||||
type state = { tokens : token list }
|
||||
type state = { tokens : token list; is_in_loop : bool }
|
||||
|
||||
let with_is_in_loop (f : state ref -> stmt_result) (state : state ref) : stmt_result =
|
||||
let was_in_loop = !state.is_in_loop in
|
||||
state := { !state with is_in_loop = true };
|
||||
let result = f state in
|
||||
state := { !state with is_in_loop = was_in_loop };
|
||||
result
|
||||
|
||||
let make_state tokens = ref { tokens; is_in_loop = false }
|
||||
let is_at_end state = (List.hd !state.tokens).token_type = Eof
|
||||
let advance state = state := { tokens = List.tl !state.tokens }
|
||||
let advance state = state := { !state with tokens = List.tl !state.tokens }
|
||||
|
||||
let next state =
|
||||
assert (not ((List.hd !state.tokens).token_type = Eof));
|
||||
|
|
@ -257,7 +265,12 @@ and while_loop (state : state ref) : stmt_result =
|
|||
let* _ = consume state LeftParen in
|
||||
let* cond = expression state in
|
||||
let* _ = consume state RightParen in
|
||||
let* body = statement state in
|
||||
(* let was_in_loop = !state.is_in_loop in
|
||||
state := { !state with is_in_loop = true };
|
||||
let body = statement state in
|
||||
state := { !state with is_in_loop = was_in_loop };
|
||||
let* body = body in *)
|
||||
let* body = with_is_in_loop statement state in
|
||||
make_while pos cond body |> Result.ok
|
||||
|
||||
and for_loop (state : state ref) : stmt_result =
|
||||
|
|
@ -287,7 +300,12 @@ and for_loop (state : state ref) : stmt_result =
|
|||
| _ -> expression state |> Result.map Option.some
|
||||
in
|
||||
let* _ = consume state RightParen in
|
||||
let* body = statement state in
|
||||
(* let was_in_loop = !state.is_in_loop in
|
||||
state := { !state with is_in_loop = true };
|
||||
let body = statement state in
|
||||
state := { !state with is_in_loop = was_in_loop };
|
||||
let* body = body in *)
|
||||
let* body = with_is_in_loop statement state in
|
||||
let body =
|
||||
match update with
|
||||
| Some update ->
|
||||
|
|
@ -311,6 +329,14 @@ and expr_stmt (state : state ref) : stmt_result =
|
|||
and statement (state : state ref) : stmt_result =
|
||||
let pos = cur_pos state in
|
||||
match peek_tt state with
|
||||
| Break ->
|
||||
if !state.is_in_loop then (
|
||||
advance state;
|
||||
let* _ = consume state Semicolon in
|
||||
make_break pos |> Result.ok)
|
||||
else
|
||||
let msg = "Can use break only in loops" in
|
||||
ParserError.make pos msg |> Result.error
|
||||
| Print ->
|
||||
advance state;
|
||||
let* expr = expression state in
|
||||
|
|
@ -371,5 +397,5 @@ let parse (tokens : token list) : parse_result =
|
|||
let tokens =
|
||||
List.filter (fun tok -> match tok.token_type with Comment _ -> false | _ -> true) tokens
|
||||
in
|
||||
let state = ref { tokens } in
|
||||
let state = make_state tokens in
|
||||
parse_impl state
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue