diff options
Diffstat (limited to 'src/zisp/io/Parser.zig')
| -rw-r--r-- | src/zisp/io/Parser.zig | 165 |
1 files changed, 57 insertions, 108 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 { |
