onToken: null,diff --git a/docs/acorn.html b/docs/acorn.html index 9a8c3459e7..16abf53e11 100644 --- a/docs/acorn.html +++ b/docs/acorn.html @@ -28,9 +28,10 @@ ¶
Acorn is a tiny, fast JavaScript parser written in JavaScript.
-Acorn was written by Marijn Haverbeke and released under an MIT -license. The Unicode regexps (for identifiers and whitespace) were -taken from Esprima by Ariya Hidayat.
+Acorn was written by Marijn Haverbeke and various contributors and +released under an MIT license. The Unicode regexps (for identifiers +and whitespace) were taken from Esprima by +Ariya Hidayat.
Git repositories for Acorn are available at
http://marijnhaverbeke.nl/git/acorn
https://github.com/marijnh/acorn.git
@@ -49,7 +50,7 @@ with a error-tolerant parser and an
})(this, function(exports) {
"use strict";
- exports.version = "0.6.1";
+ exports.version = "0.7.1";
@@ -205,6 +206,25 @@ nodes.
+ A function can be passed as onToken option, which will
+cause Acorn to call that function with object in the same
+format as tokenize() returns. Note that you are not
+allowed to call the parser from the callback—that will
+corrupt its internal state.
onToken: null,A function can be passed as onComment option, which will
cause Acorn to call that function with (block, text, start,
end) parameters whenever a comment is skipped. block is a
@@ -223,11 +243,11 @@ parser from the callback—that will corrupt its internal state.
Nodes have their start and end characters offsets recorded in
start and end properties (directly on the node, rather than
@@ -243,11 +263,11 @@ end] array with the same numbers, set the ranges option to
-
It is possible to parse multiple files into a single AST by passing the tree produced by parsing the first file as @@ -262,11 +282,11 @@ of an existing parse tree.
-When locations is on, you can pass this to record the source
file in every node’s loc object.
loc object.
- This value, if given, is stored in every node, whether
locations is on or off.
loc object.
directSourceFile: null
};
+ var isArray = function (obj) {
+ return Object.prototype.toString.call(obj) === "[object Array]";
+ };
+
function setOptions(opts) {
options = opts || {};
- for (var opt in defaultOptions) if (!Object.prototype.hasOwnProperty.call(options, opt))
+ for (var opt in defaultOptions) if (!has(options, opt))
options[opt] = defaultOptions[opt];
sourceFile = options.sourceFile || null;
-
+ if (isArray(options.onToken)) {
+ var tokens = options.onToken;
+ options.onToken = function (token) {
+ tokens.push(token);
+ };
+ }
+ if (isArray(options.onComment)) {
+ var comments = options.onComment;
+ options.onComment = function (block, text, start, end, startLoc, endLoc) {
+ var comment = {
+ type: block ? 'Block' : 'Line',
+ value: text,
+ start: start,
+ end: end
+ };
+ if (options.locations) {
+ comment.loc = new SourceLocation();
+ comment.loc.start = startLoc;
+ comment.loc.end = endLoc;
+ }
+ if (options.ranges)
+ comment.range = [start, end];
+ comments.push(comment);
+ };
+ }
isKeyword = options.ecmaVersion >= 6 ? isEcma6Keyword : isEcma5AndLessKeyword;
} this.startLoc = tokStartLoc;
+ this.endLoc = tokEndLoc;
+ }
+ if (options.ranges)
+ this.range = [tokStart, tokEnd];
+ }
+
+ exports.Token = Token;Acorn is organized as a tokenizer and a recursive-descent parser.
The tokenize export provides an interface to the tokenizer.
@@ -355,14 +434,10 @@ reset the internal state, and invalidate existing tokenizers.
State is kept in (closure-)global variables. We already saw the
options, input, and inputLen variables above.
The current position of the tokenizer in the input.
@@ -414,11 +489,11 @@ reset the internal state, and invalidate existing tokenizers. -The start and end offsets of the current token.
@@ -430,11 +505,11 @@ reset the internal state, and invalidate existing tokenizers. -When options.locations is true, these hold objects
containing the tokens start and end line/column pairs.
The type and value of the current token. Token types are objects, named by variables against which they can be compared, and @@ -469,11 +544,11 @@ for operators, the operator name, and so on.
-Internal state for the tokenizer. To distinguish between division operators and regular expressions, it remembers whether the last @@ -490,11 +565,11 @@ caveat.)
-When options.locations is true, these are used to keep
track of the current line, and know when a new line has been
@@ -508,11 +583,11 @@ entered.
These store the position of the previous token, which is useful
when finishing a node and assigning its end position.
end position.
- This is the parser’s state. inFunction is used to reject
return statements outside of functions, inGenerator to
@@ -545,11 +620,11 @@ that break and continue have somewhere to jump to, and
-
This counter is used for checking that arrow expressions did not contain nested parentheses in argument list.
@@ -562,11 +637,11 @@ not contain nested parentheses in argument list. -This is used by parser for detecting if it’s inside ES6 Template String. If it is, it should treat ‘$’ as prefix before @@ -575,16 +650,16 @@ Template String. If it is, it should treat ‘$’ as prefix before
- var inTemplate = false;This function is used to raise exceptions on parse errors. It
takes an offset integer (into the current input) to indicate
@@ -606,11 +681,11 @@ message.
Reused empty array added for node fields that are always empty.
@@ -622,42 +697,13 @@ message. -The assignment of fine-grained, information-carrying type objects -allows the tokenizer to store the information it has about a -token in a way that is very cheap for the parser to look up.
- -All token type variables start with an underscore, to make them -easy to recognize.
+The assignment of fine-grained, information-carrying type objects +allows the tokenizer to store the information it has about a +token in a way that is very cheap for the parser to look up.
+ +All token type variables start with an underscore, to make them +easy to recognize.
+ +These are the general types. The type property is only used to
make them recognizeable when debugging.
These are JSX-specific token types
@@ -698,11 +773,11 @@ make them recognizeable when debugging. -Keyword tokens. The keyword property (also used in keyword-like
operators) indicates that the token originated from an
@@ -734,11 +809,11 @@ continue jumps to that label.
The keywords that denote values.
@@ -751,11 +826,11 @@ continue jumps to that label. -Some keywords are treated as regular operators. in sometimes
(when parsing for) needs to be tested against specifically, so
@@ -769,11 +844,11 @@ we assign a variable name to it for quick comparing.
Map keyword names to token types.
@@ -797,11 +872,11 @@ we assign a variable name to it for quick comparing. -Punctuation token types. Again, the type property is purely for debugging.
Operators. These carry several kinds of properties to help the parser use them properly (the presence of these properties is @@ -852,16 +927,16 @@ in AssignmentExpression nodes.
var _relational = {binop: 7, beforeExpr: true}; var _bitShift = {binop: 8, beforeExpr: true}; var _plusMin = {binop: 9, prefix: true, beforeExpr: true}; - var _multiplyModulo = {binop: 10, beforeExpr: true};‘*’ may be multiply or have special meaning in ES6
@@ -872,11 +947,11 @@ in AssignmentExpression nodes. -‘<’, ‘>’ may be relational or have special meaning in JSX
@@ -887,11 +962,11 @@ in AssignmentExpression nodes. -Provide access to the token types for external users of the tokenizer.
@@ -910,11 +985,11 @@ tokenizer. -This is a trick taken from Esprima. It turns out that, on non-Chrome browsers, to check whether a string is in a set, a @@ -948,11 +1023,11 @@ predicate from a space-separated string of words.
-When there are more than three length categories, an outer switch first dispatches on the lengths, to save on comparisons.
@@ -973,11 +1048,11 @@ switch first dispatches on the lengths, to save on comparisons. -Otherwise, simply generate a flat switch statement.
The ECMAScript 3 reserved word list.
@@ -1009,11 +1084,11 @@ switch first dispatches on the lengths, to save on comparisons. -ECMAScript 5 reserved words.
@@ -1025,11 +1100,11 @@ switch first dispatches on the lengths, to save on comparisons. -The additional reserved words in strict mode.
@@ -1041,11 +1116,11 @@ switch first dispatches on the lengths, to save on comparisons. -The forbidden variable names in strict mode.
@@ -1057,11 +1132,11 @@ switch first dispatches on the lengths, to save on comparisons. -And the keywords.
@@ -1079,11 +1154,11 @@ switch first dispatches on the lengths, to save on comparisons. -Big ugly regular expressions that match characters in the
whitespace, identifier, and identifier-start categories. These
@@ -1116,11 +1191,11 @@ Generated by tools/generate-identifier-regex.js.
Whether a single character denotes a newline.
@@ -1132,11 +1207,11 @@ Generated bytools/generate-identifier-regex.js.
- Matches a whole line break (where CRLF is considered a single line break). Used to count lines.
@@ -1149,11 +1224,11 @@ line break). Used to count lines. -Test whether a given character code starts an identifier.
@@ -1171,11 +1246,11 @@ line break). Used to count lines. -Test whether a given character is part of an identifier.
@@ -1195,11 +1270,11 @@ line break). Used to count lines. -These are used when options.locations is on, for the
tokStartLoc and tokEndLoc properties.
Reset the token state. Used at the start of a parse.
@@ -1251,11 +1326,11 @@ line break). Used to count lines. -Called at the end of every token. Sets tokEnd, tokVal, and
tokRegexpAllowed, and skips the space after the token, so that
@@ -1264,15 +1339,18 @@ the next one’s tokStart will point at the right position.
- function finishToken(type, val) {
+ function finishToken(type, val, shouldSkipSpace) {
tokEnd = tokPos;
if (options.locations) tokEndLoc = new Position;
tokType = type;
- if (inTemplate || type !== _bquote && !(inXJSTag && type === _gt) && !(inXJSChild && tokType !== _braceL)) {
+ if (shouldSkipSpace !== false && !(inXJSTag && type === _gt) && !(inXJSChild && tokType !== _braceL)) {
skipSpace();
}
tokVal = val;
tokRegexpAllowed = type.beforeExpr;
+ if (options.onToken) {
+ options.onToken(new Token());
+ }
}
function skipBlockComment() {
@@ -1293,27 +1371,27 @@ the next one’s tokStart will point at the right position.
startLoc, options.locations && new Position);
}
- function skipLineComment() {
+ function skipLineComment(startSkip) {
var start = tokPos;
var startLoc = options.onComment && options.locations && new Position;
- var ch = input.charCodeAt(tokPos+=2);
+ var ch = input.charCodeAt(tokPos+=startSkip);
while (tokPos < inputLen && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) {
++tokPos;
ch = input.charCodeAt(tokPos);
}
if (options.onComment)
- options.onComment(false, input.slice(start + 2, tokPos), start, tokPos,
+ options.onComment(false, input.slice(start + startSkip, tokPos), start, tokPos,
startLoc, options.locations && new Position);
}Called at the start of the parse and after every token. Skips whitespace and comments, and.
@@ -1349,7 +1427,7 @@ whitespace and comments, and. if (next === 42) { // '*' skipBlockComment(); } else if (next === 47) { // '/' - skipLineComment(); + skipLineComment(2); } else break; } else if (ch === 160) { // '\xa0' ++tokPos; @@ -1364,11 +1442,11 @@ whitespace and comments, and. -This is the function that is called to fetch the next token. It is somewhat obscure, because it works in character codes rather @@ -1417,7 +1495,7 @@ into it.
function readToken_mult_modulo(code) { // '%*' var next = input.charCodeAt(tokPos + 1); if (next === 61) return finishOp(_assign, 2); - return finishOp(code === 42 ? _star : _multiplyModulo, 1); + return finishOp(code === 42 ? _star : _modulo, 1); } function readToken_pipe_amp(code) { // '|&' @@ -1442,18 +1520,17 @@ into it. - tokPos += 3;
- skipLineComment();
+ skipLineComment(3);
skipSpace();
return readToken();
}
@@ -1477,18 +1554,17 @@ into it.
-
+
- tokPos += 4;
- skipLineComment();
+ skipLineComment(4);
skipSpace();
return readToken();
}
@@ -1501,11 +1577,11 @@ into it.
-
+
-
-
-
-
-
-
-
-
- ¶
-
- Special rules work inside ES6 template strings.
-
-
-
- if (inTemplate) {
-
-
-
-
-
-
-
-
- ¶
-
- ‘`’ and ‘${‘ have special meanings, but they should follow string (can be empty)
-
-
-
- if (tokType === _string) {
- if (code === 96) { // '`'
- ++tokPos;
- return finishToken(_bquote);
- }
- if (code === 36 && input.charCodeAt(tokPos + 1) === 123) { // '${'
- tokPos += 2;
- return finishToken(_dollarBraceL);
- }
- }
+ }
@@ -1577,14 +1612,12 @@ into it.
- anything else is considered string literal
+ Get token inside ES6 template (special rules work there).
- return readString();
- }
-
- switch(code) {
+
+ function getTemplateToken(code) {
@@ -1595,6 +1628,55 @@ into it.
+ ‘`’ and ‘${‘ have special meanings, but they should follow
+string (can be empty)
+
+
+
+ if (tokType === _string) {
+ if (code === 96) { // '`'
+ ++tokPos;
+ return finishToken(_bquote);
+ } else
+ if (code === 36 && input.charCodeAt(tokPos + 1) === 123) { // '${'
+ tokPos += 2;
+ return finishToken(_dollarBraceL);
+ }
+ }
+
+ if (code === 125) { // '}'
+ ++tokPos;
+ return finishToken(_braceR, undefined, false);
+ }
+
+
+
+
+
+
+
+
+ ¶
+
+ anything else is considered string literal
+
+
+
+ return readTmplString();
+ }
+
+ function getTokenFromCode(code) {
+ switch(code) {
+
+
+
+
+
+
+
+
+ ¶
+
The interpretation of a dot depends on whether it is followed
by a digit or another two dots.
@@ -1606,11 +1688,11 @@ by a digit or another two dots.
-
+
Punctuation tokens.
@@ -1630,7 +1712,7 @@ by a digit or another two dots.
case 96: // '`'
if (options.ecmaVersion >= 6) {
++tokPos;
- return finishToken(_bquote);
+ return finishToken(_bquote, undefined, false);
}
case 48: // '0'
@@ -1644,11 +1726,11 @@ by a digit or another two dots.
-
+
Anything else beginning with a digit is an integer, octal
number, or float.
@@ -1661,11 +1743,11 @@ number, or float.
-
+
Quotes produce strings.
@@ -1677,11 +1759,11 @@ number, or float.
-
+
Operators are parsed inline in tiny state machines. ‘=’ (61) is
often referred to. finishOp simply skips the amount of
@@ -1731,11 +1813,11 @@ of the type given by its first argument.
-
+
JSX content - either simple text, start of or {expression}
@@ -1743,23 +1825,26 @@ of the type given by its first argument.
if (inXJSChild && tokType !== _braceL && code !== 60 && code !== 123 && code !== 125) {
return readXJSText(['<', '{']);
- }
+ }
+
+
+ if (inTemplate) return getTemplateToken(code);
-
+
Identifier or keyword. ‘\uXXXX’ sequences are allowed in
identifiers, so ‘\’ also dispatches to that.
- if (!inTemplate && (isIdentifierStart(code) || code === 92 /* '\' */)) return readWord();
+ if (isIdentifierStart(code) || code === 92 /* '\' */) return readWord();
var tok = getTokenFromCode(code);
@@ -1768,11 +1853,11 @@ identifiers, so ‘\’ also dispatches to that.
-
+
If we are here, we either found a non-ASCII identifier
character, or something that’s entirely disallowed.
@@ -1795,11 +1880,11 @@ character, or something that’s entirely disallowed.
-
+
Parse a regular expression. Some context-awareness is necessary,
since a ‘/‘ inside a ‘[]’ set does not end the expression.
@@ -1811,7 +1896,7 @@ since a ‘/‘ inside a ‘[]’ set does not end the expression.
var content = "", escaped, inClass, start = tokPos;
for (;;) {
if (tokPos >= inputLen) raise(start, "Unterminated regular expression");
- var ch = input.charAt(tokPos);
+ var ch = nextChar();
if (newline.test(ch)) raise(start, "Unterminated regular expression");
if (!escaped) {
if (ch === "[") inClass = true;
@@ -1827,11 +1912,11 @@ since a ‘/‘ inside a ‘[]’ set does not end the expression.
-
+
Need to use readWord1 because ‘\uXXXX’ sequences are allowed
here (don’t ask).
@@ -1852,11 +1937,11 @@ here (don’t ask).
-
+
Read an integer in the given radix. Return null if zero digits
were read, the integer value otherwise. When len is given, this
@@ -1893,11 +1978,11 @@ will return null unless the integer has exactly len di
-
+
Read an integer, octal integer, or floating-point number.
@@ -1932,11 +2017,11 @@ will return null unless the integer has exactly len di
-
+
Read a string value, interpreting backslash-escapes.
@@ -1959,11 +2044,11 @@ will return null unless the integer has exactly len di
-
+
UTF-16 Encoding
@@ -1978,52 +2063,39 @@ will return null unless the integer has exactly len di
}
function readString(quote) {
- if (!inTemplate) tokPos++;
+ ++tokPos;
var out = "";
for (;;) {
if (tokPos >= inputLen) raise(tokStart, "Unterminated string constant");
var ch = input.charCodeAt(tokPos);
- if (inTemplate) {
- if (ch === 96 || ch === 36 && input.charCodeAt(tokPos + 1) === 123) // '`', '${'
- return finishToken(_string, out);
- } else if (ch === quote) {
+ if (ch === quote) {
++tokPos;
return finishToken(_string, out);
}
if (ch === 92) { // '\'
- ch = input.charCodeAt(++tokPos);
- var octal = /^[0-7]+/.exec(input.slice(tokPos, tokPos + 3));
- if (octal) octal = octal[0];
- while (octal && parseInt(octal, 8) > 255) octal = octal.slice(0, -1);
- if (octal === "0") octal = null;
- ++tokPos;
- if (octal) {
- if (strict) raise(tokPos - 2, "Octal literal in strict mode");
- out += String.fromCharCode(parseInt(octal, 8));
- tokPos += octal.length - 1;
- } else {
- switch (ch) {
- case 110: out += "\n"; break; // 'n' -> '\n'
- case 114: out += "\r"; break; // 'r' -> '\r'
- case 120: out += String.fromCharCode(readHexChar(2)); break; // 'x'
- case 117: out += readCodePoint(); break; // 'u'
- case 85: out += String.fromCharCode(readHexChar(8)); break; // 'U'
- case 116: out += "\t"; break; // 't' -> '\t'
- case 98: out += "\b"; break; // 'b' -> '\b'
- case 118: out += "\u000b"; break; // 'v' -> '\u000b'
- case 102: out += "\f"; break; // 'f' -> '\f'
- case 48: out += "\0"; break; // 0 -> '\0'
- case 13: if (input.charCodeAt(tokPos) === 10) ++tokPos; // '\r\n'
- case 10: // ' \n'
- if (options.locations) { tokLineStart = tokPos; ++tokCurLine; }
- break;
- default: out += String.fromCharCode(ch); break;
- }
- }
+ out += readEscapedChar();
+ } else {
+ ++tokPos;
+ if (newline.test(String.fromCharCode(ch))) {
+ raise(tokStart, "Unterminated string constant");
+ }
+ out += String.fromCharCode(ch); // '\'
+ }
+ }
+ }
+
+ function readTmplString() {
+ var out = "";
+ for (;;) {
+ if (tokPos >= inputLen) raise(tokStart, "Unterminated string constant");
+ var ch = input.charCodeAt(tokPos);
+ if (ch === 96 || ch === 36 && input.charCodeAt(tokPos + 1) === 123) // '`', '${'
+ return finishToken(_string, out);
+ if (ch === 92) { // '\'
+ out += readEscapedChar();
} else {
++tokPos;
if (newline.test(String.fromCharCode(ch))) {
- if (inTemplate) {
if (ch === 13 && input.charCodeAt(tokPos) === 10) {
++tokPos;
ch = 10;
@@ -2032,13 +2104,56 @@ will return null unless the integer has exactly len di
++tokCurLine;
tokLineStart = tokPos;
}
- } else {
- raise(tokStart, "Unterminated string constant");
}
- }
out += String.fromCharCode(ch); // '\'
}
}
+ }
+
+
+
+
+
+
+
+
+ ¶
+
+ Used to read escaped characters
+
+
+
+
+ function readEscapedChar() {
+ var ch = input.charCodeAt(++tokPos);
+ var octal = /^[0-7]+/.exec(input.slice(tokPos, tokPos + 3));
+ if (octal) octal = octal[0];
+ while (octal && parseInt(octal, 8) > 255) octal = octal.slice(0, -1);
+ if (octal === "0") octal = null;
+ ++tokPos;
+ if (octal) {
+ if (strict) raise(tokPos - 2, "Octal literal in strict mode");
+ tokPos += octal.length - 1;
+ return String.fromCharCode(parseInt(octal, 8));
+ } else {
+ switch (ch) {
+ case 110: return "\n"; // 'n' -> '\n'
+ case 114: return "\r"; // 'r' -> '\r'
+ case 120: return String.fromCharCode(readHexChar(2)); // 'x'
+ case 117: return readCodePoint(); // 'u'
+ case 85: return String.fromCharCode(readHexChar(8)); // 'U'
+ case 116: return "\t"; // 't' -> '\t'
+ case 98: return "\b"; // 'b' -> '\b'
+ case 118: return "\u000b"; // 'v' -> '\u000b'
+ case 102: return "\f"; // 'f' -> '\f'
+ case 48: return "\0"; // 0 -> '\0'
+ case 13: if (input.charCodeAt(tokPos) === 10) ++tokPos; // '\r\n'
+ case 10: // ' \n'
+ if (options.locations) { tokLineStart = tokPos; ++tokCurLine; }
+ return "";
+ default: return String.fromCharCode(ch);
+ }
+ }
}
var XHTMLEntities = {
@@ -2303,7 +2418,8 @@ will return null unless the integer has exactly len di
if (ch !== '&') raise(tokPos, "Entity must start with an ampersand");
tokPos++;
while (tokPos < inputLen && count++ < 10) {
- ch = input.charAt(tokPos++);
+ ch = nextChar();
+ tokPos++;
if (ch === ';') {
break;
}
@@ -2371,11 +2487,11 @@ will return null unless the integer has exactly len di
-
+
Used to read character escape sequences (‘\x’, ‘\u’, ‘\U’).
@@ -2391,11 +2507,11 @@ will return null unless the integer has exactly len di
-
+
Used to signal to callers of readWord1 whether the word
contained any escape sequences. This is needed because words with
@@ -2409,11 +2525,11 @@ escape sequences must not be interpreted as keywords.
-
+
Read an identifier, and return it as a string. Sets containsEsc
to whether the word contained a ‘\u’ escape.
@@ -2429,7 +2545,7 @@ containeds an escape, as a micro-optimization.
for (;;) {
var ch = input.charCodeAt(tokPos);
if (isIdentifierChar(ch) || (inXJSTag && ch === 45)) {
- if (containsEsc) word += input.charAt(tokPos);
+ if (containsEsc) word += nextChar();
++tokPos;
} else if (ch === 92 && !inXJSTag) { // "\"
if (!containsEsc) word = input.slice(start, tokPos);
@@ -2454,11 +2570,11 @@ containeds an escape, as a micro-optimization.
-
+
Read an identifier or keyword token. Will check for reserved
words when necessary.
@@ -2477,11 +2593,11 @@ words when necessary.
-
+
Parser
@@ -2490,11 +2606,11 @@ words when necessary.
-
+
A recursive descent parser operates by defining functions for all
syntactic elements, and recursively calling those, each function
@@ -2516,11 +2632,11 @@ precedence levels that JavaScript defines.
-
+
Parser utilities
@@ -2529,11 +2645,11 @@ precedence levels that JavaScript defines.
-
+
Continue to the next token.
@@ -2550,11 +2666,11 @@ precedence levels that JavaScript defines.
-
+
Enter strict mode. Re-reads the next token to please pedantic
tests (“use strict”; 010; — should fail).
@@ -2578,11 +2694,11 @@ tests (“use strict”; 010; — should fail).
-
+
Start an AST node, attaching a start offset.
@@ -2617,11 +2733,11 @@ tests (“use strict”; 010; — should fail).
-
+
Start a node whose start offset information should be based on
the start of another node. For example, a binary operator node is
@@ -2646,11 +2762,11 @@ only started after its left-hand side has already been parsed.
-
+
Finish an AST node, adding type and end properties.
@@ -2670,11 +2786,11 @@ only started after its left-hand side has already been parsed.
-
+
Test whether a statement node is the string literal "use strict".
@@ -2689,11 +2805,11 @@ only started after its left-hand side has already been parsed.
-
+
Predicate that tests whether the next token is of the given
type, and if yes, consumes it as a side effect.
@@ -2713,11 +2829,11 @@ type, and if yes, consumes it as a side effect.
-
+
Test whether a semicolon can be inserted at the current position.
@@ -2732,11 +2848,11 @@ type, and if yes, consumes it as a side effect.
-
+
Consume a semicolon, or, failing that, see if we are allowed to
pretend that there is a semicolon at this position.
@@ -2751,11 +2867,11 @@ pretend that there is a semicolon at this position.
-
+
Expect a token of a given type. If found, consume it, otherwise,
raise an unexpected token error.
@@ -2770,31 +2886,11 @@ raise an unexpected token error.
-
+
- ¶
-
- Expect a char. If found, consume it, otherwise,
-raise an unexpected token error.
-
-
-
-
- function expectChar(ch) {
- if (tokVal === ch) next();
- else unexpected();
- }
-
-
-
-
-
-
-
-
Get following char.
@@ -2808,11 +2904,11 @@ raise an unexpected token error.
-
+
Raise an unexpected token error.
@@ -2826,29 +2922,29 @@ raise an unexpected token error.
-
+
- function hash() {
- return Object.create(null);
+ function has(obj, propName) {
+ return Object.prototype.hasOwnProperty.call(obj, propName);
}
-
+
Convert existing expression atom to assignable pattern
if possible.
@@ -2898,11 +2994,11 @@ if possible.
-
+
Checks if node can be assignable spread argument.
@@ -2917,11 +3013,11 @@ if possible.
-
+
Verify that argument names are not repeated, and it does not
try to bind the words eval or arguments.
@@ -2934,7 +3030,7 @@ try to bind the words eval or arguments.
case "Identifier":
if (isStrictReservedWord(param.name) || isStrictBadIdWord(param.name))
raise(param.start, "Defining '" + param.name + "' in strict mode");
- if (nameHash[param.name])
+ if (has(nameHash, param.name))
raise(param.start, "Argument name clash in strict mode");
nameHash[param.name] = true;
break;
@@ -2954,11 +3050,11 @@ try to bind the words eval or arguments.
-
+
Check if property name clashes with already added.
Object/class getters and setters are not allowed to clash —
@@ -2969,20 +3065,25 @@ strict mode, init properties are also not allowed to be repeated.
function checkPropClash(prop, propHash) {
+ if (prop.computed) return;
var key = prop.key, name;
switch (key.type) {
case "Identifier": name = key.name; break;
case "Literal": name = String(key.value); break;
default: return;
}
- var kind = prop.kind || "init", other = propHash[name];
- if (other) {
+ var kind = prop.kind || "init", other;
+ if (has(propHash, name)) {
+ other = propHash[name];
var isGetSet = kind !== "init";
if ((strict || isGetSet) && other[kind] || !(isGetSet ^ other.init))
raise(key.start, "Redefinition of property");
} else {
- other = propHash[name] = hash();
- other.init = other.get = other.set = false;
+ other = propHash[name] = {
+ init: false,
+ get: false,
+ set: false
+ };
}
other[kind] = true;
}
@@ -2990,11 +3091,11 @@ strict mode, init properties are also not allowed to be repeated.
-
+
Verify that a node is an lval — something that can be assigned
to.
@@ -3038,11 +3139,11 @@ to.
-
+
Statement parsing
@@ -3051,11 +3152,11 @@ to.
-
+
Parse a program. Initializes the parser, reads any number of
statements, and wraps them in a Program node. Optionally takes a
@@ -3088,11 +3189,11 @@ to its body instead of creating a new node.
-
+
Parse a single statement.
If expecting a statement and finding a slash operator, parse a
@@ -3112,11 +3213,11 @@ does not help.
-
+
Most types of statements are recognized by the keyword they
start with. Many are trivial to parse, some require a bit of
@@ -3148,11 +3249,11 @@ complexity.
-
+
If the statement does not start with a statement keyword or a
brace, it’s an ExpressionStatement or LabeledStatement. We
@@ -3183,11 +3284,11 @@ Identifier node, we switch to interpreting it as a label.
-
+
Verify that there is an actual destination to break or
continue to.
@@ -3225,11 +3326,11 @@ continue to.
-
+
Disambiguating between a for and a for/in or for/of
loop is non-trivial. Basically, we have to parse the init var
@@ -3286,11 +3387,11 @@ is a regular for loop.
-
+
In return (and break/continue), the keywords with
optional arguments, we eagerly look for a semicolon or the
@@ -3314,11 +3415,11 @@ possibility to insert one.
-
+
Statements under must be grouped (by label) in SwitchCase
nodes. cur is used to keep the node that we are currently
@@ -3432,11 +3533,11 @@ adding statements to.
-
+
Used for constructs like switch and if that insist on
parentheses around their expression.
@@ -3454,11 +3555,11 @@ parentheses around their expression.
-
+
Parse a semicolon-enclosed block of statements, handling "use
strict" declarations when allowStrict is true (used for
@@ -3487,11 +3588,11 @@ function bodies).
-
+
Parse a regular for loop. The disambiguation code in
parseStatement will already have parsed the init statement or
@@ -3515,11 +3616,11 @@ expression.
-
+
Parse a for/in and for/of loop, which are almost
same from parser’s perspective.
@@ -3541,11 +3642,11 @@ same from parser’s perspective.
-
+
Parse a list of variable declarations.
@@ -3569,11 +3670,11 @@ same from parser’s perspective.
-
+
Expression parsing
@@ -3582,11 +3683,11 @@ same from parser’s perspective.
-
+
These nest, from the most general expression type at the top to
‘atomic’, nondivisible expression types at the bottom. Most of
@@ -3599,11 +3700,11 @@ the AST node that the inner parser gave them in another node.
-
+
Parse a full expression. The arguments are used to forbid comma
sequences (in argument lists, array literals, or object literals)
@@ -3626,11 +3727,11 @@ or the in operator (in for loops initalization expressions).
-
+
Parse an assignment expression. This includes applications of
operators like +=.
@@ -3655,11 +3756,11 @@ operators like +=.
-
+
Parse a ternary conditional (?:) operator.
@@ -3682,11 +3783,11 @@ operators like +=.
-
+
Start the precedence parser.
@@ -3700,11 +3801,11 @@ operators like +=.
-
+
Parse binary operators with the operator precedence parsing
algorithm. left is the left-hand side of the operator.
@@ -3735,11 +3836,11 @@ operator that has a lower precedence than the set it is parsing.
-
+
Parse unary operators, both prefix and postfix.
@@ -3776,11 +3877,11 @@ operator that has a lower precedence than the set it is parsing.
-
+
Parse call, dot, and []-subscript expressions.
@@ -3821,11 +3922,11 @@ operator that has a lower precedence than the set it is parsing.
-
+
Parse an atomic expression — either a single token that is an
expression, an expression started by a keyword like function or
@@ -3867,8 +3968,25 @@ or {}.
return finishNode(node, "Literal");
case _parenL:
- var node = startNode(), tokStartLoc1 = tokStartLoc, tokStart1 = tokStart, val, exprList;
- next();
+ var tokStartLoc1 = tokStartLoc, tokStart1 = tokStart, val, exprList;
+ next();
+
+
+
+
+
+
+
+
+ ¶
+
+ check whether this is generator comprehension or regular expression
+
+
+
+ if (options.ecmaVersion >= 6 && tokType === _for) {
+ val = parseComprehension(startNode(), true);
+ } else {
var oldParenL = ++metParenL;
if (tokType !== _parenR) {
val = parseExpression();
@@ -3881,28 +3999,28 @@ or {}.
-
+
if (metParenL === oldParenL && eat(_arrow)) {
- val = parseArrowExpression(node, exprList);
+ val = parseArrowExpression(startNode(), exprList);
} else {
-
+
forbid ‘()’ before everything but ‘=>’
@@ -3913,11 +4031,11 @@ or {}.
-
+
forbid ‘…’ in sequence expressions
@@ -3929,6 +4047,7 @@ or {}.
}
}
}
+ }
val.start = tokStart1;
val.end = lastEnd;
if (options.locations) {
@@ -3947,51 +4066,19 @@ or {}.
-
+
if (options.ecmaVersion >= 6 && tokType === _for) {
- node.blocks = [];
- while (tokType === _for) {
- var block = startNode();
- next();
- expect(_parenL);
- block.left = toAssignable(parseExprAtom());
- checkLVal(block.left, true);
- if (tokType !== _name || tokVal !== "of") unexpected();
- next();
-
-
-
-
-
-
-
-
- ¶
-
- of property is here for compatibility with Esprima’s AST
-which also supports deprecated [for (… in …) expr]
-
-
-
- block.of = true;
- block.right = parseExpression();
- expect(_parenR);
- node.blocks.push(finishNode(block, "ComprehensionBlock"));
+ return parseComprehension(node, false);
}
- node.filter = eat(_if) ? parseParenExpression() : null;
- node.body = parseExpression();
- expect(_bracketR);
- return finishNode(node, "ComprehensionExpression");
- }
node.elements = parseExprList(_bracketR, true, true);
return finishNode(node, "ArrayExpression");
@@ -4026,11 +4113,11 @@ which also supports deprecated [for (… in …) expr]
-
+
New’s precedence is slightly tricky. It must allow its argument
to be a [] or dot subscript expression, but not a call — at
@@ -4051,11 +4138,11 @@ least, not without wrapping it in parentheses. Thus, it uses the
-
+
Parse spread element ‘…expr’
@@ -4072,11 +4159,11 @@ least, not without wrapping it in parentheses. Thus, it uses the
-
+
Parse template expression.
@@ -4112,11 +4199,11 @@ least, not without wrapping it in parentheses. Thus, it uses the
-
+
Parse an object literal.
@@ -4124,7 +4211,7 @@ least, not without wrapping it in parentheses. Thus, it uses the
function parseObj() {
- var node = startNode(), first = true, propHash = hash();
+ var node = startNode(), first = true, propHash = {};
node.properties = [];
next();
while (!eat(_braceR)) {
@@ -4133,7 +4220,7 @@ least, not without wrapping it in parentheses. Thus, it uses the
if (options.allowTrailingCommas && eat(_braceR)) break;
} else first = false;
- var prop = startNode(), kind, isGenerator;
+ var prop = startNode(), isGenerator;
if (options.ecmaVersion >= 6) {
prop.method = false;
prop.shorthand = false;
@@ -4142,19 +4229,19 @@ least, not without wrapping it in parentheses. Thus, it uses the
parsePropertyName(prop);
if (eat(_colon)) {
prop.value = parseExpression(true);
- kind = prop.kind = "init";
+ prop.kind = "init";
} else if (options.ecmaVersion >= 6 && tokType === _parenL) {
- kind = prop.kind = "init";
+ prop.kind = "init";
prop.method = true;
prop.value = parseMethod(isGenerator);
} else if (options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" &&
(prop.key.name === "get" || prop.key.name === "set")) {
if (isGenerator) unexpected();
- kind = prop.kind = prop.key.name;
+ prop.kind = prop.key.name;
parsePropertyName(prop);
prop.value = parseMethod(false);
} else if (options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
- kind = prop.kind = "init";
+ prop.kind = "init";
prop.value = prop.key;
prop.shorthand = true;
} else unexpected();
@@ -4182,11 +4269,11 @@ least, not without wrapping it in parentheses. Thus, it uses the
-
+
Initialize empty function node.
@@ -4206,11 +4293,11 @@ least, not without wrapping it in parentheses. Thus, it uses the
-
+
Parse a function declaration or literal (depending on the
isStatement parameter).
@@ -4234,11 +4321,11 @@ least, not without wrapping it in parentheses. Thus, it uses the
-
+
Parse object or class method.
@@ -4263,11 +4350,11 @@ least, not without wrapping it in parentheses. Thus, it uses the
-
+
Parse arrow function expression with given parameters.
@@ -4307,11 +4394,11 @@ least, not without wrapping it in parentheses. Thus, it uses the
-
+
Parse function parameters.
@@ -4350,11 +4437,11 @@ least, not without wrapping it in parentheses. Thus, it uses the
-
+
Parse function body and check parameters.
@@ -4372,11 +4459,11 @@ least, not without wrapping it in parentheses. Thus, it uses the
-
+
Start a new scope with regard to labels and the inFunction
flag (restore them to their old value afterwards).
@@ -4393,11 +4480,11 @@ flag (restore them to their old value afterwards).
-
+
If this is a strict mode function, verify that argument names
are not repeated, and it does not try to bind the words eval
@@ -4406,9 +4493,9 @@ or arguments.
if (strict || !isExpression && node.body.body.length && isUseStrict(node.body.body[0])) {
- var nameHash = hash();
+ var nameHash = {};
if (node.id)
- checkFunctionParam(node.id, nameHash);
+ checkFunctionParam(node.id, {});
for (var i = 0; i < node.params.length; i++)
checkFunctionParam(node.params[i], nameHash);
if (node.rest)
@@ -4419,11 +4506,11 @@ or arguments.
-
+
Parse a class declaration or literal (depending on the
isStatement parameter).
@@ -4435,28 +4522,29 @@ or arguments.
next();
node.id = tokType === _name ? parseIdent() : isStatement ? unexpected() : null;
node.superClass = eat(_extends) ? parseExpression() : null;
- var classBody = startNode(), methodHash = hash(), staticMethodHash = hash();
+ var classBody = startNode(), methodHash = {}, staticMethodHash = {};
classBody.body = [];
expect(_braceL);
while (!eat(_braceR)) {
var method = startNode();
if (tokType === _name && tokVal === "static") {
next();
- method.static = true;
+ method['static'] = true;
} else {
- method.static = false;
+ method['static'] = false;
}
var isGenerator = eat(_star);
- method.key = parseIdent(true);
- if ((method.key.name === "get" || method.key.name === "set") && tokType === _name) {
+ parsePropertyName(method);
+ if (tokType === _name && !method.computed && method.key.type === "Identifier" &&
+ (method.key.name === "get" || method.key.name === "set")) {
if (isGenerator) unexpected();
method.kind = method.key.name;
- method.key = parseIdent(true);
+ parsePropertyName(method);
} else {
method.kind = "";
}
method.value = parseMethod(isGenerator);
- checkPropClash(method, method.static ? staticMethodHash : methodHash);
+ checkPropClash(method, method['static'] ? staticMethodHash : methodHash);
classBody.body.push(finishNode(method, "MethodDefinition"));
eat(_semi);
}
@@ -4467,11 +4555,11 @@ or arguments.
-
+
Parses a comma-separated list of expressions, and returns them as
an array. close is the token type that ends the list, and
@@ -4499,11 +4587,11 @@ for array literals).
-
+
Parse the next token as an identifier. If liberal is true (used
when parsing properties), it will also convert keywords into
@@ -4536,11 +4624,11 @@ identifiers.
-
+