refactor: return null on utils match fail
This commit is contained in:
parent
1a3bdc7592
commit
5f75392d6b
@ -16,7 +16,12 @@ pub const Statement = struct {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/// Parses a Statement and return the position of the next token
|
/// Parses a Statement and return the position of the next token
|
||||||
pub fn init(target: *Statement, tokens: *const TokenStream, pos: usize, allocator: std.mem.Allocator) ParseError!usize {
|
pub fn init(
|
||||||
|
target: *Statement,
|
||||||
|
tokens: *const TokenStream,
|
||||||
|
pos: usize,
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
) ParseError!usize {
|
||||||
// try to parse a variable definition
|
// try to parse a variable definition
|
||||||
|
|
||||||
var vardef = allocator.create(variable.VariableBinding) catch {
|
var vardef = allocator.create(variable.VariableBinding) catch {
|
||||||
@ -34,13 +39,15 @@ pub const Statement = struct {
|
|||||||
return err;
|
return err;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
if (vardef_end) |v| {
|
||||||
if (!parse_failed) {
|
if (!parse_failed) {
|
||||||
// return the parsed variable definition
|
// return the parsed variable definition
|
||||||
target.* = .{
|
target.* = .{
|
||||||
.alloc = allocator,
|
.alloc = allocator,
|
||||||
.value = .{ .variableBinding = vardef },
|
.value = .{ .variableBinding = vardef },
|
||||||
};
|
};
|
||||||
return vardef_end;
|
return v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fail
|
// fail
|
||||||
|
@ -4,18 +4,18 @@ const lexic = @import("lexic");
|
|||||||
/// Expects that the given token `t` has type `value`.
|
/// Expects that the given token `t` has type `value`.
|
||||||
/// If it fails returns `error.Unmatched`, otherwise
|
/// If it fails returns `error.Unmatched`, otherwise
|
||||||
/// returns the same token passed (`t`)
|
/// returns the same token passed (`t`)
|
||||||
pub inline fn expect_token_type(comptime value: lexic.TokenType, t: *lexic.Token) error{Unmatched}!*lexic.Token {
|
pub inline fn expect_token_type(comptime value: lexic.TokenType, t: *lexic.Token) ?*lexic.Token {
|
||||||
if (t.token_type == value) {
|
if (t.token_type == value) {
|
||||||
return t;
|
return t;
|
||||||
} else {
|
} else {
|
||||||
return error.Unmatched;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub inline fn expect_operator(comptime value: []const u8, t: *lexic.Token) error{Unmatched}!*lexic.Token {
|
pub inline fn expect_operator(comptime value: []const u8, t: *lexic.Token) ?*lexic.Token {
|
||||||
if (t.token_type == lexic.TokenType.Operator and std.mem.eql(u8, value, t.value)) {
|
if (t.token_type == lexic.TokenType.Operator and std.mem.eql(u8, value, t.value)) {
|
||||||
return t;
|
return t;
|
||||||
} else {
|
} else {
|
||||||
return error.Unmatched;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,18 @@ pub const VariableBinding = struct {
|
|||||||
alloc: std.mem.Allocator,
|
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(target: *VariableBinding, tokens: *const TokenStream, pos: usize, allocator: std.mem.Allocator) ParseError!usize {
|
pub fn init(
|
||||||
|
target: *VariableBinding,
|
||||||
|
tokens: *const TokenStream,
|
||||||
|
pos: usize,
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
) ParseError!?usize {
|
||||||
std.debug.assert(pos < tokens.items.len);
|
std.debug.assert(pos < tokens.items.len);
|
||||||
|
|
||||||
// try to parse a var keyword
|
// try to parse a var keyword
|
||||||
const var_keyword = try utils.expect_token_type(lexic.TokenType.K_Var, &tokens.items[pos]);
|
const var_keyword = if (utils.expect_token_type(lexic.TokenType.K_Var, &tokens.items[pos])) |t| t else {
|
||||||
|
return null;
|
||||||
|
};
|
||||||
_ = var_keyword;
|
_ = var_keyword;
|
||||||
|
|
||||||
// check there is still input
|
// check there is still input
|
||||||
@ -30,13 +37,13 @@ pub const VariableBinding = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try to parse an identifier
|
// try to parse an identifier
|
||||||
const identifier = utils.expect_token_type(lexic.TokenType.Identifier, &tokens.items[pos + 1]) catch {
|
const identifier = if (utils.expect_token_type(lexic.TokenType.Identifier, &tokens.items[pos + 1])) |i| i else {
|
||||||
return ParseError.Error;
|
return ParseError.Error;
|
||||||
};
|
};
|
||||||
|
|
||||||
// parse equal sign
|
// parse equal sign
|
||||||
if (pos + 2 >= tokens.items.len) return ParseError.Error;
|
if (pos + 2 >= tokens.items.len) return ParseError.Error;
|
||||||
const equal_sign = utils.expect_operator("=", &tokens.items[pos + 2]) catch {
|
const equal_sign = if (utils.expect_operator("=", &tokens.items[pos + 2])) |x| x else {
|
||||||
return ParseError.Error;
|
return ParseError.Error;
|
||||||
};
|
};
|
||||||
_ = equal_sign;
|
_ = equal_sign;
|
||||||
@ -92,7 +99,7 @@ test "should parse a minimal var" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test "should fail is it doesnt start with var" {
|
test "should return null if stream doesnt start with var" {
|
||||||
const input = "different_token_stream()";
|
const input = "different_token_stream()";
|
||||||
var error_list = std.ArrayList(errors.ErrorData).init(std.testing.allocator);
|
var error_list = std.ArrayList(errors.ErrorData).init(std.testing.allocator);
|
||||||
defer error_list.deinit();
|
defer error_list.deinit();
|
||||||
@ -100,13 +107,10 @@ test "should fail is it doesnt start with var" {
|
|||||||
defer tokens.deinit();
|
defer tokens.deinit();
|
||||||
|
|
||||||
var binding: VariableBinding = undefined;
|
var binding: VariableBinding = undefined;
|
||||||
_ = binding.init(&tokens, 0, std.testing.allocator) catch |err| {
|
if (try binding.init(&tokens, 0, std.testing.allocator)) |_| {
|
||||||
try std.testing.expectEqual(ParseError.Unmatched, err);
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
try std.testing.expect(false);
|
try std.testing.expect(false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
test "should fail if the identifier is missing" {
|
test "should fail if the identifier is missing" {
|
||||||
const input = "var ";
|
const input = "var ";
|
||||||
|
Loading…
Reference in New Issue
Block a user