|
17 | 17 | #include <stdarg.h>
|
18 | 18 | #include <stdbool.h>
|
19 | 19 | #include <stdlib.h>
|
| 20 | +#include <string.h> |
20 | 21 |
|
21 | 22 | #include "interpreter/ast.h"
|
22 | 23 | #include "interpreter/error.h"
|
@@ -77,6 +78,19 @@ static ArenaLL arguments(Parser *parser);
|
77 | 78 |
|
78 | 79 | static void handle_parse_err(Parser *parser, char *msg);
|
79 | 80 |
|
| 81 | +static ParseError *new_parse_error(Arena *arena, char *msg, Token *failed) |
| 82 | +{ |
| 83 | + ParseError *error = m_arena_alloc_struct(arena, ParseError); |
| 84 | + size_t msg_len = strlen(msg); // TODO: could we avoid strlen somehow? |
| 85 | + char *msg_arena = m_arena_alloc(arena, msg_len + 1); |
| 86 | + memcpy(msg_arena, msg, msg_len + 1); |
| 87 | + error->msg = msg_arena; |
| 88 | + error->failed = failed; |
| 89 | + error->next = NULL; |
| 90 | + |
| 91 | + return error; |
| 92 | +} |
| 93 | + |
80 | 94 | /* util/helper functions */
|
81 | 95 | static Token *peek(Parser *parser)
|
82 | 96 | {
|
@@ -196,13 +210,24 @@ static bool match_either(Parser *parser, unsigned int n, ...)
|
196 | 210 | static void handle_parse_err(Parser *parser, char *msg)
|
197 | 211 | {
|
198 | 212 | parser->n_errors++;
|
| 213 | + Token *failed = arraylist_get(parser->tokens, parser->token_pos); |
| 214 | + ParseError *error = new_parse_error(parser->ast_arena, msg, failed); |
| 215 | + if (parser->perr_head == NULL) { |
| 216 | + parser->perr_head = error; |
| 217 | + parser->perr_tail = error; |
| 218 | + } else { |
| 219 | + parser->perr_tail->next = error; |
| 220 | + parser->perr_tail = error; |
| 221 | + } |
| 222 | + |
| 223 | + // report_parse_err(parser, msg); |
| 224 | + |
199 | 225 | if (parser->n_errors >= MAX_PARSE_ERRORS) {
|
200 |
| - report_parse_err(parser, msg); |
201 | 226 | REPORT_IMPL("TOO MANY PARSE ERRORS. Quitting now ...\n");
|
202 | 227 | TODO_LOG("Gracfully quit after deciding to stop parsing.");
|
203 | 228 | exit(1);
|
204 | 229 | }
|
205 |
| - report_parse_err(parser, msg); |
| 230 | + |
206 | 231 | advance(parser);
|
207 | 232 | }
|
208 | 233 |
|
@@ -884,26 +909,31 @@ static ArenaLL arguments(Parser *parser)
|
884 | 909 | }
|
885 | 910 |
|
886 | 911 |
|
887 |
| -StmtsOrErr parse(Arena *ast_arena, ArrayList *tokens, char *input) |
| 912 | +ParseResult parse(Arena *ast_arena, ArrayList *tokens, char *input) |
888 | 913 | {
|
889 | 914 | Parser parser = { .ast_arena = ast_arena,
|
890 | 915 | .tokens = tokens,
|
891 | 916 | .token_pos = 0,
|
892 | 917 | .input = input,
|
893 |
| - .had_error = false, |
894 |
| - .n_errors = 0 }; |
| 918 | + .n_errors = 0, |
| 919 | + .perr_head = NULL, |
| 920 | + .perr_tail = NULL }; |
895 | 921 | ArrayList statements;
|
896 | 922 | arraylist_init(&statements, sizeof(Stmt *));
|
897 | 923 |
|
898 | 924 | /* edge case: empty source file */
|
899 | 925 | ignore(&parser, t_newline);
|
900 | 926 | if (check(&parser, t_eof))
|
901 |
| - return (StmtsOrErr){ .had_error = parser.had_error, .stmts = statements }; |
| 927 | + return (ParseResult){ .n_errors = parser.n_errors, |
| 928 | + .perr_head = parser.perr_head, |
| 929 | + .stmts = statements }; |
902 | 930 |
|
903 | 931 | while (!check(&parser, t_eof)) {
|
904 | 932 | Stmt *stmt = declaration(&parser);
|
905 | 933 | arraylist_append(&statements, &stmt);
|
906 | 934 | }
|
907 | 935 |
|
908 |
| - return (StmtsOrErr){ .had_error = parser.had_error, .stmts = statements }; |
| 936 | + return (ParseResult){ .n_errors = parser.n_errors, |
| 937 | + .perr_head = parser.perr_head, |
| 938 | + .stmts = statements }; |
909 | 939 | }
|
0 commit comments