refactor: migrate syntax parser to new compiler context
This commit is contained in:
parent
ac30ea169c
commit
2aa81dd39f
@ -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, ¤t_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,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user