refactor string reader for reuse

This commit is contained in:
2022-05-20 19:51:55 +00:00
parent b3999cab2b
commit 9db9ced2e2

View File

@@ -35,7 +35,7 @@ class Reader {
// and also handles string interpolation cases like "${exp}moreString" // and also handles string interpolation cases like "${exp}moreString"
readTable["{"] = (stream:Stream, k) -> CallExp(Symbol("begin").withPos(stream.position()), readExpArray(stream, "}", k)); readTable["{"] = (stream:Stream, k) -> CallExp(Symbol("begin").withPos(stream.position()), readExpArray(stream, "}", k));
readTable['"'] = readString; readTable['"'] = readString.bind(_, _, false);
readTable["#"] = readRawString; readTable["#"] = readRawString;
// Special symbols that wouldn't read as symbols, but should: // Special symbols that wouldn't read as symbols, but should:
@@ -339,8 +339,8 @@ class Reader {
}; };
} }
// Read a string literal // Read a string literal OR a shell section which supports interpolation
static function readString(stream:Stream, k:KissState) { static function readString(stream:Stream, k:KissState, shell = false) {
var pos = stream.position(); var pos = stream.position();
var stringParts:Array<ReaderExp> = []; var stringParts:Array<ReaderExp> = [];
var currentStringPart = ""; var currentStringPart = "";
@@ -350,6 +350,16 @@ class Reader {
currentStringPart = ""; currentStringPart = "";
} }
var terminator = if (shell) "```" else '"';
var escapes = ["$" => "$"];
if (!shell) {
escapes['\\'] = '\\';
escapes['t'] = '\t';
escapes['n'] = '\n';
escapes['r'] = '\r';
escapes['"'] = '"';
}
do { do {
var next = switch (stream.takeChars(1)) { var next = switch (stream.takeChars(1)) {
case Some(c): c; case Some(c): c;
@@ -374,24 +384,13 @@ class Reader {
stringParts.push(interpExpression); stringParts.push(interpExpression);
case '\\': case '\\':
var escapeSequence = stream.expect('valid escape sequence', () -> stream.takeChars(1)); var escapeSequence = stream.expect('valid escape sequence', () -> stream.takeChars(1));
switch (escapeSequence) { if (escapes.exists(escapeSequence)) {
case '\\': currentStringPart += escapes[escapeSequence];
currentStringPart += "\\"; } else {
case 't': stream.error('unsupported escape sequence \\$escapeSequence');
currentStringPart += "\t"; return null;
case 'n':
currentStringPart += "\n";
case 'r':
currentStringPart += "\r";
case '"':
currentStringPart += '"';
case '$':
currentStringPart += '$';
default:
stream.error('unsupported escape sequence \\$escapeSequence');
return null;
} }
case '"': case t if (t == terminator):
endCurrentStringPart(); endCurrentStringPart();
return if (stringParts.length == 1) { return if (stringParts.length == 1) {
stringParts[0].def; stringParts[0].def;