refactor: pass all tests on lexic analyzer

This commit is contained in:
Fernando Araoz 2025-01-30 20:55:36 -05:00
parent 8425f621eb
commit 35a022cdf9
4 changed files with 33 additions and 31 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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.