Skip to content

Commit c8dd0e5

Browse files
gh-111: Interpreter doesn't hang on seperated TRY and CATCH.
1 parent 9c95556 commit c8dd0e5

1 file changed

Lines changed: 39 additions & 12 deletions

File tree

src/parser.c

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,22 @@ static Expr* parse_expression(Parser* parser);
188188
static Stmt* parse_statement(Parser* parser);
189189
static Stmt* parse_block(Parser* parser);
190190

191+
static void append_parse_error_throw_stmt(Parser* parser, Stmt* block) {
192+
if (!parser || !block || !parser->error_msg) return;
193+
194+
char* msg_dup = strdup(parser->error_msg);
195+
Expr* callee = expr_ident(strdup("THROW"), parser->error_line, parser->error_col);
196+
Expr* call = expr_call(callee, parser->error_line, parser->error_col);
197+
Expr* arg = expr_str(msg_dup, parser->error_line, parser->error_col);
198+
expr_list_add(&call->as.call.args, arg);
199+
Stmt* err_stmt = stmt_expr(call, parser->error_line, parser->error_col);
200+
stmt_list_add(&block->as.block, err_stmt);
201+
free(parser->error_msg);
202+
parser->error_msg = NULL;
203+
parser->had_error = false;
204+
parser->panic_mode = false;
205+
}
206+
191207
static bool is_type_token(PTokenType type) {
192208
return type == TOKEN_IDENT || type == TOKEN_FUNC || type == TOKEN_THR;
193209
}
@@ -606,6 +622,20 @@ static Stmt* parse_block(Parser* parser) {
606622
stmt_set_src(stmt, line_text);
607623
free(line_text);
608624
stmt_list_add(&block->as.block, stmt);
625+
skip_newlines(parser);
626+
continue;
627+
}
628+
629+
if (!parser->error_msg) {
630+
break;
631+
}
632+
633+
append_parse_error_throw_stmt(parser, block);
634+
635+
while (parser->current_token.type != TOKEN_EOF &&
636+
parser->current_token.type != TOKEN_NEWLINE &&
637+
parser->current_token.type != TOKEN_RBRACE) {
638+
advance(parser);
609639
}
610640
skip_newlines(parser);
611641
}
@@ -693,7 +723,14 @@ static Stmt* parse_try(Parser* parser) {
693723
Token tok = parser->current_token;
694724
consume(parser, TOKEN_TRY, "Expected 'TRY'");
695725
Stmt* try_block = parse_block(parser);
696-
consume(parser, TOKEN_CATCH, "Expected 'CATCH' after TRY");
726+
if (parser->current_token.type != TOKEN_CATCH) {
727+
report_error(parser, "Expected 'CATCH' after TRY");
728+
while (parser->current_token.type != TOKEN_EOF && parser->current_token.type != TOKEN_RBRACE) {
729+
advance(parser);
730+
}
731+
return NULL;
732+
}
733+
advance(parser);
697734
char* catch_name = NULL;
698735
if (match(parser, TOKEN_LPAREN)) {
699736
if (parser->current_token.type == TOKEN_IDENT) {
@@ -1015,17 +1052,7 @@ Stmt* parser_parse(Parser* parser) {
10151052
state so callers (e.g. RUN/IMPORT) don't treat it as a fatal
10161053
top-level parse failure. */
10171054
if (parser->error_msg) {
1018-
char* msg_dup = strdup(parser->error_msg);
1019-
Expr* callee = expr_ident(strdup("THROW"), parser->error_line, parser->error_col);
1020-
Expr* call = expr_call(callee, parser->error_line, parser->error_col);
1021-
Expr* arg = expr_str(msg_dup, parser->error_line, parser->error_col);
1022-
expr_list_add(&call->as.call.args, arg);
1023-
Stmt* err_stmt = stmt_expr(call, parser->error_line, parser->error_col);
1024-
stmt_list_add(&program->as.block, err_stmt);
1025-
free(parser->error_msg);
1026-
parser->error_msg = NULL;
1027-
parser->had_error = false;
1028-
parser->panic_mode = false;
1055+
append_parse_error_throw_stmt(parser, program);
10291056
}
10301057

10311058
/* Synchronize after an error: advance to next newline or EOF so the

0 commit comments

Comments
 (0)