about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMel <mel@rnrd.eu>2025-07-10 00:27:39 +0200
committerMel <mel@rnrd.eu>2025-07-10 00:27:39 +0200
commit4ef58f4d2b7ea810ab4d5db08fe45216f6597336 (patch)
tree57d9f00a74dabfda6f221b97579cd78f35641182
parent961ca5fb2c5aaf45b81c154874e503564afc2290 (diff)
downloadcatskill-4ef58f4d2b7ea810ab4d5db08fe45216f6597336.tar.zst
catskill-4ef58f4d2b7ea810ab4d5db08fe45216f6597336.zip
Display causing tokens lexeme directly from source for error messages
Signed-off-by: Mel <mel@rnrd.eu>
-rw-r--r--boot/catboot.c2
-rw-r--r--boot/lex.c12
-rw-r--r--boot/parse.c13
3 files changed, 19 insertions, 8 deletions
diff --git a/boot/catboot.c b/boot/catboot.c
index ed5831e..155c3c5 100644
--- a/boot/catboot.c
+++ b/boot/catboot.c
@@ -87,7 +87,7 @@ debug_lex_pass(struct String source)
     struct Token token;
     do {
         token = lexer_next(&lexer);
-        token_print(&token);
+        token_debug_print(&token);
         printf(" ");
     } while (token.kind != TOKEN_END_OF_FILE);
 
diff --git a/boot/lex.c b/boot/lex.c
index 2efb33d..594905f 100644
--- a/boot/lex.c
+++ b/boot/lex.c
@@ -192,6 +192,8 @@ enum Token_Kind
     TOKEN_ASSIGN_RIGHT_SHIFT,
 };
 
+// returns a string representation of the token kind.
+// non-human-friendly, for debugging purposes.
 const ascii*
 token_kind_to_string(enum Token_Kind kind)
 {
@@ -454,8 +456,9 @@ token_can_begin_declaration(const struct Token* t)
     return token_is(t, TOKEN_WORD_VAR) || token_is(t, TOKEN_WORD_LET);
 }
 
+// prints non-human-friendly representation of the token kind, along with its value, if applicable.
 void
-token_print(const struct Token* t)
+token_debug_print(const struct Token* t)
 {
     printf("%s", token_kind_to_string(t->kind));
 
@@ -472,6 +475,13 @@ token_print(const struct Token* t)
     }
 }
 
+// get a view of the token's lexeme in the source file.
+struct String_View
+token_lexeme(const struct Token* t, struct String source)
+{
+    return string_substring(source, t->span.start, t->span.end);
+}
+
 bool
 ascii_in_range(ascii c, ascii from, ascii to)
 {
diff --git a/boot/parse.c b/boot/parse.c
index adf434b..687659e 100644
--- a/boot/parse.c
+++ b/boot/parse.c
@@ -124,7 +124,7 @@ parser_error_display(const struct Parser_Error* error, struct Source_File source
 
     struct Token cause = error->cause;
 
-    fprintf(stderr, ANSI_WHITE "%s:%lu:%lu:\n", source_file.path.data, line, column);
+    STRING_FORMAT_TO(source_file.path, stderr, ANSI_WHITE "%s:%lu:%lu:\n", 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),
@@ -132,15 +132,16 @@ parser_error_display(const struct Parser_Error* error, struct Source_File source
     } else {
         fprintf(stderr, "%s", parser_error_kind_to_string(error->kind));
     }
-    // TODO: display tokens nicely
-    fprintf(stderr, ", got '%s' :(\n", token_kind_to_string(cause.kind));
+    struct String_View cause_lexeme = token_lexeme(&cause, source_file.source);
+    STRING_FORMAT_TO(cause_lexeme, stderr, ", got '%S' :(\n");
 
     struct Span line_span = token_span_to_line_span(cause.span, source_file.source);
 
-    ascii* source_line = source_file.source.data + line_span.start;
-    int source_line_length = line_span.end - line_span.start;
+    struct String_View source_line =
+        string_substring(source_file.source, line_span.start, line_span.end);
 
-    fprintf(stderr, ANSI_WHITE ANSI_NO_BOLD "%lu| %.*s\n", line, source_line_length, source_line);
+    fprintf(stderr, ANSI_WHITE ANSI_NO_BOLD "%lu| ", line);
+    STRING_FORMAT_TO(source_line, stderr, "%S\n");
 
     uint line_number_length = ceil(log10(line + 1));
     fprintf(stderr, ANSI_RED "%*s", (int)(column + 1 + line_number_length), " ");