diff --git a/src/02_syntax/statement.zig b/src/02_syntax/statement.zig index ff8b449..7db845d 100644 --- a/src/02_syntax/statement.zig +++ b/src/02_syntax/statement.zig @@ -16,7 +16,12 @@ pub const Statement = struct { }, /// 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 var vardef = allocator.create(variable.VariableBinding) catch { @@ -34,13 +39,15 @@ pub const Statement = struct { return err; }, }; - if (!parse_failed) { - // return the parsed variable definition - target.* = .{ - .alloc = allocator, - .value = .{ .variableBinding = vardef }, - }; - return vardef_end; + if (vardef_end) |v| { + if (!parse_failed) { + // return the parsed variable definition + target.* = .{ + .alloc = allocator, + .value = .{ .variableBinding = vardef }, + }; + return v; + } } // fail diff --git a/src/02_syntax/utils.zig b/src/02_syntax/utils.zig index 262ba87..942385e 100644 --- a/src/02_syntax/utils.zig +++ b/src/02_syntax/utils.zig @@ -4,18 +4,18 @@ const lexic = @import("lexic"); /// Expects that the given token `t` has type `value`. /// If it fails returns `error.Unmatched`, otherwise /// 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) { return t; } 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)) { return t; } else { - return error.Unmatched; + return null; } } diff --git a/src/02_syntax/variable.zig b/src/02_syntax/variable.zig index 7455616..8265f0d 100644 --- a/src/02_syntax/variable.zig +++ b/src/02_syntax/variable.zig @@ -16,11 +16,18 @@ pub const VariableBinding = struct { 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, 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); // 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; // check there is still input @@ -30,13 +37,13 @@ pub const VariableBinding = struct { } // 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; }; // parse equal sign 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; }; _ = 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()"; var error_list = std.ArrayList(errors.ErrorData).init(std.testing.allocator); defer error_list.deinit(); @@ -100,12 +107,9 @@ test "should fail is it doesnt start with var" { defer tokens.deinit(); var binding: VariableBinding = undefined; - _ = binding.init(&tokens, 0, std.testing.allocator) catch |err| { - try std.testing.expectEqual(ParseError.Unmatched, err); - return; - }; - - try std.testing.expect(false); + if (try binding.init(&tokens, 0, std.testing.allocator)) |_| { + try std.testing.expect(false); + } } test "should fail if the identifier is missing" {