summaryrefslogtreecommitdiff
path: root/src/zisp/io/Parser.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/zisp/io/Parser.zig')
-rw-r--r--src/zisp/io/Parser.zig165
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 {