diff --git a/src/parser2.ts b/src/parser2.ts index c9a65a8..3fc959c 100644 --- a/src/parser2.ts +++ b/src/parser2.ts @@ -178,6 +178,19 @@ class Parser { break; } + case "quote": { + if (wip.startOfWord()) { + wip.addWordPiece({ text: "" }, pos); + this.advance(); + this.parseQuoteWord(wip); + this.expect("quote"); + wip.freezeWord("Extra characters after quoted word"); + } else { + wip.addWordPiece({ bare: chars }, pos); + } + break; + } + case "[": { this.advance(); const script = this.parseScript(); @@ -225,8 +238,55 @@ class Parser { break; } + default: + throw new ParseError( + `Unhandled case: ${type satisfies never} (${chars})`, + pos + ); + } + + this.advance(); + } + } + + parseQuoteWord(wip: WipScript) { + while (true) { + const [type, chars, pos] = this.next; + switch (type) { + case "text": + case "{": + case "}": + case "]": + case "whitespace": + case "newline": + case "semicolon": + case "comment": + wip.addWordPiece({ text: chars }, pos); + break; + + case "[": { + this.advance(); + const script = this.parseScript(); + wip.addWordPiece({ script }, pos); + this.expect("]"); + break; + } + + case "EOF": + throw new ParseError( + "Reached end of input while parsing a quoted word", + pos + ); + + case "backslash": { + this.advance(); + this.parseBackslashEscape(wip, "quote"); + break; + } + case "quote": - throw new Error(`Unhandled case: ${type} (${chars})`); + return; + default: throw new ParseError( `Unhandled case: ${type satisfies never} (${chars})`,