44#include <string.h>
55#include <stdlib.h>
66
7+ #ifdef _MSC_VER
8+ #define strdup _strdup
9+ #endif
10+
711static void report_error (Parser * parser , const char * message ) {
812 if (parser -> panic_mode ) return ;
913 parser -> panic_mode = true;
1014 parser -> had_error = true;
15+ /* Record last error for possible conversion into a runtime THROW
16+ so TRY/CATCH can handle parse-time errors that occur inside
17+ parsed blocks. Also emit the usual diagnostic to stderr. */
18+ if (parser -> error_msg ) { free (parser -> error_msg ); parser -> error_msg = NULL ; }
19+ parser -> error_msg = strdup (message );
20+ parser -> error_line = parser -> current_token .line ;
21+ parser -> error_col = parser -> current_token .column ;
1122 fprintf (stderr , "ParseError at %d:%d: %s\n" ,
1223 parser -> current_token .line , parser -> current_token .column , message );
1324}
@@ -16,6 +27,9 @@ void parser_init(Parser* parser, Lexer* lexer) {
1627 parser -> lexer = lexer ;
1728 parser -> panic_mode = false;
1829 parser -> had_error = false;
30+ parser -> error_msg = NULL ;
31+ parser -> error_line = 0 ;
32+ parser -> error_col = 0 ;
1933 parser -> current_token = lexer_next_token (parser -> lexer );
2034 parser -> next_token = lexer_next_token (parser -> lexer );
2135}
@@ -784,9 +798,28 @@ Stmt* parser_parse(Parser* parser) {
784798 continue ;
785799 }
786800
801+ /* If a parse error was recorded, synthesize a runtime THROW call
802+ statement so that runtime TRY/CATCH can observe the parse error
803+ as a catchable runtime exception. Then clear the parser error
804+ state so callers (e.g. RUN/IMPORT) don't treat it as a fatal
805+ top-level parse failure. */
806+ if (parser -> error_msg ) {
807+ char * msg_dup = strdup (parser -> error_msg );
808+ Expr * callee = expr_ident (strdup ("THROW" ), parser -> error_line , parser -> error_col );
809+ Expr * call = expr_call (callee , parser -> error_line , parser -> error_col );
810+ Expr * arg = expr_str (msg_dup , parser -> error_line , parser -> error_col );
811+ expr_list_add (& call -> as .call .args , arg );
812+ Stmt * err_stmt = stmt_expr (call , parser -> error_line , parser -> error_col );
813+ stmt_list_add (& program -> as .block , err_stmt );
814+ free (parser -> error_msg );
815+ parser -> error_msg = NULL ;
816+ parser -> had_error = false;
817+ parser -> panic_mode = false;
818+ }
819+
787820 /* Synchronize after an error: advance to next newline or EOF so the
788821 parser makes progress instead of repeatedly returning NULL and
789- hanging. Clear panic mode to allow further error reports. */
822+ hanging. */
790823 while (parser -> current_token .type != TOKEN_EOF && parser -> current_token .type != TOKEN_NEWLINE ) {
791824 advance (parser );
792825 }
0 commit comments