diff --git a/src/02_syntax/expression.zig b/src/02_syntax/expression.zig index 2f22e6e..1a1b71d 100644 --- a/src/02_syntax/expression.zig +++ b/src/02_syntax/expression.zig @@ -8,15 +8,17 @@ pub const Expression = union(enum) { number: *const Token, /// Attempts to parse an expression from a token stream. - fn parse(tokens: *const std.ArrayList(Token), pos: usize) ParseError!@This() { + /// + /// Receives a pointer to the memory for initialization + pub fn init(target: *Expression, tokens: *const std.ArrayList(Token), pos: usize) error{Unmatched}!void { std.debug.assert(pos < tokens.items.len); const t = tokens.items[pos]; if (t.token_type != TokenType.Int) { - return ParseError.Unmatched; + return error.Unmatched; } - return .{ + target.* = .{ .number = &t, }; } @@ -27,7 +29,8 @@ test "should parse expression" { const tokens = try lexic.tokenize(input, std.testing.allocator); defer tokens.deinit(); - const expr = try Expression.parse(&tokens, 0); + var expr: Expression = undefined; + try expr.init(&tokens, 0); try std.testing.expectEqualDeep("322", expr.number.value); try std.testing.expectEqualDeep(TokenType.Int, expr.number.token_type); } @@ -37,7 +40,8 @@ test "should fail on non expression" { const tokens = try lexic.tokenize(input, std.testing.allocator); defer tokens.deinit(); - const expr = Expression.parse(&tokens, 0) catch |err| { + var expr: Expression = undefined; + expr.init(&tokens, 0) catch |err| { try std.testing.expectEqual(ParseError.Unmatched, err); return; }; diff --git a/src/02_syntax/types.zig b/src/02_syntax/types.zig index ae1199c..7673404 100644 --- a/src/02_syntax/types.zig +++ b/src/02_syntax/types.zig @@ -10,6 +10,8 @@ pub const ParseError = error{ /// For example, a `var` keyword was found, but then no identifier /// The parsing should stop Error, + /// OOM. Fatal error, blows up everything + OutOfMemory, }; pub const TokenStream = std.ArrayList(lexic.Token); diff --git a/src/02_syntax/variable.zig b/src/02_syntax/variable.zig index f8e7358..d6478fa 100644 --- a/src/02_syntax/variable.zig +++ b/src/02_syntax/variable.zig @@ -11,14 +11,12 @@ const VariableBinding = struct { is_mutable: bool, datatype: ?*lexic.Token, identifier: *lexic.Token, - expression: expression.Expression, + expression: *expression.Expression, alloc: std.mem.Allocator, - fn init(tokens: *const TokenStream, pos: usize, allocator: std.mem.Allocator) ParseError!@This() { + fn init(target: *VariableBinding, tokens: *const TokenStream, pos: usize, allocator: std.mem.Allocator) ParseError!void { std.debug.assert(pos < tokens.items.len); - _ = allocator; - // try to parse a var keyword const var_keyword = try utils.expect_token_type(lexic.TokenType.K_Var, &tokens.items[pos]); _ = var_keyword; @@ -33,7 +31,6 @@ const VariableBinding = struct { const identifier = utils.expect_token_type(lexic.TokenType.Identifier, &tokens.items[pos + 1]) catch { return ParseError.Error; }; - _ = identifier; // parse equal sign if (pos + 2 >= tokens.items.len) return ParseError.Error; @@ -43,25 +40,36 @@ const VariableBinding = struct { _ = equal_sign; // parse expression + if (pos + 3 >= tokens.items.len) return ParseError.Error; + var exp = allocator.create(expression.Expression) catch { + return ParseError.Error; + }; + errdefer allocator.destroy(exp); + try exp.init(tokens, pos + 3); - // provisional good return value - return ParseError.Unmatched; + // return + target.* = .{ + .is_mutable = true, + .datatype = null, + .identifier = identifier, + .expression = exp, + .alloc = allocator, + }; } fn deinit(self: *@This()) void { - _ = self; + self.alloc.destroy(self.expression); } }; test "should parse a minimal var" { - const input = "var my_variable ="; + const input = "var my_variable = 322"; const tokens = try lexic.tokenize(input, std.testing.allocator); defer tokens.deinit(); - const binding = VariableBinding.init(&tokens, 0, std.testing.allocator) catch |err| { - try std.testing.expectEqual(ParseError.Unmatched, err); - return; - }; + var binding: VariableBinding = undefined; + try binding.init(&tokens, 0, std.testing.allocator); + defer binding.deinit(); - try std.testing.expectEqual(false, binding.is_mutable); + try std.testing.expectEqual(true, binding.is_mutable); }