summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTaylan Kammer <taylan.kammer@gmail.com>2025-03-19 16:20:12 +0100
committerTaylan Kammer <taylan.kammer@gmail.com>2025-03-19 16:20:12 +0100
commitdd6f15ce5cb359116d0278771ce14ddc9e3de06f (patch)
treec7367e3c999b10671ebbdeaf2a44b3f2e4a8140a
parent8a658ca3f9de8a4b3ebf518a034d72e3c0a608ca (diff)
* src/libzisp/io/parser.zig: Cleanup & optimize.
-rw-r--r--src/libzisp/io/parser.zig49
1 files changed, 35 insertions, 14 deletions
diff --git a/src/libzisp/io/parser.zig b/src/libzisp/io/parser.zig
index b79b679..e501462 100644
--- a/src/libzisp/io/parser.zig
+++ b/src/libzisp/io/parser.zig
@@ -229,6 +229,7 @@
// (foo bar baz)| <- parser reached EOF (assuming no trailing spaces)
//
+const builtin = @import("builtin");
const std = @import("std");
const lib = @import("../lib.zig");
@@ -268,10 +269,13 @@ const Context = struct {
const BUF_SIZE = 16;
const POS_TYPE = u4;
-const debug_mode = @import("builtin").mode == .Debug;
+const is_test = builtin.is_test;
+const is_debug = builtin.mode == .Debug;
const State = struct {
input: std.io.AnyReader,
+ alloc: std.mem.Allocator,
+
counter: usize = 0,
buf: [BUF_SIZE]u8 = undefined,
@@ -279,22 +283,22 @@ const State = struct {
write_pos: POS_TYPE = 0,
context: Context = .{},
- stack: std.ArrayList(Context),
+ stack: std.ArrayListUnmanaged(Context) = .{},
retval: Value = undefined,
// For debugging.
checked_eof: bool = false,
fn init(input: std.io.AnyReader, alloc: std.mem.Allocator) State {
- return .{ .input = input, .stack = .init(alloc) };
+ return .{ .input = input, .alloc = alloc };
}
fn deinit(s: *State) void {
- s.stack.deinit();
+ s.stack.deinit(s.alloc);
}
fn recurParse(s: *State, start: Fn, end: Fn) void {
- s.stack.append(.{
+ s.stack.append(s.alloc, .{
.next = end,
.val = s.context.val,
.char = s.context.char,
@@ -320,7 +324,7 @@ const State = struct {
}
fn eof(s: *State) bool {
- if (debug_mode) {
+ if (is_debug) {
s.checked_eof = true;
}
readNext(s) catch |e| switch (e) {
@@ -331,7 +335,7 @@ const State = struct {
}
fn peek(s: *State) u8 {
- if (debug_mode) {
+ if (is_debug) {
if (!s.checked_eof) {
@panic("Didn't check EOF before calling peek()!");
}
@@ -340,7 +344,7 @@ const State = struct {
}
fn skip(s: *State) void {
- if (debug_mode) {
+ if (is_debug) {
s.checked_eof = false;
}
// std.debug.print("{c}\n", .{s.buf[s.pos]});
@@ -415,10 +419,28 @@ const Fn = enum {
};
pub fn parse(input: std.io.AnyReader) Value {
- var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init;
- defer if (gpa.deinit() == .leak) @panic("leak");
- var s: State = .init(input, gpa.allocator());
+ var debug_alloc: std.heap.DebugAllocator(.{}) = undefined;
+ if (!is_test and is_debug) {
+ debug_alloc = .init;
+ }
+ defer if (!is_test and is_debug) {
+ if (debug_alloc.deinit() == .leak) {
+ @panic("leak");
+ }
+ };
+
+ const alloc = if (is_test)
+ std.testing.allocator
+ else if (is_debug)
+ debug_alloc.allocator()
+ else
+ std.heap.smp_allocator;
+
+ var sfa = std.heap.stackFallback(4096, alloc);
+
+ var s: State = .init(input, sfa.get());
defer s.deinit();
+
while (s.context.next != .done) call(&s);
return s.retval;
}
@@ -642,7 +664,7 @@ fn readQuotedSstr(s: *State) !?Value {
// TODO: Handle escapes.
var buf: [6]u8 = undefined;
var i: u8 = 0;
- while (!s.eof()) {
+ while (!s.eof()) : (i += 1) {
const c = s.getc();
if (c == '"') {
// ok, return what we accumulated
@@ -655,7 +677,6 @@ fn readQuotedSstr(s: *State) !?Value {
}
// ok, save this byte and go on
buf[i] = c;
- i += 1;
}
return error.Unclosed;
}
@@ -823,6 +844,6 @@ fn endImproperList(s: *State) void {
fn err(s: *State, msg: []const u8) noreturn {
std.debug.print("{s}\n", .{msg});
- std.debug.print("pos: {}\n", .{s.counter});
+ std.debug.print("position: {}\n", .{s.counter});
@panic("parse error");
}