diff options
Diffstat (limited to 'src/zisp/io/Parser.zig')
| -rw-r--r-- | src/zisp/io/Parser.zig | 71 |
1 files changed, 39 insertions, 32 deletions
diff --git a/src/zisp/io/Parser.zig b/src/zisp/io/Parser.zig index 57c3207..3ac0d8c 100644 --- a/src/zisp/io/Parser.zig +++ b/src/zisp/io/Parser.zig @@ -35,11 +35,15 @@ const builtin = @import("builtin"); const std = @import("std"); +const gc = @import("../gc.zig"); const lib = @import("../lib.zig"); const value = @import("../value.zig"); +const Alloc = std.mem.Allocator; const List = std.ArrayListUnmanaged; +const IstrSet = gc.IstrSet; +const PairPool = gc.PairPool; const Value = value.Value; const Parser = @This(); @@ -65,21 +69,6 @@ pub const SQUARE = value.rune.pack("SQUARE"); pub const BRACE = value.rune.pack("BRACE"); // zig fmt: on -// We could implement an optimization where we swap in a dummy cons when the -// parser is handling a commented-out datum, but this would require changes to -// the algorithm and doesn't seem very important, so it's not implemented. - -const Cons = *const fn (v1: Value, v2: Value) Value; - -fn dummyCons(v1: Value, v2: Value) Value { - _ = v1; - _ = v2; - return value.undef; -} - -const real_cons = &value.pair.cons; -const fake_cons = &dummyCons; - pub const Error = enum { ReadError, UnexpectedEof, @@ -99,28 +88,38 @@ pub const Context = struct { char: u8 = undefined, }; -alloc: std.mem.Allocator, -io: std.Io, +alloc: Alloc, +istr_set: *IstrSet, +pair_pool: *PairPool, + input: *std.Io.Reader = undefined, + context: Context = .{}, stack: List(Context) = undefined, chars: List(u8) = undefined, -cons: Cons = real_cons, + result: Value = undefined, unread_char: ?u8 = null, err_msg: []const u8 = undefined, -pub fn init(alloc: std.mem.Allocator, io: std.Io) !Parser { - return initCustom(alloc, io, 32, 2048); +pub fn init(alloc: Alloc) !Parser { + const istr_set = gc.mainIstrSet(); + const pair_pool = gc.mainPairPool(); + return initCustom(alloc, 32, 2048, istr_set, pair_pool); } pub fn initCustom( - alloc: std.mem.Allocator, - io: std.Io, + alloc: Alloc, init_ctx_stack_cap: usize, init_str_chars_cap: usize, + istr_set: *IstrSet, + pair_pool: *PairPool, ) !Parser { - var p: Parser = .{ .alloc = alloc, .io = io }; + var p: Parser = .{ + .alloc = alloc, + .istr_set = istr_set, + .pair_pool = pair_pool, + }; p.stack = try .initCapacity(alloc, init_ctx_stack_cap); p.chars = try .initCapacity(alloc, init_str_chars_cap); return p; @@ -156,8 +155,8 @@ fn readNoEof(p: *Parser, comptime emsg: []const u8) !u8 { return try p.read() orelse p.err(.UnexpectedEof, emsg); } -// Fake optional, for use in: while (readNoEof2()) |c| { } -fn readNoEof2(p: *Parser, comptime emsg: []const u8) !?u8 { +// Fake optional, for use in: while (readNoEofOpt()) |c| { } +fn readNoEofOpt(p: *Parser, comptime emsg: []const u8) !?u8 { return try p.read() orelse p.err(.UnexpectedEof, emsg); } @@ -196,7 +195,7 @@ fn getCharsAsString(p: *Parser) !Value { return if (value.sstr.isValidSstr(s)) value.sstr.pack(s) else if (value.istr.isValidIstr(s)) - value.istr.intern(s) + value.istr.internInSet(p.istr_set, s) else value.array.newString(p.alloc, s); } @@ -207,6 +206,14 @@ fn getCharsAsRune(p: *Parser) Value { } // +// Pair consing +// + +fn cons(p: *Parser, car: Value, cdr: Value) Value { + return value.pair.consInPool(p.pair_pool, car, cdr) catch @panic("OOM"); // TODO +} + +// // Stack management & control flow // @@ -451,7 +458,7 @@ fn parseCladDatum(p: *Parser, c: u8, next: Fn) !void { fn getString(p: *Parser, comptime close: u8) !Value { const msg = "string(" ++ .{close} ++ ")"; - while (try p.readNoEof2(msg)) |c| sw: switch (c) { + while (try p.readNoEofOpt(msg)) |c| sw: switch (c) { close => break, '\\' => switch (try p.readNoEof("string backslash escape")) { '\\', '|', '"' => |c2| try p.addChar(c2), @@ -481,7 +488,7 @@ fn getString(p: *Parser, comptime close: u8) !Value { fn getAtString(p: *Parser) !Value { const stop = try p.readNoEof("at-string"); - while (try p.readNoEof2("at-string")) |c| { + while (try p.readNoEofOpt("at-string")) |c| { if (c == stop) break; try p.addChar(c); } @@ -492,7 +499,7 @@ fn getAtString(p: *Parser) !Value { fn skipStringLfEscape(p: *Parser) !u8 { const msg = "string linefeed escape"; - while (try p.readNoEof2(msg)) |c| switch (c) { + while (try p.readNoEofOpt(msg)) |c| switch (c) { '\t', ' ' => continue, '\n' => return p.skipStringIndent(), else => return p.err(.InvalidCharacter, msg), @@ -502,7 +509,7 @@ fn skipStringLfEscape(p: *Parser) !u8 { fn skipStringIndent(p: *Parser) !u8 { const msg = "string newline escape"; - while (try p.readNoEof2(msg)) |c| switch (c) { + while (try p.readNoEofOpt(msg)) |c| switch (c) { '\t', ' ' => continue, else => return c, }; @@ -511,7 +518,7 @@ fn skipStringIndent(p: *Parser) !u8 { fn parseStringRawHexEsc(p: *Parser) !void { const msg = "string raw hex escape"; - while (try p.readNoEof2(msg)) |c1| { + while (try p.readNoEofOpt(msg)) |c1| { if (c1 == ';') break; const c2 = try p.readNoEof(msg); const hi = try p.parseHexDigit(c1, msg); @@ -625,7 +632,7 @@ fn parseHashBang(p: *Parser, next: Fn) !void { } fn getHashBangValue(p: *Parser) !Value { - while (try p.readNoEof2("hash-bang")) |c| switch (c) { + while (try p.readNoEofOpt("hash-bang")) |c| switch (c) { ' ', '\t' => continue, '\n' => return p.err(.InvalidCharacter, "hash-bang"), else => { |
