diff options
Diffstat (limited to 'src/zisp/io')
| -rw-r--r-- | src/zisp/io/Parser.zig | 165 | ||||
| -rw-r--r-- | src/zisp/io/unparser.zig | 98 |
2 files changed, 97 insertions, 166 deletions
diff --git a/src/zisp/io/Parser.zig b/src/zisp/io/Parser.zig index 7d14808..14db959 100644 --- a/src/zisp/io/Parser.zig +++ b/src/zisp/io/Parser.zig @@ -188,20 +188,12 @@ fn addChar(p: *Parser, c: u8) !void { try p.chars.append(p.alloc.chars, c); } -fn getBareString(p: *Parser) Value { +fn getString(p: *Parser) Value { defer p.chars.clearRetainingCapacity(); - return if (p.chars.items.len <= 6) + return if (value.sstr.isValidSstr(p.chars.items)) value.sstr.pack(p.chars.items) else - value.istr.intern(p.chars.items, false); -} - -fn getQuotedString(p: *Parser) Value { - defer p.chars.clearRetainingCapacity(); - return if (p.chars.items.len <= 6) - value.sstr.packQuoted(p.chars.items) - else - value.istr.intern(p.chars.items, true); + value.istr.intern(p.chars.items); } fn getRune(p: *Parser) Value { @@ -223,7 +215,6 @@ const Fn = enum { parseJoin, parseHashDatum, endHashDatum, - parseRuneDatum, endRuneDatum, endLabelDatum, continueList, @@ -234,22 +225,21 @@ const Fn = enum { fn call(p: *Parser, f: Fn) !void { try switch (f) { - .parseUnit => parseUnit(p), - .parseDatum => parseDatum(p), - .endUnit => endUnit(p), - .returnContext => returnContext(p), - .endFirstDatum => endFirstDatum(p), - .endJoinDatum => endJoinDatum(p), - .parseJoin => parseJoin(p), - .parseHashDatum => parseHashDatum(p), - .endHashDatum => endHashDatum(p), - .parseRuneDatum => parseRuneDatum(p), - .endRuneDatum => endRuneDatum(p), - .endLabelDatum => endLabelDatum(p), - .continueList => continueList(p), - .endImproperList => endImproperList(p), - .closeImproperList => closeImproperList(p), - .endQuoteExpr => endQuoteExpr(p), + .parseUnit => p.parseUnit(), + .parseDatum => p.parseDatum(), + .endUnit => p.endUnit(), + .returnContext => p.returnContext(), + .endFirstDatum => p.endFirstDatum(), + .endJoinDatum => p.endJoinDatum(), + .parseJoin => p.parseJoin(), + .parseHashDatum => p.parseHashDatum(), + .endHashDatum => p.endHashDatum(), + .endRuneDatum => p.endRuneDatum(), + .endLabelDatum => p.endLabelDatum(), + .continueList => p.continueList(), + .endImproperList => p.endImproperList(), + .closeImproperList => p.closeImproperList(), + .endQuoteExpr => p.endQuoteExpr(), }; } @@ -257,7 +247,7 @@ pub fn run(p: *Parser, input: std.io.AnyReader) !Value { p.input = input; p.context.next = .parseUnit; while (p.context.next) |next| { - if (detailed_debug) printStack(p); + if (detailed_debug) p.printStack(); try p.call(next); } if (p.unread_char) |_| { @@ -360,7 +350,7 @@ fn endUnit(p: *Parser) !void { const c = p.getUnread() orelse return p.ret(); switch (try p.checkBlanks(c)) { .yes => {}, - .skip_unit => return skipUnitAndReturn(p), + .skip_unit => return p.skipUnitAndReturn(), .no => p.unread(c), } return p.ret(); @@ -383,7 +373,7 @@ fn endFirstDatum(p: *Parser) !void { if (p.result.eq(value.none)) { return p.ret(); } - return parseJoin(p); + return p.parseJoin(); } fn parseJoin(p: *Parser) !void { @@ -429,54 +419,27 @@ fn parseOneDatum(p: *Parser, c: u8, next: Fn) !void { return p.parseCladDatum(c, next); } -fn parseBareString(p: *Parser, c: u8) !Value { - const allow_dots = std.ascii.isDigit(c) or switch (c) { +fn parseBareString(p: *Parser, c1: u8) !Value { + const allow_dots = std.ascii.isDigit(c1) or switch (c1) { '.', '+', '-' => true, else => false, }; - try p.addChar(c); - return p.parseBareStringRest(allow_dots); -} - -fn parseBareEscString(p: *Parser) !Value { - try p.addChar(try parseBareEsc(p)); - return p.parseBareStringRest(false); -} - -fn parseBareStringRest(p: *Parser, allow_dots: bool) !Value { + try p.addChar(c1); while (try p.read()) |c| { if (isBareChar(c) or (allow_dots and c == '.')) { try p.addChar(c); - } else if (c == '\\') { - try p.addChar(try parseBareEsc(p)); } else { p.unread(c); break; } } - return p.getBareString(); -} - -fn parseBareEsc(p: *Parser) !u8 { - const c = try p.readNoEof("bare escape"); - if (isBareEsc(c)) { - return c; - } else { - return p.err(.InvalidCharacter, "bare escape"); - } + return p.getString(); } fn parseCladDatum(p: *Parser, c: u8, next: Fn) !void { - if (c == '\\') { - return p.jump(next, try parseBareEscString(p)); - } - if (c == '"') { - return p.jump(next, try p.parseQuotedString('"')); - } - if (c == '|') { - return p.jump(next, try p.parseQuotedString('|')); - } return switch (c) { + '|' => p.jump(next, try p.parseEscapedString('|')), + '"' => p.jump(next, try p.parseEscapedString('"')), '#' => p.parseHashExpression(next), '(', '[', '{' => p.parseList(c, next), '\'', '`', ',' => p.parseQuoteExpr(c, next), @@ -484,10 +447,11 @@ fn parseCladDatum(p: *Parser, c: u8, next: Fn) !void { }; } -fn parseQuotedString(p: *Parser, close: u8) !Value { +fn parseEscapedString(p: *Parser, close: u8) !Value { while (try p.read()) |c| { if (c == close) { - return p.getQuotedString(); + const s = p.getString(); + return if (close == '"') p.cons(QUOTE, s) else s; } if (c != '\\') { try p.addChar(c); @@ -500,12 +464,8 @@ fn parseQuotedString(p: *Parser, close: u8) !Value { fn parseQuotedEsc(p: *Parser, close: u8) !void { const c = try p.readNoEof("quoted escape"); - if (c == close) { - return p.addChar(close); - } - if (c == 'u') { - return parseUniHexHandleErrors(p); - } + if (c == close) return p.addChar(close); + if (c == 'u') return p.parseUniHexHandleErrors(); try p.addChar(switch (c) { '\\' => c, '0' => 0, @@ -523,7 +483,7 @@ fn parseQuotedEsc(p: *Parser, close: u8) !void { } fn parseUniHexHandleErrors(p: *Parser) !void { - return parseUniHex(p) catch |e| switch (e) { + return p.parseUniHex() catch |e| switch (e) { error.Utf8CannotEncodeSurrogateHalf => p.err( .UnicodeError, "unicode escape", @@ -552,16 +512,16 @@ fn parseUniHex(p: *Parser) !void { fn parseHashExpression(p: *Parser, next: Fn) !void { const c = try p.readNoEof("hash expression"); - if (try p.checkBlanks(c) != .no) { - return p.err(.InvalidCharacter, "hash expression"); - } if (std.ascii.isAlphabetic(c)) { const r = try p.parseRune(c); return p.parseRuneEnd(r, next); } + if (c == '\\') { + const c1 = try p.readNoEof("bare string after hash"); + return p.jump(next, p.cons(HASH, try p.parseBareString(c1))); + } if (c == '%') { - const l = try parseLabel(p); - return p.parseLabelEnd(l, next); + return p.parseLabel(next); } p.unread(c); return p.subr(.parseHashDatum, next); @@ -594,53 +554,42 @@ fn parseRune(p: *Parser, c1: u8) !Value { fn parseRuneEnd(p: *Parser, r: Value, next: Fn) !void { const c = p.getUnread() orelse return p.jump(next, r); if (c == '\\') { - return p.jump(next, p.cons(r, try p.parseBareString(c))); + const c1 = try p.readNoEof("bare string at rune end"); + return p.jump(next, p.cons(r, try p.parseBareString(c1))); } if (c == '"') { - return p.jump(next, p.cons(r, try p.parseQuotedString('"'))); + return p.jump(next, p.cons(r, try p.parseEscapedString('"'))); } if (c == '|') { - return p.jump(next, p.cons(r, try p.parseQuotedString('|'))); + return p.jump(next, p.cons(r, try p.parseEscapedString('|'))); } p.unread(c); switch (c) { '#', '(', '[', '{', '\'', '`', ',' => { try p.push(next); p.context.val = r; - // Use jump to prevent recursion. - return p.jump(.parseRuneDatum, null); + return p.subr(.parseDatum, .endRuneDatum); }, else => return p.jump(next, r), } } -fn parseRuneDatum(p: *Parser) !void { - return p.parseCladDatum(p.getUnread().?, .endRuneDatum); -} - fn endRuneDatum(p: *Parser) !void { - if (p.result.eq(value.none)) { - p.retval(p.context.val); - } return p.retval(p.cons(p.context.val, p.result)); } -fn parseLabel(p: *Parser) !Value { - const label = try p.parseHex(u48, "datum label"); - return value.fixnum.pack(label); -} - -fn parseLabelEnd(p: *Parser, l: Value, next: Fn) !void { - const c = p.getUnread() orelse return p.err(.UnexpectedEof, "datum label"); - if (c == '%') { - return p.jump(next, p.cons(LABEL, l)); - } - if (c == '=') { - try p.push(next); - p.context.val = l; - return p.subr(.parseDatum, .endLabelDatum); +fn parseLabel(p: *Parser, next: Fn) !void { + const n = try p.parseHex(u48, "datum label"); + const l = value.fixnum.pack(n); + switch (p.getUnread() orelse try p.readNoEof("datum label")) { + '%' => return p.jump(next, p.cons(LABEL, l)), + '=' => { + try p.push(next); + p.context.val = l; + return p.subr(.parseDatum, .endLabelDatum); + }, + else => return p.err(.InvalidCharacter, "datum label"), } - return p.err(.InvalidCharacter, "datum label"); } fn endLabelDatum(p: *Parser) !void { @@ -696,7 +645,7 @@ fn continueList(p: *Parser) !void { if (p.result.eq(value.none)) { const c = p.getUnread().?; if (c == close) { - return endList(p); + return p.endList(); } return p.err(.InvalidCharacter, "list"); } @@ -710,7 +659,7 @@ fn continueList(p: *Parser) !void { var c1 = p.getUnread() orelse try p.read(); while (c1) |c| : (c1 = try p.read()) { if (c == close) { - return endList(p); + return p.endList(); } switch (try p.checkBlanks(c)) { .yes => {}, @@ -736,7 +685,7 @@ fn endImproperList(p: *Parser) !void { return p.err(.InvalidCharacter, "list tail"); } p.context.val = lib.list.reverseWithTail(p.context.val, p.result); - return closeImproperList(p); + return p.closeImproperList(); } fn closeImproperList(p: *Parser) !void { diff --git a/src/zisp/io/unparser.zig b/src/zisp/io/unparser.zig index e72f130..64e18d0 100644 --- a/src/zisp/io/unparser.zig +++ b/src/zisp/io/unparser.zig @@ -1,23 +1,27 @@ const std = @import("std"); +const gc = @import("../gc.zig"); const value = @import("../value.zig"); const istr = value.istr; const seq = value.seq; const ShortString = value.ShortString; -const OtherTag = value.OtherTag; const Value = value.Value; pub fn unparse(w: anytype, v: Value) anyerror!void { - try if (value.double.check(v)) - unparseDouble(w, v) - else if (value.fixnum.check(v)) - unparseFixnum(w, v) - else if (value.ptr.checkZisp(v)) - unparseHeap(w, v) - else - unparseOther(w, v); + // zig fmt: off + try if (v.isDouble()) unparseDouble(w, v) + else if (v.isFixnum()) unparseFixnum(w, v) + else if (v.getPtr(.pair)) |p| unparsePair(w, @ptrCast(p)) + else if (v.getPtr(.seq)) |p| unparseSeq(w, @ptrCast(p)) + else if (v.isRune()) unparseRune(w, v) + else if (v.isChar()) unparseChar(w, v) + else if (v.isMisc()) unparseMisc(w, v) + else if (v.isSrat()) unparseSrat(w, v) + else if (v.isSstr()) unparseSstr(w, v) + ; + // zig fmt: on } fn unparseDouble(w: anytype, v: Value) !void { @@ -32,25 +36,6 @@ fn unparseFixnum(w: anytype, v: Value) !void { @panic("not implemented"); } -fn unparseHeap(w: anytype, v: Value) !void { - const p, const t = value.ptr.unpack(v); - try switch (t) { - .pair => unparsePair(w, @ptrCast(p)), - .seq => unparseSeq(w, @ptrCast(p)), - else => @panic("not implemented"), - }; -} - -fn unparseOther(w: anytype, v: Value) !void { - try switch (v.other.tag) { - .rune => unparseRune(w, v), - .sstr => unparseSstr(w, v), - .qstr => unparseQstr(w, v), - .char => unparseChar(w, v), - .misc => unparseMisc(w, v), - }; -} - fn unparseRune(w: anytype, v: Value) !void { const name = value.rune.unpack(v); try w.writeByte('#'); @@ -58,41 +43,43 @@ fn unparseRune(w: anytype, v: Value) !void { } fn unparseSstr(w: anytype, v: Value) !void { + // TODO: Check if pipes/escapes necessary. const str = value.sstr.unpack(v); try w.writeAll(str.constSlice()); } -fn unparseQstr(w: anytype, v: Value) !void { - const str = value.sstr.unpack(v); - try w.writeByte('"'); - try w.writeAll(str.constSlice()); - try w.writeByte('"'); -} - fn unparseChar(w: anytype, v: Value) !void { + const uc: u21 = value.char.unpack(v); var buf: [4]u8 = undefined; - const len = try std.unicode.utf8Encode(v.char.value, &buf); + const len = try std.unicode.utf8Encode(uc, &buf); try w.writeAll(buf[0..len]); } fn unparseMisc(w: anytype, v: Value) !void { - try switch (v.misc.value) { - .f => w.writeAll("#f"), - .t => w.writeAll("#t"), - .nil => w.writeAll("()"), - .eof => w.writeAll("#EOF"), - .none => w.writeAll("#NONE"), - .undef => w.writeAll("#UNDEF"), + try switch (v.bits) { + value.f.bits => w.writeAll("#f"), + value.t.bits => w.writeAll("#t"), + value.nil.bits => w.writeAll("()"), + value.eof.bits => w.writeAll("#EOF"), + value.none.bits => w.writeAll("#NONE"), + value.undef.bits => w.writeAll("#UNDEF"), + else => @panic("not implemented"), }; } +fn unparseSrat(w: anytype, v: Value) !void { + _ = w; + _ = v; + @panic("not implemented"); +} + fn unparsePair(w: anytype, p: *[2]Value) !void { try w.writeByte('('); try unparse(w, p[0]); var cdr = p[1]; - while (value.pair.check(cdr)) : (cdr = value.pair.cdr(cdr)) { + while (value.pair.check(cdr)) |p2| : (cdr = value.pair.cdr(cdr)) { try w.writeByte(' '); - try unparse(w, value.pair.car(cdr)); + try unparse(w, p2[0]); } if (!value.nil.eq(cdr)) { try w.writeByte(' '); @@ -103,21 +90,16 @@ fn unparsePair(w: anytype, p: *[2]Value) !void { try w.writeByte(')'); } -fn unparseSeq(w: anytype, p: *seq.Header) !void { - const h = istr.getHeaderFromPtr(@ptrCast(p)); - switch (h.type) { - .string => try unparseString(w, h), +fn unparseSeq(w: anytype, s: *seq.Header) !void { + switch (s.type) { + .string => try unparseString(w, s), else => @panic("not implemented"), } } -fn unparseString(w: anytype, h: *seq.Header) !void { - const info = h.info.string; - if (info.quoted) { - try w.writeByte('"'); - } - try w.writeAll(h.bytes()); - if (info.quoted) { - try w.writeByte('"'); - } +fn unparseString(w: anytype, s: *seq.Header) !void { + // TODO: Check if pipes/escapes necessary. + try w.writeByte('|'); + try w.writeAll(s.bytes()); + try w.writeByte('|'); } |
