* Consume a string token. Caller advanced past the opening quote so * `pos - 1` holds the ending code point and `pos - 1` is the start. * @param {string} input input * @param {number} pos position just past the opening quote * @param {MutableToken} out token to populate * @returns {MutableToken
(input, pos, out)
| 625 | * @returns {MutableToken | undefined} the resulting token, or undefined at EOF |
| 626 | */ |
| 627 | function consumeAStringToken(input, pos, out) { |
| 628 | const start = pos - 1; |
| 629 | const endingCodePoint = input.charCodeAt(pos - 1); |
| 630 | for (;;) { |
| 631 | if (pos === input.length) { |
| 632 | return fill(out, TT_STRING, start, pos); |
| 633 | } |
| 634 | const cc = input.charCodeAt(pos); |
| 635 | pos++; |
| 636 | if (cc === endingCodePoint) { |
| 637 | return fill(out, TT_STRING, start, pos); |
| 638 | } |
| 639 | if (_isNewline(cc)) { |
| 640 | pos--; |
| 641 | return fill(out, TT_BAD_STRING_TOKEN, start, pos); |
| 642 | } |
| 643 | if (cc === CC_REVERSE_SOLIDUS) { |
| 644 | // `\` at EOF: string ends here; emit the token so ranges cover all input. |
| 645 | if (pos === input.length) return fill(out, TT_STRING, start, pos); |
| 646 | if (_isNewline(input.charCodeAt(pos))) { |
| 647 | const ccNl = input.charCodeAt(pos); |
| 648 | pos++; |
| 649 | pos = consumeExtraNewline(ccNl, input, pos); |
| 650 | } else if (_ifTwoCodePointsAreValidEscape(input, pos)) { |
| 651 | pos = _consumeAnEscapedCodePoint(input, pos); |
| 652 | } |
| 653 | } |
| 654 | } |
| 655 | } |
| 656 | |
| 657 | /** |
| 658 | * `#` — hash or delim. |
no test coverage detected