refactor: pass all tests on lexic analyzer
This commit is contained in:
parent
8425f621eb
commit
35a022cdf9
@ -31,8 +31,7 @@ pub fn lex(
|
|||||||
// check for CR, and throw error
|
// check for CR, and throw error
|
||||||
if (input[current_pos] == '\r') {
|
if (input[current_pos] == '\r') {
|
||||||
var err = try ctx.create_and_append_error("Usage of CRLF", current_pos, current_pos + 1);
|
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(ctx.create_error_label("There is a line feed (CR) here", current_pos, current_pos + 1));
|
||||||
try err.add_label(&label);
|
|
||||||
err.set_help("All THP code must use LF newline delimiters.");
|
err.set_help("All THP code must use LF newline delimiters.");
|
||||||
|
|
||||||
return LexError.CRLF;
|
return LexError.CRLF;
|
||||||
|
@ -66,8 +66,7 @@ fn prefixed(
|
|||||||
if (end_position >= cap or !validator(input[end_position])) {
|
if (end_position >= cap or !validator(input[end_position])) {
|
||||||
// populate error information
|
// populate error information
|
||||||
var new_error = try ctx.create_and_append_error("Incomplete number", start, end_position);
|
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(ctx.create_error_label("Expected a valid digit after the '" ++ [_]u8{prefix} ++ "'", start, end_position));
|
||||||
try new_error.add_label(&new_label);
|
|
||||||
|
|
||||||
switch (prefix) {
|
switch (prefix) {
|
||||||
'x' => new_error.set_help("Hex numbers should have at least one 0-9a-fA-F after the x"),
|
'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
|
// - a single zero. valid
|
||||||
if (first_char == '0' and last_pos > start + 1) {
|
if (first_char == '0' and last_pos > start + 1) {
|
||||||
var err = try ctx.create_and_append_error("Leading zero", start, 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(ctx.create_error_label("This decimal number has a leading zero.", start, last_pos));
|
||||||
try err.add_label(&label);
|
|
||||||
err.set_help("If you want an octal number use '0o', otherwise remove the leading zero");
|
err.set_help("If you want an octal number use '0o', otherwise remove the leading zero");
|
||||||
|
|
||||||
return LexError.LeadingZero;
|
return LexError.LeadingZero;
|
||||||
@ -157,8 +155,7 @@ fn integer(
|
|||||||
// leading zero on an integer, throw an error
|
// leading zero on an integer, throw an error
|
||||||
if (first_char == '0') {
|
if (first_char == '0') {
|
||||||
var err = try ctx.create_and_append_error("Leading zero", start, 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(ctx.create_error_label("This decimal number has a leading zero.", start, last_pos));
|
||||||
try err.add_label(&label);
|
|
||||||
err.set_help("If you want an octal number use '0o', otherwise remove the leading zero");
|
err.set_help("If you want an octal number use '0o', otherwise remove the leading zero");
|
||||||
|
|
||||||
return LexError.LeadingZero;
|
return LexError.LeadingZero;
|
||||||
@ -189,8 +186,7 @@ fn floating_point(
|
|||||||
if (current_pos >= cap or !utils.is_decimal_digit(input[current_pos])) {
|
if (current_pos >= cap or !utils.is_decimal_digit(input[current_pos])) {
|
||||||
// This is an error
|
// This is an error
|
||||||
var err = try ctx.create_and_append_error("Incomplete floating point number", token_start, current_pos);
|
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(ctx.create_error_label("This number is incomplete", token_start, current_pos));
|
||||||
try err.add_label(&label);
|
|
||||||
err.set_help("Add a number after the period");
|
err.set_help("Add a number after the period");
|
||||||
|
|
||||||
return LexError.IncompleteFloatingNumber;
|
return LexError.IncompleteFloatingNumber;
|
||||||
@ -228,8 +224,7 @@ fn scientific(
|
|||||||
// expect `+` or `-`
|
// expect `+` or `-`
|
||||||
if (current_pos >= cap) {
|
if (current_pos >= cap) {
|
||||||
var err = try ctx.create_and_append_error("Incomplete scientific point number", token_start, current_pos);
|
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(ctx.create_error_label("Expected a '+' or '-' after the exponent", token_start, current_pos));
|
||||||
try err.add_label(&label);
|
|
||||||
err.set_help("Add a sign and a digit to complete the scientific number");
|
err.set_help("Add a sign and a digit to complete the scientific number");
|
||||||
|
|
||||||
return LexError.IncompleteScientificNumber;
|
return LexError.IncompleteScientificNumber;
|
||||||
@ -237,8 +232,7 @@ fn scientific(
|
|||||||
const sign_char = input[current_pos];
|
const sign_char = input[current_pos];
|
||||||
if (sign_char != '+' and sign_char != '-') {
|
if (sign_char != '+' and sign_char != '-') {
|
||||||
var err = try ctx.create_and_append_error("Incomplete scientific point number", current_pos, current_pos + 1);
|
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(ctx.create_error_label("Expected a '+' or '-' here, found another char", current_pos, current_pos + 1));
|
||||||
try err.add_label(&label);
|
|
||||||
err.set_help("Add a sign and a digit after the first 'e' to complete the scientific number");
|
err.set_help("Add a sign and a digit after the first 'e' to complete the scientific number");
|
||||||
|
|
||||||
return LexError.IncompleteScientificNumber;
|
return LexError.IncompleteScientificNumber;
|
||||||
@ -254,8 +248,7 @@ fn scientific(
|
|||||||
// if there is no difference, no extra digits were lexed.
|
// if there is no difference, no extra digits were lexed.
|
||||||
if (digits_start == current_pos) {
|
if (digits_start == current_pos) {
|
||||||
var err = try ctx.create_and_append_error("Incomplete scientific point number", current_pos - 1, 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(ctx.create_error_label("Expected at least one digit after this sign", current_pos - 1, current_pos));
|
||||||
try err.add_label(&label);
|
|
||||||
err.set_help("Add a digit after the sign to complit the scientific number");
|
err.set_help("Add a digit after the sign to complit the scientific number");
|
||||||
|
|
||||||
return LexError.IncompleteScientificNumber;
|
return LexError.IncompleteScientificNumber;
|
||||||
|
@ -37,8 +37,7 @@ pub fn lex(
|
|||||||
// new line, initialize and return error
|
// new line, initialize and return error
|
||||||
else if (next_char == '\n') {
|
else if (next_char == '\n') {
|
||||||
var err = try ctx.create_and_append_error("Incomplete String", current_pos, current_pos + 1);
|
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(ctx.create_error_label("Found a new line here", current_pos, current_pos + 1));
|
||||||
try err.add_label(&label);
|
|
||||||
err.set_help("Strings must always end on the same line that they start.");
|
err.set_help("Strings must always end on the same line that they start.");
|
||||||
|
|
||||||
return LexError.IncompleteString;
|
return LexError.IncompleteString;
|
||||||
@ -48,16 +47,14 @@ pub fn lex(
|
|||||||
// if next char is EOF, return error
|
// if next char is EOF, return error
|
||||||
if (current_pos + 1 == cap) {
|
if (current_pos + 1 == cap) {
|
||||||
var err = try ctx.create_and_append_error("Incomplete String", current_pos, current_pos + 1);
|
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(ctx.create_error_label("Found EOF here", current_pos, current_pos + 1));
|
||||||
try err.add_label(&label);
|
|
||||||
err.set_help("Strings must always end on the same line that they start.");
|
err.set_help("Strings must always end on the same line that they start.");
|
||||||
return LexError.IncompleteString;
|
return LexError.IncompleteString;
|
||||||
}
|
}
|
||||||
// if next char is newline, return error
|
// if next char is newline, return error
|
||||||
else if (input[current_pos + 1] == '\n') {
|
else if (input[current_pos + 1] == '\n') {
|
||||||
var err = try ctx.create_and_append_error("Incomplete String", current_pos, current_pos + 1);
|
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(ctx.create_error_label("Found a new line here", current_pos, current_pos + 1));
|
||||||
try err.add_label(&label);
|
|
||||||
err.set_help("Strings must always end on the same line that they start.");
|
err.set_help("Strings must always end on the same line that they start.");
|
||||||
return LexError.IncompleteString;
|
return LexError.IncompleteString;
|
||||||
}
|
}
|
||||||
@ -70,10 +67,9 @@ pub fn lex(
|
|||||||
current_pos += 1;
|
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 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(ctx.create_error_label("Found EOF here", current_pos, current_pos + 1));
|
||||||
try err.add_label(&label);
|
|
||||||
err.set_help("Strings must always end on the same line that they start.");
|
err.set_help("Strings must always end on the same line that they start.");
|
||||||
|
|
||||||
return LexError.IncompleteString;
|
return LexError.IncompleteString;
|
||||||
|
@ -13,15 +13,26 @@ pub const CompilerContext = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Appends a new error to the compiler context
|
/// Creates a new compiler error and appends it to the context's error list.
|
||||||
/// and returns a handle to the just created error
|
///
|
||||||
|
/// 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(
|
pub fn create_and_append_error(
|
||||||
self: *CompilerContext,
|
self: *CompilerContext,
|
||||||
reason: []const u8,
|
reason: []const u8,
|
||||||
start_position: usize,
|
start_position: usize,
|
||||||
end_position: usize,
|
end_position: usize,
|
||||||
) !*ErrorData {
|
) !*ErrorData {
|
||||||
var new_error = ErrorData{
|
const new_error = ErrorData{
|
||||||
.reason = reason,
|
.reason = reason,
|
||||||
.start_position = start_position,
|
.start_position = start_position,
|
||||||
.end_position = end_position,
|
.end_position = end_position,
|
||||||
@ -29,8 +40,11 @@ pub const CompilerContext = struct {
|
|||||||
.help = null,
|
.help = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Append the error to the array list
|
||||||
try self.errors.append(new_error);
|
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.
|
/// Creates a new ErrorLabel with a static message.
|
||||||
@ -70,8 +84,8 @@ pub const ErrorData = struct {
|
|||||||
/// A list of detailed messages about the error
|
/// A list of detailed messages about the error
|
||||||
labels: std.ArrayList(ErrorLabel),
|
labels: std.ArrayList(ErrorLabel),
|
||||||
|
|
||||||
pub fn add_label(self: *ErrorData, label: *ErrorLabel) !void {
|
pub fn add_label(self: *ErrorData, label: ErrorLabel) !void {
|
||||||
try self.labels.append(label.*);
|
try self.labels.append(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the help message of this error.
|
/// Sets the help message of this error.
|
||||||
|
Loading…
Reference in New Issue
Block a user