refactor: use null to signal unmatch in parser
This commit is contained in:
parent
3671c221a9
commit
6a194d4065
@ -3,7 +3,6 @@ const lexic = @import("lexic");
|
|||||||
const errors = @import("errors");
|
const errors = @import("errors");
|
||||||
const Token = lexic.Token;
|
const Token = lexic.Token;
|
||||||
const TokenType = lexic.TokenType;
|
const TokenType = lexic.TokenType;
|
||||||
const ParseError = @import("./types.zig").ParseError;
|
|
||||||
|
|
||||||
pub const Expression = union(enum) {
|
pub const Expression = union(enum) {
|
||||||
number: *const Token,
|
number: *const Token,
|
||||||
|
@ -13,7 +13,7 @@ const ParseError = types.ParseError;
|
|||||||
const TokenStream = types.TokenStream;
|
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,
|
alloc: std.mem.Allocator,
|
||||||
|
|
||||||
/// Parses a module.
|
/// Parses a module.
|
||||||
@ -29,11 +29,10 @@ pub const Module = struct {
|
|||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
err_arrl: *std.ArrayList(errors.ErrorData),
|
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(allocator);
|
||||||
errdefer arrl.deinit();
|
errdefer arrl.deinit();
|
||||||
errdefer for (arrl.items) |i| {
|
errdefer for (arrl.items) |i| {
|
||||||
i.deinit();
|
i.deinit();
|
||||||
allocator.destroy(i);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const input_len = tokens.items.len;
|
const input_len = tokens.items.len;
|
||||||
@ -41,30 +40,27 @@ pub const Module = struct {
|
|||||||
|
|
||||||
// parse many statements
|
// parse many statements
|
||||||
while (current_pos < input_len) {
|
while (current_pos < input_len) {
|
||||||
var stmt = try allocator.create(statement.Statement);
|
var stmt: statement.Statement = undefined;
|
||||||
errdefer allocator.destroy(stmt);
|
|
||||||
|
|
||||||
const next_pos = stmt.init(tokens, current_pos, allocator) catch |e| {
|
// TODO: handle other errors of vardef parsing
|
||||||
switch (e) {
|
const next_pos = try stmt.init(tokens, current_pos, allocator);
|
||||||
error.Unmatched => {
|
if (next_pos) |next_pos_actual| {
|
||||||
// create the error value
|
current_pos = next_pos_actual;
|
||||||
var error_target: errors.ErrorData = undefined;
|
|
||||||
try error_target.init(
|
|
||||||
"No statement found",
|
|
||||||
current_pos,
|
|
||||||
current_pos + 1,
|
|
||||||
allocator,
|
|
||||||
);
|
|
||||||
defer error_target.deinit();
|
|
||||||
try err_arrl.append(error_target);
|
|
||||||
return error.Unmatched;
|
|
||||||
},
|
|
||||||
else => return e,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
current_pos = next_pos;
|
|
||||||
|
|
||||||
try arrl.append(stmt);
|
try arrl.append(stmt);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
return error.Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
target.* = .{
|
target.* = .{
|
||||||
@ -76,7 +72,6 @@ pub const Module = struct {
|
|||||||
pub fn deinit(self: @This()) void {
|
pub fn deinit(self: @This()) void {
|
||||||
for (self.statements.items) |stmt| {
|
for (self.statements.items) |stmt| {
|
||||||
stmt.deinit();
|
stmt.deinit();
|
||||||
self.alloc.destroy(stmt);
|
|
||||||
}
|
}
|
||||||
self.statements.deinit();
|
self.statements.deinit();
|
||||||
}
|
}
|
||||||
|
@ -21,14 +21,13 @@ pub const Statement = struct {
|
|||||||
tokens: *const TokenStream,
|
tokens: *const TokenStream,
|
||||||
pos: usize,
|
pos: usize,
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
) ParseError!usize {
|
) ParseError!?usize {
|
||||||
// try to parse a variable definition
|
// try to parse a variable definition
|
||||||
|
|
||||||
var vardef = allocator.create(variable.VariableBinding) catch {
|
var vardef = try allocator.create(variable.VariableBinding);
|
||||||
return ParseError.OutOfMemory;
|
|
||||||
};
|
|
||||||
errdefer allocator.destroy(vardef);
|
errdefer allocator.destroy(vardef);
|
||||||
|
|
||||||
|
// TODO: handle other errors of vardef parsing
|
||||||
if (try vardef.init(tokens, pos, allocator)) |vardef_end| {
|
if (try vardef.init(tokens, pos, allocator)) |vardef_end| {
|
||||||
// variable definition parsed
|
// variable definition parsed
|
||||||
// return the parsed variable definition
|
// return the parsed variable definition
|
||||||
@ -38,10 +37,10 @@ pub const Statement = struct {
|
|||||||
};
|
};
|
||||||
return vardef_end;
|
return vardef_end;
|
||||||
}
|
}
|
||||||
// TODO: handle other errors of vardef parsing
|
|
||||||
|
|
||||||
// fail
|
// manually deallocate
|
||||||
return ParseError.Unmatched;
|
allocator.destroy(vardef);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: @This()) void {
|
pub fn deinit(self: @This()) void {
|
||||||
@ -81,15 +80,11 @@ test "should fail on other constructs" {
|
|||||||
defer tokens.deinit();
|
defer tokens.deinit();
|
||||||
|
|
||||||
var statement: Statement = undefined;
|
var statement: Statement = undefined;
|
||||||
_ = statement.init(&tokens, 0, std.testing.allocator) catch |e| switch (e) {
|
const result = try statement.init(&tokens, 0, std.testing.allocator);
|
||||||
error.Unmatched => {
|
if (result == null) {
|
||||||
return;
|
// good path
|
||||||
},
|
return;
|
||||||
else => {
|
}
|
||||||
try std.testing.expect(false);
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
try std.testing.expect(false);
|
try std.testing.expect(false);
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,6 @@ const lexic = @import("lexic");
|
|||||||
|
|
||||||
/// Respresents a failure of parsing.
|
/// Respresents a failure of parsing.
|
||||||
pub const ParseError = error{
|
pub const ParseError = error{
|
||||||
/// The parse operation failed, but it is recoverable.
|
|
||||||
/// Other parsers should be considered.
|
|
||||||
Unmatched,
|
|
||||||
/// The parse operation parsed after a point of no return.
|
/// The parse operation parsed after a point of no return.
|
||||||
/// For example, a `var` keyword was found, but then no identifier
|
/// For example, a `var` keyword was found, but then no identifier
|
||||||
/// The parsing should stop
|
/// The parsing should stop
|
||||||
|
Loading…
Reference in New Issue
Block a user