diff options
Diffstat (limited to 'node_modules/meriyah/src/lexer/template.ts')
-rw-r--r-- | node_modules/meriyah/src/lexer/template.ts | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/node_modules/meriyah/src/lexer/template.ts b/node_modules/meriyah/src/lexer/template.ts new file mode 100644 index 0000000..0eeda59 --- /dev/null +++ b/node_modules/meriyah/src/lexer/template.ts @@ -0,0 +1,108 @@ +import { ParserState, Context } from '../common'; +import { Token } from '../token'; +import { Chars } from '../chars'; +import { advanceChar, fromCodePoint } from './common'; +import { parseEscape, Escape, handleStringError } from './string'; +import { report, Errors } from '../errors'; + +/** + * Scan a template section. It can start either from the quote or closing brace. + */ +export function scanTemplate(parser: ParserState, context: Context): Token { + const { index: start } = parser; + let token: Token = Token.TemplateSpan; + let ret: string | void = ''; + + let char = advanceChar(parser); + + while (char !== Chars.Backtick) { + if (char === Chars.Dollar && parser.source.charCodeAt(parser.index + 1) === Chars.LeftBrace) { + advanceChar(parser); // Skip: '}' + token = Token.TemplateContinuation; + break; + } else if ((char & 8) === 8 && char === Chars.Backslash) { + char = advanceChar(parser); + if (char > 0x7e) { + ret += fromCodePoint(char); + } else { + const code = parseEscape(parser, context | Context.Strict, char); + if (code >= 0) { + ret += fromCodePoint(code); + } else if (code !== Escape.Empty && context & Context.TaggedTemplate) { + ret = undefined; + char = scanBadTemplate(parser, char); + if (char < 0) token = Token.TemplateContinuation; + break; + } else { + handleStringError(parser, code as Escape, /* isTemplate */ 1); + } + } + } else { + if ( + parser.index < parser.end && + char === Chars.CarriageReturn && + parser.source.charCodeAt(parser.index) === Chars.LineFeed + ) { + ret += fromCodePoint(char); + parser.currentChar = parser.source.charCodeAt(++parser.index); + } + + if (((char & 83) < 3 && char === Chars.LineFeed) || (char ^ Chars.LineSeparator) <= 1) { + parser.column = -1; + parser.line++; + } + ret += fromCodePoint(char); + } + if (parser.index >= parser.end) report(parser, Errors.UnterminatedTemplate); + char = advanceChar(parser); + } + + advanceChar(parser); // Consume the quote or opening brace + parser.tokenValue = ret; + + parser.tokenRaw = parser.source.slice(start + 1, parser.index - (token === Token.TemplateSpan ? 1 : 2)); + + return token; +} + +/** + * Scans looser template segment + * + * @param parser Parser state + * @param ch Code point + */ +function scanBadTemplate(parser: ParserState, ch: number): number { + while (ch !== Chars.Backtick) { + switch (ch) { + case Chars.Dollar: { + const index = parser.index + 1; + if (index < parser.end && parser.source.charCodeAt(index) === Chars.LeftBrace) { + parser.index = index; + parser.column++; + return -ch; + } + break; + } + case Chars.LineFeed: + case Chars.LineSeparator: + case Chars.ParagraphSeparator: + parser.column = -1; + parser.line++; + // falls through + + default: + // do nothing + } + if (parser.index >= parser.end) report(parser, Errors.UnterminatedTemplate); + ch = advanceChar(parser); + } + + return ch; +} + +export function scanTemplateTail(parser: ParserState, context: Context): Token { + if (parser.index >= parser.end) report(parser, Errors.Unexpected); + parser.index--; + parser.column--; + return scanTemplate(parser, context); +} |