From 35a022cdf9c7422613dbb2d1bc579fed59270899 Mon Sep 17 00:00:00 2001 From: Fernando Araoz Date: Thu, 30 Jan 2025 20:55:36 -0500 Subject: [PATCH] refactor: pass all tests on lexic analyzer --- src/01_lexic/comment.zig | 3 +-- src/01_lexic/number.zig | 21 +++++++-------------- src/01_lexic/string.zig | 14 +++++--------- src/context/root.zig | 26 ++++++++++++++++++++------ 4 files changed, 33 insertions(+), 31 deletions(-) diff --git a/src/01_lexic/comment.zig b/src/01_lexic/comment.zig index 972d507..9e1e008 100644 --- a/src/01_lexic/comment.zig +++ b/src/01_lexic/comment.zig @@ -31,8 +31,7 @@ pub fn lex( // check for CR, and throw error if (input[current_pos] == '\r') { var err = try ctx.create_and_append_error("Usage of CRLF", current_pos, current_pos + 1); - var label = ctx.create_error_label("There is a line feed (CR) here", current_pos, current_pos + 1); - try err.add_label(&label); + try err.add_label(ctx.create_error_label("There is a line feed (CR) here", current_pos, current_pos + 1)); err.set_help("All THP code must use LF newline delimiters."); return LexError.CRLF; diff --git a/src/01_lexic/number.zig b/src/01_lexic/number.zig index 834d7d1..3cb1a6d 100644 --- a/src/01_lexic/number.zig +++ b/src/01_lexic/number.zig @@ -66,8 +66,7 @@ fn prefixed( if (end_position >= cap or !validator(input[end_position])) { // populate error information var new_error = try ctx.create_and_append_error("Incomplete number", start, end_position); - var new_label = ctx.create_error_label("Expected a valid digit after the '" ++ [_]u8{prefix} ++ "'", start, end_position); - try new_error.add_label(&new_label); + try new_error.add_label(ctx.create_error_label("Expected a valid digit after the '" ++ [_]u8{prefix} ++ "'", start, end_position)); switch (prefix) { 'x' => new_error.set_help("Hex numbers should have at least one 0-9a-fA-F after the x"), @@ -128,8 +127,7 @@ fn integer( // - a single zero. valid if (first_char == '0' and last_pos > start + 1) { var err = try ctx.create_and_append_error("Leading zero", start, start + 1); - var label = ctx.create_error_label("This decimal number has a leading zero.", start, last_pos); - try err.add_label(&label); + try err.add_label(ctx.create_error_label("This decimal number has a leading zero.", start, last_pos)); err.set_help("If you want an octal number use '0o', otherwise remove the leading zero"); return LexError.LeadingZero; @@ -157,8 +155,7 @@ fn integer( // leading zero on an integer, throw an error if (first_char == '0') { var err = try ctx.create_and_append_error("Leading zero", start, start + 1); - var label = ctx.create_error_label("This decimal number has a leading zero.", start, last_pos); - try err.add_label(&label); + try err.add_label(ctx.create_error_label("This decimal number has a leading zero.", start, last_pos)); err.set_help("If you want an octal number use '0o', otherwise remove the leading zero"); return LexError.LeadingZero; @@ -189,8 +186,7 @@ fn floating_point( if (current_pos >= cap or !utils.is_decimal_digit(input[current_pos])) { // This is an error var err = try ctx.create_and_append_error("Incomplete floating point number", token_start, current_pos); - var label = ctx.create_error_label("This number is incomplete", token_start, current_pos); - try err.add_label(&label); + try err.add_label(ctx.create_error_label("This number is incomplete", token_start, current_pos)); err.set_help("Add a number after the period"); return LexError.IncompleteFloatingNumber; @@ -228,8 +224,7 @@ fn scientific( // expect `+` or `-` if (current_pos >= cap) { var err = try ctx.create_and_append_error("Incomplete scientific point number", token_start, current_pos); - var label = ctx.create_error_label("Expected a '+' or '-' after the exponent", token_start, current_pos); - try err.add_label(&label); + try err.add_label(ctx.create_error_label("Expected a '+' or '-' after the exponent", token_start, current_pos)); err.set_help("Add a sign and a digit to complete the scientific number"); return LexError.IncompleteScientificNumber; @@ -237,8 +232,7 @@ fn scientific( const sign_char = input[current_pos]; if (sign_char != '+' and sign_char != '-') { var err = try ctx.create_and_append_error("Incomplete scientific point number", current_pos, current_pos + 1); - var label = ctx.create_error_label("Expected a '+' or '-' here, found another char", current_pos, current_pos + 1); - try err.add_label(&label); + try err.add_label(ctx.create_error_label("Expected a '+' or '-' here, found another char", current_pos, current_pos + 1)); err.set_help("Add a sign and a digit after the first 'e' to complete the scientific number"); return LexError.IncompleteScientificNumber; @@ -254,8 +248,7 @@ fn scientific( // if there is no difference, no extra digits were lexed. if (digits_start == current_pos) { var err = try ctx.create_and_append_error("Incomplete scientific point number", current_pos - 1, current_pos); - var label = ctx.create_error_label("Expected at least one digit after this sign", current_pos - 1, current_pos); - try err.add_label(&label); + try err.add_label(ctx.create_error_label("Expected at least one digit after this sign", current_pos - 1, current_pos)); err.set_help("Add a digit after the sign to complit the scientific number"); return LexError.IncompleteScientificNumber; diff --git a/src/01_lexic/string.zig b/src/01_lexic/string.zig index 76eb36a..cb6ab0d 100644 --- a/src/01_lexic/string.zig +++ b/src/01_lexic/string.zig @@ -37,8 +37,7 @@ pub fn lex( // new line, initialize and return error else if (next_char == '\n') { var err = try ctx.create_and_append_error("Incomplete String", current_pos, current_pos + 1); - var label = ctx.create_error_label("Found a new line here", current_pos, current_pos + 1); - try err.add_label(&label); + try err.add_label(ctx.create_error_label("Found a new line here", current_pos, current_pos + 1)); err.set_help("Strings must always end on the same line that they start."); return LexError.IncompleteString; @@ -48,16 +47,14 @@ pub fn lex( // if next char is EOF, return error if (current_pos + 1 == cap) { var err = try ctx.create_and_append_error("Incomplete String", current_pos, current_pos + 1); - var label = ctx.create_error_label("Found EOF here", current_pos, current_pos + 1); - try err.add_label(&label); + try err.add_label(ctx.create_error_label("Found EOF here", current_pos, current_pos + 1)); err.set_help("Strings must always end on the same line that they start."); return LexError.IncompleteString; } // if next char is newline, return error else if (input[current_pos + 1] == '\n') { var err = try ctx.create_and_append_error("Incomplete String", current_pos, current_pos + 1); - var label = ctx.create_error_label("Found a new line here", current_pos, current_pos + 1); - try err.add_label(&label); + try err.add_label(ctx.create_error_label("Found a new line here", current_pos, current_pos + 1)); err.set_help("Strings must always end on the same line that they start."); return LexError.IncompleteString; } @@ -70,10 +67,9 @@ pub fn lex( current_pos += 1; } - // this could only reach when EOF is hit, return error + // this can only happen when EOF is hit, return error var err = try ctx.create_and_append_error("Incomplete String", current_pos, current_pos + 1); - var label = ctx.create_error_label("Found EOF here", current_pos, current_pos + 1); - try err.add_label(&label); + try err.add_label(ctx.create_error_label("Found EOF here", current_pos, current_pos + 1)); err.set_help("Strings must always end on the same line that they start."); return LexError.IncompleteString; diff --git a/src/context/root.zig b/src/context/root.zig index d681c9e..32be843 100644 --- a/src/context/root.zig +++ b/src/context/root.zig @@ -13,15 +13,26 @@ pub const CompilerContext = struct { }; } - /// Appends a new error to the compiler context - /// and returns a handle to the just created error + /// Creates a new compiler error and appends it to the context's error list. + /// + /// This function creates an `ErrorData` instance and adds it to the context's error list. + /// IMPORTANT: The returned pointer becomes invalid if the error list needs to reallocate, + /// which happens when a new error is appended to the context. + /// + /// Example: + /// ```zig + /// const err = try ctx.create_and_append_error("Syntax error", 10, 15); + /// // Safe to use err here + /// try err.add_label(...); + /// // After this point, err might become invalid if new errors are added + /// ``` pub fn create_and_append_error( self: *CompilerContext, reason: []const u8, start_position: usize, end_position: usize, ) !*ErrorData { - var new_error = ErrorData{ + const new_error = ErrorData{ .reason = reason, .start_position = start_position, .end_position = end_position, @@ -29,8 +40,11 @@ pub const CompilerContext = struct { .help = null, }; + // Append the error to the array list try self.errors.append(new_error); - return &new_error; + // Get a pointer to the newly appended error + const ptr = &self.errors.items[self.errors.items.len - 1]; + return ptr; } /// Creates a new ErrorLabel with a static message. @@ -70,8 +84,8 @@ pub const ErrorData = struct { /// A list of detailed messages about the error labels: std.ArrayList(ErrorLabel), - pub fn add_label(self: *ErrorData, label: *ErrorLabel) !void { - try self.labels.append(label.*); + pub fn add_label(self: *ErrorData, label: ErrorLabel) !void { + try self.labels.append(label); } /// Sets the help message of this error.