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

View File

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

View File

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

View File

@ -116,17 +116,14 @@ fn repl() !void {
continue;
}
std.debug.print("should be syntax analizing the tokens...\n", .{});
//
// Syntax analysis
//
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 => {
// Print all the errors
for (error_array.items) |ee| {
var err_item = ee;
for (ctx.errors.items) |*err_item| {
const err_str = try err_item.get_error_str(line, "repl", alloc);
try stdout.print("\n{s}\n", .{err_str});
try bw.flush();