UNPKG

buntis

Version:

A 100% compliant, self-hosted typescript parser that emits an ESTree-compatible abstract syntax tree

107 lines (96 loc) 3.29 kB
import { CharFlags, CharTypes } from './charClassifier'; import { Chars } from '../chars'; import { Token } from '../token'; import { ParserState, Context } from '../common'; import { report, Errors } from '../errors'; import { advance } from './common'; import { scanSingleToken, firstCharKinds } from './scan'; /** * Scans JSX attribute value * * @param parser The parser instance * @param context Context masks */ export function scanJSXAttributeValue(parser: ParserState, context: Context): Token { parser.startPos = parser.index; parser.startColumn = parser.column; parser.startLine = parser.line; if (parser.nextCodePoint === Chars.SingleQuote || parser.nextCodePoint === Chars.DoubleQuote) { parser.token = scanJSXString(parser, context); } else { parser.token = scanSingleToken(parser, context); } return parser.token; } /** * Scans JSX string * * @param parser The parser object */ export function scanJSXString(parser: ParserState, context: Context): Token { const quote = parser.nextCodePoint; let char = advance(parser); const start = parser.index; while (char !== quote) { if (parser.index >= parser.length) report(parser, context, Errors.UnterminatedString, /* early */ 0); char = advance(parser); } // check for unterminated string if (char !== quote) report(parser, context, Errors.UnterminatedString, /* early */ 0); parser.tokenValue = parser.source.slice(start, parser.index); advance(parser); // skip the quote return Token.StringLiteral; } /** * Scans JSX token * * @param parser The parser object */ export function scanJSXToken(parser: ParserState): Token { parser.startPos = parser.tokenPos = parser.index; parser.startColumn = parser.endColumn = parser.column; parser.startLine = parser.endLine = parser.line; if (parser.index >= parser.length) return (parser.token = Token.EndOfSource); const token = firstCharKinds[parser.source.charCodeAt(parser.index)]; switch (token) { // '<' case Token.LessThan: { advance(parser); if (parser.nextCodePoint === Chars.Slash) { advance(parser); parser.token = Token.JSXClose; } else { parser.token = Token.LessThan; } break; } // '{' case Token.LeftBrace: { advance(parser); parser.token = Token.LeftBrace; break; } default: while (parser.index < parser.length && (CharTypes[advance(parser)] & CharFlags.JSXToken) === 0) {} parser.tokenValue = parser.source.slice(parser.tokenPos, parser.index); parser.token = Token.JSXText; } return parser.token; } /** * Scans JSX identifier * * @param parser The parser instance */ export function scanJSXIdentifier(parser: ParserState): Token { if ((parser.token & (Token.Keywords | Token.Contextual | Token.FutureReserved | Token.IsIdentifier)) !== 0) { const { index } = parser; let char = parser.nextCodePoint; while (CharTypes[char] & (CharFlags.Hyphen | CharFlags.IdentifierPart)) { char = advance(parser); } parser.tokenValue += parser.source.slice(index, parser.index); } parser.token = Token.Identifier; return parser.token; }