diff options
| author | Taylan Kammer <taylan.kammer@gmail.com> | 2026-01-08 14:56:46 +0100 |
|---|---|---|
| committer | Taylan Kammer <taylan.kammer@gmail.com> | 2026-01-08 14:56:46 +0100 |
| commit | 255e2f98680457b611e3e2b93e54da32052e6e55 (patch) | |
| tree | 32e2eb22a9d4416c87e825a72fff6a5f9a12c658 /src | |
| parent | 8bdc0ba5704dceeab9f636d267feb15fbe9e929e (diff) | |
Fix & clean parser.
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.zig | 30 | ||||
| -rw-r--r-- | src/zisp/io/Parser.zig | 80 |
2 files changed, 45 insertions, 65 deletions
diff --git a/src/main.zig b/src/main.zig index 4f1127c..55fecdf 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2,26 +2,36 @@ const std = @import("std"); const zisp = @import("zisp"); -const gst_io = std.Io.Threaded.global_single_threaded.io(); +const alloc = std.heap.smp_allocator; +const gstio = std.Io.Threaded.global_single_threaded.io(); -pub fn main() !void { +pub fn main() !u8 { var stdin_buffer: [4096]u8 = undefined; - var stdin_reader = std.Io.File.stdin().reader(gst_io, &stdin_buffer); + var stdin_reader = std.Io.File.stdin().reader(gstio, &stdin_buffer); const reader = &stdin_reader.interface; var stdout_buffer: [4096]u8 = undefined; - var stdout_writer = std.Io.File.stdout().writer(gst_io, &stdout_buffer); + var stdout_writer = std.Io.File.stdout().writer(gstio, &stdout_buffer); const writer = &stdout_writer.interface; + var sfa = zisp.io.Parser.DefaultSfa.withFallback(alloc); + var p = try zisp.io.Parser.initWithSfa(&sfa, gstio); while (true) { - try writer.writeAll("> "); - try writer.flush(); - const datum = zisp.io.parse.fromReader(reader); + const datum = p.run(reader) catch { + const format = "Parse error: {s}, pos: {d}, unread_char: {s}\n"; + const err = p.err_msg; + const pos = stdin_reader.logicalPos(); + const unread: [4]u8 = + if (p.unread_char) |c| + "0x".* ++ std.fmt.hex(c) + else + "none".*; + std.debug.print(format, .{ err, pos, unread }); + return 1; + }; if (datum.eq(zisp.value.eof)) { - try writer.writeAll("\n"); - return; + return 0; } - try writer.writeAll("= "); try zisp.io.print.toWriter(writer, datum); try writer.writeAll("\n"); try writer.flush(); diff --git a/src/zisp/io/Parser.zig b/src/zisp/io/Parser.zig index 012080b..0fea5f3 100644 --- a/src/zisp/io/Parser.zig +++ b/src/zisp/io/Parser.zig @@ -99,9 +99,10 @@ pub const Error = enum { InvalidCharacter, UnclosedString, UnexpectedEof, - UnicodeError, OutOfRange, ReadError, + UnicodeLengthError, + UnicodeEncodeError, }; pub const Context = struct { @@ -319,7 +320,8 @@ fn err( comptime e: Error, comptime msg: []const u8, ) error{ParseError} { - p.err_msg = @tagName(e) ++ " at: " ++ msg; + @branchHint(.cold); + p.err_msg = @tagName(e) ++ " @ " ++ msg; return error.ParseError; } @@ -376,7 +378,7 @@ fn parseUnit(p: *Parser) !void { .skip_unit => { // Queue another parseUnit, but continue the current one, whose // result will be silently ignored. Simpler alternative to: - // p.subr(.parseUnit, .parseUnit); + // return p.subr(.parseUnit, .parseUnit); try p.push(.parseUnit); }, .no => { @@ -406,7 +408,13 @@ fn returnContext(p: *Parser) !void { } fn parseDatum(p: *Parser) !void { - return p.parseOneDatum(p.getUnread().?, .parseJoin); + const c = p.getUnread() orelse try p.readNoEof("datum"); + if (isBareChar(c) or c == '.') { + const s = try p.parseBareString(c); + return p.jump(.parseJoin, s); + } else { + return p.parseCladDatum(c, .parseJoin); + } } fn parseJoin(p: *Parser) !void { @@ -448,17 +456,14 @@ fn endJoinDatum(p: *Parser) !void { return p.jump(.parseJoin, joined); } -fn parseOneDatum(p: *Parser, c: u8, next: Fn) !void { - if (isBareChar(c)) { - return p.jump(next, try p.parseBareString(c)); - } - return p.parseCladDatum(c, next); -} - fn parseBareString(p: *Parser, c1: u8) !Value { + const allow_dots = std.ascii.isDigit(c1) or switch (c1) { + '.', '+', '-' => true, + else => false, + }; try p.addChar(c1); while (try p.read()) |c| { - if (isBareChar(c)) { + if (isBareChar(c) or (allow_dots and c == '.')) { try p.addChar(c); } else { p.unread(c); @@ -546,11 +551,11 @@ fn parseStringUniHexEsc(p: *Parser) !void { } const n = std.unicode.utf8CodepointSequenceLength(uc) catch { - return p.err(.UnicodeError, msg); + return p.err(.UnicodeLengthError, msg); }; const buf = try p.chars.addManyAsSlice(p.alloc.chars, n); const n2 = std.unicode.utf8Encode(uc, buf) catch { - return p.err(.UnicodeError, msg); + return p.err(.UnicodeEncodeError, msg); }; std.debug.assert(n == n2); } @@ -671,37 +676,19 @@ fn parseList(p: *Parser, open: u8, next: Fn) !void { '{' => '}', else => unreachable, }; - while (try p.read()) |c| { - if (c == close) { - return p.jump(next, head); - } - switch (try p.checkBlank(c)) { - .yes => {}, - .skip_unit => { - try p.listParserSetup(head, close, next); - return p.subr(.parseUnit, .parseUnit); - }, - .no => { - try p.listParserSetup(head, close, next); - p.unread(c); - return p.jump(.parseDatum, null); - }, - } - } - return p.err(.UnexpectedEof, "list"); -} - -fn listParserSetup(p: *Parser, head: Value, close: u8, next: Fn) !void { try p.push(next); p.context.val = head; p.context.char = close; - try p.pushContext(.continueList); + return p.subr(.parseUnit, .continueList); } fn continueList(p: *Parser) !void { - const close = p.context.char; + if (p.result.eq(value.eof)) { + return p.err(.UnexpectedEof, "list"); + } if (p.result.eq(value.none)) { + const close = p.context.char; const c = p.getUnread().?; if (c == close) { return p.endList(); @@ -714,24 +701,7 @@ fn continueList(p: *Parser) !void { p.context.val = p.cons(p.result, p.context.val); - var c1 = p.getUnread() orelse try p.read(); - while (c1) |c| : (c1 = try p.read()) { - if (c == close) { - return p.endList(); - } - switch (try p.checkBlank(c)) { - .yes => {}, - .skip_unit => { - try p.pushContext(.continueList); - return p.subr(.parseUnit, .parseUnit); - }, - .no => { - p.unread(c); - return p.subr(.parseDatum, .continueList); - }, - } - } - return p.err(.UnexpectedEof, "list"); + return p.subr(.parseUnit, .continueList); } fn endList(p: *Parser) !void { |
