refactor: migrate syntax parser to new compiler context

This commit is contained in:
Fernando Araoz 2025-01-31 06:24:57 -05:00
parent ac30ea169c
commit 2aa81dd39f
4 changed files with 30 additions and 46 deletions

View File

@ -15,7 +15,6 @@ const TokenStream = types.TokenStream;
pub const Module = struct { pub const Module = struct {
statements: std.ArrayList(statement.Statement), statements: std.ArrayList(statement.Statement),
alloc: std.mem.Allocator,
/// Parses a module. /// Parses a module.
/// ///
@ -27,13 +26,12 @@ pub const Module = struct {
target: *@This(), target: *@This(),
tokens: *const TokenStream, tokens: *const TokenStream,
pos: usize, pos: usize,
allocator: std.mem.Allocator, ctx: *context.CompilerContext,
err_arrl: *std.ArrayList(errors.ErrorData),
) ParseError!void { ) ParseError!void {
var arrl = std.ArrayList(statement.Statement).init(allocator); var arrl = std.ArrayList(statement.Statement).init(ctx.allocator);
errdefer arrl.deinit(); errdefer arrl.deinit();
errdefer for (arrl.items) |i| { errdefer for (arrl.items) |i| {
i.deinit(); i.deinit(ctx);
}; };
const input_len = tokens.items.len; const input_len = tokens.items.len;
@ -42,15 +40,13 @@ pub const Module = struct {
// parse many statements // parse many statements
while (current_pos < input_len) { while (current_pos < input_len) {
var stmt: statement.Statement = undefined; var stmt: statement.Statement = undefined;
var current_error: errors.ErrorData = undefined;
// TODO: handle other errors of vardef parsing // TODO: handle other errors of vardef parsing
const next_pos = stmt.init(tokens, current_pos, &current_error, allocator) catch |e| switch (e) { const next_pos = stmt.init(tokens, current_pos, ctx) catch |e| switch (e) {
error.Error => { error.Error => {
// add the error to the list of errors, // add the error to the list of errors,
// and exit for now because i havent implemented // and exit for now because i havent implemented
// error recovery yet // error recovery yet
try err_arrl.append(current_error);
return error.Error; return error.Error;
}, },
else => return e, else => return e,
@ -63,20 +59,12 @@ pub const Module = struct {
} }
// nothing matched, but there are tokens. this in an error // nothing matched, but there are tokens. this in an error
var err: errors.ErrorData = undefined; _ = try ctx.create_and_append_error("No statement matched", current_pos, current_pos + 1);
try err.init(
"No statement matched",
current_pos,
current_pos + 1,
allocator,
);
try err_arrl.append(err);
return error.Error; return error.Error;
} }
target.* = .{ target.* = .{
.statements = arrl, .statements = arrl,
.alloc = allocator,
}; };
} }

View File

@ -11,7 +11,6 @@ const TokenStream = types.TokenStream;
const ParseError = types.ParseError; const ParseError = types.ParseError;
pub const Statement = struct { pub const Statement = struct {
alloc: std.mem.Allocator,
value: union(enum) { value: union(enum) {
variableBinding: *variable.VariableBinding, variableBinding: *variable.VariableBinding,
}, },
@ -21,35 +20,36 @@ pub const Statement = struct {
target: *Statement, target: *Statement,
tokens: *const TokenStream, tokens: *const TokenStream,
pos: usize, pos: usize,
err: *errors.ErrorData, ctx: *context.CompilerContext,
allocator: std.mem.Allocator,
) ParseError!?usize { ) ParseError!?usize {
// try to parse a variable definition // try to parse a variable definition
var vardef = try allocator.create(variable.VariableBinding); var vardef = try ctx.allocator.create(variable.VariableBinding);
errdefer allocator.destroy(vardef); errdefer ctx.allocator.destroy(vardef);
const vardef_result = try vardef.init(tokens, pos, err, allocator); const vardef_result = try vardef.init(tokens, pos, ctx);
if (vardef_result) |vardef_end| { if (vardef_result) |vardef_end| {
// variable definition parsed // variable definition parsed
// return the parsed variable definition // return the parsed variable definition
target.* = .{ target.* = .{
.alloc = allocator,
.value = .{ .variableBinding = vardef }, .value = .{ .variableBinding = vardef },
}; };
return vardef_end; return vardef_end;
} }
// manually deallocate // manually deallocate
allocator.destroy(vardef); ctx.allocator.destroy(vardef);
return null; return null;
} }
pub fn deinit(self: @This()) void { pub fn deinit(
self: @This(),
ctx: *context.CompilerContext,
) void {
switch (self.value) { switch (self.value) {
.variableBinding => |v| { .variableBinding => |v| {
v.deinit(); v.deinit(ctx);
self.alloc.destroy(v); ctx.allocator.destroy(v);
}, },
} }
} }

View File

@ -14,15 +14,13 @@ pub const VariableBinding = struct {
datatype: ?*lexic.Token, datatype: ?*lexic.Token,
identifier: *lexic.Token, identifier: *lexic.Token,
expression: *expression.Expression, expression: *expression.Expression,
alloc: std.mem.Allocator,
/// Parses a variable binding and returns the position of the next token /// Parses a variable binding and returns the position of the next token
pub fn init( pub fn init(
target: *VariableBinding, target: *VariableBinding,
tokens: *const TokenStream, tokens: *const TokenStream,
pos: usize, pos: usize,
err: *errors.ErrorData, ctx: *context.CompilerContext,
allocator: std.mem.Allocator,
) ParseError!?usize { ) ParseError!?usize {
std.debug.assert(pos < tokens.items.len); std.debug.assert(pos < tokens.items.len);
@ -34,17 +32,16 @@ pub const VariableBinding = struct {
// check there is still input // check there is still input
if (pos + 1 >= tokens.items.len) { if (pos + 1 >= tokens.items.len) {
// return error // return error
try err.init( var err = try ctx.create_and_append_error(
"Incomplete variable declaration", "Incomplete variable declaration",
var_keyword.start_pos, var_keyword.start_pos,
var_keyword.start_pos + var_keyword.value.len, var_keyword.start_pos + var_keyword.value.len,
allocator,
); );
try err.add_label( try err.add_label(ctx.create_error_label(
"This variable declaration is incomplete", "This variable declaration is incomplete",
var_keyword.start_pos, var_keyword.start_pos,
var_keyword.start_pos + var_keyword.value.len, var_keyword.start_pos + var_keyword.value.len,
); ));
return ParseError.Error; return ParseError.Error;
} }
@ -65,26 +62,28 @@ pub const VariableBinding = struct {
// parse expression // parse expression
if (pos + 3 >= tokens.items.len) return ParseError.Error; if (pos + 3 >= tokens.items.len) return ParseError.Error;
const exp = try allocator.create(expression.Expression); const exp = try ctx.allocator.create(expression.Expression);
errdefer allocator.destroy(exp); errdefer ctx.allocator.destroy(exp);
const next_pos = if (exp.init(tokens, pos + 3)) |x| x else { const next_pos = if (exp.init(tokens, pos + 3)) |x| x else {
// TODO: populate error information // TODO: populate error information
return ParseError.Error; return ParseError.Error;
}; };
// return // assign and return
target.* = .{ target.* = .{
.is_mutable = true, .is_mutable = true,
.datatype = null, .datatype = null,
.identifier = identifier, .identifier = identifier,
.expression = exp, .expression = exp,
.alloc = allocator,
}; };
return next_pos; return next_pos;
} }
pub fn deinit(self: @This()) void { pub fn deinit(
self.alloc.destroy(self.expression); self: @This(),
ctx: *context.CompilerContext,
) void {
ctx.allocator.destroy(self.expression);
} }
}; };

View File

@ -116,17 +116,14 @@ fn repl() !void {
continue; continue;
} }
std.debug.print("should be syntax analizing the tokens...\n", .{});
// //
// Syntax analysis // Syntax analysis
// //
var ast: syntax.Module = undefined; var ast: syntax.Module = undefined;
ast.init(&tokens, 0, alloc, &error_array) catch |e| switch (e) { ast.init(&tokens, 0, &ctx) catch |e| switch (e) {
error.Error => { error.Error => {
// Print all the errors // Print all the errors
for (error_array.items) |ee| { for (ctx.errors.items) |*err_item| {
var err_item = ee;
const err_str = try err_item.get_error_str(line, "repl", alloc); const err_str = try err_item.get_error_str(line, "repl", alloc);
try stdout.print("\n{s}\n", .{err_str}); try stdout.print("\n{s}\n", .{err_str});
try bw.flush(); try bw.flush();