feat: add error messages to number lexing

This commit is contained in:
Fernando Araoz 2024-12-29 08:16:40 -05:00
parent d833c44eb8
commit c969830a42
2 changed files with 36 additions and 6 deletions

View File

@ -143,11 +143,11 @@ fn integer(
return switch (next_char) { return switch (next_char) {
// if a dot is found, lex a fp number // if a dot is found, lex a fp number
'.' => { '.' => {
return floating_point(input, cap, start, last_pos); return floating_point(input, cap, start, last_pos, err, alloc);
}, },
// if an `e` (exponential notiation) is found, lex that // if an `e` (exponential notiation) is found, lex that
'e' => { 'e' => {
return scientific(input, cap, start, last_pos); return scientific(input, cap, start, last_pos, err, alloc);
}, },
// otherwise return the current integer // otherwise return the current integer
else => { else => {
@ -172,12 +172,23 @@ fn integer(
/// ///
/// token_start: the position the current token started at /// token_start: the position the current token started at
/// decimal_point: the position of the decimal point `.` /// decimal_point: the position of the decimal point `.`
fn floating_point(input: []const u8, cap: usize, token_start: usize, period_pos: usize) LexError!?LexReturn { fn floating_point(
input: []const u8,
cap: usize,
token_start: usize,
period_pos: usize,
err: *errors.ErrorData,
alloc: std.mem.Allocator,
) LexError!?LexReturn {
var current_pos = period_pos + 1; var current_pos = period_pos + 1;
// there should be at least 1 digit after the period // there should be at least 1 digit after the period
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
try err.init("Incomplete floating point number", token_start, current_pos, alloc);
try err.add_label("This number is incomplete", token_start, current_pos);
err.set_help("Add a number after the period");
return LexError.IncompleteFloatingNumber; return LexError.IncompleteFloatingNumber;
} }
@ -190,7 +201,7 @@ fn floating_point(input: []const u8, cap: usize, token_start: usize, period_pos:
// check if the current character is a `e`, // check if the current character is a `e`,
// if so lex a scientific number // if so lex a scientific number
if (current_pos < cap and input[current_pos] == 'e') { if (current_pos < cap and input[current_pos] == 'e') {
return scientific(input, cap, token_start, current_pos); return scientific(input, cap, token_start, current_pos, err, alloc);
} }
// return the matched fp number // return the matched fp number
@ -201,15 +212,30 @@ fn floating_point(input: []const u8, cap: usize, token_start: usize, period_pos:
} }
/// exp_pos is the position at the `e` character /// exp_pos is the position at the `e` character
fn scientific(input: []const u8, cap: usize, token_start: usize, exp_pos: usize) LexError!?LexReturn { fn scientific(
input: []const u8,
cap: usize,
token_start: usize,
exp_pos: usize,
err: *errors.ErrorData,
alloc: std.mem.Allocator,
) LexError!?LexReturn {
var current_pos = exp_pos + 1; var current_pos = exp_pos + 1;
// expect `+` or `-` // expect `+` or `-`
if (current_pos >= cap) { if (current_pos >= cap) {
try err.init("Incomplete scientific point number", token_start, current_pos, alloc);
try err.add_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; return LexError.IncompleteScientificNumber;
} }
const sign_char = input[current_pos]; const sign_char = input[current_pos];
if (sign_char != '+' and sign_char != '-') { if (sign_char != '+' and sign_char != '-') {
try err.init("Incomplete scientific point number", current_pos, current_pos + 1, alloc);
try err.add_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; return LexError.IncompleteScientificNumber;
} }
current_pos += 1; current_pos += 1;
@ -222,6 +248,10 @@ fn scientific(input: []const u8, cap: usize, token_start: usize, exp_pos: usize)
// 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) {
try err.init("Incomplete scientific point number", current_pos - 1, current_pos, alloc);
try err.add_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; return LexError.IncompleteScientificNumber;
} }

View File

@ -45,7 +45,7 @@ pub fn tokenize(
var current_error: errors.ErrorData = undefined; var current_error: errors.ErrorData = undefined;
const number_lex = number.lex(input, input_len, actual_next_pos, &current_error, alloc) catch |e| switch (e) { const number_lex = number.lex(input, input_len, actual_next_pos, &current_error, alloc) catch |e| switch (e) {
// recoverable errors // recoverable errors
LexError.Incomplete, LexError.LeadingZero => { LexError.Incomplete, LexError.LeadingZero, LexError.IncompleteFloatingNumber, LexError.IncompleteScientificNumber => {
// add to list of errors // add to list of errors
try err_arrl.append(current_error); try err_arrl.append(current_error);