| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- // Copyright 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Simon Lydell
- // License: MIT.
- var HashbangComment, Identifier, JSXIdentifier, JSXPunctuator, JSXString, JSXText, KeywordsWithExpressionAfter, KeywordsWithNoLineTerminatorAfter, LineTerminatorSequence, MultiLineComment, Newline, NumericLiteral, Punctuator, RegularExpressionLiteral, SingleLineComment, StringLiteral, Template, TokensNotPrecedingObjectLiteral, TokensPrecedingExpression, WhiteSpace, jsTokens;
- RegularExpressionLiteral = /\/(?![*\/])(?:\[(?:[^\]\\\n\r\u2028\u2029]+|\\.)*\]?|[^\/[\\\n\r\u2028\u2029]+|\\.)*(\/[$_\u200C\u200D\p{ID_Continue}]*|\\)?/yu;
- Punctuator = /--|\+\+|=>|\.{3}|\??\.(?!\d)|(?:&&|\|\||\?\?|[+\-%&|^]|\*{1,2}|<{1,2}|>{1,3}|!=?|={1,2}|\/(?![\/*]))=?|[?~,:;[\](){}]/y;
- Identifier = /(\x23?)(?=[$_\p{ID_Start}\\])(?:[$_\u200C\u200D\p{ID_Continue}]+|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+/yu;
- StringLiteral = /(['"])(?:[^'"\\\n\r]+|(?!\1)['"]|\\(?:\r\n|[^]))*(\1)?/y;
- NumericLiteral = /(?:0[xX][\da-fA-F](?:_?[\da-fA-F])*|0[oO][0-7](?:_?[0-7])*|0[bB][01](?:_?[01])*)n?|0n|[1-9](?:_?\d)*n|(?:(?:0(?!\d)|0\d*[89]\d*|[1-9](?:_?\d)*)(?:\.(?:\d(?:_?\d)*)?)?|\.\d(?:_?\d)*)(?:[eE][+-]?\d(?:_?\d)*)?|0[0-7]+/y;
- Template = /[`}](?:[^`\\$]+|\\[^]|\$(?!\{))*(`|\$\{)?/y;
- WhiteSpace = /[\t\v\f\ufeff\p{Zs}]+/yu;
- LineTerminatorSequence = /\r?\n|[\r\u2028\u2029]/y;
- MultiLineComment = /\/\*(?:[^*]+|\*(?!\/))*(\*\/)?/y;
- SingleLineComment = /\/\/.*/y;
- HashbangComment = /^#!.*/;
- JSXPunctuator = /[<>.:={}]|\/(?![\/*])/y;
- JSXIdentifier = /[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}-]*/yu;
- JSXString = /(['"])(?:[^'"]+|(?!\1)['"])*(\1)?/y;
- JSXText = /[^<>{}]+/y;
- TokensPrecedingExpression = /^(?:[\/+-]|\.{3}|\?(?:InterpolationIn(?:JSX|Template)|NoLineTerminatorHere|NonExpressionParenEnd|UnaryIncDec))?$|[{}([,;<>=*%&|^!~?:]$/;
- TokensNotPrecedingObjectLiteral = /^(?:=>|[;\]){}]|else|\?(?:NoLineTerminatorHere|NonExpressionParenEnd))?$/;
- KeywordsWithExpressionAfter = /^(?:await|case|default|delete|do|else|instanceof|new|return|throw|typeof|void|yield)$/;
- KeywordsWithNoLineTerminatorAfter = /^(?:return|throw|yield)$/;
- Newline = RegExp(LineTerminatorSequence.source);
- module.exports = jsTokens = function*(input, {jsx = false} = {}) {
- var braces, firstCodePoint, isExpression, lastIndex, lastSignificantToken, length, match, mode, nextLastIndex, nextLastSignificantToken, parenNesting, postfixIncDec, punctuator, stack;
- ({length} = input);
- lastIndex = 0;
- lastSignificantToken = "";
- stack = [
- {tag: "JS"}
- ];
- braces = [];
- parenNesting = 0;
- postfixIncDec = false;
- if (match = HashbangComment.exec(input)) {
- yield ({
- type: "HashbangComment",
- value: match[0]
- });
- lastIndex = match[0].length;
- }
- while (lastIndex < length) {
- mode = stack[stack.length - 1];
- switch (mode.tag) {
- case "JS":
- case "JSNonExpressionParen":
- case "InterpolationInTemplate":
- case "InterpolationInJSX":
- if (input[lastIndex] === "/" && (TokensPrecedingExpression.test(lastSignificantToken) || KeywordsWithExpressionAfter.test(lastSignificantToken))) {
- RegularExpressionLiteral.lastIndex = lastIndex;
- if (match = RegularExpressionLiteral.exec(input)) {
- lastIndex = RegularExpressionLiteral.lastIndex;
- lastSignificantToken = match[0];
- postfixIncDec = true;
- yield ({
- type: "RegularExpressionLiteral",
- value: match[0],
- closed: match[1] !== void 0 && match[1] !== "\\"
- });
- continue;
- }
- }
- Punctuator.lastIndex = lastIndex;
- if (match = Punctuator.exec(input)) {
- punctuator = match[0];
- nextLastIndex = Punctuator.lastIndex;
- nextLastSignificantToken = punctuator;
- switch (punctuator) {
- case "(":
- if (lastSignificantToken === "?NonExpressionParenKeyword") {
- stack.push({
- tag: "JSNonExpressionParen",
- nesting: parenNesting
- });
- }
- parenNesting++;
- postfixIncDec = false;
- break;
- case ")":
- parenNesting--;
- postfixIncDec = true;
- if (mode.tag === "JSNonExpressionParen" && parenNesting === mode.nesting) {
- stack.pop();
- nextLastSignificantToken = "?NonExpressionParenEnd";
- postfixIncDec = false;
- }
- break;
- case "{":
- Punctuator.lastIndex = 0;
- isExpression = !TokensNotPrecedingObjectLiteral.test(lastSignificantToken) && (TokensPrecedingExpression.test(lastSignificantToken) || KeywordsWithExpressionAfter.test(lastSignificantToken));
- braces.push(isExpression);
- postfixIncDec = false;
- break;
- case "}":
- switch (mode.tag) {
- case "InterpolationInTemplate":
- if (braces.length === mode.nesting) {
- Template.lastIndex = lastIndex;
- match = Template.exec(input);
- lastIndex = Template.lastIndex;
- lastSignificantToken = match[0];
- if (match[1] === "${") {
- lastSignificantToken = "?InterpolationInTemplate";
- postfixIncDec = false;
- yield ({
- type: "TemplateMiddle",
- value: match[0]
- });
- } else {
- stack.pop();
- postfixIncDec = true;
- yield ({
- type: "TemplateTail",
- value: match[0],
- closed: match[1] === "`"
- });
- }
- continue;
- }
- break;
- case "InterpolationInJSX":
- if (braces.length === mode.nesting) {
- stack.pop();
- lastIndex += 1;
- lastSignificantToken = "}";
- yield ({
- type: "JSXPunctuator",
- value: "}"
- });
- continue;
- }
- }
- postfixIncDec = braces.pop();
- nextLastSignificantToken = postfixIncDec ? "?ExpressionBraceEnd" : "}";
- break;
- case "]":
- postfixIncDec = true;
- break;
- case "++":
- case "--":
- nextLastSignificantToken = postfixIncDec ? "?PostfixIncDec" : "?UnaryIncDec";
- break;
- case "<":
- if (jsx && (TokensPrecedingExpression.test(lastSignificantToken) || KeywordsWithExpressionAfter.test(lastSignificantToken))) {
- stack.push({tag: "JSXTag"});
- lastIndex += 1;
- lastSignificantToken = "<";
- yield ({
- type: "JSXPunctuator",
- value: punctuator
- });
- continue;
- }
- postfixIncDec = false;
- break;
- default:
- postfixIncDec = false;
- }
- lastIndex = nextLastIndex;
- lastSignificantToken = nextLastSignificantToken;
- yield ({
- type: "Punctuator",
- value: punctuator
- });
- continue;
- }
- Identifier.lastIndex = lastIndex;
- if (match = Identifier.exec(input)) {
- lastIndex = Identifier.lastIndex;
- nextLastSignificantToken = match[0];
- switch (match[0]) {
- case "for":
- case "if":
- case "while":
- case "with":
- if (lastSignificantToken !== "." && lastSignificantToken !== "?.") {
- nextLastSignificantToken = "?NonExpressionParenKeyword";
- }
- }
- lastSignificantToken = nextLastSignificantToken;
- postfixIncDec = !KeywordsWithExpressionAfter.test(match[0]);
- yield ({
- type: match[1] === "#" ? "PrivateIdentifier" : "IdentifierName",
- value: match[0]
- });
- continue;
- }
- StringLiteral.lastIndex = lastIndex;
- if (match = StringLiteral.exec(input)) {
- lastIndex = StringLiteral.lastIndex;
- lastSignificantToken = match[0];
- postfixIncDec = true;
- yield ({
- type: "StringLiteral",
- value: match[0],
- closed: match[2] !== void 0
- });
- continue;
- }
- NumericLiteral.lastIndex = lastIndex;
- if (match = NumericLiteral.exec(input)) {
- lastIndex = NumericLiteral.lastIndex;
- lastSignificantToken = match[0];
- postfixIncDec = true;
- yield ({
- type: "NumericLiteral",
- value: match[0]
- });
- continue;
- }
- Template.lastIndex = lastIndex;
- if (match = Template.exec(input)) {
- lastIndex = Template.lastIndex;
- lastSignificantToken = match[0];
- if (match[1] === "${") {
- lastSignificantToken = "?InterpolationInTemplate";
- stack.push({
- tag: "InterpolationInTemplate",
- nesting: braces.length
- });
- postfixIncDec = false;
- yield ({
- type: "TemplateHead",
- value: match[0]
- });
- } else {
- postfixIncDec = true;
- yield ({
- type: "NoSubstitutionTemplate",
- value: match[0],
- closed: match[1] === "`"
- });
- }
- continue;
- }
- break;
- case "JSXTag":
- case "JSXTagEnd":
- JSXPunctuator.lastIndex = lastIndex;
- if (match = JSXPunctuator.exec(input)) {
- lastIndex = JSXPunctuator.lastIndex;
- nextLastSignificantToken = match[0];
- switch (match[0]) {
- case "<":
- stack.push({tag: "JSXTag"});
- break;
- case ">":
- stack.pop();
- if (lastSignificantToken === "/" || mode.tag === "JSXTagEnd") {
- nextLastSignificantToken = "?JSX";
- postfixIncDec = true;
- } else {
- stack.push({tag: "JSXChildren"});
- }
- break;
- case "{":
- stack.push({
- tag: "InterpolationInJSX",
- nesting: braces.length
- });
- nextLastSignificantToken = "?InterpolationInJSX";
- postfixIncDec = false;
- break;
- case "/":
- if (lastSignificantToken === "<") {
- stack.pop();
- if (stack[stack.length - 1].tag === "JSXChildren") {
- stack.pop();
- }
- stack.push({tag: "JSXTagEnd"});
- }
- }
- lastSignificantToken = nextLastSignificantToken;
- yield ({
- type: "JSXPunctuator",
- value: match[0]
- });
- continue;
- }
- JSXIdentifier.lastIndex = lastIndex;
- if (match = JSXIdentifier.exec(input)) {
- lastIndex = JSXIdentifier.lastIndex;
- lastSignificantToken = match[0];
- yield ({
- type: "JSXIdentifier",
- value: match[0]
- });
- continue;
- }
- JSXString.lastIndex = lastIndex;
- if (match = JSXString.exec(input)) {
- lastIndex = JSXString.lastIndex;
- lastSignificantToken = match[0];
- yield ({
- type: "JSXString",
- value: match[0],
- closed: match[2] !== void 0
- });
- continue;
- }
- break;
- case "JSXChildren":
- JSXText.lastIndex = lastIndex;
- if (match = JSXText.exec(input)) {
- lastIndex = JSXText.lastIndex;
- lastSignificantToken = match[0];
- yield ({
- type: "JSXText",
- value: match[0]
- });
- continue;
- }
- switch (input[lastIndex]) {
- case "<":
- stack.push({tag: "JSXTag"});
- lastIndex++;
- lastSignificantToken = "<";
- yield ({
- type: "JSXPunctuator",
- value: "<"
- });
- continue;
- case "{":
- stack.push({
- tag: "InterpolationInJSX",
- nesting: braces.length
- });
- lastIndex++;
- lastSignificantToken = "?InterpolationInJSX";
- postfixIncDec = false;
- yield ({
- type: "JSXPunctuator",
- value: "{"
- });
- continue;
- }
- }
- WhiteSpace.lastIndex = lastIndex;
- if (match = WhiteSpace.exec(input)) {
- lastIndex = WhiteSpace.lastIndex;
- yield ({
- type: "WhiteSpace",
- value: match[0]
- });
- continue;
- }
- LineTerminatorSequence.lastIndex = lastIndex;
- if (match = LineTerminatorSequence.exec(input)) {
- lastIndex = LineTerminatorSequence.lastIndex;
- postfixIncDec = false;
- if (KeywordsWithNoLineTerminatorAfter.test(lastSignificantToken)) {
- lastSignificantToken = "?NoLineTerminatorHere";
- }
- yield ({
- type: "LineTerminatorSequence",
- value: match[0]
- });
- continue;
- }
- MultiLineComment.lastIndex = lastIndex;
- if (match = MultiLineComment.exec(input)) {
- lastIndex = MultiLineComment.lastIndex;
- if (Newline.test(match[0])) {
- postfixIncDec = false;
- if (KeywordsWithNoLineTerminatorAfter.test(lastSignificantToken)) {
- lastSignificantToken = "?NoLineTerminatorHere";
- }
- }
- yield ({
- type: "MultiLineComment",
- value: match[0],
- closed: match[1] !== void 0
- });
- continue;
- }
- SingleLineComment.lastIndex = lastIndex;
- if (match = SingleLineComment.exec(input)) {
- lastIndex = SingleLineComment.lastIndex;
- postfixIncDec = false;
- yield ({
- type: "SingleLineComment",
- value: match[0]
- });
- continue;
- }
- firstCodePoint = String.fromCodePoint(input.codePointAt(lastIndex));
- lastIndex += firstCodePoint.length;
- lastSignificantToken = firstCodePoint;
- postfixIncDec = false;
- yield ({
- type: mode.tag.startsWith("JSX") ? "JSXInvalid" : "Invalid",
- value: firstCodePoint
- });
- }
- return void 0;
- };
|