refactor: use new context in number lexer
This commit is contained in:
parent
e695777f07
commit
f1a6261f32
@ -3,6 +3,7 @@ const assert = std.debug.assert;
|
|||||||
const token = @import("./token.zig");
|
const token = @import("./token.zig");
|
||||||
const utils = @import("./utils.zig");
|
const utils = @import("./utils.zig");
|
||||||
const errors = @import("errors");
|
const errors = @import("errors");
|
||||||
|
const context = @import("context");
|
||||||
|
|
||||||
const Token = token.Token;
|
const Token = token.Token;
|
||||||
const TokenType = token.TokenType;
|
const TokenType = token.TokenType;
|
||||||
@ -18,8 +19,7 @@ pub fn lex(
|
|||||||
input: []const u8,
|
input: []const u8,
|
||||||
cap: usize,
|
cap: usize,
|
||||||
start: usize,
|
start: usize,
|
||||||
err: *errors.ErrorData,
|
ctx: *context.CompilerContext,
|
||||||
alloc: std.mem.Allocator,
|
|
||||||
) LexError!?LexReturn {
|
) LexError!?LexReturn {
|
||||||
assert(start < cap);
|
assert(start < cap);
|
||||||
const first_char = input[start];
|
const first_char = input[start];
|
||||||
@ -28,9 +28,9 @@ pub fn lex(
|
|||||||
if (first_char == '0' and cap > start + 1) {
|
if (first_char == '0' and cap > start + 1) {
|
||||||
const second_char = input[start + 1];
|
const second_char = input[start + 1];
|
||||||
switch (second_char) {
|
switch (second_char) {
|
||||||
'x', 'X' => return prefixed('x', input, cap, start, err, alloc),
|
'x', 'X' => return prefixed('x', input, cap, start, ctx),
|
||||||
'o', 'O' => return prefixed('o', input, cap, start, err, alloc),
|
'o', 'O' => return prefixed('o', input, cap, start, ctx),
|
||||||
'b', 'B' => return prefixed('b', input, cap, start, err, alloc),
|
'b', 'B' => return prefixed('b', input, cap, start, ctx),
|
||||||
else => {
|
else => {
|
||||||
// Continue
|
// Continue
|
||||||
},
|
},
|
||||||
@ -39,7 +39,7 @@ pub fn lex(
|
|||||||
|
|
||||||
// Attempt to lex an integer.
|
// Attempt to lex an integer.
|
||||||
// Floating point numbers are lexed through the int lexer
|
// Floating point numbers are lexed through the int lexer
|
||||||
return integer(input, cap, start, err, alloc);
|
return integer(input, cap, start, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// comptime function for lexing hex, octal and binary numbers.
|
/// comptime function for lexing hex, octal and binary numbers.
|
||||||
@ -51,8 +51,7 @@ fn prefixed(
|
|||||||
input: []const u8,
|
input: []const u8,
|
||||||
cap: usize,
|
cap: usize,
|
||||||
start: usize,
|
start: usize,
|
||||||
err: *errors.ErrorData,
|
ctx: *context.CompilerContext,
|
||||||
alloc: std.mem.Allocator,
|
|
||||||
) !?LexReturn {
|
) !?LexReturn {
|
||||||
const validator = switch (prefix) {
|
const validator = switch (prefix) {
|
||||||
'x' => utils.is_hex_digit,
|
'x' => utils.is_hex_digit,
|
||||||
@ -66,12 +65,14 @@ fn prefixed(
|
|||||||
// There should be at least 1 valid digit
|
// There should be at least 1 valid digit
|
||||||
if (end_position >= cap or !validator(input[end_position])) {
|
if (end_position >= cap or !validator(input[end_position])) {
|
||||||
// populate error information
|
// populate error information
|
||||||
try err.init("Incomplete number", start, end_position, alloc);
|
var new_error = try ctx.create_and_append_error("Incomplete number", start, end_position);
|
||||||
try err.add_label("Expected a valid digit after the '" ++ [_]u8{prefix} ++ "'", start, end_position);
|
var new_label = ctx.create_error_label("Expected a valid digit after the '" ++ [_]u8{prefix} ++ "'", start, end_position);
|
||||||
|
new_error.add_label(&new_label);
|
||||||
|
|
||||||
switch (prefix) {
|
switch (prefix) {
|
||||||
'x' => err.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"),
|
||||||
'o' => err.set_help("Octal numbers should have at least one 0-7 after the o"),
|
'o' => new_error.set_help("Octal numbers should have at least one 0-7 after the o"),
|
||||||
'b' => err.set_help("Binary numbers should have at least one 0-1 after the b"),
|
'b' => new_error.set_help("Binary numbers should have at least one 0-1 after the b"),
|
||||||
else => @compileError("Invalid prefix passed to `prefixed` function."),
|
else => @compileError("Invalid prefix passed to `prefixed` function."),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,8 +105,7 @@ fn integer(
|
|||||||
input: []const u8,
|
input: []const u8,
|
||||||
cap: usize,
|
cap: usize,
|
||||||
start: usize,
|
start: usize,
|
||||||
err: *errors.ErrorData,
|
ctx: *context.CompilerContext,
|
||||||
alloc: std.mem.Allocator,
|
|
||||||
) LexError!?LexReturn {
|
) LexError!?LexReturn {
|
||||||
assert(start < cap);
|
assert(start < cap);
|
||||||
const first_char = input[start];
|
const first_char = input[start];
|
||||||
@ -127,7 +127,7 @@ fn integer(
|
|||||||
// - a number with a leading zero. throw an error
|
// - a number with a leading zero. throw an error
|
||||||
// - 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) {
|
||||||
try err.init("Leading zero", start, start + 1, alloc);
|
var err = try ctx.create_and_append_error("Leading zero", start, start + 1);
|
||||||
try err.add_label("This decimal number has a leading zero.", start, last_pos);
|
try err.add_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");
|
err.set_help("If you want an octal number use '0o', otherwise remove the leading zero");
|
||||||
|
|
||||||
@ -145,17 +145,17 @@ 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, err, alloc);
|
return floating_point(input, cap, start, last_pos, ctx);
|
||||||
},
|
},
|
||||||
// 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, err, alloc);
|
return scientific(input, cap, start, last_pos, ctx);
|
||||||
},
|
},
|
||||||
// otherwise return the current integer
|
// otherwise return the current integer
|
||||||
else => {
|
else => {
|
||||||
// leading zero on an integer, throw an error
|
// leading zero on an integer, throw an error
|
||||||
if (first_char == '0') {
|
if (first_char == '0') {
|
||||||
try err.init("Leading zero", start, start + 1, alloc);
|
var err = try ctx.create_and_append_error("Leading zero", start, start + 1);
|
||||||
try err.add_label("This decimal number has a leading zero.", start, last_pos);
|
try err.add_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");
|
err.set_help("If you want an octal number use '0o', otherwise remove the leading zero");
|
||||||
|
|
||||||
@ -179,15 +179,14 @@ fn floating_point(
|
|||||||
cap: usize,
|
cap: usize,
|
||||||
token_start: usize,
|
token_start: usize,
|
||||||
period_pos: usize,
|
period_pos: usize,
|
||||||
err: *errors.ErrorData,
|
ctx: *context.CompilerContext,
|
||||||
alloc: std.mem.Allocator,
|
|
||||||
) LexError!?LexReturn {
|
) 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);
|
var err = try ctx.create_and_append_error("Incomplete floating point number", token_start, current_pos);
|
||||||
try err.add_label("This number is incomplete", token_start, current_pos);
|
try err.add_label("This number is incomplete", token_start, current_pos);
|
||||||
err.set_help("Add a number after the period");
|
err.set_help("Add a number after the period");
|
||||||
|
|
||||||
@ -203,7 +202,7 @@ fn floating_point(
|
|||||||
// 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, err, alloc);
|
return scientific(input, cap, token_start, current_pos, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the matched fp number
|
// return the matched fp number
|
||||||
@ -219,14 +218,13 @@ fn scientific(
|
|||||||
cap: usize,
|
cap: usize,
|
||||||
token_start: usize,
|
token_start: usize,
|
||||||
exp_pos: usize,
|
exp_pos: usize,
|
||||||
err: *errors.ErrorData,
|
ctx: *context.CompilerContext,
|
||||||
alloc: std.mem.Allocator,
|
|
||||||
) LexError!?LexReturn {
|
) 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);
|
var err = try ctx.create_and_append_error("Incomplete scientific point number", token_start, current_pos);
|
||||||
try err.add_label("Expected a '+' or '-' after the exponent", token_start, current_pos);
|
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");
|
err.set_help("Add a sign and a digit to complete the scientific number");
|
||||||
|
|
||||||
@ -234,7 +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 != '-') {
|
||||||
try err.init("Incomplete scientific point number", current_pos, current_pos + 1, alloc);
|
var err = try ctx.create_and_append_error("Incomplete scientific point number", current_pos, current_pos + 1);
|
||||||
try err.add_label("Expected a '+' or '-' here, found another char", current_pos, current_pos + 1);
|
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");
|
err.set_help("Add a sign and a digit after the first 'e' to complete the scientific number");
|
||||||
|
|
||||||
@ -250,7 +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) {
|
||||||
try err.init("Incomplete scientific point number", current_pos - 1, current_pos, alloc);
|
var err = try ctx.create_and_append_error("Incomplete scientific point number", current_pos - 1, current_pos);
|
||||||
try err.add_label("Expected at least one digit after this sign", current_pos - 1, current_pos);
|
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");
|
err.set_help("Add a digit after the sign to complit the scientific number");
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user