diff --git a/source/ona/kym/ast.zig b/source/ona/kym/ast.zig index e612a6b..e6da61c 100644 --- a/source/ona/kym/ast.zig +++ b/source/ona/kym/ast.zig @@ -321,12 +321,92 @@ pub const ParsedExpression = union (enum) { defer _ = tokenizer.step(); return ParsedExpression{ - .valid = .{ - .string_literal = value, - }, + .valid = .{.string_literal = value}, }; }, + .symbol_brace_left => { + if (tokenizer.step()) { + return ParsedExpression{.invalid = "unexpected end of table literal"}; + } + + var is_invalid = true; + var table_fields = try TableFields.init(allocator, 0); + + defer if (is_invalid) { + table_fields.deinit(allocator); + }; + + while (true) { + switch (tokenizer.current_token) { + .symbol_brace_right => { + _ = tokenizer.step(); + is_invalid = false; + + return ParsedExpression{ + .valid = .{.table_literal = table_fields}, + }; + }, + + .local => |identifier| { + const key = identifier; + + if (!tokenizer.step() or tokenizer.current_token != .symbol_equals) { + return ParsedExpression{.invalid = "expected `=` after identifier"}; + } + + if (!tokenizer.step()) { + return ParsedExpression{.invalid = "unexpected end after `=`"}; + } + + var parsed_expression = try init(allocator, tokenizer); + + switch (parsed_expression) { + .valid => |*expression| { + errdefer expression.deinit(allocator); + + try table_fields.push_one(allocator, .{ + .identifier = key, + .expression = expression, + }); + }, + + .invalid => |details| return ParsedExpression{.invalid = details}, + } + }, + + .string => |identifier| { + const key = identifier; + + if (!tokenizer.step() or tokenizer.current_token != .symbol_equals) { + return ParsedExpression{.invalid = "expected `=` after identifier"}; + } + + if (!tokenizer.step()) { + return ParsedExpression{.invalid = "unexpected end after `=`"}; + } + + var parsed_expression = try init(allocator, tokenizer); + + switch (parsed_expression) { + .valid => |*expression| { + errdefer expression.deinit(allocator); + + try table_fields.push_one(allocator, .{ + .identifier = key, + .expression = expression, + }); + }, + + .invalid => |details| return ParsedExpression{.invalid = details}, + } + }, + + else => return ParsedExpression{.invalid = "expected `}` or fields in table expression"} + } + } + }, + .symbol_minus => { if (!tokenizer.step()) { return ParsedExpression{.invalid = "expected expression after numeric negation (`-`)"}; @@ -519,7 +599,7 @@ pub const Expression = union (enum) { integer_literal: types.Integer, float_literal: types.Float, string_literal: []const u8, - table_literal: TableLiteral, + table_literal: TableFields, grouped_expression: *Expression, binary_operation: struct { @@ -533,11 +613,6 @@ pub const Expression = union (enum) { expression: *Expression, }, - const TableLiteral = coral.list.Stack(struct { - identifier: []const u8, - expression: *Expression, - }); - fn deinit(self: *Expression, allocator: coral.io.Allocator) void { switch (self.*) { .nil_literal, .true_literal, .false_literal, .integer_literal, .float_literal, .string_literal => {}, @@ -639,6 +714,11 @@ pub const Statements = struct { } }; +const TableFields = coral.list.Stack(struct { + identifier: []const u8, + expression: *Expression, +}); + pub const UnaryOperation = enum { boolean_negation, numeric_negation,