diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/jq/codegen.zig | 246 | ||||
| -rw-r--r-- | src/jq/compile.zig | 244 | ||||
| -rw-r--r-- | src/jq/execute.zig | 6 | ||||
| -rw-r--r-- | src/jq/parse.zig | 50 |
4 files changed, 274 insertions, 272 deletions
diff --git a/src/jq/codegen.zig b/src/jq/codegen.zig new file mode 100644 index 0000000..e377a5c --- /dev/null +++ b/src/jq/codegen.zig @@ -0,0 +1,246 @@ +const std = @import("std"); +const jv = @import("../jv.zig"); +const Ast = @import("./parse.zig").Ast; +const BinaryOp = @import("./parse.zig").BinaryOp; + +pub const ConstIndex = enum(u32) { _ }; + +pub const Opcode = enum { + nop, + ret, + jump, + jump_unless, + fork, + dup, + pop, + subexp_begin, + subexp_end, + index, + index_opt, + add, + sub, + mul, + div, + mod, + eq, + ne, + lt, + gt, + le, + ge, + @"const", + const_true, + const_false, +}; + +pub const Instr = union(Opcode) { + const Self = @This(); + + nop, + ret, + jump: usize, + jump_unless: usize, + fork: usize, + dup, + pop, + subexp_begin, + subexp_end, + index, + index_opt, + add, + sub, + mul, + div, + mod, + eq, + ne, + lt, + gt, + le, + ge, + @"const": ConstIndex, + const_true, + const_false, + + pub fn op(self: Self) Opcode { + return self; + } +}; + +const Codegen = struct { + instrs: std.ArrayList(Instr), + allocator: std.mem.Allocator, + + fn init(allocator: std.mem.Allocator) !Codegen { + return .{ + .instrs = try std.ArrayList(Instr).initCapacity(allocator, 16), + .allocator = allocator, + }; + } + + fn generate(self: *Codegen, ast: *const Ast) !void { + switch (ast.*) { + .identity => try self.emit(.nop), + .index => |idx| { + try self.generate(idx.base); + try self.emit(.subexp_begin); + try self.generate(idx.index); + try self.emit(.subexp_end); + try self.emit(if (idx.is_optional) .index_opt else .index); + }, + .literal => |idx| try self.emit(.{ .@"const" = idx }), + .binary_expr => |binary_expr| { + try self.emit(.subexp_begin); + try self.generate(binary_expr.rhs); + try self.emit(.subexp_end); + try self.emit(.subexp_begin); + try self.generate(binary_expr.lhs); + try self.emit(.subexp_end); + const op_instr: Instr = switch (binary_expr.op) { + .add => .add, + .sub => .sub, + .mul => .mul, + .div => .div, + .mod => .mod, + .eq => .eq, + .ne => .ne, + .lt => .lt, + .gt => .gt, + .le => .le, + .ge => .ge, + else => return error.Unimplemented, + }; + try self.emit(op_instr); + }, + .and_expr => |and_expr| { + // DUP + // <lhs> + // JUMP_UNLESS l3 + // POP + // <rhs> + // JUMP_UNLESS l1 + // CONST_TRUE + // JUMP l2 + // l1: CONST_FALSE + // l2: JUMP l4 + // l3: POP + // CONST_FALSE + // l4: + try self.emit(.dup); + try self.generate(and_expr.lhs); + const jump1_idx = self.pos(); + try self.emit(.{ .jump_unless = 0 }); + try self.emit(.pop); + try self.generate(and_expr.rhs); + const jump2_idx = self.pos(); + try self.emit(.{ .jump_unless = 0 }); + try self.emit(.const_true); + const jump3_idx = self.pos(); + try self.emit(.{ .jump = 0 }); + const l1 = self.pos(); + try self.emit(.const_false); + const jump4_idx = self.pos(); + const l2 = self.pos(); + try self.emit(.{ .jump = 0 }); + const l3 = self.pos(); + try self.emit(.pop); + try self.emit(.const_false); + const l4 = self.pos(); + + self.patchLabel(jump1_idx, l3); + self.patchLabel(jump2_idx, l1); + self.patchLabel(jump3_idx, l2); + self.patchLabel(jump4_idx, l4); + }, + .or_expr => |or_expr| { + // DUP + // <lhs> + // JUMP_UNLESS l1 + // POP + // CONST_TRUE + // JUMP l3 + // l1: POP + // <rhs> + // JUMP_UNLESS l2 + // CONST_TRUE + // JUMP l3 + // l2: CONST_FALSE + // l3: + try self.emit(.dup); + try self.generate(or_expr.lhs); + const jump1_idx = self.pos(); + try self.emit(.{ .jump_unless = 0 }); + try self.emit(.pop); + try self.emit(.const_true); + const jump2_idx = self.pos(); + try self.emit(.{ .jump = 0 }); + const l1 = self.pos(); + try self.emit(.pop); + try self.generate(or_expr.rhs); + const jump3_idx = self.pos(); + try self.emit(.{ .jump_unless = 0 }); + try self.emit(.const_true); + const jump4_idx = self.pos(); + try self.emit(.{ .jump = 0 }); + const l2 = self.pos(); + try self.emit(.const_false); + const l3 = self.pos(); + + self.patchLabel(jump1_idx, l1); + self.patchLabel(jump2_idx, l3); + self.patchLabel(jump3_idx, l2); + self.patchLabel(jump4_idx, l3); + }, + .pipe => |pipe_expr| { + try self.generate(pipe_expr.lhs); + try self.generate(pipe_expr.rhs); + }, + .comma => |comma_expr| { + // FORK l1 + // <lhs> + // JUMP l2 + // l1: <rhs> + // l2: + const fork_index = self.pos(); + try self.emit(.{ .fork = 0 }); + try self.generate(comma_expr.lhs); + const jump_index = self.pos(); + try self.emit(.{ .jump = 0 }); + const l1 = self.pos(); + try self.generate(comma_expr.rhs); + const l2 = self.pos(); + self.patchLabel(fork_index, l1); + self.patchLabel(jump_index, l2); + }, + } + } + + fn toOwnedSlice(self: *Codegen) ![]Instr { + return self.instrs.toOwnedSlice(self.allocator); + } + + fn emit(self: *Codegen, instr: Instr) !void { + try self.instrs.append(self.allocator, instr); + } + + fn pos(self: *const Codegen) usize { + return self.instrs.items.len; + } + + fn patchLabel(self: *Codegen, index: usize, target: usize) void { + const offset = target - index; + self.instrs.items[index] = switch (self.instrs.items[index]) { + .jump => .{ .jump = offset }, + .jump_unless => .{ .jump_unless = offset }, + .fork => .{ .fork = offset }, + else => unreachable, + }; + } +}; + +pub fn codegen(allocator: std.mem.Allocator, ast: *const Ast) ![]Instr { + var gen = try Codegen.init(allocator); + try gen.generate(ast); + try gen.emit(.ret); + return gen.toOwnedSlice(); +} diff --git a/src/jq/compile.zig b/src/jq/compile.zig deleted file mode 100644 index 043262e..0000000 --- a/src/jq/compile.zig +++ /dev/null @@ -1,244 +0,0 @@ -const std = @import("std"); -const jv = @import("../jv.zig"); -const Ast = @import("./parse.zig").Ast; -const BinaryOp = @import("./parse.zig").BinaryOp; - -pub const ConstIndex = enum(u32) { _ }; - -pub const Opcode = enum { - nop, - ret, - jump, - jump_unless, - fork, - dup, - pop, - subexp_begin, - subexp_end, - index, - index_opt, - add, - sub, - mul, - div, - mod, - eq, - ne, - lt, - gt, - le, - ge, - @"const", - const_true, - const_false, -}; - -pub const Instr = union(Opcode) { - const Self = @This(); - - nop, - ret, - jump: usize, - jump_unless: usize, - fork: usize, - dup, - pop, - subexp_begin, - subexp_end, - index, - index_opt, - add, - sub, - mul, - div, - mod, - eq, - ne, - lt, - gt, - le, - ge, - @"const": ConstIndex, - const_true, - const_false, - - pub fn op(self: Self) Opcode { - return self; - } -}; - -fn compileExpr(allocator: std.mem.Allocator, compile_allocator: std.mem.Allocator, ast: *const Ast) ![]Instr { - var instrs = try std.ArrayList(Instr).initCapacity(allocator, 16); - - switch (ast.*) { - .identity => try instrs.append(allocator, .nop), - .index => |idx| { - const base_instrs = try compileExpr(allocator, compile_allocator, idx.base); - defer allocator.free(base_instrs); - const index_instrs = try compileExpr(allocator, compile_allocator, idx.index); - defer allocator.free(index_instrs); - try instrs.appendSlice(allocator, base_instrs); - try instrs.append(allocator, .subexp_begin); - try instrs.appendSlice(allocator, index_instrs); - try instrs.append(allocator, .subexp_end); - try instrs.append(allocator, if (idx.is_optional) .index_opt else .index); - }, - .literal => |idx| try instrs.append(allocator, .{ .@"const" = idx }), - .binary_expr => |binary_expr| { - const rhs_instrs = try compileExpr(allocator, compile_allocator, binary_expr.rhs); - defer allocator.free(rhs_instrs); - const lhs_instrs = try compileExpr(allocator, compile_allocator, binary_expr.lhs); - defer allocator.free(lhs_instrs); - try instrs.append(allocator, .subexp_begin); - try instrs.appendSlice(allocator, rhs_instrs); - try instrs.append(allocator, .subexp_end); - try instrs.append(allocator, .subexp_begin); - try instrs.appendSlice(allocator, lhs_instrs); - try instrs.append(allocator, .subexp_end); - const op_instr: Instr = switch (binary_expr.op) { - .add => .add, - .sub => .sub, - .mul => .mul, - .div => .div, - .mod => .mod, - .eq => .eq, - .ne => .ne, - .lt => .lt, - .gt => .gt, - .le => .le, - .ge => .ge, - else => return error.Unimplemented, - }; - try instrs.append(allocator, op_instr); - }, - .and_expr => |and_expr| { - // DUP - // <lhs> - // JUMP_UNLESS l3 - // POP - // <rhs> - // JUMP_UNLESS l1 - // CONST_TRUE - // JUMP l2 - // l1: CONST_FALSE - // l2: JUMP l4 - // l3: POP - // CONST_FALSE - // l4: - const lhs_instrs = try compileExpr(allocator, compile_allocator, and_expr.lhs); - defer allocator.free(lhs_instrs); - const rhs_instrs = try compileExpr(allocator, compile_allocator, and_expr.rhs); - defer allocator.free(rhs_instrs); - - try instrs.append(allocator, .dup); - try instrs.appendSlice(allocator, lhs_instrs); - const jump1_idx = instrs.items.len; - try instrs.append(allocator, .{ .jump_unless = 0 }); - try instrs.append(allocator, .pop); - try instrs.appendSlice(allocator, rhs_instrs); - const jump2_idx = instrs.items.len; - try instrs.append(allocator, .{ .jump_unless = 0 }); - try instrs.append(allocator, .const_true); - const jump3_idx = instrs.items.len; - try instrs.append(allocator, .{ .jump = 0 }); - const l1 = instrs.items.len; - try instrs.append(allocator, .const_false); - const jump4_idx = instrs.items.len; - const l2 = instrs.items.len; - try instrs.append(allocator, .{ .jump = 0 }); - const l3 = instrs.items.len; - try instrs.append(allocator, .pop); - try instrs.append(allocator, .const_false); - const l4 = instrs.items.len; - - instrs.items[jump1_idx] = .{ .jump_unless = l3 - jump1_idx }; - instrs.items[jump2_idx] = .{ .jump_unless = l1 - jump2_idx }; - instrs.items[jump3_idx] = .{ .jump = l2 - jump3_idx }; - instrs.items[jump4_idx] = .{ .jump = l4 - jump4_idx }; - }, - .or_expr => |or_expr| { - // DUP - // <lhs> - // JUMP_UNLESS l1 - // POP - // CONST_TRUE - // JUMP l3 - // l1: POP - // <rhs> - // JUMP_UNLESS l2 - // CONST_TRUE - // JUMP l3 - // l2: CONST_FALSE - // l3: - const lhs_instrs = try compileExpr(allocator, compile_allocator, or_expr.lhs); - defer allocator.free(lhs_instrs); - const rhs_instrs = try compileExpr(allocator, compile_allocator, or_expr.rhs); - defer allocator.free(rhs_instrs); - - try instrs.append(allocator, .dup); - try instrs.appendSlice(allocator, lhs_instrs); - const jump1_idx = instrs.items.len; - try instrs.append(allocator, .{ .jump_unless = 0 }); - try instrs.append(allocator, .pop); - try instrs.append(allocator, .const_true); - const jump2_idx = instrs.items.len; - try instrs.append(allocator, .{ .jump = 0 }); - const l1 = instrs.items.len; - try instrs.append(allocator, .pop); - try instrs.appendSlice(allocator, rhs_instrs); - const jump3_idx = instrs.items.len; - try instrs.append(allocator, .{ .jump_unless = 0 }); - try instrs.append(allocator, .const_true); - const jump4_idx = instrs.items.len; - try instrs.append(allocator, .{ .jump = 0 }); - const l2 = instrs.items.len; - try instrs.append(allocator, .const_false); - const l3 = instrs.items.len; - - instrs.items[jump1_idx] = .{ .jump_unless = l1 - jump1_idx }; - instrs.items[jump2_idx] = .{ .jump = l3 - jump2_idx }; - instrs.items[jump3_idx] = .{ .jump_unless = l2 - jump3_idx }; - instrs.items[jump4_idx] = .{ .jump = l3 - jump4_idx }; - }, - .pipe => |pipe_expr| { - const lhs_instrs = try compileExpr(allocator, compile_allocator, pipe_expr.lhs); - defer allocator.free(lhs_instrs); - const rhs_instrs = try compileExpr(allocator, compile_allocator, pipe_expr.rhs); - defer allocator.free(rhs_instrs); - try instrs.appendSlice(allocator, lhs_instrs); - try instrs.appendSlice(allocator, rhs_instrs); - }, - .comma => |comma_expr| { - // FORK l1 - // <lhs> - // JUMP l2 - // l1: <rhs> - // l2: - const lhs_instrs = try compileExpr(allocator, compile_allocator, comma_expr.lhs); - defer allocator.free(lhs_instrs); - const rhs_instrs = try compileExpr(allocator, compile_allocator, comma_expr.rhs); - defer allocator.free(rhs_instrs); - const fork_index = instrs.items.len; - try instrs.append(allocator, .{ .fork = 0 }); - try instrs.appendSlice(allocator, lhs_instrs); - const jump_index = instrs.items.len; - try instrs.append(allocator, .{ .jump = 0 }); - const l1 = instrs.items.len; - try instrs.appendSlice(allocator, rhs_instrs); - const l2 = instrs.items.len; - instrs.items[fork_index] = .{ .fork = l1 - fork_index }; - instrs.items[jump_index] = .{ .jump = l2 - jump_index }; - }, - } - - return instrs.toOwnedSlice(allocator); -} - -pub fn compile(allocator: std.mem.Allocator, compile_allocator: std.mem.Allocator, ast: *const Ast) ![]Instr { - var instrs = try std.ArrayList(Instr).initCapacity(allocator, 16); - const expr_instrs = try compileExpr(allocator, compile_allocator, ast); - defer allocator.free(expr_instrs); - try instrs.appendSlice(allocator, expr_instrs); - try instrs.append(allocator, .ret); - return instrs.toOwnedSlice(allocator); -} diff --git a/src/jq/execute.zig b/src/jq/execute.zig index b30bd3d..f2bfe8c 100644 --- a/src/jq/execute.zig +++ b/src/jq/execute.zig @@ -2,8 +2,8 @@ const std = @import("std"); const jv = @import("../jv.zig"); const tokenize = @import("./tokenize.zig").tokenize; const parse = @import("./parse.zig").parse; -const Instr = @import("./compile.zig").Instr; -const compile = @import("./compile.zig").compile; +const Instr = @import("./codegen.zig").Instr; +const codegen = @import("./codegen.zig").codegen; pub const ExecuteError = error{ Unimplemented, @@ -148,7 +148,7 @@ pub const Runtime = struct { defer compile_allocator.deinit(); const tokens = try tokenize(compile_allocator.allocator(), reader); const ast = try parse(self.allocator, compile_allocator.allocator(), tokens, &self.constants); - const instrs = try compile(self.allocator, compile_allocator.allocator(), ast); + const instrs = try codegen(self.allocator, ast); self.instrs = instrs; // std.debug.print("BEGIN\n", .{}); // for (self.instrs) |instr| { diff --git a/src/jq/parse.zig b/src/jq/parse.zig index 1760875..fece14c 100644 --- a/src/jq/parse.zig +++ b/src/jq/parse.zig @@ -2,7 +2,7 @@ const std = @import("std"); const jv = @import("../jv.zig"); const Token = @import("./tokenize.zig").Token; const TokenKind = @import("./tokenize.zig").TokenKind; -const ConstIndex = @import("./compile.zig").ConstIndex; +const ConstIndex = @import("./codegen.zig").ConstIndex; pub const ParseError = error{ UnexpectedEnd, @@ -112,7 +112,7 @@ const Parser = struct { const Error = ParseError || std.mem.Allocator.Error; allocator: std.mem.Allocator, - parse_allocator: std.mem.Allocator, + compile_allocator: std.mem.Allocator, tokens: *TokenStream, constants: *std.ArrayList(jv.Value), @@ -132,7 +132,7 @@ const Parser = struct { var lhs = try self.parseQuery3(); while (self.tokens.consumeIf(.pipe)) { const rhs = try self.parseQuery3(); - const ast = try self.parse_allocator.create(Ast); + const ast = try self.compile_allocator.create(Ast); ast.* = .{ .pipe = .{ .lhs = lhs, .rhs = rhs, @@ -147,7 +147,7 @@ const Parser = struct { var lhs = try self.parseExpr(); while (self.tokens.consumeIf(.comma)) { const rhs = try self.parseExpr(); - const ast = try self.parse_allocator.create(Ast); + const ast = try self.compile_allocator.create(Ast); ast.* = .{ .comma = .{ .lhs = lhs, .rhs = rhs, @@ -161,7 +161,7 @@ const Parser = struct { var lhs = try self.parseExpr2(); while (self.tokens.consumeIf(.slash_slash)) { const rhs = try self.parseExpr2(); - const ast = try self.parse_allocator.create(Ast); + const ast = try self.compile_allocator.create(Ast); ast.* = .{ .binary_expr = .{ .op = .alt, .lhs = lhs, @@ -188,7 +188,7 @@ const Parser = struct { }; _ = try self.tokens.next(); const rhs = try self.parseExpr3(); - const ast = try self.parse_allocator.create(Ast); + const ast = try self.compile_allocator.create(Ast); ast.* = .{ .binary_expr = .{ .op = op, .lhs = lhs, @@ -203,7 +203,7 @@ const Parser = struct { return lhs; } const rhs = try self.parseExpr4(); - const ast = try self.parse_allocator.create(Ast); + const ast = try self.compile_allocator.create(Ast); ast.* = .{ .or_expr = .{ .lhs = lhs, .rhs = rhs, @@ -217,7 +217,7 @@ const Parser = struct { return lhs; } const rhs = try self.parseExpr5(); - const ast = try self.parse_allocator.create(Ast); + const ast = try self.compile_allocator.create(Ast); ast.* = .{ .and_expr = .{ .lhs = lhs, .rhs = rhs, @@ -239,7 +239,7 @@ const Parser = struct { }; _ = try self.tokens.next(); const rhs = try self.parseExpr6(); - const ast = try self.parse_allocator.create(Ast); + const ast = try self.compile_allocator.create(Ast); ast.* = .{ .binary_expr = .{ .op = op, .lhs = lhs, @@ -259,7 +259,7 @@ const Parser = struct { }; _ = try self.tokens.next(); const rhs = try self.parseExpr7(); - const ast = try self.parse_allocator.create(Ast); + const ast = try self.compile_allocator.create(Ast); ast.* = .{ .binary_expr = .{ .op = op, .lhs = lhs, @@ -281,7 +281,7 @@ const Parser = struct { }; _ = try self.tokens.next(); const rhs = try self.parseTerm(); - const ast = try self.parse_allocator.create(Ast); + const ast = try self.compile_allocator.create(Ast); ast.* = .{ .binary_expr = .{ .op = op, .lhs = lhs, @@ -311,7 +311,7 @@ const Parser = struct { _ = try self.tokens.next(); try self.constants.append(self.allocator, .null); const idx: ConstIndex = @enumFromInt(self.constants.items.len - 1); - const null_node = try self.parse_allocator.create(Ast); + const null_node = try self.compile_allocator.create(Ast); null_node.* = .{ .literal = idx }; return null_node; }, @@ -319,7 +319,7 @@ const Parser = struct { _ = try self.tokens.next(); try self.constants.append(self.allocator, .{ .bool = true }); const idx: ConstIndex = @enumFromInt(self.constants.items.len - 1); - const true_node = try self.parse_allocator.create(Ast); + const true_node = try self.compile_allocator.create(Ast); true_node.* = .{ .literal = idx }; return true_node; }, @@ -327,7 +327,7 @@ const Parser = struct { _ = try self.tokens.next(); try self.constants.append(self.allocator, .{ .bool = false }); const idx: ConstIndex = @enumFromInt(self.constants.items.len - 1); - const false_node = try self.parse_allocator.create(Ast); + const false_node = try self.compile_allocator.create(Ast); false_node.* = .{ .literal = idx }; return false_node; }, @@ -340,7 +340,7 @@ const Parser = struct { try self.constants.append(self.allocator, .{ .float = f }); } const idx: ConstIndex = @enumFromInt(self.constants.items.len - 1); - const number_node = try self.parse_allocator.create(Ast); + const number_node = try self.compile_allocator.create(Ast); number_node.* = .{ .literal = idx }; return number_node; }, @@ -348,13 +348,13 @@ const Parser = struct { _ = try self.tokens.next(); try self.constants.append(self.allocator, .{ .string = try self.allocator.dupe(u8, s) }); const idx: ConstIndex = @enumFromInt(self.constants.items.len - 1); - const string_node = try self.parse_allocator.create(Ast); + const string_node = try self.compile_allocator.create(Ast); string_node.* = .{ .literal = idx }; return string_node; }, .dot => { _ = try self.tokens.next(); - const ast = try self.parse_allocator.create(Ast); + const ast = try self.compile_allocator.create(Ast); ast.* = .identity; return ast; }, @@ -363,7 +363,7 @@ const Parser = struct { _ = try self.tokens.expect(.bracket_right); try self.constants.append(self.allocator, .{ .array = jv.Array.init(self.allocator) }); const idx: ConstIndex = @enumFromInt(self.constants.items.len - 1); - const array_node = try self.parse_allocator.create(Ast); + const array_node = try self.compile_allocator.create(Ast); array_node.* = .{ .literal = idx }; return array_node; }, @@ -372,20 +372,20 @@ const Parser = struct { _ = try self.tokens.expect(.brace_right); try self.constants.append(self.allocator, .{ .object = jv.Object.init(self.allocator) }); const idx: ConstIndex = @enumFromInt(self.constants.items.len - 1); - const object_node = try self.parse_allocator.create(Ast); + const object_node = try self.compile_allocator.create(Ast); object_node.* = .{ .literal = idx }; return object_node; }, .field => |name| { _ = try self.tokens.next(); const is_optional = self.tokens.consumeIf(.question); - const base_ast = try self.parse_allocator.create(Ast); + const base_ast = try self.compile_allocator.create(Ast); base_ast.* = .identity; try self.constants.append(self.allocator, .{ .string = try self.allocator.dupe(u8, name) }); const idx: ConstIndex = @enumFromInt(self.constants.items.len - 1); - const key_ast = try self.parse_allocator.create(Ast); + const key_ast = try self.compile_allocator.create(Ast); key_ast.* = .{ .literal = idx }; - const ast = try self.parse_allocator.create(Ast); + const ast = try self.compile_allocator.create(Ast); ast.* = .{ .index = .{ .base = base_ast, .index = key_ast, .is_optional = is_optional } }; return ast; }, @@ -400,17 +400,17 @@ const Parser = struct { const is_optional = self.tokens.consumeIf(.question); - const ast = try self.parse_allocator.create(Ast); + const ast = try self.compile_allocator.create(Ast); ast.* = .{ .index = .{ .base = base, .index = index_expr, .is_optional = is_optional } }; return ast; } }; -pub fn parse(allocator: std.mem.Allocator, parse_allocator: std.mem.Allocator, tokens: []const Token, constants: *std.ArrayList(jv.Value)) !*Ast { +pub fn parse(allocator: std.mem.Allocator, compile_allocator: std.mem.Allocator, tokens: []const Token, constants: *std.ArrayList(jv.Value)) !*Ast { var token_stream = TokenStream.init(tokens); var parser = Parser{ .allocator = allocator, - .parse_allocator = parse_allocator, + .compile_allocator = compile_allocator, .tokens = &token_stream, .constants = constants, }; |
