about summary refs log tree commit diff
path: root/boot/parse.c
diff options
context:
space:
mode:
authorMel <mel@rnrd.eu>2025-07-09 17:06:19 +0200
committerMel <mel@rnrd.eu>2025-07-09 17:06:19 +0200
commitdeb7edadc446653a70c03e9312bc949cc27ce8c4 (patch)
tree235d39d33a39d6da0023c829aed413cdf743cf99 /boot/parse.c
parentefa510e6b58ce13c53e94f13a5be0007240e9dcc (diff)
downloadcatskill-deb7edadc446653a70c03e9312bc949cc27ce8c4.tar.zst
catskill-deb7edadc446653a70c03e9312bc949cc27ce8c4.zip
Multi-error display and fix up finding line boundries
Signed-off-by: Mel <mel@rnrd.eu>
Diffstat (limited to 'boot/parse.c')
-rw-r--r--boot/parse.c54
1 files changed, 28 insertions, 26 deletions
diff --git a/boot/parse.c b/boot/parse.c
index 6daca8f..2891a0f 100644
--- a/boot/parse.c
+++ b/boot/parse.c
@@ -103,18 +103,13 @@ token_span_to_line_span(struct Span span, struct String source)
     Pos line_start = span.start + 1, line_end = span.end - 1;
     // expand `line_start` to start from the beginning of the line,
     // and `line_end` to end at the end of the line.
-    ascii c;
-    if (line_start > 0) {
-        do {
-            c = string_at(source, line_start - 1);
-            line_start--;
-        } while (line_start > 0 && c != '\n');
+    while (line_start > 0) {
+        if (string_at(source, line_start - 1) == '\n') break;
+        line_start--;
     }
-    if (line_end < string_length(source)) {
-        do {
-            c = string_at(source, line_end + 1);
-            line_end++;
-        } while (line_end < string_length(source) && c != '\n');
+    while (line_end < string_length(source)) {
+        if (string_at(source, line_end) == '\n') break;
+        line_end++;
     }
 
     return span_new(line_start, line_end);
@@ -137,13 +132,13 @@ parser_error_display(const struct Parser_Error* error, struct Source_File source
     fprintf(stderr, ANSI_WHITE "%s:%lu:%lu:\n", source_file.path.data, line, column);
     fprintf(stderr, ANSI_BOLD ANSI_RED "error: " ANSI_WHITE);
     if (error->subkind != PARSER_ERROR_NONE) {
-        fprintf(stderr, "%s: %s ", parser_error_kind_to_string(error->kind),
+        fprintf(stderr, "%s: %s", parser_error_kind_to_string(error->kind),
                 parser_error_kind_to_string(error->subkind));
     } else {
-        fprintf(stderr, "%s ", parser_error_kind_to_string(error->kind));
+        fprintf(stderr, "%s", parser_error_kind_to_string(error->kind));
     }
     // TODO: display tokens nicely
-    fprintf(stderr, "'%s' :(\n", token_kind_to_string(cause.kind));
+    fprintf(stderr, ", got '%s' :(\n", token_kind_to_string(cause.kind));
 
     struct Span line_span = token_span_to_line_span(cause.span, source_file.source);
 
@@ -151,7 +146,9 @@ parser_error_display(const struct Parser_Error* error, struct Source_File source
     int source_line_length = line_span.end - line_span.start;
 
     fprintf(stderr, ANSI_WHITE ANSI_NO_BOLD "%lu| %.*s\n", line, source_line_length, source_line);
-    fprintf(stderr, ANSI_RED "%*s", (int)column + 3 - 1, " "); // +3 for the line number and space
+
+    uint line_number_length = ceil(log10(line + 1));
+    fprintf(stderr, ANSI_RED "%*s", (int)(column + 1 + line_number_length), " ");
     for (uint w = 0; w < span_length(cause.span); w++) { fprintf(stderr, "^"); }
     fprintf(stderr, "\n" ANSI_RESET);
 }
@@ -1475,23 +1472,28 @@ parser_do_your_thing(struct Parser* p, struct Tree* tree)
     parser_error_none(&error);
 
     struct Statement* head = nil;
-
     struct Statement* current = nil;
     while (!parser_reached_end(p)) {
         struct Statement* next = parser_statement(p, &error);
         parser_handle_error(p, &error);
 
-        if (!next) break; // on eof
-
-        parser_end_statement(p, &error);
-        parser_handle_error(p, &error);
-
-        if (current) {
-            current->next = next;
-        } else {
-            head = next;
+        if (next) {
+            parser_end_statement(p, &error);
+
+            if (parser_error_is_none(&error)) {
+                if (current) {
+                    current->next = next;
+                } else {
+                    head = next;
+                }
+                current = next;
+            } else {
+                parser_handle_error(p, &error);
+            }
+        } else if (parser_reached_end(p)) {
+            // `parser_statement` returns nil on EOF.
+            break;
         }
-        current = next;
     }
 
     parser_error_none(&error);