babel/docs/acorn.html
Ingvar Stepanyan 533d1d62ec Updated docs.
2014-09-09 00:06:06 +03:00

5508 lines
279 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<title>acorn.js</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
<link rel="stylesheet" media="all" href="docco.css" />
</head>
<body>
<div id="container">
<div id="background"></div>
<ul class="sections">
<li id="title">
<div class="annotation">
<h1>acorn.js</h1>
</div>
</li>
<li id="section-1">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-1">&#182;</a>
</div>
<p>Acorn is a tiny, fast JavaScript parser written in JavaScript.</p>
<p>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 <a href="http://esprima.org">Esprima</a> by
Ariya Hidayat.</p>
<p>Git repositories for Acorn are available at</p>
<pre><code>http:<span class="hljs-comment">//marijnhaverbeke.nl/git/acorn</span>
https:<span class="hljs-comment">//github.com/marijnh/acorn.git</span>
</code></pre><p>Please use the <a href="https://github.com/marijnh/acorn/issues">github bug tracker</a> to report issues.</p>
<p>This file defines the main parser interface. The library also comes
with a <a href="acorn_loose.js">error-tolerant parser</a> and an
<a href="util/walk.js">abstract syntax tree walker</a>, defined in other files.</p>
</div>
<div class="content"><div class='highlight'><pre>
(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(root, mod)</span> </span>{
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> exports == <span class="hljs-string">"object"</span> &amp;&amp; <span class="hljs-keyword">typeof</span> <span class="hljs-built_in">module</span> == <span class="hljs-string">"object"</span>) <span class="hljs-keyword">return</span> mod(exports); <span class="hljs-comment">// CommonJS</span>
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> define == <span class="hljs-string">"function"</span> &amp;&amp; define.amd) <span class="hljs-keyword">return</span> define([<span class="hljs-string">"exports"</span>], mod); <span class="hljs-comment">// AMD</span>
mod(root.acorn || (root.acorn = {})); <span class="hljs-comment">// Plain browser env</span>
})(<span class="hljs-keyword">this</span>, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(exports)</span> </span>{
<span class="hljs-pi"> "use strict"</span>;
exports.version = <span class="hljs-string">"0.7.1"</span>;</pre></div></div>
</li>
<li id="section-2">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
</div>
<p>The main exported interface (under <code>self.acorn</code> when in the
browser) is a <code>parse</code> function that takes a code string and
returns an abstract syntax tree as specified by <a href="https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API">Mozilla parser
API</a>, with the caveat that inline XML is not recognized.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> options, input, inputLen, sourceFile;
exports.parse = <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(inpt, opts)</span> </span>{
input = <span class="hljs-built_in">String</span>(inpt); inputLen = input.length;
setOptions(opts);
initTokenState();
<span class="hljs-keyword">return</span> parseTopLevel(options.program);
};</pre></div></div>
</li>
<li id="section-3">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
</div>
<p>A second optional argument can be given to further configure
the parser process. These options are recognized:</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> defaultOptions = exports.defaultOptions = {</pre></div></div>
</li>
<li id="section-4">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
</div>
<p><code>ecmaVersion</code> indicates the ECMAScript version to parse. Must
be either 3, or 5, or 6. This influences support for strict
mode, the set of reserved words, support for getters and
setters and other features.</p>
</div>
<div class="content"><div class='highlight'><pre> ecmaVersion: <span class="hljs-number">5</span>,</pre></div></div>
</li>
<li id="section-5">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
</div>
<p>Turn on <code>strictSemicolons</code> to prevent the parser from doing
automatic semicolon insertion.</p>
</div>
<div class="content"><div class='highlight'><pre> strictSemicolons: <span class="hljs-literal">false</span>,</pre></div></div>
</li>
<li id="section-6">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
</div>
<p>When <code>allowTrailingCommas</code> is false, the parser will not allow
trailing commas in array and object literals.</p>
</div>
<div class="content"><div class='highlight'><pre> allowTrailingCommas: <span class="hljs-literal">true</span>,</pre></div></div>
</li>
<li id="section-7">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
</div>
<p>By default, reserved words are not enforced. Enable
<code>forbidReserved</code> to enforce them. When this option has the
value “everywhere”, reserved words and keywords can also not be
used as property names.</p>
</div>
<div class="content"><div class='highlight'><pre> forbidReserved: <span class="hljs-literal">false</span>,</pre></div></div>
</li>
<li id="section-8">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
</div>
<p>When enabled, a return at the top level is not considered an
error.</p>
</div>
<div class="content"><div class='highlight'><pre> allowReturnOutsideFunction: <span class="hljs-literal">false</span>,</pre></div></div>
</li>
<li id="section-9">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
</div>
<p>When <code>locations</code> is on, <code>loc</code> properties holding objects with
<code>start</code> and <code>end</code> properties in <code>{line, column}</code> form (with
line being 1-based and column 0-based) will be attached to the
nodes.</p>
</div>
<div class="content"><div class='highlight'><pre> locations: <span class="hljs-literal">false</span>,</pre></div></div>
</li>
<li id="section-10">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
</div>
<p>A function can be passed as <code>onToken</code> 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.</p>
</div>
<div class="content"><div class='highlight'><pre> onToken: <span class="hljs-literal">null</span>,</pre></div></div>
</li>
<li id="section-11">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
</div>
<p>A function can be passed as <code>onComment</code> option, which will
cause Acorn to call that function with <code>(block, text, start,
end)</code> parameters whenever a comment is skipped. <code>block</code> is a
boolean indicating whether this is a block (<code>/* */</code>) comment,
<code>text</code> is the content of the comment, and <code>start</code> and <code>end</code> are
character offsets that denote the start and end of the comment.
When the <code>locations</code> option is on, two more parameters are
passed, the full <code>{line, column}</code> locations of the start and
end of the comments. Note that you are not allowed to call the
parser from the callback—that will corrupt its internal state.</p>
</div>
<div class="content"><div class='highlight'><pre> onComment: <span class="hljs-literal">null</span>,</pre></div></div>
</li>
<li id="section-12">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
</div>
<p>Nodes have their start and end characters offsets recorded in
<code>start</code> and <code>end</code> properties (directly on the node, rather than
the <code>loc</code> object, which holds line/column data. To also add a
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=745678">semi-standardized</a> <code>range</code> property holding a <code>[start,
end]</code> array with the same numbers, set the <code>ranges</code> option to
<code>true</code>.</p>
</div>
<div class="content"><div class='highlight'><pre> ranges: <span class="hljs-literal">false</span>,</pre></div></div>
</li>
<li id="section-13">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-13">&#182;</a>
</div>
<p>It is possible to parse multiple files into a single AST by
passing the tree produced by parsing the first file as
<code>program</code> option in subsequent parses. This will add the
toplevel forms of the parsed file to the <code>Program</code> (top) node
of an existing parse tree.</p>
</div>
<div class="content"><div class='highlight'><pre> program: <span class="hljs-literal">null</span>,</pre></div></div>
</li>
<li id="section-14">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
</div>
<p>When <code>locations</code> is on, you can pass this to record the source
file in every nodes <code>loc</code> object.</p>
</div>
<div class="content"><div class='highlight'><pre> sourceFile: <span class="hljs-literal">null</span>,</pre></div></div>
</li>
<li id="section-15">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
</div>
<p>This value, if given, is stored in every node, whether
<code>locations</code> is on or off.</p>
</div>
<div class="content"><div class='highlight'><pre> directSourceFile: <span class="hljs-literal">null</span>
};
<span class="hljs-keyword">var</span> isArray = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">(obj)</span> </span>{
<span class="hljs-keyword">return</span> <span class="hljs-built_in">Object</span>.prototype.toString.call(obj) === <span class="hljs-string">"[object Array]"</span>;
};
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setOptions</span><span class="hljs-params">(opts)</span> </span>{
options = opts || {};
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> opt <span class="hljs-keyword">in</span> defaultOptions) <span class="hljs-keyword">if</span> (!has(options, opt))
options[opt] = defaultOptions[opt];
sourceFile = options.sourceFile || <span class="hljs-literal">null</span>;
<span class="hljs-keyword">if</span> (isArray(options.onToken)) {
<span class="hljs-keyword">var</span> tokens = options.onToken;
options.onToken = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">(token)</span> </span>{
tokens.push(token);
};
}
<span class="hljs-keyword">if</span> (isArray(options.onComment)) {
<span class="hljs-keyword">var</span> comments = options.onComment;
options.onComment = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">(block, text, start, end, startLoc, endLoc)</span> </span>{
<span class="hljs-keyword">var</span> comment = {
type: block ? <span class="hljs-string">'Block'</span> : <span class="hljs-string">'Line'</span>,
value: text,
start: start,
end: end
};
<span class="hljs-keyword">if</span> (options.locations) {
comment.loc = <span class="hljs-keyword">new</span> SourceLocation();
comment.loc.start = startLoc;
comment.loc.end = endLoc;
}
<span class="hljs-keyword">if</span> (options.ranges)
comment.range = [start, end];
comments.push(comment);
};
}
isKeyword = options.ecmaVersion &gt;= <span class="hljs-number">6</span> ? isEcma6Keyword : isEcma5AndLessKeyword;
}</pre></div></div>
</li>
<li id="section-16">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-16">&#182;</a>
</div>
<p>The <code>getLineInfo</code> function is mostly useful when the
<code>locations</code> option is off (for performance reasons) and you
want to find the line/column position for a given character
offset. <code>input</code> should be the code string that the offset refers
into.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> getLineInfo = exports.getLineInfo = <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(input, offset)</span> </span>{
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> line = <span class="hljs-number">1</span>, cur = <span class="hljs-number">0</span>;;) {
lineBreak.lastIndex = cur;
<span class="hljs-keyword">var</span> match = lineBreak.exec(input);
<span class="hljs-keyword">if</span> (match &amp;&amp; match.index &lt; offset) {
++line;
cur = match.index + match[<span class="hljs-number">0</span>].length;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">break</span>;
}
<span class="hljs-keyword">return</span> {line: line, column: offset - cur};
};
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Token</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">this</span>.type = tokType;
<span class="hljs-keyword">this</span>.value = tokVal;
<span class="hljs-keyword">this</span>.start = tokStart;
<span class="hljs-keyword">this</span>.end = tokEnd;
<span class="hljs-keyword">if</span> (options.locations) {
<span class="hljs-keyword">this</span>.loc = <span class="hljs-keyword">new</span> SourceLocation();
<span class="hljs-keyword">this</span>.loc.end = tokEndLoc;</pre></div></div>
</li>
<li id="section-17">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-17">&#182;</a>
</div>
<p>TODO: remove in next major release</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">this</span>.startLoc = tokStartLoc;
<span class="hljs-keyword">this</span>.endLoc = tokEndLoc;
}
<span class="hljs-keyword">if</span> (options.ranges)
<span class="hljs-keyword">this</span>.range = [tokStart, tokEnd];
}
exports.Token = Token;</pre></div></div>
</li>
<li id="section-18">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-18">&#182;</a>
</div>
<p>Acorn is organized as a tokenizer and a recursive-descent parser.
The <code>tokenize</code> export provides an interface to the tokenizer.
Because the tokenizer is optimized for being efficiently used by
the Acorn parser itself, this interface is somewhat crude and not
very modular. Performing another parse or call to <code>tokenize</code> will
reset the internal state, and invalidate existing tokenizers.</p>
</div>
<div class="content"><div class='highlight'><pre>
exports.tokenize = <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(inpt, opts)</span> </span>{
input = <span class="hljs-built_in">String</span>(inpt); inputLen = input.length;
setOptions(opts);
initTokenState();
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getToken</span><span class="hljs-params">(forceRegexp)</span> </span>{
lastEnd = tokEnd;
readToken(forceRegexp);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Token();
}
getToken.jumpTo = <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(pos, reAllowed)</span> </span>{
tokPos = pos;
<span class="hljs-keyword">if</span> (options.locations) {
tokCurLine = <span class="hljs-number">1</span>;
tokLineStart = lineBreak.lastIndex = <span class="hljs-number">0</span>;
<span class="hljs-keyword">var</span> match;
<span class="hljs-keyword">while</span> ((match = lineBreak.exec(input)) &amp;&amp; match.index &lt; pos) {
++tokCurLine;
tokLineStart = match.index + match[<span class="hljs-number">0</span>].length;
}
}
tokRegexpAllowed = reAllowed;
skipSpace();
};
<span class="hljs-keyword">return</span> getToken;
};</pre></div></div>
</li>
<li id="section-19">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-19">&#182;</a>
</div>
<p>State is kept in (closure-)global variables. We already saw the
<code>options</code>, <code>input</code>, and <code>inputLen</code> variables above.</p>
</div>
</li>
<li id="section-20">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-20">&#182;</a>
</div>
<p>The current position of the tokenizer in the input.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> tokPos;</pre></div></div>
</li>
<li id="section-21">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-21">&#182;</a>
</div>
<p>The start and end offsets of the current token.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> tokStart, tokEnd;</pre></div></div>
</li>
<li id="section-22">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-22">&#182;</a>
</div>
<p>When <code>options.locations</code> is true, these hold objects
containing the tokens start and end line/column pairs.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> tokStartLoc, tokEndLoc;</pre></div></div>
</li>
<li id="section-23">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-23">&#182;</a>
</div>
<p>The type and value of the current token. Token types are objects,
named by variables against which they can be compared, and
holding properties that describe them (indicating, for example,
the precedence of an infix operator, and the original name of a
keyword token). The kind of value thats held in <code>tokVal</code> depends
on the type of the token. For literals, it is the literal value,
for operators, the operator name, and so on.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> tokType, tokVal;</pre></div></div>
</li>
<li id="section-24">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-24">&#182;</a>
</div>
<p>Internal state for the tokenizer. To distinguish between division
operators and regular expressions, it remembers whether the last
token was one that is allowed to be followed by an expression.
(If it is, a slash is probably a regexp, if it isnt its a
division operator. See the <code>parseStatement</code> function for a
caveat.)</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> tokRegexpAllowed;</pre></div></div>
</li>
<li id="section-25">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-25">&#182;</a>
</div>
<p>When <code>options.locations</code> is true, these are used to keep
track of the current line, and know when a new line has been
entered.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> tokCurLine, tokLineStart;</pre></div></div>
</li>
<li id="section-26">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-26">&#182;</a>
</div>
<p>These store the position of the previous token, which is useful
when finishing a node and assigning its <code>end</code> position.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> lastStart, lastEnd, lastEndLoc;</pre></div></div>
</li>
<li id="section-27">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-27">&#182;</a>
</div>
<p>This is the parsers state. <code>inFunction</code> is used to reject
<code>return</code> statements outside of functions, <code>inGenerator</code> to
reject <code>yield</code>s outside of generators, <code>labels</code> to verify
that <code>break</code> and <code>continue</code> have somewhere to jump to, and
<code>strict</code> indicates whether strict mode is on.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> inFunction, inGenerator, labels, strict, inXJSChild, inXJSTag;</pre></div></div>
</li>
<li id="section-28">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-28">&#182;</a>
</div>
<p>This counter is used for checking that arrow expressions did
not contain nested parentheses in argument list.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> metParenL;</pre></div></div>
</li>
<li id="section-29">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-29">&#182;</a>
</div>
<p>This is used by parser for detecting if its inside ES6
Template String. If it is, it should treat $ as prefix before
{expression} and everything else as string literals.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> inTemplate;</pre></div></div>
</li>
<li id="section-30">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-30">&#182;</a>
</div>
<p>This function is used to raise exceptions on parse errors. It
takes an offset integer (into the current <code>input</code>) to indicate
the location of the error, attaches the position to the end
of the error message, and then raises a <code>SyntaxError</code> with that
message.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">raise</span><span class="hljs-params">(pos, message)</span> </span>{
<span class="hljs-keyword">var</span> loc = getLineInfo(input, pos);
message += <span class="hljs-string">" ("</span> + loc.line + <span class="hljs-string">":"</span> + loc.column + <span class="hljs-string">")"</span>;
<span class="hljs-keyword">var</span> err = <span class="hljs-keyword">new</span> <span class="hljs-built_in">SyntaxError</span>(message);
err.pos = pos; err.loc = loc; err.raisedAt = tokPos;
<span class="hljs-keyword">throw</span> err;
}</pre></div></div>
</li>
<li id="section-31">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-31">&#182;</a>
</div>
<p>Reused empty array added for node fields that are always empty.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> empty = [];</pre></div></div>
</li>
<li id="section-32">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-32">&#182;</a>
</div>
<h2 id="token-types">Token types</h2>
</div>
</li>
<li id="section-33">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-33">&#182;</a>
</div>
<p>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.</p>
</div>
</li>
<li id="section-34">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-34">&#182;</a>
</div>
<p>All token type variables start with an underscore, to make them
easy to recognize.</p>
</div>
</li>
<li id="section-35">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-35">&#182;</a>
</div>
<p>These are the general types. The <code>type</code> property is only used to
make them recognizeable when debugging.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> _num = {type: <span class="hljs-string">"num"</span>}, _regexp = {type: <span class="hljs-string">"regexp"</span>}, _string = {type: <span class="hljs-string">"string"</span>};
<span class="hljs-keyword">var</span> _name = {type: <span class="hljs-string">"name"</span>}, _eof = {type: <span class="hljs-string">"eof"</span>};</pre></div></div>
</li>
<li id="section-36">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-36">&#182;</a>
</div>
<p>These are JSX-specific token types</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> _xjsName = {type: <span class="hljs-string">"xjsName"</span>}, _xjsText = {type: <span class="hljs-string">"xjsText"</span>};</pre></div></div>
</li>
<li id="section-37">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-37">&#182;</a>
</div>
<p>Keyword tokens. The <code>keyword</code> property (also used in keyword-like
operators) indicates that the token originated from an
identifier-like word, which is used when parsing property names.</p>
<p>The <code>beforeExpr</code> property is used to disambiguate between regular
expressions and divisions. It is set on all token types that can
be followed by an expression (thus, a slash after them would be a
regular expression).</p>
<p><code>isLoop</code> marks a keyword as starting a loop, which is important
to know when parsing a label, in order to allow or disallow
continue jumps to that label.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> _break = {keyword: <span class="hljs-string">"break"</span>}, _case = {keyword: <span class="hljs-string">"case"</span>, beforeExpr: <span class="hljs-literal">true</span>}, _catch = {keyword: <span class="hljs-string">"catch"</span>};
<span class="hljs-keyword">var</span> _continue = {keyword: <span class="hljs-string">"continue"</span>}, _debugger = {keyword: <span class="hljs-string">"debugger"</span>}, _default = {keyword: <span class="hljs-string">"default"</span>};
<span class="hljs-keyword">var</span> _do = {keyword: <span class="hljs-string">"do"</span>, isLoop: <span class="hljs-literal">true</span>}, _else = {keyword: <span class="hljs-string">"else"</span>, beforeExpr: <span class="hljs-literal">true</span>};
<span class="hljs-keyword">var</span> _finally = {keyword: <span class="hljs-string">"finally"</span>}, _for = {keyword: <span class="hljs-string">"for"</span>, isLoop: <span class="hljs-literal">true</span>}, _function = {keyword: <span class="hljs-string">"function"</span>};
<span class="hljs-keyword">var</span> _if = {keyword: <span class="hljs-string">"if"</span>}, _return = {keyword: <span class="hljs-string">"return"</span>, beforeExpr: <span class="hljs-literal">true</span>}, _switch = {keyword: <span class="hljs-string">"switch"</span>};
<span class="hljs-keyword">var</span> _throw = {keyword: <span class="hljs-string">"throw"</span>, beforeExpr: <span class="hljs-literal">true</span>}, _try = {keyword: <span class="hljs-string">"try"</span>}, _var = {keyword: <span class="hljs-string">"var"</span>};
<span class="hljs-keyword">var</span> _let = {keyword: <span class="hljs-string">"let"</span>}, _const = {keyword: <span class="hljs-string">"const"</span>};
<span class="hljs-keyword">var</span> _while = {keyword: <span class="hljs-string">"while"</span>, isLoop: <span class="hljs-literal">true</span>}, _with = {keyword: <span class="hljs-string">"with"</span>}, _new = {keyword: <span class="hljs-string">"new"</span>, beforeExpr: <span class="hljs-literal">true</span>};
<span class="hljs-keyword">var</span> _this = {keyword: <span class="hljs-string">"this"</span>};
<span class="hljs-keyword">var</span> _class = {keyword: <span class="hljs-string">"class"</span>}, _extends = {keyword: <span class="hljs-string">"extends"</span>, beforeExpr: <span class="hljs-literal">true</span>};
<span class="hljs-keyword">var</span> _export = {keyword: <span class="hljs-string">"export"</span>}, _import = {keyword: <span class="hljs-string">"import"</span>};
<span class="hljs-keyword">var</span> _yield = {keyword: <span class="hljs-string">"yield"</span>, beforeExpr: <span class="hljs-literal">true</span>};</pre></div></div>
</li>
<li id="section-38">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-38">&#182;</a>
</div>
<p>The keywords that denote values.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> _null = {keyword: <span class="hljs-string">"null"</span>, atomValue: <span class="hljs-literal">null</span>}, _true = {keyword: <span class="hljs-string">"true"</span>, atomValue: <span class="hljs-literal">true</span>};
<span class="hljs-keyword">var</span> _false = {keyword: <span class="hljs-string">"false"</span>, atomValue: <span class="hljs-literal">false</span>};</pre></div></div>
</li>
<li id="section-39">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-39">&#182;</a>
</div>
<p>Some keywords are treated as regular operators. <code>in</code> sometimes
(when parsing <code>for</code>) needs to be tested against specifically, so
we assign a variable name to it for quick comparing.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> _in = {keyword: <span class="hljs-string">"in"</span>, binop: <span class="hljs-number">7</span>, beforeExpr: <span class="hljs-literal">true</span>};</pre></div></div>
</li>
<li id="section-40">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-40">&#182;</a>
</div>
<p>Map keyword names to token types.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> keywordTypes = {<span class="hljs-string">"break"</span>: _break, <span class="hljs-string">"case"</span>: _case, <span class="hljs-string">"catch"</span>: _catch,
<span class="hljs-string">"continue"</span>: _continue, <span class="hljs-string">"debugger"</span>: _debugger, <span class="hljs-string">"default"</span>: _default,
<span class="hljs-string">"do"</span>: _do, <span class="hljs-string">"else"</span>: _else, <span class="hljs-string">"finally"</span>: _finally, <span class="hljs-string">"for"</span>: _for,
<span class="hljs-string">"function"</span>: _function, <span class="hljs-string">"if"</span>: _if, <span class="hljs-string">"return"</span>: _return, <span class="hljs-string">"switch"</span>: _switch,
<span class="hljs-string">"throw"</span>: _throw, <span class="hljs-string">"try"</span>: _try, <span class="hljs-string">"var"</span>: _var, <span class="hljs-string">"let"</span>: _let, <span class="hljs-string">"const"</span>: _const,
<span class="hljs-string">"while"</span>: _while, <span class="hljs-string">"with"</span>: _with,
<span class="hljs-string">"null"</span>: _null, <span class="hljs-string">"true"</span>: _true, <span class="hljs-string">"false"</span>: _false, <span class="hljs-string">"new"</span>: _new, <span class="hljs-string">"in"</span>: _in,
<span class="hljs-string">"instanceof"</span>: {keyword: <span class="hljs-string">"instanceof"</span>, binop: <span class="hljs-number">7</span>, beforeExpr: <span class="hljs-literal">true</span>}, <span class="hljs-string">"this"</span>: _this,
<span class="hljs-string">"typeof"</span>: {keyword: <span class="hljs-string">"typeof"</span>, prefix: <span class="hljs-literal">true</span>, beforeExpr: <span class="hljs-literal">true</span>},
<span class="hljs-string">"void"</span>: {keyword: <span class="hljs-string">"void"</span>, prefix: <span class="hljs-literal">true</span>, beforeExpr: <span class="hljs-literal">true</span>},
<span class="hljs-string">"delete"</span>: {keyword: <span class="hljs-string">"delete"</span>, prefix: <span class="hljs-literal">true</span>, beforeExpr: <span class="hljs-literal">true</span>},
<span class="hljs-string">"class"</span>: _class, <span class="hljs-string">"extends"</span>: _extends,
<span class="hljs-string">"export"</span>: _export, <span class="hljs-string">"import"</span>: _import, <span class="hljs-string">"yield"</span>: _yield};</pre></div></div>
</li>
<li id="section-41">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-41">&#182;</a>
</div>
<p>Punctuation token types. Again, the <code>type</code> property is purely for debugging.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> _bracketL = {type: <span class="hljs-string">"["</span>, beforeExpr: <span class="hljs-literal">true</span>}, _bracketR = {type: <span class="hljs-string">"]"</span>}, _braceL = {type: <span class="hljs-string">"{"</span>, beforeExpr: <span class="hljs-literal">true</span>};
<span class="hljs-keyword">var</span> _braceR = {type: <span class="hljs-string">"}"</span>}, _parenL = {type: <span class="hljs-string">"("</span>, beforeExpr: <span class="hljs-literal">true</span>}, _parenR = {type: <span class="hljs-string">")"</span>};
<span class="hljs-keyword">var</span> _comma = {type: <span class="hljs-string">","</span>, beforeExpr: <span class="hljs-literal">true</span>}, _semi = {type: <span class="hljs-string">";"</span>, beforeExpr: <span class="hljs-literal">true</span>};
<span class="hljs-keyword">var</span> _colon = {type: <span class="hljs-string">":"</span>, beforeExpr: <span class="hljs-literal">true</span>}, _dot = {type: <span class="hljs-string">"."</span>}, _ellipsis = {type: <span class="hljs-string">"..."</span>}, _question = {type: <span class="hljs-string">"?"</span>, beforeExpr: <span class="hljs-literal">true</span>};
<span class="hljs-keyword">var</span> _arrow = {type: <span class="hljs-string">"=&gt;"</span>, beforeExpr: <span class="hljs-literal">true</span>}, _bquote = {type: <span class="hljs-string">"`"</span>}, _dollarBraceL = {type: <span class="hljs-string">"${"</span>, beforeExpr: <span class="hljs-literal">true</span>};
<span class="hljs-keyword">var</span> _ltSlash = {type: <span class="hljs-string">"&lt;/"</span>};</pre></div></div>
</li>
<li id="section-42">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-42">&#182;</a>
</div>
<p>Operators. These carry several kinds of properties to help the
parser use them properly (the presence of these properties is
what categorizes them as operators).</p>
<p><code>binop</code>, when present, specifies that this operator is a binary
operator, and will refer to its precedence.</p>
<p><code>prefix</code> and <code>postfix</code> mark the operator as a prefix or postfix
unary operator. <code>isUpdate</code> specifies that the node produced by
the operator should be of type UpdateExpression rather than
simply UnaryExpression (<code>++</code> and <code>--</code>).</p>
<p><code>isAssign</code> marks all of <code>=</code>, <code>+=</code>, <code>-=</code> etcetera, which act as
binary operators with a very low precedence, that should result
in AssignmentExpression nodes.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> _slash = {binop: <span class="hljs-number">10</span>, beforeExpr: <span class="hljs-literal">true</span>}, _eq = {isAssign: <span class="hljs-literal">true</span>, beforeExpr: <span class="hljs-literal">true</span>};
<span class="hljs-keyword">var</span> _assign = {isAssign: <span class="hljs-literal">true</span>, beforeExpr: <span class="hljs-literal">true</span>};
<span class="hljs-keyword">var</span> _incDec = {postfix: <span class="hljs-literal">true</span>, prefix: <span class="hljs-literal">true</span>, isUpdate: <span class="hljs-literal">true</span>}, _prefix = {prefix: <span class="hljs-literal">true</span>, beforeExpr: <span class="hljs-literal">true</span>};
<span class="hljs-keyword">var</span> _logicalOR = {binop: <span class="hljs-number">1</span>, beforeExpr: <span class="hljs-literal">true</span>};
<span class="hljs-keyword">var</span> _logicalAND = {binop: <span class="hljs-number">2</span>, beforeExpr: <span class="hljs-literal">true</span>};
<span class="hljs-keyword">var</span> _bitwiseOR = {binop: <span class="hljs-number">3</span>, beforeExpr: <span class="hljs-literal">true</span>};
<span class="hljs-keyword">var</span> _bitwiseXOR = {binop: <span class="hljs-number">4</span>, beforeExpr: <span class="hljs-literal">true</span>};
<span class="hljs-keyword">var</span> _bitwiseAND = {binop: <span class="hljs-number">5</span>, beforeExpr: <span class="hljs-literal">true</span>};
<span class="hljs-keyword">var</span> _equality = {binop: <span class="hljs-number">6</span>, beforeExpr: <span class="hljs-literal">true</span>};
<span class="hljs-keyword">var</span> _relational = {binop: <span class="hljs-number">7</span>, beforeExpr: <span class="hljs-literal">true</span>};
<span class="hljs-keyword">var</span> _bitShift = {binop: <span class="hljs-number">8</span>, beforeExpr: <span class="hljs-literal">true</span>};
<span class="hljs-keyword">var</span> _plusMin = {binop: <span class="hljs-number">9</span>, prefix: <span class="hljs-literal">true</span>, beforeExpr: <span class="hljs-literal">true</span>};
<span class="hljs-keyword">var</span> _modulo = {binop: <span class="hljs-number">10</span>, beforeExpr: <span class="hljs-literal">true</span>};</pre></div></div>
</li>
<li id="section-43">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-43">&#182;</a>
</div>
<p>* may be multiply or have special meaning in ES6</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> _star = {binop: <span class="hljs-number">10</span>, beforeExpr: <span class="hljs-literal">true</span>};</pre></div></div>
</li>
<li id="section-44">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-44">&#182;</a>
</div>
<p>&lt;, &gt; may be relational or have special meaning in JSX</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> _lt = {binop: <span class="hljs-number">7</span>, beforeExpr: <span class="hljs-literal">true</span>}, _gt = {binop: <span class="hljs-number">7</span>, beforeExpr: <span class="hljs-literal">true</span>};</pre></div></div>
</li>
<li id="section-45">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-45">&#182;</a>
</div>
<p>Provide access to the token types for external users of the
tokenizer.</p>
</div>
<div class="content"><div class='highlight'><pre>
exports.tokTypes = {bracketL: _bracketL, bracketR: _bracketR, braceL: _braceL, braceR: _braceR,
parenL: _parenL, parenR: _parenR, comma: _comma, semi: _semi, colon: _colon,
dot: _dot, ellipsis: _ellipsis, question: _question, slash: _slash, eq: _eq,
name: _name, eof: _eof, num: _num, regexp: _regexp, string: _string,
arrow: _arrow, bquote: _bquote, dollarBraceL: _dollarBraceL,
xjsName: _xjsName, xjsText: _xjsText};
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> kw <span class="hljs-keyword">in</span> keywordTypes) exports.tokTypes[<span class="hljs-string">"_"</span> + kw] = keywordTypes[kw];</pre></div></div>
</li>
<li id="section-46">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-46">&#182;</a>
</div>
<p>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
predicate containing a big ugly <code>switch</code> statement is faster than
a regular expression, and on Chrome the two are about on par.
This function uses <code>eval</code> (non-lexical) to produce such a
predicate from a space-separated string of words.</p>
<p>It starts by sorting the words by length.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">makePredicate</span><span class="hljs-params">(words)</span> </span>{
words = words.split(<span class="hljs-string">" "</span>);
<span class="hljs-keyword">var</span> f = <span class="hljs-string">""</span>, cats = [];
out: <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; words.length; ++i) {
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> j = <span class="hljs-number">0</span>; j &lt; cats.length; ++j)
<span class="hljs-keyword">if</span> (cats[j][<span class="hljs-number">0</span>].length == words[i].length) {
cats[j].push(words[i]);
<span class="hljs-keyword">continue</span> out;
}
cats.push([words[i]]);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">compareTo</span><span class="hljs-params">(arr)</span> </span>{
<span class="hljs-keyword">if</span> (arr.length == <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> f += <span class="hljs-string">"return str === "</span> + <span class="hljs-built_in">JSON</span>.stringify(arr[<span class="hljs-number">0</span>]) + <span class="hljs-string">";"</span>;
f += <span class="hljs-string">"switch(str){"</span>;
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; arr.length; ++i) f += <span class="hljs-string">"case "</span> + <span class="hljs-built_in">JSON</span>.stringify(arr[i]) + <span class="hljs-string">":"</span>;
f += <span class="hljs-string">"return true}return false;"</span>;
}</pre></div></div>
</li>
<li id="section-47">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-47">&#182;</a>
</div>
<p>When there are more than three length categories, an outer
switch first dispatches on the lengths, to save on comparisons.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">if</span> (cats.length &gt; <span class="hljs-number">3</span>) {
cats.sort(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(a, b)</span> </span>{<span class="hljs-keyword">return</span> b.length - a.length;});
f += <span class="hljs-string">"switch(str.length){"</span>;
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; cats.length; ++i) {
<span class="hljs-keyword">var</span> cat = cats[i];
f += <span class="hljs-string">"case "</span> + cat[<span class="hljs-number">0</span>].length + <span class="hljs-string">":"</span>;
compareTo(cat);
}
f += <span class="hljs-string">"}"</span>;</pre></div></div>
</li>
<li id="section-48">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-48">&#182;</a>
</div>
<p>Otherwise, simply generate a flat <code>switch</code> statement.</p>
</div>
<div class="content"><div class='highlight'><pre>
} <span class="hljs-keyword">else</span> {
compareTo(words);
}
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Function</span>(<span class="hljs-string">"str"</span>, f);
}</pre></div></div>
</li>
<li id="section-49">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-49">&#182;</a>
</div>
<p>The ECMAScript 3 reserved word list.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> isReservedWord3 = makePredicate(<span class="hljs-string">"abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile"</span>);</pre></div></div>
</li>
<li id="section-50">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-50">&#182;</a>
</div>
<p>ECMAScript 5 reserved words.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> isReservedWord5 = makePredicate(<span class="hljs-string">"class enum extends super const export import"</span>);</pre></div></div>
</li>
<li id="section-51">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-51">&#182;</a>
</div>
<p>The additional reserved words in strict mode.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> isStrictReservedWord = makePredicate(<span class="hljs-string">"implements interface let package private protected public static yield"</span>);</pre></div></div>
</li>
<li id="section-52">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-52">&#182;</a>
</div>
<p>The forbidden variable names in strict mode.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> isStrictBadIdWord = makePredicate(<span class="hljs-string">"eval arguments"</span>);</pre></div></div>
</li>
<li id="section-53">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-53">&#182;</a>
</div>
<p>And the keywords.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> ecma5AndLessKeywords = <span class="hljs-string">"break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"</span>;
<span class="hljs-keyword">var</span> isEcma5AndLessKeyword = makePredicate(ecma5AndLessKeywords);
<span class="hljs-keyword">var</span> isEcma6Keyword = makePredicate(ecma5AndLessKeywords + <span class="hljs-string">" let const class extends export import yield"</span>);
<span class="hljs-keyword">var</span> isKeyword = isEcma5AndLessKeyword;</pre></div></div>
</li>
<li id="section-54">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-54">&#182;</a>
</div>
<h2 id="character-categories">Character categories</h2>
</div>
</li>
<li id="section-55">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-55">&#182;</a>
</div>
<p>Big ugly regular expressions that match characters in the
whitespace, identifier, and identifier-start categories. These
are only applied when a character is found to actually have a
code point above 128.
Generated by <code>tools/generate-identifier-regex.js</code>.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> nonASCIIwhitespace = <span class="hljs-regexp">/[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/</span>;
<span class="hljs-keyword">var</span> nonASCIIidentifierStartChars = <span class="hljs-string">"\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC"</span>;
<span class="hljs-keyword">var</span> nonASCIIidentifierChars = <span class="hljs-string">"\u0300-\u036F\u0483-\u0487\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u0669\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u06F0-\u06F9\u0711\u0730-\u074A\u07A6-\u07B0\u07C0-\u07C9\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08E4-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0966-\u096F\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09E6-\u09EF\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A66-\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B66-\u0B6F\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0CE6-\u0CEF\u0D01-\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D66-\u0D6F\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0E50-\u0E59\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0ED0-\u0ED9\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1040-\u1049\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u18A9\u1920-\u192B\u1930-\u193B\u1946-\u194F\u19B0-\u19C0\u19C8\u19C9\u19D0-\u19D9\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AB0-\u1ABD\u1B00-\u1B04\u1B34-\u1B44\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BB0-\u1BB9\u1BE6-\u1BF3\u1C24-\u1C37\u1C40-\u1C49\u1C50-\u1C59\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF8\u1CF9\u1DC0-\u1DF5\u1DFC-\u1DFF\u200C\u200D\u203F\u2040\u2054\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA620-\uA629\uA66F\uA674-\uA67D\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F1\uA900-\uA909\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9D0-\uA9D9\uA9E5\uA9F0-\uA9F9\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA50-\uAA59\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uABF0-\uABF9\uFB1E\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFF10-\uFF19\uFF3F"</span>;
<span class="hljs-keyword">var</span> nonASCIIidentifierStart = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">"["</span> + nonASCIIidentifierStartChars + <span class="hljs-string">"]"</span>);
<span class="hljs-keyword">var</span> nonASCIIidentifier = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">"["</span> + nonASCIIidentifierStartChars + nonASCIIidentifierChars + <span class="hljs-string">"]"</span>);</pre></div></div>
</li>
<li id="section-56">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-56">&#182;</a>
</div>
<p>Whether a single character denotes a newline.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> newline = <span class="hljs-regexp">/[\n\r\u2028\u2029]/</span>;</pre></div></div>
</li>
<li id="section-57">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-57">&#182;</a>
</div>
<p>Matches a whole line break (where CRLF is considered a single
line break). Used to count lines.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> lineBreak = <span class="hljs-regexp">/\r\n|[\n\r\u2028\u2029]/g</span>;</pre></div></div>
</li>
<li id="section-58">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-58">&#182;</a>
</div>
<p>Test whether a given character code starts an identifier.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> isIdentifierStart = exports.isIdentifierStart = <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(code)</span> </span>{
<span class="hljs-keyword">if</span> (code &lt; <span class="hljs-number">65</span>) <span class="hljs-keyword">return</span> code === <span class="hljs-number">36</span>;
<span class="hljs-keyword">if</span> (code &lt; <span class="hljs-number">91</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
<span class="hljs-keyword">if</span> (code &lt; <span class="hljs-number">97</span>) <span class="hljs-keyword">return</span> code === <span class="hljs-number">95</span>;
<span class="hljs-keyword">if</span> (code &lt; <span class="hljs-number">123</span>)<span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
<span class="hljs-keyword">return</span> code &gt;= <span class="hljs-number">0xaa</span> &amp;&amp; nonASCIIidentifierStart.test(<span class="hljs-built_in">String</span>.fromCharCode(code));
};</pre></div></div>
</li>
<li id="section-59">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-59">&#182;</a>
</div>
<p>Test whether a given character is part of an identifier.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> isIdentifierChar = exports.isIdentifierChar = <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(code)</span> </span>{
<span class="hljs-keyword">if</span> (code &lt; <span class="hljs-number">48</span>) <span class="hljs-keyword">return</span> code === <span class="hljs-number">36</span>;
<span class="hljs-keyword">if</span> (code &lt; <span class="hljs-number">58</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
<span class="hljs-keyword">if</span> (code &lt; <span class="hljs-number">65</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
<span class="hljs-keyword">if</span> (code &lt; <span class="hljs-number">91</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
<span class="hljs-keyword">if</span> (code &lt; <span class="hljs-number">97</span>) <span class="hljs-keyword">return</span> code === <span class="hljs-number">95</span>;
<span class="hljs-keyword">if</span> (code &lt; <span class="hljs-number">123</span>)<span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
<span class="hljs-keyword">return</span> code &gt;= <span class="hljs-number">0xaa</span> &amp;&amp; nonASCIIidentifier.test(<span class="hljs-built_in">String</span>.fromCharCode(code));
};</pre></div></div>
</li>
<li id="section-60">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-60">&#182;</a>
</div>
<h2 id="tokenizer">Tokenizer</h2>
</div>
</li>
<li id="section-61">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-61">&#182;</a>
</div>
<p>These are used when <code>options.locations</code> is on, for the
<code>tokStartLoc</code> and <code>tokEndLoc</code> properties.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Position</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">this</span>.line = tokCurLine;
<span class="hljs-keyword">this</span>.column = tokPos - tokLineStart;
}</pre></div></div>
</li>
<li id="section-62">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-62">&#182;</a>
</div>
<p>Reset the token state. Used at the start of a parse.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">initTokenState</span><span class="hljs-params">()</span> </span>{
tokCurLine = <span class="hljs-number">1</span>;
tokPos = tokLineStart = <span class="hljs-number">0</span>;
tokRegexpAllowed = <span class="hljs-literal">true</span>;
metParenL = <span class="hljs-number">0</span>;
inTemplate = inXJSChild = inXJSTag = <span class="hljs-literal">false</span>;
skipSpace();
}</pre></div></div>
</li>
<li id="section-63">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-63">&#182;</a>
</div>
<p>Called at the end of every token. Sets <code>tokEnd</code>, <code>tokVal</code>, and
<code>tokRegexpAllowed</code>, and skips the space after the token, so that
the next ones <code>tokStart</code> will point at the right position.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">finishToken</span><span class="hljs-params">(type, val, shouldSkipSpace)</span> </span>{
tokEnd = tokPos;
<span class="hljs-keyword">if</span> (options.locations) tokEndLoc = <span class="hljs-keyword">new</span> Position;
tokType = type;
<span class="hljs-keyword">if</span> (shouldSkipSpace !== <span class="hljs-literal">false</span> &amp;&amp; !(inXJSTag &amp;&amp; type === _gt) &amp;&amp; !(inXJSChild &amp;&amp; tokType !== _braceL)) {
skipSpace();
}
tokVal = val;
tokRegexpAllowed = type.beforeExpr;
<span class="hljs-keyword">if</span> (options.onToken) {
options.onToken(<span class="hljs-keyword">new</span> Token());
}
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">skipBlockComment</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> startLoc = options.onComment &amp;&amp; options.locations &amp;&amp; <span class="hljs-keyword">new</span> Position;
<span class="hljs-keyword">var</span> start = tokPos, end = input.indexOf(<span class="hljs-string">"*/"</span>, tokPos += <span class="hljs-number">2</span>);
<span class="hljs-keyword">if</span> (end === -<span class="hljs-number">1</span>) raise(tokPos - <span class="hljs-number">2</span>, <span class="hljs-string">"Unterminated comment"</span>);
tokPos = end + <span class="hljs-number">2</span>;
<span class="hljs-keyword">if</span> (options.locations) {
lineBreak.lastIndex = start;
<span class="hljs-keyword">var</span> match;
<span class="hljs-keyword">while</span> ((match = lineBreak.exec(input)) &amp;&amp; match.index &lt; tokPos) {
++tokCurLine;
tokLineStart = match.index + match[<span class="hljs-number">0</span>].length;
}
}
<span class="hljs-keyword">if</span> (options.onComment)
options.onComment(<span class="hljs-literal">true</span>, input.slice(start + <span class="hljs-number">2</span>, end), start, tokPos,
startLoc, options.locations &amp;&amp; <span class="hljs-keyword">new</span> Position);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">skipLineComment</span><span class="hljs-params">(startSkip)</span> </span>{
<span class="hljs-keyword">var</span> start = tokPos;
<span class="hljs-keyword">var</span> startLoc = options.onComment &amp;&amp; options.locations &amp;&amp; <span class="hljs-keyword">new</span> Position;
<span class="hljs-keyword">var</span> ch = input.charCodeAt(tokPos+=startSkip);
<span class="hljs-keyword">while</span> (tokPos &lt; inputLen &amp;&amp; ch !== <span class="hljs-number">10</span> &amp;&amp; ch !== <span class="hljs-number">13</span> &amp;&amp; ch !== <span class="hljs-number">8232</span> &amp;&amp; ch !== <span class="hljs-number">8233</span>) {
++tokPos;
ch = input.charCodeAt(tokPos);
}
<span class="hljs-keyword">if</span> (options.onComment)
options.onComment(<span class="hljs-literal">false</span>, input.slice(start + startSkip, tokPos), start, tokPos,
startLoc, options.locations &amp;&amp; <span class="hljs-keyword">new</span> Position);
}</pre></div></div>
</li>
<li id="section-64">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-64">&#182;</a>
</div>
<p>Called at the start of the parse and after every token. Skips
whitespace and comments, and.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">skipSpace</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">while</span> (tokPos &lt; inputLen) {
<span class="hljs-keyword">var</span> ch = input.charCodeAt(tokPos);
<span class="hljs-keyword">if</span> (ch === <span class="hljs-number">32</span>) { <span class="hljs-comment">// ' '</span>
++tokPos;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (ch === <span class="hljs-number">13</span>) {
++tokPos;
<span class="hljs-keyword">var</span> next = input.charCodeAt(tokPos);
<span class="hljs-keyword">if</span> (next === <span class="hljs-number">10</span>) {
++tokPos;
}
<span class="hljs-keyword">if</span> (options.locations) {
++tokCurLine;
tokLineStart = tokPos;
}
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (ch === <span class="hljs-number">10</span> || ch === <span class="hljs-number">8232</span> || ch === <span class="hljs-number">8233</span>) {
++tokPos;
<span class="hljs-keyword">if</span> (options.locations) {
++tokCurLine;
tokLineStart = tokPos;
}
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (ch &gt; <span class="hljs-number">8</span> &amp;&amp; ch &lt; <span class="hljs-number">14</span>) {
++tokPos;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (ch === <span class="hljs-number">47</span>) { <span class="hljs-comment">// '/'</span>
<span class="hljs-keyword">var</span> next = input.charCodeAt(tokPos + <span class="hljs-number">1</span>);
<span class="hljs-keyword">if</span> (next === <span class="hljs-number">42</span>) { <span class="hljs-comment">// '*'</span>
skipBlockComment();
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (next === <span class="hljs-number">47</span>) { <span class="hljs-comment">// '/'</span>
skipLineComment(<span class="hljs-number">2</span>);
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">break</span>;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (ch === <span class="hljs-number">160</span>) { <span class="hljs-comment">// '\xa0'</span>
++tokPos;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (ch &gt;= <span class="hljs-number">5760</span> &amp;&amp; nonASCIIwhitespace.test(<span class="hljs-built_in">String</span>.fromCharCode(ch))) {
++tokPos;
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">break</span>;
}
}
}</pre></div></div>
</li>
<li id="section-65">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-65">&#182;</a>
</div>
<h3 id="token-reading">Token reading</h3>
</div>
</li>
<li id="section-66">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-66">&#182;</a>
</div>
<p>This is the function that is called to fetch the next token. It
is somewhat obscure, because it works in character codes rather
than characters, and because operator parsing has been inlined
into it.</p>
<p>All in the name of speed.</p>
<p>The <code>forceRegexp</code> parameter is used in the one case where the
<code>tokRegexpAllowed</code> trick does not work. See <code>parseStatement</code>.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readToken_dot</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> next = input.charCodeAt(tokPos + <span class="hljs-number">1</span>);
<span class="hljs-keyword">if</span> (next &gt;= <span class="hljs-number">48</span> &amp;&amp; next &lt;= <span class="hljs-number">57</span>) <span class="hljs-keyword">return</span> readNumber(<span class="hljs-literal">true</span>);
<span class="hljs-keyword">var</span> next2 = input.charCodeAt(tokPos + <span class="hljs-number">2</span>);
<span class="hljs-keyword">if</span> (options.ecmaVersion &gt;= <span class="hljs-number">6</span> &amp;&amp; next === <span class="hljs-number">46</span> &amp;&amp; next2 === <span class="hljs-number">46</span>) { <span class="hljs-comment">// 46 = dot '.'</span>
tokPos += <span class="hljs-number">3</span>;
<span class="hljs-keyword">return</span> finishToken(_ellipsis);
} <span class="hljs-keyword">else</span> {
++tokPos;
<span class="hljs-keyword">return</span> finishToken(_dot);
}
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readToken_slash</span><span class="hljs-params">()</span> </span>{ <span class="hljs-comment">// '/'</span>
<span class="hljs-keyword">var</span> next = input.charCodeAt(tokPos + <span class="hljs-number">1</span>);
<span class="hljs-keyword">if</span> (tokRegexpAllowed) {++tokPos; <span class="hljs-keyword">return</span> readRegexp();}
<span class="hljs-keyword">if</span> (next === <span class="hljs-number">61</span>) <span class="hljs-keyword">return</span> finishOp(_assign, <span class="hljs-number">2</span>);
<span class="hljs-keyword">return</span> finishOp(_slash, <span class="hljs-number">1</span>);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readToken_mult_modulo</span><span class="hljs-params">(code)</span> </span>{ <span class="hljs-comment">// '%*'</span>
<span class="hljs-keyword">var</span> next = input.charCodeAt(tokPos + <span class="hljs-number">1</span>);
<span class="hljs-keyword">if</span> (next === <span class="hljs-number">61</span>) <span class="hljs-keyword">return</span> finishOp(_assign, <span class="hljs-number">2</span>);
<span class="hljs-keyword">return</span> finishOp(code === <span class="hljs-number">42</span> ? _star : _modulo, <span class="hljs-number">1</span>);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readToken_pipe_amp</span><span class="hljs-params">(code)</span> </span>{ <span class="hljs-comment">// '|&amp;'</span>
<span class="hljs-keyword">var</span> next = input.charCodeAt(tokPos + <span class="hljs-number">1</span>);
<span class="hljs-keyword">if</span> (next === code) <span class="hljs-keyword">return</span> finishOp(code === <span class="hljs-number">124</span> ? _logicalOR : _logicalAND, <span class="hljs-number">2</span>);
<span class="hljs-keyword">if</span> (next === <span class="hljs-number">61</span>) <span class="hljs-keyword">return</span> finishOp(_assign, <span class="hljs-number">2</span>);
<span class="hljs-keyword">return</span> finishOp(code === <span class="hljs-number">124</span> ? _bitwiseOR : _bitwiseAND, <span class="hljs-number">1</span>);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readToken_caret</span><span class="hljs-params">()</span> </span>{ <span class="hljs-comment">// '^'</span>
<span class="hljs-keyword">var</span> next = input.charCodeAt(tokPos + <span class="hljs-number">1</span>);
<span class="hljs-keyword">if</span> (next === <span class="hljs-number">61</span>) <span class="hljs-keyword">return</span> finishOp(_assign, <span class="hljs-number">2</span>);
<span class="hljs-keyword">return</span> finishOp(_bitwiseXOR, <span class="hljs-number">1</span>);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readToken_plus_min</span><span class="hljs-params">(code)</span> </span>{ <span class="hljs-comment">// '+-'</span>
<span class="hljs-keyword">var</span> next = input.charCodeAt(tokPos + <span class="hljs-number">1</span>);
<span class="hljs-keyword">if</span> (next === code) {
<span class="hljs-keyword">if</span> (next == <span class="hljs-number">45</span> &amp;&amp; input.charCodeAt(tokPos + <span class="hljs-number">2</span>) == <span class="hljs-number">62</span> &amp;&amp;
newline.test(input.slice(lastEnd, tokPos))) {</pre></div></div>
</li>
<li id="section-67">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-67">&#182;</a>
</div>
<p>A <code>--&gt;</code> line comment</p>
</div>
<div class="content"><div class='highlight'><pre> skipLineComment(<span class="hljs-number">3</span>);
skipSpace();
<span class="hljs-keyword">return</span> readToken();
}
<span class="hljs-keyword">return</span> finishOp(_incDec, <span class="hljs-number">2</span>);
}
<span class="hljs-keyword">if</span> (next === <span class="hljs-number">61</span>) <span class="hljs-keyword">return</span> finishOp(_assign, <span class="hljs-number">2</span>);
<span class="hljs-keyword">return</span> finishOp(_plusMin, <span class="hljs-number">1</span>);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readToken_lt_gt</span><span class="hljs-params">(code)</span> </span>{ <span class="hljs-comment">// '&lt;&gt;'</span>
<span class="hljs-keyword">var</span> next = input.charCodeAt(tokPos + <span class="hljs-number">1</span>);
<span class="hljs-keyword">var</span> size = <span class="hljs-number">1</span>;
<span class="hljs-keyword">if</span> (next === code) {
size = code === <span class="hljs-number">62</span> &amp;&amp; input.charCodeAt(tokPos + <span class="hljs-number">2</span>) === <span class="hljs-number">62</span> ? <span class="hljs-number">3</span> : <span class="hljs-number">2</span>;
<span class="hljs-keyword">if</span> (input.charCodeAt(tokPos + size) === <span class="hljs-number">61</span>) <span class="hljs-keyword">return</span> finishOp(_assign, size + <span class="hljs-number">1</span>);
<span class="hljs-keyword">return</span> finishOp(_bitShift, size);
}
<span class="hljs-keyword">if</span> (next == <span class="hljs-number">33</span> &amp;&amp; code == <span class="hljs-number">60</span> &amp;&amp; input.charCodeAt(tokPos + <span class="hljs-number">2</span>) == <span class="hljs-number">45</span> &amp;&amp;
input.charCodeAt(tokPos + <span class="hljs-number">3</span>) == <span class="hljs-number">45</span>) {</pre></div></div>
</li>
<li id="section-68">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-68">&#182;</a>
</div>
<p><code>&lt;!--</code>, an XML-style comment that should be interpreted as a line comment</p>
</div>
<div class="content"><div class='highlight'><pre> skipLineComment(<span class="hljs-number">4</span>);
skipSpace();
<span class="hljs-keyword">return</span> readToken();
}
<span class="hljs-keyword">if</span> (next === <span class="hljs-number">61</span>) {
size = input.charCodeAt(tokPos + <span class="hljs-number">2</span>) === <span class="hljs-number">61</span> ? <span class="hljs-number">3</span> : <span class="hljs-number">2</span>;
<span class="hljs-keyword">return</span> finishOp(_relational, size);
}
<span class="hljs-keyword">if</span> (next === <span class="hljs-number">47</span>) {</pre></div></div>
</li>
<li id="section-69">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-69">&#182;</a>
</div>
<p>&lt;/, beginning of JSX closing element</p>
</div>
<div class="content"><div class='highlight'><pre> size = <span class="hljs-number">2</span>;
<span class="hljs-keyword">return</span> finishOp(_ltSlash, size);
}
<span class="hljs-keyword">return</span> finishOp(code === <span class="hljs-number">60</span> ? _lt : _gt, size);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readToken_eq_excl</span><span class="hljs-params">(code)</span> </span>{ <span class="hljs-comment">// '=!', '=&gt;'</span>
<span class="hljs-keyword">var</span> next = input.charCodeAt(tokPos + <span class="hljs-number">1</span>);
<span class="hljs-keyword">if</span> (next === <span class="hljs-number">61</span>) <span class="hljs-keyword">return</span> finishOp(_equality, input.charCodeAt(tokPos + <span class="hljs-number">2</span>) === <span class="hljs-number">61</span> ? <span class="hljs-number">3</span> : <span class="hljs-number">2</span>);
<span class="hljs-keyword">if</span> (code === <span class="hljs-number">61</span> &amp;&amp; next === <span class="hljs-number">62</span> &amp;&amp; options.ecmaVersion &gt;= <span class="hljs-number">6</span>) { <span class="hljs-comment">// '=&gt;'</span>
tokPos += <span class="hljs-number">2</span>;
<span class="hljs-keyword">return</span> finishToken(_arrow);
}
<span class="hljs-keyword">return</span> finishOp(code === <span class="hljs-number">61</span> ? _eq : _prefix, <span class="hljs-number">1</span>);
}</pre></div></div>
</li>
<li id="section-70">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-70">&#182;</a>
</div>
<p>Get token inside ES6 template (special rules work there).</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getTemplateToken</span><span class="hljs-params">(code)</span> </span>{</pre></div></div>
</li>
<li id="section-71">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-71">&#182;</a>
</div>
<p>` and ${ have special meanings, but they should follow
string (can be empty)</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (tokType === _string) {
<span class="hljs-keyword">if</span> (code === <span class="hljs-number">96</span>) { <span class="hljs-comment">// '`'</span>
++tokPos;
<span class="hljs-keyword">return</span> finishToken(_bquote);
} <span class="hljs-keyword">else</span>
<span class="hljs-keyword">if</span> (code === <span class="hljs-number">36</span> &amp;&amp; input.charCodeAt(tokPos + <span class="hljs-number">1</span>) === <span class="hljs-number">123</span>) { <span class="hljs-comment">// '${'</span>
tokPos += <span class="hljs-number">2</span>;
<span class="hljs-keyword">return</span> finishToken(_dollarBraceL);
}
}
<span class="hljs-keyword">if</span> (code === <span class="hljs-number">125</span>) { <span class="hljs-comment">// '}'</span>
++tokPos;
<span class="hljs-keyword">return</span> finishToken(_braceR, <span class="hljs-literal">undefined</span>, <span class="hljs-literal">false</span>);
}</pre></div></div>
</li>
<li id="section-72">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-72">&#182;</a>
</div>
<p>anything else is considered string literal</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> readTmplString();
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getTokenFromCode</span><span class="hljs-params">(code)</span> </span>{
<span class="hljs-keyword">switch</span>(code) {</pre></div></div>
</li>
<li id="section-73">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-73">&#182;</a>
</div>
<p>The interpretation of a dot depends on whether it is followed
by a digit or another two dots.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-number">46</span>: <span class="hljs-comment">// '.'</span>
<span class="hljs-keyword">return</span> readToken_dot();</pre></div></div>
</li>
<li id="section-74">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-74">&#182;</a>
</div>
<p>Punctuation tokens.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-number">40</span>: ++tokPos; <span class="hljs-keyword">return</span> finishToken(_parenL);
<span class="hljs-keyword">case</span> <span class="hljs-number">41</span>: ++tokPos; <span class="hljs-keyword">return</span> finishToken(_parenR);
<span class="hljs-keyword">case</span> <span class="hljs-number">59</span>: ++tokPos; <span class="hljs-keyword">return</span> finishToken(_semi);
<span class="hljs-keyword">case</span> <span class="hljs-number">44</span>: ++tokPos; <span class="hljs-keyword">return</span> finishToken(_comma);
<span class="hljs-keyword">case</span> <span class="hljs-number">91</span>: ++tokPos; <span class="hljs-keyword">return</span> finishToken(_bracketL);
<span class="hljs-keyword">case</span> <span class="hljs-number">93</span>: ++tokPos; <span class="hljs-keyword">return</span> finishToken(_bracketR);
<span class="hljs-keyword">case</span> <span class="hljs-number">123</span>: ++tokPos; <span class="hljs-keyword">return</span> finishToken(_braceL);
<span class="hljs-keyword">case</span> <span class="hljs-number">125</span>: ++tokPos; <span class="hljs-keyword">return</span> finishToken(_braceR);
<span class="hljs-keyword">case</span> <span class="hljs-number">58</span>: ++tokPos; <span class="hljs-keyword">return</span> finishToken(_colon);
<span class="hljs-keyword">case</span> <span class="hljs-number">63</span>: ++tokPos; <span class="hljs-keyword">return</span> finishToken(_question);
<span class="hljs-keyword">case</span> <span class="hljs-number">96</span>: <span class="hljs-comment">// '`'</span>
<span class="hljs-keyword">if</span> (options.ecmaVersion &gt;= <span class="hljs-number">6</span>) {
++tokPos;
<span class="hljs-keyword">return</span> finishToken(_bquote, <span class="hljs-literal">undefined</span>, <span class="hljs-literal">false</span>);
}
<span class="hljs-keyword">case</span> <span class="hljs-number">48</span>: <span class="hljs-comment">// '0'</span>
<span class="hljs-keyword">var</span> next = input.charCodeAt(tokPos + <span class="hljs-number">1</span>);
<span class="hljs-keyword">if</span> (next === <span class="hljs-number">120</span> || next === <span class="hljs-number">88</span>) <span class="hljs-keyword">return</span> readRadixNumber(<span class="hljs-number">16</span>); <span class="hljs-comment">// '0x', '0X' - hex number</span>
<span class="hljs-keyword">if</span> (options.ecmaVersion &gt;= <span class="hljs-number">6</span>) {
<span class="hljs-keyword">if</span> (next === <span class="hljs-number">111</span> || next === <span class="hljs-number">79</span>) <span class="hljs-keyword">return</span> readRadixNumber(<span class="hljs-number">8</span>); <span class="hljs-comment">// '0o', '0O' - octal number</span>
<span class="hljs-keyword">if</span> (next === <span class="hljs-number">98</span> || next === <span class="hljs-number">66</span>) <span class="hljs-keyword">return</span> readRadixNumber(<span class="hljs-number">2</span>); <span class="hljs-comment">// '0b', '0B' - binary number</span>
}</pre></div></div>
</li>
<li id="section-75">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-75">&#182;</a>
</div>
<p>Anything else beginning with a digit is an integer, octal
number, or float.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-number">49</span>: <span class="hljs-keyword">case</span> <span class="hljs-number">50</span>: <span class="hljs-keyword">case</span> <span class="hljs-number">51</span>: <span class="hljs-keyword">case</span> <span class="hljs-number">52</span>: <span class="hljs-keyword">case</span> <span class="hljs-number">53</span>: <span class="hljs-keyword">case</span> <span class="hljs-number">54</span>: <span class="hljs-keyword">case</span> <span class="hljs-number">55</span>: <span class="hljs-keyword">case</span> <span class="hljs-number">56</span>: <span class="hljs-keyword">case</span> <span class="hljs-number">57</span>: <span class="hljs-comment">// 1-9</span>
<span class="hljs-keyword">return</span> readNumber(<span class="hljs-literal">false</span>);</pre></div></div>
</li>
<li id="section-76">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-76">&#182;</a>
</div>
<p>Quotes produce strings.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-number">34</span>: <span class="hljs-keyword">case</span> <span class="hljs-number">39</span>: <span class="hljs-comment">// '"', "'"</span>
<span class="hljs-keyword">return</span> inXJSTag ? readXJSStringLiteral() : readString(code);</pre></div></div>
</li>
<li id="section-77">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-77">&#182;</a>
</div>
<p>Operators are parsed inline in tiny state machines. = (61) is
often referred to. <code>finishOp</code> simply skips the amount of
characters it is given as second argument, and returns a token
of the type given by its first argument.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">case</span> <span class="hljs-number">47</span>: <span class="hljs-comment">// '/'</span>
<span class="hljs-keyword">return</span> readToken_slash();
<span class="hljs-keyword">case</span> <span class="hljs-number">37</span>: <span class="hljs-keyword">case</span> <span class="hljs-number">42</span>: <span class="hljs-comment">// '%*'</span>
<span class="hljs-keyword">return</span> readToken_mult_modulo(code);
<span class="hljs-keyword">case</span> <span class="hljs-number">124</span>: <span class="hljs-keyword">case</span> <span class="hljs-number">38</span>: <span class="hljs-comment">// '|&amp;'</span>
<span class="hljs-keyword">return</span> readToken_pipe_amp(code);
<span class="hljs-keyword">case</span> <span class="hljs-number">94</span>: <span class="hljs-comment">// '^'</span>
<span class="hljs-keyword">return</span> readToken_caret();
<span class="hljs-keyword">case</span> <span class="hljs-number">43</span>: <span class="hljs-keyword">case</span> <span class="hljs-number">45</span>: <span class="hljs-comment">// '+-'</span>
<span class="hljs-keyword">return</span> readToken_plus_min(code);
<span class="hljs-keyword">case</span> <span class="hljs-number">60</span>: <span class="hljs-keyword">case</span> <span class="hljs-number">62</span>: <span class="hljs-comment">// '&lt;&gt;'</span>
<span class="hljs-keyword">return</span> readToken_lt_gt(code);
<span class="hljs-keyword">case</span> <span class="hljs-number">61</span>: <span class="hljs-keyword">case</span> <span class="hljs-number">33</span>: <span class="hljs-comment">// '=!'</span>
<span class="hljs-keyword">return</span> readToken_eq_excl(code);
<span class="hljs-keyword">case</span> <span class="hljs-number">126</span>: <span class="hljs-comment">// '~'</span>
<span class="hljs-keyword">return</span> finishOp(_prefix, <span class="hljs-number">1</span>);
}
<span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readToken</span><span class="hljs-params">(forceRegexp)</span> </span>{
<span class="hljs-keyword">if</span> (!forceRegexp) tokStart = tokPos;
<span class="hljs-keyword">else</span> tokPos = tokStart + <span class="hljs-number">1</span>;
<span class="hljs-keyword">if</span> (options.locations) tokStartLoc = <span class="hljs-keyword">new</span> Position;
<span class="hljs-keyword">if</span> (forceRegexp) <span class="hljs-keyword">return</span> readRegexp();
<span class="hljs-keyword">if</span> (tokPos &gt;= inputLen) <span class="hljs-keyword">return</span> finishToken(_eof);
<span class="hljs-keyword">var</span> code = input.charCodeAt(tokPos);</pre></div></div>
</li>
<li id="section-78">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-78">&#182;</a>
</div>
<p>JSX content - either simple text, start of <tag> or {expression}</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (inXJSChild &amp;&amp; tokType !== _braceL &amp;&amp; code !== <span class="hljs-number">60</span> &amp;&amp; code !== <span class="hljs-number">123</span> &amp;&amp; code !== <span class="hljs-number">125</span>) {
<span class="hljs-keyword">return</span> readXJSText([<span class="hljs-string">'&lt;'</span>, <span class="hljs-string">'{'</span>]);
}
<span class="hljs-keyword">if</span> (inTemplate) <span class="hljs-keyword">return</span> getTemplateToken(code);</pre></div></div>
</li>
<li id="section-79">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-79">&#182;</a>
</div>
<p>Identifier or keyword. \uXXXX sequences are allowed in
identifiers, so \ also dispatches to that.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (isIdentifierStart(code) || code === <span class="hljs-number">92</span> <span class="hljs-comment">/* '\' */</span>) <span class="hljs-keyword">return</span> readWord();
<span class="hljs-keyword">var</span> tok = getTokenFromCode(code);
<span class="hljs-keyword">if</span> (tok === <span class="hljs-literal">false</span>) {</pre></div></div>
</li>
<li id="section-80">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-80">&#182;</a>
</div>
<p>If we are here, we either found a non-ASCII identifier
character, or something thats entirely disallowed.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> ch = <span class="hljs-built_in">String</span>.fromCharCode(code);
<span class="hljs-keyword">if</span> (ch === <span class="hljs-string">"\\"</span> || nonASCIIidentifierStart.test(ch)) <span class="hljs-keyword">return</span> readWord();
raise(tokPos, <span class="hljs-string">"Unexpected character '"</span> + ch + <span class="hljs-string">"'"</span>);
}
<span class="hljs-keyword">return</span> tok;
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">finishOp</span><span class="hljs-params">(type, size)</span> </span>{
<span class="hljs-keyword">var</span> str = input.slice(tokPos, tokPos + size);
tokPos += size;
finishToken(type, str);
}</pre></div></div>
</li>
<li id="section-81">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-81">&#182;</a>
</div>
<p>Parse a regular expression. Some context-awareness is necessary,
since a / inside a [] set does not end the expression.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readRegexp</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> content = <span class="hljs-string">""</span>, escaped, inClass, start = tokPos;
<span class="hljs-keyword">for</span> (;;) {
<span class="hljs-keyword">if</span> (tokPos &gt;= inputLen) raise(start, <span class="hljs-string">"Unterminated regular expression"</span>);
<span class="hljs-keyword">var</span> ch = nextChar();
<span class="hljs-keyword">if</span> (newline.test(ch)) raise(start, <span class="hljs-string">"Unterminated regular expression"</span>);
<span class="hljs-keyword">if</span> (!escaped) {
<span class="hljs-keyword">if</span> (ch === <span class="hljs-string">"["</span>) inClass = <span class="hljs-literal">true</span>;
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (ch === <span class="hljs-string">"]"</span> &amp;&amp; inClass) inClass = <span class="hljs-literal">false</span>;
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (ch === <span class="hljs-string">"/"</span> &amp;&amp; !inClass) <span class="hljs-keyword">break</span>;
escaped = ch === <span class="hljs-string">"\\"</span>;
} <span class="hljs-keyword">else</span> escaped = <span class="hljs-literal">false</span>;
++tokPos;
}
<span class="hljs-keyword">var</span> content = input.slice(start, tokPos);
++tokPos;</pre></div></div>
</li>
<li id="section-82">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-82">&#182;</a>
</div>
<p>Need to use <code>readWord1</code> because \uXXXX sequences are allowed
here (dont ask).</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> mods = readWord1();
<span class="hljs-keyword">if</span> (mods &amp;&amp; !<span class="hljs-regexp">/^[gmsiy]*$/</span>.test(mods)) raise(start, <span class="hljs-string">"Invalid regular expression flag"</span>);
<span class="hljs-keyword">try</span> {
<span class="hljs-keyword">var</span> value = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(content, mods);
} <span class="hljs-keyword">catch</span> (e) {
<span class="hljs-keyword">if</span> (e <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">SyntaxError</span>) raise(start, <span class="hljs-string">"Error parsing regular expression: "</span> + e.message);
raise(e);
}
<span class="hljs-keyword">return</span> finishToken(_regexp, value);
}</pre></div></div>
</li>
<li id="section-83">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-83">&#182;</a>
</div>
<p>Read an integer in the given radix. Return null if zero digits
were read, the integer value otherwise. When <code>len</code> is given, this
will return <code>null</code> unless the integer has exactly <code>len</code> digits.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readInt</span><span class="hljs-params">(radix, len)</span> </span>{
<span class="hljs-keyword">var</span> start = tokPos, total = <span class="hljs-number">0</span>;
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>, e = len == <span class="hljs-literal">null</span> ? <span class="hljs-literal">Infinity</span> : len; i &lt; e; ++i) {
<span class="hljs-keyword">var</span> code = input.charCodeAt(tokPos), val;
<span class="hljs-keyword">if</span> (code &gt;= <span class="hljs-number">97</span>) val = code - <span class="hljs-number">97</span> + <span class="hljs-number">10</span>; <span class="hljs-comment">// a</span>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (code &gt;= <span class="hljs-number">65</span>) val = code - <span class="hljs-number">65</span> + <span class="hljs-number">10</span>; <span class="hljs-comment">// A</span>
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (code &gt;= <span class="hljs-number">48</span> &amp;&amp; code &lt;= <span class="hljs-number">57</span>) val = code - <span class="hljs-number">48</span>; <span class="hljs-comment">// 0-9</span>
<span class="hljs-keyword">else</span> val = <span class="hljs-literal">Infinity</span>;
<span class="hljs-keyword">if</span> (val &gt;= radix) <span class="hljs-keyword">break</span>;
++tokPos;
total = total * radix + val;
}
<span class="hljs-keyword">if</span> (tokPos === start || len != <span class="hljs-literal">null</span> &amp;&amp; tokPos - start !== len) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
<span class="hljs-keyword">return</span> total;
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readRadixNumber</span><span class="hljs-params">(radix)</span> </span>{
tokPos += <span class="hljs-number">2</span>; <span class="hljs-comment">// 0x</span>
<span class="hljs-keyword">var</span> val = readInt(radix);
<span class="hljs-keyword">if</span> (val == <span class="hljs-literal">null</span>) raise(tokStart + <span class="hljs-number">2</span>, <span class="hljs-string">"Expected number in radix "</span> + radix);
<span class="hljs-keyword">if</span> (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, <span class="hljs-string">"Identifier directly after number"</span>);
<span class="hljs-keyword">return</span> finishToken(_num, val);
}</pre></div></div>
</li>
<li id="section-84">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-84">&#182;</a>
</div>
<p>Read an integer, octal integer, or floating-point number.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readNumber</span><span class="hljs-params">(startsWithDot)</span> </span>{
<span class="hljs-keyword">var</span> start = tokPos, isFloat = <span class="hljs-literal">false</span>, octal = input.charCodeAt(tokPos) === <span class="hljs-number">48</span>;
<span class="hljs-keyword">if</span> (!startsWithDot &amp;&amp; readInt(<span class="hljs-number">10</span>) === <span class="hljs-literal">null</span>) raise(start, <span class="hljs-string">"Invalid number"</span>);
<span class="hljs-keyword">if</span> (input.charCodeAt(tokPos) === <span class="hljs-number">46</span>) {
++tokPos;
readInt(<span class="hljs-number">10</span>);
isFloat = <span class="hljs-literal">true</span>;
}
<span class="hljs-keyword">var</span> next = input.charCodeAt(tokPos);
<span class="hljs-keyword">if</span> (next === <span class="hljs-number">69</span> || next === <span class="hljs-number">101</span>) { <span class="hljs-comment">// 'eE'</span>
next = input.charCodeAt(++tokPos);
<span class="hljs-keyword">if</span> (next === <span class="hljs-number">43</span> || next === <span class="hljs-number">45</span>) ++tokPos; <span class="hljs-comment">// '+-'</span>
<span class="hljs-keyword">if</span> (readInt(<span class="hljs-number">10</span>) === <span class="hljs-literal">null</span>) raise(start, <span class="hljs-string">"Invalid number"</span>);
isFloat = <span class="hljs-literal">true</span>;
}
<span class="hljs-keyword">if</span> (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, <span class="hljs-string">"Identifier directly after number"</span>);
<span class="hljs-keyword">var</span> str = input.slice(start, tokPos), val;
<span class="hljs-keyword">if</span> (isFloat) val = <span class="hljs-built_in">parseFloat</span>(str);
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (!octal || str.length === <span class="hljs-number">1</span>) val = <span class="hljs-built_in">parseInt</span>(str, <span class="hljs-number">10</span>);
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-regexp">/[89]/</span>.test(str) || strict) raise(start, <span class="hljs-string">"Invalid number"</span>);
<span class="hljs-keyword">else</span> val = <span class="hljs-built_in">parseInt</span>(str, <span class="hljs-number">8</span>);
<span class="hljs-keyword">return</span> finishToken(_num, val);
}</pre></div></div>
</li>
<li id="section-85">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-85">&#182;</a>
</div>
<p>Read a string value, interpreting backslash-escapes.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readCodePoint</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> ch = input.charCodeAt(tokPos), code;
<span class="hljs-keyword">if</span> (ch === <span class="hljs-number">123</span>) {
<span class="hljs-keyword">if</span> (options.ecmaVersion &lt; <span class="hljs-number">6</span>) unexpected();
++tokPos;
code = readHexChar(input.indexOf(<span class="hljs-string">'}'</span>, tokPos) - tokPos);
++tokPos;
<span class="hljs-keyword">if</span> (code &gt; <span class="hljs-number">0x10FFFF</span>) unexpected();
} <span class="hljs-keyword">else</span> {
code = readHexChar(<span class="hljs-number">4</span>);
}</pre></div></div>
</li>
<li id="section-86">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-86">&#182;</a>
</div>
<p>UTF-16 Encoding</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (code &lt;= <span class="hljs-number">0xFFFF</span>) {
<span class="hljs-keyword">return</span> <span class="hljs-built_in">String</span>.fromCharCode(code);
}
<span class="hljs-keyword">var</span> cu1 = ((code - <span class="hljs-number">0x10000</span>) &gt;&gt; <span class="hljs-number">10</span>) + <span class="hljs-number">0xD800</span>;
<span class="hljs-keyword">var</span> cu2 = ((code - <span class="hljs-number">0x10000</span>) &amp; <span class="hljs-number">1023</span>) + <span class="hljs-number">0xDC00</span>;
<span class="hljs-keyword">return</span> <span class="hljs-built_in">String</span>.fromCharCode(cu1, cu2);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readString</span><span class="hljs-params">(quote)</span> </span>{
++tokPos;
<span class="hljs-keyword">var</span> out = <span class="hljs-string">""</span>;
<span class="hljs-keyword">for</span> (;;) {
<span class="hljs-keyword">if</span> (tokPos &gt;= inputLen) raise(tokStart, <span class="hljs-string">"Unterminated string constant"</span>);
<span class="hljs-keyword">var</span> ch = input.charCodeAt(tokPos);
<span class="hljs-keyword">if</span> (ch === quote) {
++tokPos;
<span class="hljs-keyword">return</span> finishToken(_string, out);
}
<span class="hljs-keyword">if</span> (ch === <span class="hljs-number">92</span>) { <span class="hljs-comment">// '\'</span>
out += readEscapedChar();
} <span class="hljs-keyword">else</span> {
++tokPos;
<span class="hljs-keyword">if</span> (newline.test(<span class="hljs-built_in">String</span>.fromCharCode(ch))) {
raise(tokStart, <span class="hljs-string">"Unterminated string constant"</span>);
}
out += <span class="hljs-built_in">String</span>.fromCharCode(ch); <span class="hljs-comment">// '\'</span>
}
}
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readTmplString</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> out = <span class="hljs-string">""</span>;
<span class="hljs-keyword">for</span> (;;) {
<span class="hljs-keyword">if</span> (tokPos &gt;= inputLen) raise(tokStart, <span class="hljs-string">"Unterminated string constant"</span>);
<span class="hljs-keyword">var</span> ch = input.charCodeAt(tokPos);
<span class="hljs-keyword">if</span> (ch === <span class="hljs-number">96</span> || ch === <span class="hljs-number">36</span> &amp;&amp; input.charCodeAt(tokPos + <span class="hljs-number">1</span>) === <span class="hljs-number">123</span>) <span class="hljs-comment">// '`', '${'</span>
<span class="hljs-keyword">return</span> finishToken(_string, out);
<span class="hljs-keyword">if</span> (ch === <span class="hljs-number">92</span>) { <span class="hljs-comment">// '\'</span>
out += readEscapedChar();
} <span class="hljs-keyword">else</span> {
++tokPos;
<span class="hljs-keyword">if</span> (newline.test(<span class="hljs-built_in">String</span>.fromCharCode(ch))) {
<span class="hljs-keyword">if</span> (ch === <span class="hljs-number">13</span> &amp;&amp; input.charCodeAt(tokPos) === <span class="hljs-number">10</span>) {
++tokPos;
ch = <span class="hljs-number">10</span>;
}
<span class="hljs-keyword">if</span> (options.locations) {
++tokCurLine;
tokLineStart = tokPos;
}
}
out += <span class="hljs-built_in">String</span>.fromCharCode(ch); <span class="hljs-comment">// '\'</span>
}
}
}</pre></div></div>
</li>
<li id="section-87">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-87">&#182;</a>
</div>
<p>Used to read escaped characters</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readEscapedChar</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> ch = input.charCodeAt(++tokPos);
<span class="hljs-keyword">var</span> octal = <span class="hljs-regexp">/^[0-7]+/</span>.exec(input.slice(tokPos, tokPos + <span class="hljs-number">3</span>));
<span class="hljs-keyword">if</span> (octal) octal = octal[<span class="hljs-number">0</span>];
<span class="hljs-keyword">while</span> (octal &amp;&amp; <span class="hljs-built_in">parseInt</span>(octal, <span class="hljs-number">8</span>) &gt; <span class="hljs-number">255</span>) octal = octal.slice(<span class="hljs-number">0</span>, -<span class="hljs-number">1</span>);
<span class="hljs-keyword">if</span> (octal === <span class="hljs-string">"0"</span>) octal = <span class="hljs-literal">null</span>;
++tokPos;
<span class="hljs-keyword">if</span> (octal) {
<span class="hljs-keyword">if</span> (strict) raise(tokPos - <span class="hljs-number">2</span>, <span class="hljs-string">"Octal literal in strict mode"</span>);
tokPos += octal.length - <span class="hljs-number">1</span>;
<span class="hljs-keyword">return</span> <span class="hljs-built_in">String</span>.fromCharCode(<span class="hljs-built_in">parseInt</span>(octal, <span class="hljs-number">8</span>));
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">switch</span> (ch) {
<span class="hljs-keyword">case</span> <span class="hljs-number">110</span>: <span class="hljs-keyword">return</span> <span class="hljs-string">"\n"</span>; <span class="hljs-comment">// 'n' -&gt; '\n'</span>
<span class="hljs-keyword">case</span> <span class="hljs-number">114</span>: <span class="hljs-keyword">return</span> <span class="hljs-string">"\r"</span>; <span class="hljs-comment">// 'r' -&gt; '\r'</span>
<span class="hljs-keyword">case</span> <span class="hljs-number">120</span>: <span class="hljs-keyword">return</span> <span class="hljs-built_in">String</span>.fromCharCode(readHexChar(<span class="hljs-number">2</span>)); <span class="hljs-comment">// 'x'</span>
<span class="hljs-keyword">case</span> <span class="hljs-number">117</span>: <span class="hljs-keyword">return</span> readCodePoint(); <span class="hljs-comment">// 'u'</span>
<span class="hljs-keyword">case</span> <span class="hljs-number">85</span>: <span class="hljs-keyword">return</span> <span class="hljs-built_in">String</span>.fromCharCode(readHexChar(<span class="hljs-number">8</span>)); <span class="hljs-comment">// 'U'</span>
<span class="hljs-keyword">case</span> <span class="hljs-number">116</span>: <span class="hljs-keyword">return</span> <span class="hljs-string">"\t"</span>; <span class="hljs-comment">// 't' -&gt; '\t'</span>
<span class="hljs-keyword">case</span> <span class="hljs-number">98</span>: <span class="hljs-keyword">return</span> <span class="hljs-string">"\b"</span>; <span class="hljs-comment">// 'b' -&gt; '\b'</span>
<span class="hljs-keyword">case</span> <span class="hljs-number">118</span>: <span class="hljs-keyword">return</span> <span class="hljs-string">"\u000b"</span>; <span class="hljs-comment">// 'v' -&gt; '\u000b'</span>
<span class="hljs-keyword">case</span> <span class="hljs-number">102</span>: <span class="hljs-keyword">return</span> <span class="hljs-string">"\f"</span>; <span class="hljs-comment">// 'f' -&gt; '\f'</span>
<span class="hljs-keyword">case</span> <span class="hljs-number">48</span>: <span class="hljs-keyword">return</span> <span class="hljs-string">"\0"</span>; <span class="hljs-comment">// 0 -&gt; '\0'</span>
<span class="hljs-keyword">case</span> <span class="hljs-number">13</span>: <span class="hljs-keyword">if</span> (input.charCodeAt(tokPos) === <span class="hljs-number">10</span>) ++tokPos; <span class="hljs-comment">// '\r\n'</span>
<span class="hljs-keyword">case</span> <span class="hljs-number">10</span>: <span class="hljs-comment">// ' \n'</span>
<span class="hljs-keyword">if</span> (options.locations) { tokLineStart = tokPos; ++tokCurLine; }
<span class="hljs-keyword">return</span> <span class="hljs-string">""</span>;
<span class="hljs-keyword">default</span>: <span class="hljs-keyword">return</span> <span class="hljs-built_in">String</span>.fromCharCode(ch);
}
}
}
<span class="hljs-keyword">var</span> XHTMLEntities = {
quot: <span class="hljs-string">'\u0022'</span>,
amp: <span class="hljs-string">'&amp;'</span>,
apos: <span class="hljs-string">'\u0027'</span>,
lt: <span class="hljs-string">'&lt;'</span>,
gt: <span class="hljs-string">'&gt;'</span>,
nbsp: <span class="hljs-string">'\u00A0'</span>,
iexcl: <span class="hljs-string">'\u00A1'</span>,
cent: <span class="hljs-string">'\u00A2'</span>,
pound: <span class="hljs-string">'\u00A3'</span>,
curren: <span class="hljs-string">'\u00A4'</span>,
yen: <span class="hljs-string">'\u00A5'</span>,
brvbar: <span class="hljs-string">'\u00A6'</span>,
sect: <span class="hljs-string">'\u00A7'</span>,
uml: <span class="hljs-string">'\u00A8'</span>,
copy: <span class="hljs-string">'\u00A9'</span>,
ordf: <span class="hljs-string">'\u00AA'</span>,
laquo: <span class="hljs-string">'\u00AB'</span>,
not: <span class="hljs-string">'\u00AC'</span>,
shy: <span class="hljs-string">'\u00AD'</span>,
reg: <span class="hljs-string">'\u00AE'</span>,
macr: <span class="hljs-string">'\u00AF'</span>,
deg: <span class="hljs-string">'\u00B0'</span>,
plusmn: <span class="hljs-string">'\u00B1'</span>,
sup2: <span class="hljs-string">'\u00B2'</span>,
sup3: <span class="hljs-string">'\u00B3'</span>,
acute: <span class="hljs-string">'\u00B4'</span>,
micro: <span class="hljs-string">'\u00B5'</span>,
para: <span class="hljs-string">'\u00B6'</span>,
middot: <span class="hljs-string">'\u00B7'</span>,
cedil: <span class="hljs-string">'\u00B8'</span>,
sup1: <span class="hljs-string">'\u00B9'</span>,
ordm: <span class="hljs-string">'\u00BA'</span>,
raquo: <span class="hljs-string">'\u00BB'</span>,
frac14: <span class="hljs-string">'\u00BC'</span>,
frac12: <span class="hljs-string">'\u00BD'</span>,
frac34: <span class="hljs-string">'\u00BE'</span>,
iquest: <span class="hljs-string">'\u00BF'</span>,
Agrave: <span class="hljs-string">'\u00C0'</span>,
Aacute: <span class="hljs-string">'\u00C1'</span>,
Acirc: <span class="hljs-string">'\u00C2'</span>,
Atilde: <span class="hljs-string">'\u00C3'</span>,
Auml: <span class="hljs-string">'\u00C4'</span>,
Aring: <span class="hljs-string">'\u00C5'</span>,
AElig: <span class="hljs-string">'\u00C6'</span>,
Ccedil: <span class="hljs-string">'\u00C7'</span>,
Egrave: <span class="hljs-string">'\u00C8'</span>,
Eacute: <span class="hljs-string">'\u00C9'</span>,
Ecirc: <span class="hljs-string">'\u00CA'</span>,
Euml: <span class="hljs-string">'\u00CB'</span>,
Igrave: <span class="hljs-string">'\u00CC'</span>,
Iacute: <span class="hljs-string">'\u00CD'</span>,
Icirc: <span class="hljs-string">'\u00CE'</span>,
Iuml: <span class="hljs-string">'\u00CF'</span>,
ETH: <span class="hljs-string">'\u00D0'</span>,
Ntilde: <span class="hljs-string">'\u00D1'</span>,
Ograve: <span class="hljs-string">'\u00D2'</span>,
Oacute: <span class="hljs-string">'\u00D3'</span>,
Ocirc: <span class="hljs-string">'\u00D4'</span>,
Otilde: <span class="hljs-string">'\u00D5'</span>,
Ouml: <span class="hljs-string">'\u00D6'</span>,
times: <span class="hljs-string">'\u00D7'</span>,
Oslash: <span class="hljs-string">'\u00D8'</span>,
Ugrave: <span class="hljs-string">'\u00D9'</span>,
Uacute: <span class="hljs-string">'\u00DA'</span>,
Ucirc: <span class="hljs-string">'\u00DB'</span>,
Uuml: <span class="hljs-string">'\u00DC'</span>,
Yacute: <span class="hljs-string">'\u00DD'</span>,
THORN: <span class="hljs-string">'\u00DE'</span>,
szlig: <span class="hljs-string">'\u00DF'</span>,
agrave: <span class="hljs-string">'\u00E0'</span>,
aacute: <span class="hljs-string">'\u00E1'</span>,
acirc: <span class="hljs-string">'\u00E2'</span>,
atilde: <span class="hljs-string">'\u00E3'</span>,
auml: <span class="hljs-string">'\u00E4'</span>,
aring: <span class="hljs-string">'\u00E5'</span>,
aelig: <span class="hljs-string">'\u00E6'</span>,
ccedil: <span class="hljs-string">'\u00E7'</span>,
egrave: <span class="hljs-string">'\u00E8'</span>,
eacute: <span class="hljs-string">'\u00E9'</span>,
ecirc: <span class="hljs-string">'\u00EA'</span>,
euml: <span class="hljs-string">'\u00EB'</span>,
igrave: <span class="hljs-string">'\u00EC'</span>,
iacute: <span class="hljs-string">'\u00ED'</span>,
icirc: <span class="hljs-string">'\u00EE'</span>,
iuml: <span class="hljs-string">'\u00EF'</span>,
eth: <span class="hljs-string">'\u00F0'</span>,
ntilde: <span class="hljs-string">'\u00F1'</span>,
ograve: <span class="hljs-string">'\u00F2'</span>,
oacute: <span class="hljs-string">'\u00F3'</span>,
ocirc: <span class="hljs-string">'\u00F4'</span>,
otilde: <span class="hljs-string">'\u00F5'</span>,
ouml: <span class="hljs-string">'\u00F6'</span>,
divide: <span class="hljs-string">'\u00F7'</span>,
oslash: <span class="hljs-string">'\u00F8'</span>,
ugrave: <span class="hljs-string">'\u00F9'</span>,
uacute: <span class="hljs-string">'\u00FA'</span>,
ucirc: <span class="hljs-string">'\u00FB'</span>,
uuml: <span class="hljs-string">'\u00FC'</span>,
yacute: <span class="hljs-string">'\u00FD'</span>,
thorn: <span class="hljs-string">'\u00FE'</span>,
yuml: <span class="hljs-string">'\u00FF'</span>,
OElig: <span class="hljs-string">'\u0152'</span>,
oelig: <span class="hljs-string">'\u0153'</span>,
Scaron: <span class="hljs-string">'\u0160'</span>,
scaron: <span class="hljs-string">'\u0161'</span>,
Yuml: <span class="hljs-string">'\u0178'</span>,
fnof: <span class="hljs-string">'\u0192'</span>,
circ: <span class="hljs-string">'\u02C6'</span>,
tilde: <span class="hljs-string">'\u02DC'</span>,
Alpha: <span class="hljs-string">'\u0391'</span>,
Beta: <span class="hljs-string">'\u0392'</span>,
Gamma: <span class="hljs-string">'\u0393'</span>,
Delta: <span class="hljs-string">'\u0394'</span>,
Epsilon: <span class="hljs-string">'\u0395'</span>,
Zeta: <span class="hljs-string">'\u0396'</span>,
Eta: <span class="hljs-string">'\u0397'</span>,
Theta: <span class="hljs-string">'\u0398'</span>,
Iota: <span class="hljs-string">'\u0399'</span>,
Kappa: <span class="hljs-string">'\u039A'</span>,
Lambda: <span class="hljs-string">'\u039B'</span>,
Mu: <span class="hljs-string">'\u039C'</span>,
Nu: <span class="hljs-string">'\u039D'</span>,
Xi: <span class="hljs-string">'\u039E'</span>,
Omicron: <span class="hljs-string">'\u039F'</span>,
Pi: <span class="hljs-string">'\u03A0'</span>,
Rho: <span class="hljs-string">'\u03A1'</span>,
Sigma: <span class="hljs-string">'\u03A3'</span>,
Tau: <span class="hljs-string">'\u03A4'</span>,
Upsilon: <span class="hljs-string">'\u03A5'</span>,
Phi: <span class="hljs-string">'\u03A6'</span>,
Chi: <span class="hljs-string">'\u03A7'</span>,
Psi: <span class="hljs-string">'\u03A8'</span>,
Omega: <span class="hljs-string">'\u03A9'</span>,
alpha: <span class="hljs-string">'\u03B1'</span>,
beta: <span class="hljs-string">'\u03B2'</span>,
gamma: <span class="hljs-string">'\u03B3'</span>,
delta: <span class="hljs-string">'\u03B4'</span>,
epsilon: <span class="hljs-string">'\u03B5'</span>,
zeta: <span class="hljs-string">'\u03B6'</span>,
eta: <span class="hljs-string">'\u03B7'</span>,
theta: <span class="hljs-string">'\u03B8'</span>,
iota: <span class="hljs-string">'\u03B9'</span>,
kappa: <span class="hljs-string">'\u03BA'</span>,
lambda: <span class="hljs-string">'\u03BB'</span>,
mu: <span class="hljs-string">'\u03BC'</span>,
nu: <span class="hljs-string">'\u03BD'</span>,
xi: <span class="hljs-string">'\u03BE'</span>,
omicron: <span class="hljs-string">'\u03BF'</span>,
pi: <span class="hljs-string">'\u03C0'</span>,
rho: <span class="hljs-string">'\u03C1'</span>,
sigmaf: <span class="hljs-string">'\u03C2'</span>,
sigma: <span class="hljs-string">'\u03C3'</span>,
tau: <span class="hljs-string">'\u03C4'</span>,
upsilon: <span class="hljs-string">'\u03C5'</span>,
phi: <span class="hljs-string">'\u03C6'</span>,
chi: <span class="hljs-string">'\u03C7'</span>,
psi: <span class="hljs-string">'\u03C8'</span>,
omega: <span class="hljs-string">'\u03C9'</span>,
thetasym: <span class="hljs-string">'\u03D1'</span>,
upsih: <span class="hljs-string">'\u03D2'</span>,
piv: <span class="hljs-string">'\u03D6'</span>,
ensp: <span class="hljs-string">'\u2002'</span>,
emsp: <span class="hljs-string">'\u2003'</span>,
thinsp: <span class="hljs-string">'\u2009'</span>,
zwnj: <span class="hljs-string">'\u200C'</span>,
zwj: <span class="hljs-string">'\u200D'</span>,
lrm: <span class="hljs-string">'\u200E'</span>,
rlm: <span class="hljs-string">'\u200F'</span>,
ndash: <span class="hljs-string">'\u2013'</span>,
mdash: <span class="hljs-string">'\u2014'</span>,
lsquo: <span class="hljs-string">'\u2018'</span>,
rsquo: <span class="hljs-string">'\u2019'</span>,
sbquo: <span class="hljs-string">'\u201A'</span>,
ldquo: <span class="hljs-string">'\u201C'</span>,
rdquo: <span class="hljs-string">'\u201D'</span>,
bdquo: <span class="hljs-string">'\u201E'</span>,
dagger: <span class="hljs-string">'\u2020'</span>,
Dagger: <span class="hljs-string">'\u2021'</span>,
bull: <span class="hljs-string">'\u2022'</span>,
hellip: <span class="hljs-string">'\u2026'</span>,
permil: <span class="hljs-string">'\u2030'</span>,
prime: <span class="hljs-string">'\u2032'</span>,
Prime: <span class="hljs-string">'\u2033'</span>,
lsaquo: <span class="hljs-string">'\u2039'</span>,
rsaquo: <span class="hljs-string">'\u203A'</span>,
oline: <span class="hljs-string">'\u203E'</span>,
frasl: <span class="hljs-string">'\u2044'</span>,
euro: <span class="hljs-string">'\u20AC'</span>,
image: <span class="hljs-string">'\u2111'</span>,
weierp: <span class="hljs-string">'\u2118'</span>,
real: <span class="hljs-string">'\u211C'</span>,
trade: <span class="hljs-string">'\u2122'</span>,
alefsym: <span class="hljs-string">'\u2135'</span>,
larr: <span class="hljs-string">'\u2190'</span>,
uarr: <span class="hljs-string">'\u2191'</span>,
rarr: <span class="hljs-string">'\u2192'</span>,
darr: <span class="hljs-string">'\u2193'</span>,
harr: <span class="hljs-string">'\u2194'</span>,
crarr: <span class="hljs-string">'\u21B5'</span>,
lArr: <span class="hljs-string">'\u21D0'</span>,
uArr: <span class="hljs-string">'\u21D1'</span>,
rArr: <span class="hljs-string">'\u21D2'</span>,
dArr: <span class="hljs-string">'\u21D3'</span>,
hArr: <span class="hljs-string">'\u21D4'</span>,
forall: <span class="hljs-string">'\u2200'</span>,
part: <span class="hljs-string">'\u2202'</span>,
exist: <span class="hljs-string">'\u2203'</span>,
empty: <span class="hljs-string">'\u2205'</span>,
nabla: <span class="hljs-string">'\u2207'</span>,
isin: <span class="hljs-string">'\u2208'</span>,
notin: <span class="hljs-string">'\u2209'</span>,
ni: <span class="hljs-string">'\u220B'</span>,
prod: <span class="hljs-string">'\u220F'</span>,
sum: <span class="hljs-string">'\u2211'</span>,
minus: <span class="hljs-string">'\u2212'</span>,
lowast: <span class="hljs-string">'\u2217'</span>,
radic: <span class="hljs-string">'\u221A'</span>,
prop: <span class="hljs-string">'\u221D'</span>,
infin: <span class="hljs-string">'\u221E'</span>,
ang: <span class="hljs-string">'\u2220'</span>,
and: <span class="hljs-string">'\u2227'</span>,
or: <span class="hljs-string">'\u2228'</span>,
cap: <span class="hljs-string">'\u2229'</span>,
cup: <span class="hljs-string">'\u222A'</span>,
<span class="hljs-string">'int'</span>: <span class="hljs-string">'\u222B'</span>,
there4: <span class="hljs-string">'\u2234'</span>,
sim: <span class="hljs-string">'\u223C'</span>,
cong: <span class="hljs-string">'\u2245'</span>,
asymp: <span class="hljs-string">'\u2248'</span>,
ne: <span class="hljs-string">'\u2260'</span>,
equiv: <span class="hljs-string">'\u2261'</span>,
le: <span class="hljs-string">'\u2264'</span>,
ge: <span class="hljs-string">'\u2265'</span>,
sub: <span class="hljs-string">'\u2282'</span>,
sup: <span class="hljs-string">'\u2283'</span>,
nsub: <span class="hljs-string">'\u2284'</span>,
sube: <span class="hljs-string">'\u2286'</span>,
supe: <span class="hljs-string">'\u2287'</span>,
oplus: <span class="hljs-string">'\u2295'</span>,
otimes: <span class="hljs-string">'\u2297'</span>,
perp: <span class="hljs-string">'\u22A5'</span>,
sdot: <span class="hljs-string">'\u22C5'</span>,
lceil: <span class="hljs-string">'\u2308'</span>,
rceil: <span class="hljs-string">'\u2309'</span>,
lfloor: <span class="hljs-string">'\u230A'</span>,
rfloor: <span class="hljs-string">'\u230B'</span>,
lang: <span class="hljs-string">'\u2329'</span>,
rang: <span class="hljs-string">'\u232A'</span>,
loz: <span class="hljs-string">'\u25CA'</span>,
spades: <span class="hljs-string">'\u2660'</span>,
clubs: <span class="hljs-string">'\u2663'</span>,
hearts: <span class="hljs-string">'\u2665'</span>,
diams: <span class="hljs-string">'\u2666'</span>
};
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readXJSEntity</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> str = <span class="hljs-string">''</span>, count = <span class="hljs-number">0</span>, entity;
<span class="hljs-keyword">var</span> ch = nextChar();
<span class="hljs-keyword">if</span> (ch !== <span class="hljs-string">'&amp;'</span>) raise(tokPos, <span class="hljs-string">"Entity must start with an ampersand"</span>);
tokPos++;
<span class="hljs-keyword">while</span> (tokPos &lt; inputLen &amp;&amp; count++ <span class="xml"><span class="hljs-tag">&lt; <span class="hljs-attribute">10</span>) {
<span class="hljs-attribute">ch</span> = <span class="hljs-attribute">nextChar</span>();
<span class="hljs-attribute">tokPos</span>++;
<span class="hljs-attribute">if</span> (<span class="hljs-attribute">ch</span> =<span class="hljs-value">==</span> ';') {
<span class="hljs-attribute">break</span>;
}
<span class="hljs-attribute">str</span> += <span class="hljs-attribute">ch</span>;
}
<span class="hljs-attribute">if</span> (<span class="hljs-attribute">str</span>[<span class="hljs-attribute">0</span>] =<span class="hljs-value">==</span> '#' &amp;&amp; <span class="hljs-attribute">str</span>[<span class="hljs-attribute">1</span>] =<span class="hljs-value">==</span> '<span class="hljs-attribute">x</span>') {
<span class="hljs-attribute">entity</span> = <span class="hljs-attribute">String.fromCharCode</span>(<span class="hljs-attribute">parseInt</span>(<span class="hljs-attribute">str.substr</span>(<span class="hljs-attribute">2</span>), <span class="hljs-attribute">16</span>));
} <span class="hljs-attribute">else</span> <span class="hljs-attribute">if</span> (<span class="hljs-attribute">str</span>[<span class="hljs-attribute">0</span>] =<span class="hljs-value">==</span> '#') {
<span class="hljs-attribute">entity</span> = <span class="hljs-attribute">String.fromCharCode</span>(<span class="hljs-attribute">parseInt</span>(<span class="hljs-attribute">str.substr</span>(<span class="hljs-attribute">1</span>), <span class="hljs-attribute">10</span>));
} <span class="hljs-attribute">else</span> {
<span class="hljs-attribute">entity</span> = <span class="hljs-attribute">XHTMLEntities</span>[<span class="hljs-attribute">str</span>];
}
<span class="hljs-attribute">return</span> <span class="hljs-attribute">entity</span>;
}
<span class="hljs-attribute">function</span> <span class="hljs-attribute">readXJSText</span>(<span class="hljs-attribute">stopChars</span>) {
<span class="hljs-attribute">var</span> <span class="hljs-attribute">str</span> = '';
<span class="hljs-attribute">while</span> (<span class="hljs-attribute">tokPos</span> &lt; <span class="hljs-attribute">inputLen</span>) {
<span class="hljs-attribute">var</span> <span class="hljs-attribute">ch</span> = <span class="hljs-attribute">nextChar</span>();
<span class="hljs-attribute">if</span> (<span class="hljs-attribute">stopChars.indexOf</span>(<span class="hljs-attribute">ch</span>) !=<span class="hljs-value">=</span> <span class="hljs-attribute">-1</span>) {
<span class="hljs-attribute">break</span>;
}
<span class="hljs-attribute">if</span> (<span class="hljs-attribute">ch</span> =<span class="hljs-value">==</span> '&amp;') {
<span class="hljs-attribute">str</span> += <span class="hljs-attribute">readXJSEntity</span>();
} <span class="hljs-attribute">else</span> {
++<span class="hljs-attribute">tokPos</span>;
<span class="hljs-attribute">if</span> (<span class="hljs-attribute">ch</span> =<span class="hljs-value">==</span> '\<span class="hljs-attribute">r</span>' &amp;&amp; <span class="hljs-attribute">nextChar</span>() =<span class="hljs-value">==</span> '\<span class="hljs-attribute">n</span>') {
<span class="hljs-attribute">str</span> += <span class="hljs-attribute">ch</span>;
++<span class="hljs-attribute">tokPos</span>;
<span class="hljs-attribute">ch</span> = '\<span class="hljs-attribute">n</span>';
}
<span class="hljs-attribute">if</span> (<span class="hljs-attribute">ch</span> =<span class="hljs-value">==</span> '\<span class="hljs-attribute">n</span>' &amp;&amp; <span class="hljs-attribute">options.locations</span>) {
<span class="hljs-attribute">tokLineStart</span> = <span class="hljs-attribute">tokPos</span>;
++<span class="hljs-attribute">tokCurLine</span>;
}
<span class="hljs-attribute">str</span> += <span class="hljs-attribute">ch</span>;
}
}
<span class="hljs-attribute">return</span> <span class="hljs-attribute">finishToken</span>(<span class="hljs-attribute">_xjsText</span>, <span class="hljs-attribute">str</span>);
}
<span class="hljs-attribute">function</span> <span class="hljs-attribute">readXJSStringLiteral</span>() {
<span class="hljs-attribute">var</span> <span class="hljs-attribute">quote</span> = <span class="hljs-attribute">input.charCodeAt</span>(<span class="hljs-attribute">tokPos</span>);
<span class="hljs-attribute">if</span> (<span class="hljs-attribute">quote</span> !=<span class="hljs-value">=</span> <span class="hljs-attribute">34</span> &amp;&amp; <span class="hljs-attribute">quote</span> !=<span class="hljs-value">=</span> <span class="hljs-attribute">39</span>) {
<span class="hljs-attribute">raise</span>("<span class="hljs-attribute">String</span> <span class="hljs-attribute">literal</span> <span class="hljs-attribute">must</span> <span class="hljs-attribute">starts</span> <span class="hljs-attribute">with</span> <span class="hljs-attribute">a</span> <span class="hljs-attribute">quote</span>");
}
++<span class="hljs-attribute">tokPos</span>;
<span class="hljs-attribute">readXJSText</span>([<span class="hljs-attribute">String.fromCharCode</span>(<span class="hljs-attribute">quote</span>)]);
<span class="hljs-attribute">if</span> (<span class="hljs-attribute">quote</span> !=<span class="hljs-value">=</span> <span class="hljs-attribute">input.charCodeAt</span>(<span class="hljs-attribute">tokPos</span>)) {
<span class="hljs-attribute">unexpected</span>();
}
++<span class="hljs-attribute">tokPos</span>;
<span class="hljs-attribute">return</span> <span class="hljs-attribute">finishToken</span>(<span class="hljs-attribute">tokType</span>, <span class="hljs-attribute">tokVal</span>);
}
</span></span></pre></div></div>
</li>
<li id="section-88">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-88">&#182;</a>
</div>
<p>Used to read character escape sequences (\x, \u, \U).</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readHexChar</span><span class="hljs-params">(len)</span> </span>{
<span class="hljs-keyword">var</span> n = readInt(<span class="hljs-number">16</span>, len);
<span class="hljs-keyword">if</span> (n === <span class="hljs-literal">null</span>) raise(tokStart, <span class="hljs-string">"Bad character escape sequence"</span>);
<span class="hljs-keyword">return</span> n;
}</pre></div></div>
</li>
<li id="section-89">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-89">&#182;</a>
</div>
<p>Used to signal to callers of <code>readWord1</code> whether the word
contained any escape sequences. This is needed because words with
escape sequences must not be interpreted as keywords.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">var</span> containsEsc;</pre></div></div>
</li>
<li id="section-90">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-90">&#182;</a>
</div>
<p>Read an identifier, and return it as a string. Sets <code>containsEsc</code>
to whether the word contained a \u escape.</p>
<p>Only builds up the word character-by-character when it actually
containeds an escape, as a micro-optimization.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readWord1</span><span class="hljs-params">()</span> </span>{
containsEsc = <span class="hljs-literal">false</span>;
<span class="hljs-keyword">var</span> word, first = <span class="hljs-literal">true</span>, start = tokPos;
<span class="hljs-keyword">for</span> (;;) {
<span class="hljs-keyword">var</span> ch = input.charCodeAt(tokPos);
<span class="hljs-keyword">if</span> (isIdentifierChar(ch) || (inXJSTag &amp;&amp; ch === <span class="hljs-number">45</span>)) {
<span class="hljs-keyword">if</span> (containsEsc) word += nextChar();
++tokPos;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (ch === <span class="hljs-number">92</span> &amp;&amp; !inXJSTag) { <span class="hljs-comment">// "\"</span>
<span class="hljs-keyword">if</span> (!containsEsc) word = input.slice(start, tokPos);
containsEsc = <span class="hljs-literal">true</span>;
<span class="hljs-keyword">if</span> (input.charCodeAt(++tokPos) != <span class="hljs-number">117</span>) <span class="hljs-comment">// "u"</span>
raise(tokPos, <span class="hljs-string">"Expecting Unicode escape sequence \\uXXXX"</span>);
++tokPos;
<span class="hljs-keyword">var</span> esc = readHexChar(<span class="hljs-number">4</span>);
<span class="hljs-keyword">var</span> escStr = <span class="hljs-built_in">String</span>.fromCharCode(esc);
<span class="hljs-keyword">if</span> (!escStr) raise(tokPos - <span class="hljs-number">1</span>, <span class="hljs-string">"Invalid Unicode escape"</span>);
<span class="hljs-keyword">if</span> (!(first ? isIdentifierStart(esc) : isIdentifierChar(esc)))
raise(tokPos - <span class="hljs-number">4</span>, <span class="hljs-string">"Invalid Unicode escape"</span>);
word += escStr;
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">break</span>;
}
first = <span class="hljs-literal">false</span>;
}
<span class="hljs-keyword">return</span> containsEsc ? word : input.slice(start, tokPos);
}</pre></div></div>
</li>
<li id="section-91">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-91">&#182;</a>
</div>
<p>Read an identifier or keyword token. Will check for reserved
words when necessary.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readWord</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> word = readWord1();
<span class="hljs-keyword">var</span> type = inXJSTag ? _xjsName : _name;
<span class="hljs-keyword">if</span> (!containsEsc &amp;&amp; isKeyword(word))
type = keywordTypes[word];
<span class="hljs-keyword">return</span> finishToken(type, word);
}</pre></div></div>
</li>
<li id="section-92">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-92">&#182;</a>
</div>
<h2 id="parser">Parser</h2>
</div>
</li>
<li id="section-93">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-93">&#182;</a>
</div>
<p>A recursive descent parser operates by defining functions for all
syntactic elements, and recursively calling those, each function
advancing the input stream and returning an AST node. Precedence
of constructs (for example, the fact that <code>!x[1]</code> means <code>!(x[1])</code>
instead of <code>(!x)[1]</code> is handled by the fact that the parser
function that parses unary prefix operators is called first, and
in turn calls the function that parses <code>[]</code> subscripts — that
way, itll receive the node for <code>x[1]</code> already parsed, and wraps
<em>that</em> in the unary operator node.</p>
<p>Acorn uses an <a href="http://en.wikipedia.org/wiki/Operator-precedence_parser">operator precedence parser</a> to handle binary
operator precedence, because it is much more compact than using
the technique outlined above, which uses different, nesting
functions to specify precedence, for all of the ten binary
precedence levels that JavaScript defines.</p>
</div>
</li>
<li id="section-94">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-94">&#182;</a>
</div>
<h3 id="parser-utilities">Parser utilities</h3>
</div>
</li>
<li id="section-95">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-95">&#182;</a>
</div>
<p>Continue to the next token.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">next</span><span class="hljs-params">()</span> </span>{
lastStart = tokStart;
lastEnd = tokEnd;
lastEndLoc = tokEndLoc;
readToken();
}</pre></div></div>
</li>
<li id="section-96">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-96">&#182;</a>
</div>
<p>Enter strict mode. Re-reads the next token to please pedantic
tests (“use strict”; 010; — should fail).</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setStrict</span><span class="hljs-params">(strct)</span> </span>{
strict = strct;
tokPos = tokStart;
<span class="hljs-keyword">if</span> (options.locations) {
<span class="hljs-keyword">while</span> (tokPos &lt; tokLineStart) {
tokLineStart = input.lastIndexOf(<span class="hljs-string">"\n"</span>, tokLineStart - <span class="hljs-number">2</span>) + <span class="hljs-number">1</span>;
--tokCurLine;
}
}
skipSpace();
readToken();
}</pre></div></div>
</li>
<li id="section-97">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-97">&#182;</a>
</div>
<p>Start an AST node, attaching a start offset.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Node</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">this</span>.type = <span class="hljs-literal">null</span>;
<span class="hljs-keyword">this</span>.start = tokStart;
<span class="hljs-keyword">this</span>.end = <span class="hljs-literal">null</span>;
}
exports.Node = Node;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">SourceLocation</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">this</span>.start = tokStartLoc;
<span class="hljs-keyword">this</span>.end = <span class="hljs-literal">null</span>;
<span class="hljs-keyword">if</span> (sourceFile !== <span class="hljs-literal">null</span>) <span class="hljs-keyword">this</span>.source = sourceFile;
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">startNode</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> node = <span class="hljs-keyword">new</span> Node();
<span class="hljs-keyword">if</span> (options.locations)
node.loc = <span class="hljs-keyword">new</span> SourceLocation();
<span class="hljs-keyword">if</span> (options.directSourceFile)
node.sourceFile = options.directSourceFile;
<span class="hljs-keyword">if</span> (options.ranges)
node.range = [tokStart, <span class="hljs-number">0</span>];
<span class="hljs-keyword">return</span> node;
}</pre></div></div>
</li>
<li id="section-98">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-98">&#182;</a>
</div>
<p>Start a node whose start offset information should be based on
the start of another node. For example, a binary operator node is
only started after its left-hand side has already been parsed.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">startNodeFrom</span><span class="hljs-params">(other)</span> </span>{
<span class="hljs-keyword">var</span> node = <span class="hljs-keyword">new</span> Node();
node.start = other.start;
<span class="hljs-keyword">if</span> (options.locations) {
node.loc = <span class="hljs-keyword">new</span> SourceLocation();
node.loc.start = other.loc.start;
}
<span class="hljs-keyword">if</span> (options.ranges)
node.range = [other.range[<span class="hljs-number">0</span>], <span class="hljs-number">0</span>];
<span class="hljs-keyword">return</span> node;
}</pre></div></div>
</li>
<li id="section-99">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-99">&#182;</a>
</div>
<p>Finish an AST node, adding <code>type</code> and <code>end</code> properties.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">finishNode</span><span class="hljs-params">(node, type)</span> </span>{
node.type = type;
node.end = lastEnd;
<span class="hljs-keyword">if</span> (options.locations)
node.loc.end = lastEndLoc;
<span class="hljs-keyword">if</span> (options.ranges)
node.range[<span class="hljs-number">1</span>] = lastEnd;
<span class="hljs-keyword">return</span> node;
}</pre></div></div>
</li>
<li id="section-100">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-100">&#182;</a>
</div>
<p>Test whether a statement node is the string literal <code>&quot;use strict&quot;</code>.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isUseStrict</span><span class="hljs-params">(stmt)</span> </span>{
<span class="hljs-keyword">return</span> options.ecmaVersion &gt;= <span class="hljs-number">5</span> &amp;&amp; stmt.type === <span class="hljs-string">"ExpressionStatement"</span> &amp;&amp;
stmt.expression.type === <span class="hljs-string">"Literal"</span> &amp;&amp; stmt.expression.value === <span class="hljs-string">"use strict"</span>;
}</pre></div></div>
</li>
<li id="section-101">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-101">&#182;</a>
</div>
<p>Predicate that tests whether the next token is of the given
type, and if yes, consumes it as a side effect.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">eat</span><span class="hljs-params">(type)</span> </span>{
<span class="hljs-keyword">if</span> (tokType === type) {
next();
<span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}
}</pre></div></div>
</li>
<li id="section-102">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-102">&#182;</a>
</div>
<p>Test whether a semicolon can be inserted at the current position.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">canInsertSemicolon</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">return</span> !options.strictSemicolons &amp;&amp;
(tokType === _eof || tokType === _braceR || newline.test(input.slice(lastEnd, tokStart)));
}</pre></div></div>
</li>
<li id="section-103">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-103">&#182;</a>
</div>
<p>Consume a semicolon, or, failing that, see if we are allowed to
pretend that there is a semicolon at this position.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">semicolon</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">if</span> (!eat(_semi) &amp;&amp; !canInsertSemicolon()) unexpected();
}</pre></div></div>
</li>
<li id="section-104">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-104">&#182;</a>
</div>
<p>Expect a token of a given type. If found, consume it, otherwise,
raise an unexpected token error.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">expect</span><span class="hljs-params">(type)</span> </span>{
eat(type) || unexpected();
}</pre></div></div>
</li>
<li id="section-105">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-105">&#182;</a>
</div>
<p>Get following char.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">nextChar</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">return</span> input.charAt(tokPos);
}</pre></div></div>
</li>
<li id="section-106">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-106">&#182;</a>
</div>
<p>Raise an unexpected token error.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">unexpected</span><span class="hljs-params">(pos)</span> </span>{
raise(pos != <span class="hljs-literal">null</span> ? pos : tokStart, <span class="hljs-string">"Unexpected token"</span>);
}</pre></div></div>
</li>
<li id="section-107">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-107">&#182;</a>
</div>
<p>Checks if hash object has a property.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">has</span><span class="hljs-params">(obj, propName)</span> </span>{
<span class="hljs-keyword">return</span> <span class="hljs-built_in">Object</span>.prototype.hasOwnProperty.call(obj, propName);
}</pre></div></div>
</li>
<li id="section-108">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-108">&#182;</a>
</div>
<p>Convert existing expression atom to assignable pattern
if possible.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">toAssignable</span><span class="hljs-params">(node, allowSpread, checkType)</span> </span>{
<span class="hljs-keyword">if</span> (options.ecmaVersion &gt;= <span class="hljs-number">6</span> &amp;&amp; node) {
<span class="hljs-keyword">switch</span> (node.type) {
<span class="hljs-keyword">case</span> <span class="hljs-string">"Identifier"</span>:
<span class="hljs-keyword">case</span> <span class="hljs-string">"MemberExpression"</span>:
<span class="hljs-keyword">break</span>;
<span class="hljs-keyword">case</span> <span class="hljs-string">"ObjectExpression"</span>:
node.type = <span class="hljs-string">"ObjectPattern"</span>;
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; node.properties.length; i++) {
<span class="hljs-keyword">var</span> prop = node.properties[i];
<span class="hljs-keyword">if</span> (prop.kind !== <span class="hljs-string">"init"</span>) unexpected(prop.key.start);
toAssignable(prop.value, <span class="hljs-literal">false</span>, checkType);
}
<span class="hljs-keyword">break</span>;
<span class="hljs-keyword">case</span> <span class="hljs-string">"ArrayExpression"</span>:
node.type = <span class="hljs-string">"ArrayPattern"</span>;
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>, lastI = node.elements.length - <span class="hljs-number">1</span>; i &lt;= lastI; i++) {
toAssignable(node.elements[i], i === lastI, checkType);
}
<span class="hljs-keyword">break</span>;
<span class="hljs-keyword">case</span> <span class="hljs-string">"SpreadElement"</span>:
<span class="hljs-keyword">if</span> (allowSpread) {
toAssignable(node.argument, <span class="hljs-literal">false</span>, checkType);
checkSpreadAssign(node.argument);
} <span class="hljs-keyword">else</span> {
unexpected(node.start);
}
<span class="hljs-keyword">break</span>;
<span class="hljs-keyword">default</span>:
<span class="hljs-keyword">if</span> (checkType) unexpected(node.start);
}
}
<span class="hljs-keyword">return</span> node;
}</pre></div></div>
</li>
<li id="section-109">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-109">&#182;</a>
</div>
<p>Checks if node can be assignable spread argument.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">checkSpreadAssign</span><span class="hljs-params">(node)</span> </span>{
<span class="hljs-keyword">if</span> (node.type !== <span class="hljs-string">"Identifier"</span> &amp;&amp; node.type !== <span class="hljs-string">"ArrayPattern"</span>)
unexpected(node.start);
}</pre></div></div>
</li>
<li id="section-110">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-110">&#182;</a>
</div>
<p>Verify that argument names are not repeated, and it does not
try to bind the words <code>eval</code> or <code>arguments</code>.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">checkFunctionParam</span><span class="hljs-params">(param, nameHash)</span> </span>{
<span class="hljs-keyword">switch</span> (param.type) {
<span class="hljs-keyword">case</span> <span class="hljs-string">"Identifier"</span>:
<span class="hljs-keyword">if</span> (isStrictReservedWord(param.name) || isStrictBadIdWord(param.name))
raise(param.start, <span class="hljs-string">"Defining '"</span> + param.name + <span class="hljs-string">"' in strict mode"</span>);
<span class="hljs-keyword">if</span> (has(nameHash, param.name))
raise(param.start, <span class="hljs-string">"Argument name clash in strict mode"</span>);
nameHash[param.name] = <span class="hljs-literal">true</span>;
<span class="hljs-keyword">break</span>;
<span class="hljs-keyword">case</span> <span class="hljs-string">"ObjectPattern"</span>:
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; param.properties.length; i++)
checkFunctionParam(param.properties[i].value, nameHash);
<span class="hljs-keyword">break</span>;
<span class="hljs-keyword">case</span> <span class="hljs-string">"ArrayPattern"</span>:
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; param.elements.length; i++)
checkFunctionParam(param.elements[i], nameHash);
<span class="hljs-keyword">break</span>;
}
}</pre></div></div>
</li>
<li id="section-111">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-111">&#182;</a>
</div>
<p>Check if property name clashes with already added.
Object/class getters and setters are not allowed to clash —
either with each other or with an init property — and in
strict mode, init properties are also not allowed to be repeated.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">checkPropClash</span><span class="hljs-params">(prop, propHash)</span> </span>{
<span class="hljs-keyword">if</span> (prop.computed) <span class="hljs-keyword">return</span>;
<span class="hljs-keyword">var</span> key = prop.key, name;
<span class="hljs-keyword">switch</span> (key.type) {
<span class="hljs-keyword">case</span> <span class="hljs-string">"Identifier"</span>: name = key.name; <span class="hljs-keyword">break</span>;
<span class="hljs-keyword">case</span> <span class="hljs-string">"Literal"</span>: name = <span class="hljs-built_in">String</span>(key.value); <span class="hljs-keyword">break</span>;
<span class="hljs-keyword">default</span>: <span class="hljs-keyword">return</span>;
}
<span class="hljs-keyword">var</span> kind = prop.kind || <span class="hljs-string">"init"</span>, other;
<span class="hljs-keyword">if</span> (has(propHash, name)) {
other = propHash[name];
<span class="hljs-keyword">var</span> isGetSet = kind !== <span class="hljs-string">"init"</span>;
<span class="hljs-keyword">if</span> ((strict || isGetSet) &amp;&amp; other[kind] || !(isGetSet ^ other.init))
raise(key.start, <span class="hljs-string">"Redefinition of property"</span>);
} <span class="hljs-keyword">else</span> {
other = propHash[name] = {
init: <span class="hljs-literal">false</span>,
get: <span class="hljs-literal">false</span>,
set: <span class="hljs-literal">false</span>
};
}
other[kind] = <span class="hljs-literal">true</span>;
}</pre></div></div>
</li>
<li id="section-112">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-112">&#182;</a>
</div>
<p>Verify that a node is an lval — something that can be assigned
to.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">checkLVal</span><span class="hljs-params">(expr, isBinding)</span> </span>{
<span class="hljs-keyword">switch</span> (expr.type) {
<span class="hljs-keyword">case</span> <span class="hljs-string">"Identifier"</span>:
<span class="hljs-keyword">if</span> (strict &amp;&amp; (isStrictBadIdWord(expr.name) || isStrictReservedWord(expr.name)))
raise(expr.start, isBinding
? <span class="hljs-string">"Binding "</span> + expr.name + <span class="hljs-string">" in strict mode"</span>
: <span class="hljs-string">"Assigning to "</span> + expr.name + <span class="hljs-string">" in strict mode"</span>
);
<span class="hljs-keyword">break</span>;
<span class="hljs-keyword">case</span> <span class="hljs-string">"MemberExpression"</span>:
<span class="hljs-keyword">if</span> (!isBinding) <span class="hljs-keyword">break</span>;
<span class="hljs-keyword">case</span> <span class="hljs-string">"ObjectPattern"</span>:
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; expr.properties.length; i++)
checkLVal(expr.properties[i].value, isBinding);
<span class="hljs-keyword">break</span>;
<span class="hljs-keyword">case</span> <span class="hljs-string">"ArrayPattern"</span>:
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; expr.elements.length; i++) {
<span class="hljs-keyword">var</span> elem = expr.elements[i];
<span class="hljs-keyword">if</span> (elem) checkLVal(elem, isBinding);
}
<span class="hljs-keyword">break</span>;
<span class="hljs-keyword">case</span> <span class="hljs-string">"SpreadElement"</span>:
<span class="hljs-keyword">break</span>;
<span class="hljs-keyword">default</span>:
raise(expr.start, <span class="hljs-string">"Assigning to rvalue"</span>);
}
}</pre></div></div>
</li>
<li id="section-113">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-113">&#182;</a>
</div>
<h3 id="statement-parsing">Statement parsing</h3>
</div>
</li>
<li id="section-114">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-114">&#182;</a>
</div>
<p>Parse a program. Initializes the parser, reads any number of
statements, and wraps them in a Program node. Optionally takes a
<code>program</code> argument. If present, the statements will be appended
to its body instead of creating a new node.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseTopLevel</span><span class="hljs-params">(program)</span> </span>{
lastStart = lastEnd = tokPos;
<span class="hljs-keyword">if</span> (options.locations) lastEndLoc = <span class="hljs-keyword">new</span> Position;
inFunction = inGenerator = strict = <span class="hljs-literal">null</span>;
labels = [];
readToken();
<span class="hljs-keyword">var</span> node = program || startNode(), first = <span class="hljs-literal">true</span>;
<span class="hljs-keyword">if</span> (!program) node.body = [];
<span class="hljs-keyword">while</span> (tokType !== _eof) {
<span class="hljs-keyword">var</span> stmt = parseStatement();
node.body.push(stmt);
<span class="hljs-keyword">if</span> (first &amp;&amp; isUseStrict(stmt)) setStrict(<span class="hljs-literal">true</span>);
first = <span class="hljs-literal">false</span>;
}
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"Program"</span>);
}
<span class="hljs-keyword">var</span> loopLabel = {kind: <span class="hljs-string">"loop"</span>}, switchLabel = {kind: <span class="hljs-string">"switch"</span>};</pre></div></div>
</li>
<li id="section-115">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-115">&#182;</a>
</div>
<p>Parse a single statement.</p>
<p>If expecting a statement and finding a slash operator, parse a
regular expression literal. This is to handle cases like
<code>if (foo) /blah/.exec(foo);</code>, where looking at the previous token
does not help.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseStatement</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">if</span> (tokType === _slash || tokType === _assign &amp;&amp; tokVal == <span class="hljs-string">"/="</span>)
readToken(<span class="hljs-literal">true</span>);
<span class="hljs-keyword">var</span> starttype = tokType, node = startNode();</pre></div></div>
</li>
<li id="section-116">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-116">&#182;</a>
</div>
<p>Most types of statements are recognized by the keyword they
start with. Many are trivial to parse, some require a bit of
complexity.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">switch</span> (starttype) {
<span class="hljs-keyword">case</span> _break: <span class="hljs-keyword">case</span> _continue: <span class="hljs-keyword">return</span> parseBreakContinueStatement(node, starttype.keyword);
<span class="hljs-keyword">case</span> _debugger: <span class="hljs-keyword">return</span> parseDebuggerStatement(node);
<span class="hljs-keyword">case</span> _do: <span class="hljs-keyword">return</span> parseDoStatement(node);
<span class="hljs-keyword">case</span> _for: <span class="hljs-keyword">return</span> parseForStatement(node);
<span class="hljs-keyword">case</span> _function: <span class="hljs-keyword">return</span> parseFunctionStatement(node);
<span class="hljs-keyword">case</span> _class: <span class="hljs-keyword">return</span> parseClass(node, <span class="hljs-literal">true</span>);
<span class="hljs-keyword">case</span> _if: <span class="hljs-keyword">return</span> parseIfStatement(node);
<span class="hljs-keyword">case</span> _return: <span class="hljs-keyword">return</span> parseReturnStatement(node);
<span class="hljs-keyword">case</span> _switch: <span class="hljs-keyword">return</span> parseSwitchStatement(node);
<span class="hljs-keyword">case</span> _throw: <span class="hljs-keyword">return</span> parseThrowStatement(node);
<span class="hljs-keyword">case</span> _try: <span class="hljs-keyword">return</span> parseTryStatement(node);
<span class="hljs-keyword">case</span> _var: <span class="hljs-keyword">case</span> _let: <span class="hljs-keyword">case</span> _const: <span class="hljs-keyword">return</span> parseVarStatement(node, starttype.keyword);
<span class="hljs-keyword">case</span> _while: <span class="hljs-keyword">return</span> parseWhileStatement(node);
<span class="hljs-keyword">case</span> _with: <span class="hljs-keyword">return</span> parseWithStatement(node);
<span class="hljs-keyword">case</span> _braceL: <span class="hljs-keyword">return</span> parseBlock(); <span class="hljs-comment">// no point creating a function for this</span>
<span class="hljs-keyword">case</span> _semi: <span class="hljs-keyword">return</span> parseEmptyStatement(node);
<span class="hljs-keyword">case</span> _export: <span class="hljs-keyword">return</span> parseExport(node);
<span class="hljs-keyword">case</span> _import: <span class="hljs-keyword">return</span> parseImport(node);</pre></div></div>
</li>
<li id="section-117">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-117">&#182;</a>
</div>
<p>If the statement does not start with a statement keyword or a
brace, its an ExpressionStatement or LabeledStatement. We
simply start parsing an expression, and afterwards, if the
next token is a colon and the expression was a simple
Identifier node, we switch to interpreting it as a label.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">default</span>:
<span class="hljs-keyword">var</span> maybeName = tokVal, expr = parseExpression();
<span class="hljs-keyword">if</span> (starttype === _name &amp;&amp; expr.type === <span class="hljs-string">"Identifier"</span> &amp;&amp; eat(_colon))
<span class="hljs-keyword">return</span> parseLabeledStatement(node, maybeName, expr);
<span class="hljs-keyword">else</span> <span class="hljs-keyword">return</span> parseExpressionStatement(node, expr);
}
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseBreakContinueStatement</span><span class="hljs-params">(node, keyword)</span> </span>{
<span class="hljs-keyword">var</span> isBreak = keyword == <span class="hljs-string">"break"</span>;
next();
<span class="hljs-keyword">if</span> (eat(_semi) || canInsertSemicolon()) node.label = <span class="hljs-literal">null</span>;
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (tokType !== _name) unexpected();
<span class="hljs-keyword">else</span> {
node.label = parseIdent();
semicolon();
}</pre></div></div>
</li>
<li id="section-118">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-118">&#182;</a>
</div>
<p>Verify that there is an actual destination to break or
continue to.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; labels.length; ++i) {
<span class="hljs-keyword">var</span> lab = labels[i];
<span class="hljs-keyword">if</span> (node.label == <span class="hljs-literal">null</span> || lab.name === node.label.name) {
<span class="hljs-keyword">if</span> (lab.kind != <span class="hljs-literal">null</span> &amp;&amp; (isBreak || lab.kind === <span class="hljs-string">"loop"</span>)) <span class="hljs-keyword">break</span>;
<span class="hljs-keyword">if</span> (node.label &amp;&amp; isBreak) <span class="hljs-keyword">break</span>;
}
}
<span class="hljs-keyword">if</span> (i === labels.length) raise(node.start, <span class="hljs-string">"Unsyntactic "</span> + keyword);
<span class="hljs-keyword">return</span> finishNode(node, isBreak ? <span class="hljs-string">"BreakStatement"</span> : <span class="hljs-string">"ContinueStatement"</span>);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseDebuggerStatement</span><span class="hljs-params">(node)</span> </span>{
next();
semicolon();
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"DebuggerStatement"</span>);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseDoStatement</span><span class="hljs-params">(node)</span> </span>{
next();
labels.push(loopLabel);
node.body = parseStatement();
labels.pop();
expect(_while);
node.test = parseParenExpression();
semicolon();
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"DoWhileStatement"</span>);
}</pre></div></div>
</li>
<li id="section-119">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-119">&#182;</a>
</div>
<p>Disambiguating between a <code>for</code> and a <code>for</code>/<code>in</code> or <code>for</code>/<code>of</code>
loop is non-trivial. Basically, we have to parse the init <code>var</code>
statement or expression, disallowing the <code>in</code> operator (see
the second parameter to <code>parseExpression</code>), and then check
whether the next token is <code>in</code> or <code>of</code>. When there is no init
part (semicolon immediately after the opening parenthesis), it
is a regular <code>for</code> loop.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseForStatement</span><span class="hljs-params">(node)</span> </span>{
next();
labels.push(loopLabel);
expect(_parenL);
<span class="hljs-keyword">if</span> (tokType === _semi) <span class="hljs-keyword">return</span> parseFor(node, <span class="hljs-literal">null</span>);
<span class="hljs-keyword">if</span> (tokType === _var || tokType === _let) {
<span class="hljs-keyword">var</span> init = startNode(), varKind = tokType.keyword, isLet = tokType === _let;
next();
parseVar(init, <span class="hljs-literal">true</span>, varKind);
finishNode(init, <span class="hljs-string">"VariableDeclaration"</span>);
<span class="hljs-keyword">if</span> ((tokType === _in || (tokType === _name &amp;&amp; tokVal === <span class="hljs-string">"of"</span>)) &amp;&amp; init.declarations.length === <span class="hljs-number">1</span> &amp;&amp;
!(isLet &amp;&amp; init.declarations[<span class="hljs-number">0</span>].init))
<span class="hljs-keyword">return</span> parseForIn(node, init);
<span class="hljs-keyword">return</span> parseFor(node, init);
}
<span class="hljs-keyword">var</span> init = parseExpression(<span class="hljs-literal">false</span>, <span class="hljs-literal">true</span>);
<span class="hljs-keyword">if</span> (tokType === _in || (tokType === _name &amp;&amp; tokVal === <span class="hljs-string">"of"</span>)) {
checkLVal(init);
<span class="hljs-keyword">return</span> parseForIn(node, init);
}
<span class="hljs-keyword">return</span> parseFor(node, init);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseFunctionStatement</span><span class="hljs-params">(node)</span> </span>{
next();
<span class="hljs-keyword">return</span> parseFunction(node, <span class="hljs-literal">true</span>);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseIfStatement</span><span class="hljs-params">(node)</span> </span>{
next();
node.test = parseParenExpression();
node.consequent = parseStatement();
node.alternate = eat(_else) ? parseStatement() : <span class="hljs-literal">null</span>;
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"IfStatement"</span>);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseReturnStatement</span><span class="hljs-params">(node)</span> </span>{
<span class="hljs-keyword">if</span> (!inFunction &amp;&amp; !options.allowReturnOutsideFunction)
raise(tokStart, <span class="hljs-string">"'return' outside of function"</span>);
next();</pre></div></div>
</li>
<li id="section-120">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-120">&#182;</a>
</div>
<p>In <code>return</code> (and <code>break</code>/<code>continue</code>), the keywords with
optional arguments, we eagerly look for a semicolon or the
possibility to insert one.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">if</span> (eat(_semi) || canInsertSemicolon()) node.argument = <span class="hljs-literal">null</span>;
<span class="hljs-keyword">else</span> { node.argument = parseExpression(); semicolon(); }
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"ReturnStatement"</span>);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseSwitchStatement</span><span class="hljs-params">(node)</span> </span>{
next();
node.discriminant = parseParenExpression();
node.cases = [];
expect(_braceL);
labels.push(switchLabel);</pre></div></div>
</li>
<li id="section-121">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-121">&#182;</a>
</div>
<p>Statements under must be grouped (by label) in SwitchCase
nodes. <code>cur</code> is used to keep the node that we are currently
adding statements to.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> cur, sawDefault; tokType != _braceR;) {
<span class="hljs-keyword">if</span> (tokType === _case || tokType === _default) {
<span class="hljs-keyword">var</span> isCase = tokType === _case;
<span class="hljs-keyword">if</span> (cur) finishNode(cur, <span class="hljs-string">"SwitchCase"</span>);
node.cases.push(cur = startNode());
cur.consequent = [];
next();
<span class="hljs-keyword">if</span> (isCase) cur.test = parseExpression();
<span class="hljs-keyword">else</span> {
<span class="hljs-keyword">if</span> (sawDefault) raise(lastStart, <span class="hljs-string">"Multiple default clauses"</span>); sawDefault = <span class="hljs-literal">true</span>;
cur.test = <span class="hljs-literal">null</span>;
}
expect(_colon);
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">if</span> (!cur) unexpected();
cur.consequent.push(parseStatement());
}
}
<span class="hljs-keyword">if</span> (cur) finishNode(cur, <span class="hljs-string">"SwitchCase"</span>);
next(); <span class="hljs-comment">// Closing brace</span>
labels.pop();
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"SwitchStatement"</span>);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseThrowStatement</span><span class="hljs-params">(node)</span> </span>{
next();
<span class="hljs-keyword">if</span> (newline.test(input.slice(lastEnd, tokStart)))
raise(lastEnd, <span class="hljs-string">"Illegal newline after throw"</span>);
node.argument = parseExpression();
semicolon();
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"ThrowStatement"</span>);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseTryStatement</span><span class="hljs-params">(node)</span> </span>{
next();
node.block = parseBlock();
node.handler = <span class="hljs-literal">null</span>;
<span class="hljs-keyword">if</span> (tokType === _catch) {
<span class="hljs-keyword">var</span> clause = startNode();
next();
expect(_parenL);
clause.param = parseIdent();
<span class="hljs-keyword">if</span> (strict &amp;&amp; isStrictBadIdWord(clause.param.name))
raise(clause.param.start, <span class="hljs-string">"Binding "</span> + clause.param.name + <span class="hljs-string">" in strict mode"</span>);
expect(_parenR);
clause.guard = <span class="hljs-literal">null</span>;
clause.body = parseBlock();
node.handler = finishNode(clause, <span class="hljs-string">"CatchClause"</span>);
}
node.guardedHandlers = empty;
node.finalizer = eat(_finally) ? parseBlock() : <span class="hljs-literal">null</span>;
<span class="hljs-keyword">if</span> (!node.handler &amp;&amp; !node.finalizer)
raise(node.start, <span class="hljs-string">"Missing catch or finally clause"</span>);
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"TryStatement"</span>);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseVarStatement</span><span class="hljs-params">(node, kind)</span> </span>{
next();
parseVar(node, <span class="hljs-literal">false</span>, kind);
semicolon();
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"VariableDeclaration"</span>);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseWhileStatement</span><span class="hljs-params">(node)</span> </span>{
next();
node.test = parseParenExpression();
labels.push(loopLabel);
node.body = parseStatement();
labels.pop();
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"WhileStatement"</span>);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseWithStatement</span><span class="hljs-params">(node)</span> </span>{
<span class="hljs-keyword">if</span> (strict) raise(tokStart, <span class="hljs-string">"'with' in strict mode"</span>);
next();
node.object = parseParenExpression();
node.body = parseStatement();
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"WithStatement"</span>);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseEmptyStatement</span><span class="hljs-params">(node)</span> </span>{
next();
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"EmptyStatement"</span>);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseLabeledStatement</span><span class="hljs-params">(node, maybeName, expr)</span> </span>{
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; labels.length; ++i)
<span class="hljs-keyword">if</span> (labels[i].name === maybeName) raise(expr.start, <span class="hljs-string">"Label '"</span> + maybeName + <span class="hljs-string">"' is already declared"</span>);
<span class="hljs-keyword">var</span> kind = tokType.isLoop ? <span class="hljs-string">"loop"</span> : tokType === _switch ? <span class="hljs-string">"switch"</span> : <span class="hljs-literal">null</span>;
labels.push({name: maybeName, kind: kind});
node.body = parseStatement();
labels.pop();
node.label = expr;
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"LabeledStatement"</span>);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseExpressionStatement</span><span class="hljs-params">(node, expr)</span> </span>{
node.expression = expr;
semicolon();
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"ExpressionStatement"</span>);
}</pre></div></div>
</li>
<li id="section-122">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-122">&#182;</a>
</div>
<p>Used for constructs like <code>switch</code> and <code>if</code> that insist on
parentheses around their expression.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseParenExpression</span><span class="hljs-params">()</span> </span>{
expect(_parenL);
<span class="hljs-keyword">var</span> val = parseExpression();
expect(_parenR);
<span class="hljs-keyword">return</span> val;
}</pre></div></div>
</li>
<li id="section-123">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-123">&#182;</a>
</div>
<p>Parse a semicolon-enclosed block of statements, handling <code>&quot;use
strict&quot;</code> declarations when <code>allowStrict</code> is true (used for
function bodies).</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseBlock</span><span class="hljs-params">(allowStrict)</span> </span>{
<span class="hljs-keyword">var</span> node = startNode(), first = <span class="hljs-literal">true</span>, strict = <span class="hljs-literal">false</span>, oldStrict;
node.body = [];
expect(_braceL);
<span class="hljs-keyword">while</span> (!eat(_braceR)) {
<span class="hljs-keyword">var</span> stmt = parseStatement();
node.body.push(stmt);
<span class="hljs-keyword">if</span> (first &amp;&amp; allowStrict &amp;&amp; isUseStrict(stmt)) {
oldStrict = strict;
setStrict(strict = <span class="hljs-literal">true</span>);
}
first = <span class="hljs-literal">false</span>;
}
<span class="hljs-keyword">if</span> (strict &amp;&amp; !oldStrict) setStrict(<span class="hljs-literal">false</span>);
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"BlockStatement"</span>);
}</pre></div></div>
</li>
<li id="section-124">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-124">&#182;</a>
</div>
<p>Parse a regular <code>for</code> loop. The disambiguation code in
<code>parseStatement</code> will already have parsed the init statement or
expression.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseFor</span><span class="hljs-params">(node, init)</span> </span>{
node.init = init;
expect(_semi);
node.test = tokType === _semi ? <span class="hljs-literal">null</span> : parseExpression();
expect(_semi);
node.update = tokType === _parenR ? <span class="hljs-literal">null</span> : parseExpression();
expect(_parenR);
node.body = parseStatement();
labels.pop();
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"ForStatement"</span>);
}</pre></div></div>
</li>
<li id="section-125">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-125">&#182;</a>
</div>
<p>Parse a <code>for</code>/<code>in</code> and <code>for</code>/<code>of</code> loop, which are almost
same from parsers perspective.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseForIn</span><span class="hljs-params">(node, init)</span> </span>{
<span class="hljs-keyword">var</span> type = tokType === _in ? <span class="hljs-string">"ForInStatement"</span> : <span class="hljs-string">"ForOfStatement"</span>;
next();
node.left = init;
node.right = parseExpression();
expect(_parenR);
node.body = parseStatement();
labels.pop();
<span class="hljs-keyword">return</span> finishNode(node, type);
}</pre></div></div>
</li>
<li id="section-126">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-126">&#182;</a>
</div>
<p>Parse a list of variable declarations.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseVar</span><span class="hljs-params">(node, noIn, kind)</span> </span>{
node.declarations = [];
node.kind = kind;
<span class="hljs-keyword">for</span> (;;) {
<span class="hljs-keyword">var</span> decl = startNode();
decl.id = options.ecmaVersion &gt;= <span class="hljs-number">6</span> ? toAssignable(parseExprAtom()) : parseIdent();
checkLVal(decl.id, <span class="hljs-literal">true</span>);
decl.init = eat(_eq) ? parseExpression(<span class="hljs-literal">true</span>, noIn) : (kind === _const.keyword ? unexpected() : <span class="hljs-literal">null</span>);
node.declarations.push(finishNode(decl, <span class="hljs-string">"VariableDeclarator"</span>));
<span class="hljs-keyword">if</span> (!eat(_comma)) <span class="hljs-keyword">break</span>;
}
<span class="hljs-keyword">return</span> node;
}</pre></div></div>
</li>
<li id="section-127">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-127">&#182;</a>
</div>
<h3 id="expression-parsing">Expression parsing</h3>
</div>
</li>
<li id="section-128">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-128">&#182;</a>
</div>
<p>These nest, from the most general expression type at the top to
atomic, nondivisible expression types at the bottom. Most of
the functions will simply let the function(s) below them parse,
and, <em>if</em> the syntactic construct they handle is present, wrap
the AST node that the inner parser gave them in another node.</p>
</div>
</li>
<li id="section-129">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-129">&#182;</a>
</div>
<p>Parse a full expression. The arguments are used to forbid comma
sequences (in argument lists, array literals, or object literals)
or the <code>in</code> operator (in for loops initalization expressions).</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseExpression</span><span class="hljs-params">(noComma, noIn)</span> </span>{
<span class="hljs-keyword">var</span> expr = parseMaybeAssign(noIn);
<span class="hljs-keyword">if</span> (!noComma &amp;&amp; tokType === _comma) {
<span class="hljs-keyword">var</span> node = startNodeFrom(expr);
node.expressions = [expr];
<span class="hljs-keyword">while</span> (eat(_comma)) node.expressions.push(parseMaybeAssign(noIn));
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"SequenceExpression"</span>);
}
<span class="hljs-keyword">return</span> expr;
}</pre></div></div>
</li>
<li id="section-130">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-130">&#182;</a>
</div>
<p>Parse an assignment expression. This includes applications of
operators like <code>+=</code>.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseMaybeAssign</span><span class="hljs-params">(noIn)</span> </span>{
<span class="hljs-keyword">var</span> left = parseMaybeConditional(noIn);
<span class="hljs-keyword">if</span> (tokType.isAssign) {
<span class="hljs-keyword">var</span> node = startNodeFrom(left);
node.operator = tokVal;
node.left = tokType === _eq ? toAssignable(left) : left;
checkLVal(left);
next();
node.right = parseMaybeAssign(noIn);
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"AssignmentExpression"</span>);
}
<span class="hljs-keyword">return</span> left;
}</pre></div></div>
</li>
<li id="section-131">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-131">&#182;</a>
</div>
<p>Parse a ternary conditional (<code>?:</code>) operator.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseMaybeConditional</span><span class="hljs-params">(noIn)</span> </span>{
<span class="hljs-keyword">var</span> expr = parseExprOps(noIn);
<span class="hljs-keyword">if</span> (eat(_question)) {
<span class="hljs-keyword">var</span> node = startNodeFrom(expr);
node.test = expr;
node.consequent = parseExpression(<span class="hljs-literal">true</span>);
expect(_colon);
node.alternate = parseExpression(<span class="hljs-literal">true</span>, noIn);
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"ConditionalExpression"</span>);
}
<span class="hljs-keyword">return</span> expr;
}</pre></div></div>
</li>
<li id="section-132">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-132">&#182;</a>
</div>
<p>Start the precedence parser.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseExprOps</span><span class="hljs-params">(noIn)</span> </span>{
<span class="hljs-keyword">return</span> parseExprOp(parseMaybeUnary(), -<span class="hljs-number">1</span>, noIn);
}</pre></div></div>
</li>
<li id="section-133">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-133">&#182;</a>
</div>
<p>Parse binary operators with the operator precedence parsing
algorithm. <code>left</code> is the left-hand side of the operator.
<code>minPrec</code> provides context that allows the function to stop and
defer further parser to one of its callers when it encounters an
operator that has a lower precedence than the set it is parsing.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseExprOp</span><span class="hljs-params">(left, minPrec, noIn)</span> </span>{
<span class="hljs-keyword">var</span> prec = tokType.binop;
<span class="hljs-keyword">if</span> (prec != <span class="hljs-literal">null</span> &amp;&amp; (!noIn || tokType !== _in)) {
<span class="hljs-keyword">if</span> (prec &gt; minPrec) {
<span class="hljs-keyword">var</span> node = startNodeFrom(left);
node.left = left;
node.operator = tokVal;
<span class="hljs-keyword">var</span> op = tokType;
next();
node.right = parseExprOp(parseMaybeUnary(), prec, noIn);
<span class="hljs-keyword">var</span> exprNode = finishNode(node, (op === _logicalOR || op === _logicalAND) ? <span class="hljs-string">"LogicalExpression"</span> : <span class="hljs-string">"BinaryExpression"</span>);
<span class="hljs-keyword">return</span> parseExprOp(exprNode, minPrec, noIn);
}
}
<span class="hljs-keyword">return</span> left;
}</pre></div></div>
</li>
<li id="section-134">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-134">&#182;</a>
</div>
<p>Parse unary operators, both prefix and postfix.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseMaybeUnary</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">if</span> (tokType.prefix) {
<span class="hljs-keyword">var</span> node = startNode(), update = tokType.isUpdate;
node.operator = tokVal;
node.prefix = <span class="hljs-literal">true</span>;
tokRegexpAllowed = <span class="hljs-literal">true</span>;
next();
node.argument = parseMaybeUnary();
<span class="hljs-keyword">if</span> (update) checkLVal(node.argument);
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (strict &amp;&amp; node.operator === <span class="hljs-string">"delete"</span> &amp;&amp;
node.argument.type === <span class="hljs-string">"Identifier"</span>)
raise(node.start, <span class="hljs-string">"Deleting local variable in strict mode"</span>);
<span class="hljs-keyword">return</span> finishNode(node, update ? <span class="hljs-string">"UpdateExpression"</span> : <span class="hljs-string">"UnaryExpression"</span>);
}
<span class="hljs-keyword">var</span> expr = parseExprSubscripts();
<span class="hljs-keyword">while</span> (tokType.postfix &amp;&amp; !canInsertSemicolon()) {
<span class="hljs-keyword">var</span> node = startNodeFrom(expr);
node.operator = tokVal;
node.prefix = <span class="hljs-literal">false</span>;
node.argument = expr;
checkLVal(expr);
next();
expr = finishNode(node, <span class="hljs-string">"UpdateExpression"</span>);
}
<span class="hljs-keyword">return</span> expr;
}</pre></div></div>
</li>
<li id="section-135">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-135">&#182;</a>
</div>
<p>Parse call, dot, and <code>[]</code>-subscript expressions.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseExprSubscripts</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">return</span> parseSubscripts(parseExprAtom());
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseSubscripts</span><span class="hljs-params">(base, noCalls)</span> </span>{
<span class="hljs-keyword">if</span> (eat(_dot)) {
<span class="hljs-keyword">var</span> node = startNodeFrom(base);
node.object = base;
node.property = parseIdent(<span class="hljs-literal">true</span>);
node.computed = <span class="hljs-literal">false</span>;
<span class="hljs-keyword">return</span> parseSubscripts(finishNode(node, <span class="hljs-string">"MemberExpression"</span>), noCalls);
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (eat(_bracketL)) {
<span class="hljs-keyword">var</span> node = startNodeFrom(base);
node.object = base;
node.property = parseExpression();
node.computed = <span class="hljs-literal">true</span>;
expect(_bracketR);
<span class="hljs-keyword">return</span> parseSubscripts(finishNode(node, <span class="hljs-string">"MemberExpression"</span>), noCalls);
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (!noCalls &amp;&amp; eat(_parenL)) {
<span class="hljs-keyword">var</span> node = startNodeFrom(base);
node.callee = base;
node.arguments = parseExprList(_parenR, <span class="hljs-literal">false</span>);
<span class="hljs-keyword">return</span> parseSubscripts(finishNode(node, <span class="hljs-string">"CallExpression"</span>), noCalls);
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (tokType === _bquote) {
<span class="hljs-keyword">var</span> node = startNodeFrom(base);
node.tag = base;
node.quasi = parseTemplate();
<span class="hljs-keyword">return</span> parseSubscripts(finishNode(node, <span class="hljs-string">"TaggedTemplateExpression"</span>), noCalls);
} <span class="hljs-keyword">return</span> base;
}</pre></div></div>
</li>
<li id="section-136">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-136">&#182;</a>
</div>
<p>Parse an atomic expression — either a single token that is an
expression, an expression started by a keyword like <code>function</code> or
<code>new</code>, or an expression wrapped in punctuation like <code>()</code>, <code>[]</code>,
or <code>{}</code>.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseExprAtom</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">switch</span> (tokType) {
<span class="hljs-keyword">case</span> _this:
<span class="hljs-keyword">var</span> node = startNode();
next();
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"ThisExpression"</span>);
<span class="hljs-keyword">case</span> _yield:
<span class="hljs-keyword">if</span> (inGenerator) <span class="hljs-keyword">return</span> parseYield();
<span class="hljs-keyword">case</span> _name:
<span class="hljs-keyword">var</span> id = parseIdent(tokType !== _name);
<span class="hljs-keyword">if</span> (eat(_arrow)) {
<span class="hljs-keyword">return</span> parseArrowExpression(startNodeFrom(id), [id]);
}
<span class="hljs-keyword">return</span> id;
<span class="hljs-keyword">case</span> _num: <span class="hljs-keyword">case</span> _string: <span class="hljs-keyword">case</span> _regexp: <span class="hljs-keyword">case</span> _xjsText:
<span class="hljs-keyword">var</span> node = startNode();
node.value = tokVal;
node.raw = input.slice(tokStart, tokEnd);
next();
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"Literal"</span>);
<span class="hljs-keyword">case</span> _null: <span class="hljs-keyword">case</span> _true: <span class="hljs-keyword">case</span> _false:
<span class="hljs-keyword">var</span> node = startNode();
node.value = tokType.atomValue;
node.raw = tokType.keyword;
next();
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"Literal"</span>);
<span class="hljs-keyword">case</span> _parenL:
<span class="hljs-keyword">var</span> tokStartLoc1 = tokStartLoc, tokStart1 = tokStart, val, exprList;
next();</pre></div></div>
</li>
<li id="section-137">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-137">&#182;</a>
</div>
<p>check whether this is generator comprehension or regular expression</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (options.ecmaVersion &gt;= <span class="hljs-number">6</span> &amp;&amp; tokType === _for) {
val = parseComprehension(startNode(), <span class="hljs-literal">true</span>);
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">var</span> oldParenL = ++metParenL;
<span class="hljs-keyword">if</span> (tokType !== _parenR) {
val = parseExpression();
exprList = val.type === <span class="hljs-string">"SequenceExpression"</span> ? val.expressions : [val];
} <span class="hljs-keyword">else</span> {
exprList = [];
}
expect(_parenR);</pre></div></div>
</li>
<li id="section-138">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-138">&#182;</a>
</div>
<p>if =&gt; follows (…), convert contents to arguments</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (metParenL === oldParenL &amp;&amp; eat(_arrow)) {
val = parseArrowExpression(startNode(), exprList);
} <span class="hljs-keyword">else</span> {</pre></div></div>
</li>
<li id="section-139">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-139">&#182;</a>
</div>
<p>forbid () before everything but =&gt;</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (!val) unexpected(lastStart);</pre></div></div>
</li>
<li id="section-140">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-140">&#182;</a>
</div>
<p>forbid ‘…’ in sequence expressions</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (options.ecmaVersion &gt;= <span class="hljs-number">6</span>) {
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; exprList.length; i++) {
<span class="hljs-keyword">if</span> (exprList[i].type === <span class="hljs-string">"SpreadElement"</span>) unexpected();
}
}
}
}
val.start = tokStart1;
val.end = lastEnd;
<span class="hljs-keyword">if</span> (options.locations) {
val.loc.start = tokStartLoc1;
val.loc.end = lastEndLoc;
}
<span class="hljs-keyword">if</span> (options.ranges) {
val.range = [tokStart1, lastEnd];
}
<span class="hljs-keyword">return</span> val;
<span class="hljs-keyword">case</span> _bracketL:
<span class="hljs-keyword">var</span> node = startNode();
next();</pre></div></div>
</li>
<li id="section-141">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-141">&#182;</a>
</div>
<p>check whether this is array comprehension or regular array</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (options.ecmaVersion &gt;= <span class="hljs-number">6</span> &amp;&amp; tokType === _for) {
<span class="hljs-keyword">return</span> parseComprehension(node, <span class="hljs-literal">false</span>);
}
node.elements = parseExprList(_bracketR, <span class="hljs-literal">true</span>, <span class="hljs-literal">true</span>);
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"ArrayExpression"</span>);
<span class="hljs-keyword">case</span> _braceL:
<span class="hljs-keyword">return</span> parseObj();
<span class="hljs-keyword">case</span> _function:
<span class="hljs-keyword">var</span> node = startNode();
next();
<span class="hljs-keyword">return</span> parseFunction(node, <span class="hljs-literal">false</span>);
<span class="hljs-keyword">case</span> _class:
<span class="hljs-keyword">return</span> parseClass(startNode(), <span class="hljs-literal">false</span>);
<span class="hljs-keyword">case</span> _new:
<span class="hljs-keyword">return</span> parseNew();
<span class="hljs-keyword">case</span> _ellipsis:
<span class="hljs-keyword">return</span> parseSpread();
<span class="hljs-keyword">case</span> _bquote:
<span class="hljs-keyword">return</span> parseTemplate();
<span class="hljs-keyword">case</span> _lt:
<span class="hljs-keyword">return</span> parseXJSElement();
<span class="hljs-keyword">default</span>:
unexpected();
}
}</pre></div></div>
</li>
<li id="section-142">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-142">&#182;</a>
</div>
<p>News precedence is slightly tricky. It must allow its argument
to be a <code>[]</code> or dot subscript expression, but not a call — at
least, not without wrapping it in parentheses. Thus, it uses the</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseNew</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> node = startNode();
next();
node.callee = parseSubscripts(parseExprAtom(), <span class="hljs-literal">true</span>);
<span class="hljs-keyword">if</span> (eat(_parenL)) node.arguments = parseExprList(_parenR, <span class="hljs-literal">false</span>);
<span class="hljs-keyword">else</span> node.arguments = empty;
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"NewExpression"</span>);
}</pre></div></div>
</li>
<li id="section-143">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-143">&#182;</a>
</div>
<p>Parse spread element …expr</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseSpread</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> node = startNode();
next();
node.argument = parseExpression(<span class="hljs-literal">true</span>);
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"SpreadElement"</span>);
}</pre></div></div>
</li>
<li id="section-144">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-144">&#182;</a>
</div>
<p>Parse template expression.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseTemplate</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> node = startNode();
node.expressions = [];
node.quasis = [];
inTemplate = <span class="hljs-literal">true</span>;
next();
<span class="hljs-keyword">for</span> (;;) {
<span class="hljs-keyword">var</span> elem = startNode();
elem.value = {cooked: tokVal, raw: input.slice(tokStart, tokEnd)};
elem.tail = <span class="hljs-literal">false</span>;
next();
node.quasis.push(finishNode(elem, <span class="hljs-string">"TemplateElement"</span>));
<span class="hljs-keyword">if</span> (eat(_bquote)) { <span class="hljs-comment">// '`', end of template</span>
elem.tail = <span class="hljs-literal">true</span>;
<span class="hljs-keyword">break</span>;
}
inTemplate = <span class="hljs-literal">false</span>;
expect(_dollarBraceL);
node.expressions.push(parseExpression());
inTemplate = <span class="hljs-literal">true</span>;
expect(_braceR);
}
inTemplate = <span class="hljs-literal">false</span>;
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"TemplateLiteral"</span>);
}</pre></div></div>
</li>
<li id="section-145">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-145">&#182;</a>
</div>
<p>Parse an object literal.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseObj</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> node = startNode(), first = <span class="hljs-literal">true</span>, propHash = {};
node.properties = [];
next();
<span class="hljs-keyword">while</span> (!eat(_braceR)) {
<span class="hljs-keyword">if</span> (!first) {
expect(_comma);
<span class="hljs-keyword">if</span> (options.allowTrailingCommas &amp;&amp; eat(_braceR)) <span class="hljs-keyword">break</span>;
} <span class="hljs-keyword">else</span> first = <span class="hljs-literal">false</span>;
<span class="hljs-keyword">var</span> prop = startNode(), isGenerator;
<span class="hljs-keyword">if</span> (options.ecmaVersion &gt;= <span class="hljs-number">6</span>) {
prop.method = <span class="hljs-literal">false</span>;
prop.shorthand = <span class="hljs-literal">false</span>;
isGenerator = eat(_star);
}
parsePropertyName(prop);
<span class="hljs-keyword">if</span> (eat(_colon)) {
prop.value = parseExpression(<span class="hljs-literal">true</span>);
prop.kind = <span class="hljs-string">"init"</span>;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (options.ecmaVersion &gt;= <span class="hljs-number">6</span> &amp;&amp; tokType === _parenL) {
prop.kind = <span class="hljs-string">"init"</span>;
prop.method = <span class="hljs-literal">true</span>;
prop.value = parseMethod(isGenerator);
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (options.ecmaVersion &gt;= <span class="hljs-number">5</span> &amp;&amp; !prop.computed &amp;&amp; prop.key.type === <span class="hljs-string">"Identifier"</span> &amp;&amp;
(prop.key.name === <span class="hljs-string">"get"</span> || prop.key.name === <span class="hljs-string">"set"</span>)) {
<span class="hljs-keyword">if</span> (isGenerator) unexpected();
prop.kind = prop.key.name;
parsePropertyName(prop);
prop.value = parseMethod(<span class="hljs-literal">false</span>);
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (options.ecmaVersion &gt;= <span class="hljs-number">6</span> &amp;&amp; !prop.computed &amp;&amp; prop.key.type === <span class="hljs-string">"Identifier"</span>) {
prop.kind = <span class="hljs-string">"init"</span>;
prop.value = prop.key;
prop.shorthand = <span class="hljs-literal">true</span>;
} <span class="hljs-keyword">else</span> unexpected();
checkPropClash(prop, propHash);
node.properties.push(finishNode(prop, <span class="hljs-string">"Property"</span>));
}
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"ObjectExpression"</span>);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parsePropertyName</span><span class="hljs-params">(prop)</span> </span>{
<span class="hljs-keyword">if</span> (options.ecmaVersion &gt;= <span class="hljs-number">6</span>) {
<span class="hljs-keyword">if</span> (eat(_bracketL)) {
prop.computed = <span class="hljs-literal">true</span>;
prop.key = parseExpression();
expect(_bracketR);
<span class="hljs-keyword">return</span>;
} <span class="hljs-keyword">else</span> {
prop.computed = <span class="hljs-literal">false</span>;
}
}
prop.key = (tokType === _num || tokType === _string) ? parseExprAtom() : parseIdent(<span class="hljs-literal">true</span>);
}</pre></div></div>
</li>
<li id="section-146">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-146">&#182;</a>
</div>
<p>Initialize empty function node.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">initFunction</span><span class="hljs-params">(node)</span> </span>{
node.id = <span class="hljs-literal">null</span>;
node.params = [];
<span class="hljs-keyword">if</span> (options.ecmaVersion &gt;= <span class="hljs-number">6</span>) {
node.defaults = [];
node.rest = <span class="hljs-literal">null</span>;
node.generator = <span class="hljs-literal">false</span>;
}
}</pre></div></div>
</li>
<li id="section-147">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-147">&#182;</a>
</div>
<p>Parse a function declaration or literal (depending on the
<code>isStatement</code> parameter).</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseFunction</span><span class="hljs-params">(node, isStatement, allowExpressionBody)</span> </span>{
initFunction(node);
<span class="hljs-keyword">if</span> (options.ecmaVersion &gt;= <span class="hljs-number">6</span>) {
node.generator = eat(_star);
}
<span class="hljs-keyword">if</span> (isStatement || tokType === _name) {
node.id = parseIdent();
}
parseFunctionParams(node);
parseFunctionBody(node, allowExpressionBody);
<span class="hljs-keyword">return</span> finishNode(node, isStatement ? <span class="hljs-string">"FunctionDeclaration"</span> : <span class="hljs-string">"FunctionExpression"</span>);
}</pre></div></div>
</li>
<li id="section-148">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-148">&#182;</a>
</div>
<p>Parse object or class method.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseMethod</span><span class="hljs-params">(isGenerator)</span> </span>{
<span class="hljs-keyword">var</span> node = startNode();
initFunction(node);
parseFunctionParams(node);
<span class="hljs-keyword">var</span> allowExpressionBody;
<span class="hljs-keyword">if</span> (options.ecmaVersion &gt;= <span class="hljs-number">6</span>) {
node.generator = isGenerator;
allowExpressionBody = <span class="hljs-literal">true</span>;
} <span class="hljs-keyword">else</span> {
allowExpressionBody = <span class="hljs-literal">false</span>;
}
parseFunctionBody(node, allowExpressionBody);
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"FunctionExpression"</span>);
}</pre></div></div>
</li>
<li id="section-149">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-149">&#182;</a>
</div>
<p>Parse arrow function expression with given parameters.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseArrowExpression</span><span class="hljs-params">(node, params)</span> </span>{
initFunction(node);
<span class="hljs-keyword">var</span> defaults = node.defaults, hasDefaults = <span class="hljs-literal">false</span>;
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>, lastI = params.length - <span class="hljs-number">1</span>; i &lt;= lastI; i++) {
<span class="hljs-keyword">var</span> param = params[i];
<span class="hljs-keyword">if</span> (param.type === <span class="hljs-string">"AssignmentExpression"</span> &amp;&amp; param.operator === <span class="hljs-string">"="</span>) {
hasDefaults = <span class="hljs-literal">true</span>;
params[i] = param.left;
defaults.push(param.right);
} <span class="hljs-keyword">else</span> {
toAssignable(param, i === lastI, <span class="hljs-literal">true</span>);
defaults.push(<span class="hljs-literal">null</span>);
<span class="hljs-keyword">if</span> (param.type === <span class="hljs-string">"SpreadElement"</span>) {
params.length--;
node.rest = param.argument;
<span class="hljs-keyword">break</span>;
}
}
}
node.params = params;
<span class="hljs-keyword">if</span> (!hasDefaults) node.defaults = [];
parseFunctionBody(node, <span class="hljs-literal">true</span>);
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"ArrowFunctionExpression"</span>);
}</pre></div></div>
</li>
<li id="section-150">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-150">&#182;</a>
</div>
<p>Parse function parameters.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseFunctionParams</span><span class="hljs-params">(node)</span> </span>{
<span class="hljs-keyword">var</span> defaults = [], hasDefaults = <span class="hljs-literal">false</span>;
expect(_parenL);
<span class="hljs-keyword">for</span> (;;) {
<span class="hljs-keyword">if</span> (eat(_parenR)) {
<span class="hljs-keyword">break</span>;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (options.ecmaVersion &gt;= <span class="hljs-number">6</span> &amp;&amp; eat(_ellipsis)) {
node.rest = toAssignable(parseExprAtom(), <span class="hljs-literal">false</span>, <span class="hljs-literal">true</span>);
checkSpreadAssign(node.rest);
expect(_parenR);
<span class="hljs-keyword">break</span>;
} <span class="hljs-keyword">else</span> {
node.params.push(options.ecmaVersion &gt;= <span class="hljs-number">6</span> ? toAssignable(parseExprAtom(), <span class="hljs-literal">false</span>, <span class="hljs-literal">true</span>) : parseIdent());
<span class="hljs-keyword">if</span> (options.ecmaVersion &gt;= <span class="hljs-number">6</span> &amp;&amp; tokType === _eq) {
next();
hasDefaults = <span class="hljs-literal">true</span>;
defaults.push(parseExpression(<span class="hljs-literal">true</span>));
}
<span class="hljs-keyword">if</span> (!eat(_comma)) {
expect(_parenR);
<span class="hljs-keyword">break</span>;
}
}
}
<span class="hljs-keyword">if</span> (hasDefaults) node.defaults = defaults;
}</pre></div></div>
</li>
<li id="section-151">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-151">&#182;</a>
</div>
<p>Parse function body and check parameters.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseFunctionBody</span><span class="hljs-params">(node, allowExpression)</span> </span>{
<span class="hljs-keyword">var</span> isExpression = allowExpression &amp;&amp; tokType !== _braceL;
<span class="hljs-keyword">if</span> (isExpression) {
node.body = parseExpression(<span class="hljs-literal">true</span>);
node.expression = <span class="hljs-literal">true</span>;
} <span class="hljs-keyword">else</span> {</pre></div></div>
</li>
<li id="section-152">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-152">&#182;</a>
</div>
<p>Start a new scope with regard to labels and the <code>inFunction</code>
flag (restore them to their old value afterwards).</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> oldInFunc = inFunction, oldInGen = inGenerator, oldLabels = labels;
inFunction = <span class="hljs-literal">true</span>; inGenerator = node.generator; labels = [];
node.body = parseBlock(<span class="hljs-literal">true</span>);
node.expression = <span class="hljs-literal">false</span>;
inFunction = oldInFunc; inGenerator = oldInGen; labels = oldLabels;
}</pre></div></div>
</li>
<li id="section-153">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-153">&#182;</a>
</div>
<p>If this is a strict mode function, verify that argument names
are not repeated, and it does not try to bind the words <code>eval</code>
or <code>arguments</code>.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (strict || !isExpression &amp;&amp; node.body.body.length &amp;&amp; isUseStrict(node.body.body[<span class="hljs-number">0</span>])) {
<span class="hljs-keyword">var</span> nameHash = {};
<span class="hljs-keyword">if</span> (node.id)
checkFunctionParam(node.id, {});
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; node.params.length; i++)
checkFunctionParam(node.params[i], nameHash);
<span class="hljs-keyword">if</span> (node.rest)
checkFunctionParam(node.rest, nameHash);
}
}</pre></div></div>
</li>
<li id="section-154">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-154">&#182;</a>
</div>
<p>Parse a class declaration or literal (depending on the
<code>isStatement</code> parameter).</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseClass</span><span class="hljs-params">(node, isStatement)</span> </span>{
next();
node.id = tokType === _name ? parseIdent() : isStatement ? unexpected() : <span class="hljs-literal">null</span>;
node.superClass = eat(_extends) ? parseExpression() : <span class="hljs-literal">null</span>;
<span class="hljs-keyword">var</span> classBody = startNode(), methodHash = {}, staticMethodHash = {};
classBody.body = [];
expect(_braceL);
<span class="hljs-keyword">while</span> (!eat(_braceR)) {
<span class="hljs-keyword">var</span> method = startNode();
<span class="hljs-keyword">if</span> (tokType === _name &amp;&amp; tokVal === <span class="hljs-string">"static"</span>) {
next();
method[<span class="hljs-string">'static'</span>] = <span class="hljs-literal">true</span>;
} <span class="hljs-keyword">else</span> {
method[<span class="hljs-string">'static'</span>] = <span class="hljs-literal">false</span>;
}
<span class="hljs-keyword">var</span> isGenerator = eat(_star);
parsePropertyName(method);
<span class="hljs-keyword">if</span> (tokType === _name &amp;&amp; !method.computed &amp;&amp; method.key.type === <span class="hljs-string">"Identifier"</span> &amp;&amp;
(method.key.name === <span class="hljs-string">"get"</span> || method.key.name === <span class="hljs-string">"set"</span>)) {
<span class="hljs-keyword">if</span> (isGenerator) unexpected();
method.kind = method.key.name;
parsePropertyName(method);
} <span class="hljs-keyword">else</span> {
method.kind = <span class="hljs-string">""</span>;
}
method.value = parseMethod(isGenerator);
checkPropClash(method, method[<span class="hljs-string">'static'</span>] ? staticMethodHash : methodHash);
classBody.body.push(finishNode(method, <span class="hljs-string">"MethodDefinition"</span>));
eat(_semi);
}
node.body = finishNode(classBody, <span class="hljs-string">"ClassBody"</span>);
<span class="hljs-keyword">return</span> finishNode(node, isStatement ? <span class="hljs-string">"ClassDeclaration"</span> : <span class="hljs-string">"ClassExpression"</span>);
}</pre></div></div>
</li>
<li id="section-155">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-155">&#182;</a>
</div>
<p>Parses a comma-separated list of expressions, and returns them as
an array. <code>close</code> is the token type that ends the list, and
<code>allowEmpty</code> can be turned on to allow subsequent commas with
nothing in between them to be parsed as <code>null</code> (which is needed
for array literals).</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseExprList</span><span class="hljs-params">(close, allowTrailingComma, allowEmpty)</span> </span>{
<span class="hljs-keyword">var</span> elts = [], first = <span class="hljs-literal">true</span>;
<span class="hljs-keyword">while</span> (!eat(close)) {
<span class="hljs-keyword">if</span> (!first) {
expect(_comma);
<span class="hljs-keyword">if</span> (allowTrailingComma &amp;&amp; options.allowTrailingCommas &amp;&amp; eat(close)) <span class="hljs-keyword">break</span>;
} <span class="hljs-keyword">else</span> first = <span class="hljs-literal">false</span>;
<span class="hljs-keyword">if</span> (allowEmpty &amp;&amp; tokType === _comma) elts.push(<span class="hljs-literal">null</span>);
<span class="hljs-keyword">else</span> elts.push(parseExpression(<span class="hljs-literal">true</span>));
}
<span class="hljs-keyword">return</span> elts;
}</pre></div></div>
</li>
<li id="section-156">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-156">&#182;</a>
</div>
<p>Parse the next token as an identifier. If <code>liberal</code> is true (used
when parsing properties), it will also convert keywords into
identifiers.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseIdent</span><span class="hljs-params">(liberal)</span> </span>{
<span class="hljs-keyword">var</span> node = startNode();
<span class="hljs-keyword">if</span> (liberal &amp;&amp; options.forbidReserved == <span class="hljs-string">"everywhere"</span>) liberal = <span class="hljs-literal">false</span>;
<span class="hljs-keyword">if</span> (tokType === _name) {
<span class="hljs-keyword">if</span> (!liberal &amp;&amp;
(options.forbidReserved &amp;&amp;
(options.ecmaVersion === <span class="hljs-number">3</span> ? isReservedWord3 : isReservedWord5)(tokVal) ||
strict &amp;&amp; isStrictReservedWord(tokVal)) &amp;&amp;
input.slice(tokStart, tokEnd).indexOf(<span class="hljs-string">"\\"</span>) == -<span class="hljs-number">1</span>)
raise(tokStart, <span class="hljs-string">"The keyword '"</span> + tokVal + <span class="hljs-string">"' is reserved"</span>);
node.name = tokVal;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (liberal &amp;&amp; tokType.keyword) {
node.name = tokType.keyword;
} <span class="hljs-keyword">else</span> {
unexpected();
}
tokRegexpAllowed = <span class="hljs-literal">false</span>;
next();
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"Identifier"</span>);
}</pre></div></div>
</li>
<li id="section-157">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-157">&#182;</a>
</div>
<p>Parses module export declaration.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseExport</span><span class="hljs-params">(node)</span> </span>{
next();</pre></div></div>
</li>
<li id="section-158">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-158">&#182;</a>
</div>
<p>export var|const|let|function|class …;</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (tokType === _var || tokType === _const || tokType === _let || tokType === _function || tokType === _class) {
node.declaration = parseStatement();
node[<span class="hljs-string">'default'</span>] = <span class="hljs-literal">false</span>;
node.specifiers = <span class="hljs-literal">null</span>;
node.source = <span class="hljs-literal">null</span>;
} <span class="hljs-keyword">else</span></pre></div></div>
</li>
<li id="section-159">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-159">&#182;</a>
</div>
<p>export default …;</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (eat(_default)) {
node.declaration = parseExpression(<span class="hljs-literal">true</span>);
node[<span class="hljs-string">'default'</span>] = <span class="hljs-literal">true</span>;
node.specifiers = <span class="hljs-literal">null</span>;
node.source = <span class="hljs-literal">null</span>;
semicolon();
} <span class="hljs-keyword">else</span> {</pre></div></div>
</li>
<li id="section-160">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-160">&#182;</a>
</div>
<p>export * from ‘…’
export { x, y as z } [from ‘…’]</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> isBatch = tokType === _star;
node.declaration = <span class="hljs-literal">null</span>;
node[<span class="hljs-string">'default'</span>] = <span class="hljs-literal">false</span>;
node.specifiers = parseExportSpecifiers();
<span class="hljs-keyword">if</span> (tokType === _name &amp;&amp; tokVal === <span class="hljs-string">"from"</span>) {
next();
node.source = tokType === _string ? parseExprAtom() : unexpected();
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">if</span> (isBatch) unexpected();
node.source = <span class="hljs-literal">null</span>;
}
}
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"ExportDeclaration"</span>);
}</pre></div></div>
</li>
<li id="section-161">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-161">&#182;</a>
</div>
<p>Parses a comma-separated list of module exports.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseExportSpecifiers</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> nodes = [], first = <span class="hljs-literal">true</span>;
<span class="hljs-keyword">if</span> (tokType === _star) {</pre></div></div>
</li>
<li id="section-162">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-162">&#182;</a>
</div>
<p>export * from ‘…’</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> node = startNode();
next();
nodes.push(finishNode(node, <span class="hljs-string">"ExportBatchSpecifier"</span>));
} <span class="hljs-keyword">else</span> {</pre></div></div>
</li>
<li id="section-163">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-163">&#182;</a>
</div>
<p>export { x, y as z } [from ‘…’]</p>
</div>
<div class="content"><div class='highlight'><pre> expect(_braceL);
<span class="hljs-keyword">while</span> (!eat(_braceR)) {
<span class="hljs-keyword">if</span> (!first) {
expect(_comma);
<span class="hljs-keyword">if</span> (options.allowTrailingCommas &amp;&amp; eat(_braceR)) <span class="hljs-keyword">break</span>;
} <span class="hljs-keyword">else</span> first = <span class="hljs-literal">false</span>;
<span class="hljs-keyword">var</span> node = startNode();
node.id = parseIdent();
<span class="hljs-keyword">if</span> (tokType === _name &amp;&amp; tokVal === <span class="hljs-string">"as"</span>) {
next();
node.name = parseIdent(<span class="hljs-literal">true</span>);
} <span class="hljs-keyword">else</span> {
node.name = <span class="hljs-literal">null</span>;
}
nodes.push(finishNode(node, <span class="hljs-string">"ExportSpecifier"</span>));
}
}
<span class="hljs-keyword">return</span> nodes;
}</pre></div></div>
</li>
<li id="section-164">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-164">&#182;</a>
</div>
<p>Parses import declaration.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseImport</span><span class="hljs-params">(node)</span> </span>{
next();</pre></div></div>
</li>
<li id="section-165">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-165">&#182;</a>
</div>
<p>import ‘…’;</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (tokType === _string) {
node.specifiers = [];
node.source = parseExprAtom();
node.kind = <span class="hljs-string">""</span>;
} <span class="hljs-keyword">else</span> {
node.specifiers = parseImportSpecifiers();
<span class="hljs-keyword">if</span> (tokType !== _name || tokVal !== <span class="hljs-string">"from"</span>) unexpected();
next();
node.source = tokType === _string ? parseExprAtom() : unexpected();</pre></div></div>
</li>
<li id="section-166">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-166">&#182;</a>
</div>
<p>only for backward compatibility with Esprimas AST
(it doesnt support mixed default + named yet)</p>
</div>
<div class="content"><div class='highlight'><pre> node.kind = node.specifiers[<span class="hljs-number">0</span>][<span class="hljs-string">'default'</span>] ? <span class="hljs-string">"default"</span> : <span class="hljs-string">"named"</span>;
}
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"ImportDeclaration"</span>);
}</pre></div></div>
</li>
<li id="section-167">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-167">&#182;</a>
</div>
<p>Parses a comma-separated list of module imports.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseImportSpecifiers</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> nodes = [], first = <span class="hljs-literal">true</span>;
<span class="hljs-keyword">if</span> (tokType === _star) {
<span class="hljs-keyword">var</span> node = startNode();
next();
<span class="hljs-keyword">if</span> (tokType !== _name || tokVal !== <span class="hljs-string">"as"</span>) unexpected();
next();
node.name = parseIdent();
checkLVal(node.name, <span class="hljs-literal">true</span>);
nodes.push(finishNode(node, <span class="hljs-string">"ImportBatchSpecifier"</span>));
<span class="hljs-keyword">return</span> nodes;
}
<span class="hljs-keyword">if</span> (tokType === _name) {</pre></div></div>
</li>
<li id="section-168">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-168">&#182;</a>
</div>
<p>import defaultObj, { x, y as z } from ‘…’</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> node = startNode();
node.id = parseIdent();
checkLVal(node.id, <span class="hljs-literal">true</span>);
node.name = <span class="hljs-literal">null</span>;
node[<span class="hljs-string">'default'</span>] = <span class="hljs-literal">true</span>;
nodes.push(finishNode(node, <span class="hljs-string">"ImportSpecifier"</span>));
<span class="hljs-keyword">if</span> (!eat(_comma)) <span class="hljs-keyword">return</span> nodes;
}
expect(_braceL);
<span class="hljs-keyword">while</span> (!eat(_braceR)) {
<span class="hljs-keyword">if</span> (!first) {
expect(_comma);
<span class="hljs-keyword">if</span> (options.allowTrailingCommas &amp;&amp; eat(_braceR)) <span class="hljs-keyword">break</span>;
} <span class="hljs-keyword">else</span> first = <span class="hljs-literal">false</span>;
<span class="hljs-keyword">var</span> node = startNode();
node.id = parseIdent(<span class="hljs-literal">true</span>);
<span class="hljs-keyword">if</span> (tokType === _name &amp;&amp; tokVal === <span class="hljs-string">"as"</span>) {
next();
node.name = parseIdent();
} <span class="hljs-keyword">else</span> {
node.name = <span class="hljs-literal">null</span>;
}
checkLVal(node.name || node.id, <span class="hljs-literal">true</span>);
node[<span class="hljs-string">'default'</span>] = <span class="hljs-literal">false</span>;
nodes.push(finishNode(node, <span class="hljs-string">"ImportSpecifier"</span>));
}
<span class="hljs-keyword">return</span> nodes;
}</pre></div></div>
</li>
<li id="section-169">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-169">&#182;</a>
</div>
<p>Parses yield expression inside generator.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseYield</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> node = startNode();
next();
<span class="hljs-keyword">if</span> (eat(_semi) || canInsertSemicolon()) {
node.delegate = <span class="hljs-literal">false</span>;
node.argument = <span class="hljs-literal">null</span>;
} <span class="hljs-keyword">else</span> {
node.delegate = eat(_star);
node.argument = parseExpression(<span class="hljs-literal">true</span>);
}
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"YieldExpression"</span>);
}</pre></div></div>
</li>
<li id="section-170">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-170">&#182;</a>
</div>
<p>Parses array and generator comprehensions.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseComprehension</span><span class="hljs-params">(node, isGenerator)</span> </span>{
node.blocks = [];
<span class="hljs-keyword">while</span> (tokType === _for) {
<span class="hljs-keyword">var</span> block = startNode();
next();
expect(_parenL);
block.left = toAssignable(parseExprAtom());
checkLVal(block.left, <span class="hljs-literal">true</span>);
<span class="hljs-keyword">if</span> (tokType !== _name || tokVal !== <span class="hljs-string">"of"</span>) unexpected();
next();</pre></div></div>
</li>
<li id="section-171">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-171">&#182;</a>
</div>
<p><code>of</code> property is here for compatibility with Esprimas AST
which also supports deprecated [for (… in …) expr]</p>
</div>
<div class="content"><div class='highlight'><pre> block.of = <span class="hljs-literal">true</span>;
block.right = parseExpression();
expect(_parenR);
node.blocks.push(finishNode(block, <span class="hljs-string">"ComprehensionBlock"</span>));
}
node.filter = eat(_if) ? parseParenExpression() : <span class="hljs-literal">null</span>;
node.body = parseExpression();
expect(isGenerator ? _parenR : _bracketR);
node.generator = isGenerator;
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"ComprehensionExpression"</span>);
}</pre></div></div>
</li>
<li id="section-172">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-172">&#182;</a>
</div>
<p>Transforms JSX element name to string.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getQualifiedXJSName</span><span class="hljs-params">(object)</span> </span>{
<span class="hljs-keyword">if</span> (object.type === <span class="hljs-string">"XJSIdentifier"</span>) {
<span class="hljs-keyword">return</span> object.name;
}
<span class="hljs-keyword">if</span> (object.type === <span class="hljs-string">"XJSNamespacedName"</span>) {
<span class="hljs-keyword">return</span> object.namespace.name + <span class="hljs-string">':'</span> + object.name.name;
}
<span class="hljs-keyword">if</span> (object.type === <span class="hljs-string">"XJSMemberExpression"</span>) {
<span class="hljs-keyword">return</span> (
getQualifiedXJSName(object.object) + <span class="hljs-string">'.'</span> +
getQualifiedXJSName(object.property)
);
}
}</pre></div></div>
</li>
<li id="section-173">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-173">&#182;</a>
</div>
<p>Parse next token as JSX identifier</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseXJSIdentifier</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> node = startNode();
<span class="hljs-keyword">if</span> (tokType === _xjsName) {
node.name = tokVal;
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (tokType.keyword) {
node.name = tokType.keyword;
} <span class="hljs-keyword">else</span> {
unexpected();
}
tokRegexpAllowed = <span class="hljs-literal">false</span>;
next();
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"XJSIdentifier"</span>);
}</pre></div></div>
</li>
<li id="section-174">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-174">&#182;</a>
</div>
<p>Parse namespaced identifier.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseXJSNamespacedName</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> node = startNode();
node.namespace = parseXJSIdentifier();
expect(_colon);
node.name = parseXJSIdentifier();
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"XJSNamespacedName"</span>);
}</pre></div></div>
</li>
<li id="section-175">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-175">&#182;</a>
</div>
<p>Parse JSX object.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseXJSMemberExpression</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> node = parseXJSIdentifier();
<span class="hljs-keyword">while</span> (eat(_dot)) {
<span class="hljs-keyword">var</span> newNode = startNodeFrom(node);
newNode.object = node;
newNode.property = parseXJSIdentifier();
node = finishNode(newNode, <span class="hljs-string">"XJSMemberExpression"</span>);
}
<span class="hljs-keyword">return</span> node;
}</pre></div></div>
</li>
<li id="section-176">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-176">&#182;</a>
</div>
<p>Parses element name in any form - namespaced, object
or single identifier.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseXJSElementName</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">switch</span> (nextChar()) {
<span class="hljs-keyword">case</span> <span class="hljs-string">':'</span>:
<span class="hljs-keyword">return</span> parseXJSNamespacedName();
<span class="hljs-keyword">case</span> <span class="hljs-string">'.'</span>:
<span class="hljs-keyword">return</span> parseXJSMemberExpression();
<span class="hljs-keyword">default</span>:
<span class="hljs-keyword">return</span> parseXJSIdentifier();
}
}</pre></div></div>
</li>
<li id="section-177">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-177">&#182;</a>
</div>
<p>Parses attribute name as optionally namespaced identifier.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseXJSAttributeName</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">if</span> (nextChar() === <span class="hljs-string">':'</span>) {
<span class="hljs-keyword">return</span> parseXJSNamespacedName();
}
<span class="hljs-keyword">return</span> parseXJSIdentifier();
}</pre></div></div>
</li>
<li id="section-178">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-178">&#182;</a>
</div>
<p>Parses any type of JSX attribute value.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseXJSAttributeValue</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">switch</span> (tokType) {
<span class="hljs-keyword">case</span> _braceL:
<span class="hljs-keyword">var</span> node = parseXJSExpressionContainer();
<span class="hljs-keyword">if</span> (node.expression.type === <span class="hljs-string">"XJSEmptyExpression"</span>) {
raise(
node.start,
<span class="hljs-string">'XJS attributes must only be assigned a non-empty '</span> +
<span class="hljs-string">'expression'</span>
);
}
<span class="hljs-keyword">return</span> node;
<span class="hljs-keyword">case</span> _lt:
<span class="hljs-keyword">return</span> parseXJSElement();
<span class="hljs-keyword">case</span> _xjsText:
<span class="hljs-keyword">return</span> parseExprAtom();
<span class="hljs-keyword">default</span>:
raise(tokStart, <span class="hljs-string">"XJS value should be either an expression or a quoted XJS text"</span>);
}
}</pre></div></div>
</li>
<li id="section-179">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-179">&#182;</a>
</div>
<p>XJSEmptyExpression is unique type since it doesnt actually parse anything,
and so it should start at the end of last read token (left brace) and finish
at the beginning of the next one (right brace).</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseXJSEmptyExpression</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">if</span> (tokType !== _braceR) {
unexpected();
}
<span class="hljs-keyword">var</span> tmp;
tmp = tokStart;
tokStart = lastEnd;
lastEnd = tmp;
tmp = tokStartLoc;
tokStartLoc = lastEndLoc;
lastEndLoc = tmp;
<span class="hljs-keyword">return</span> finishNode(startNode(), <span class="hljs-string">"XJSEmptyExpression"</span>);
}</pre></div></div>
</li>
<li id="section-180">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-180">&#182;</a>
</div>
<p>Parses JSX expression enclosed into curly brackets.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseXJSExpressionContainer</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> node = startNode();
<span class="hljs-keyword">var</span> origInXJSTag = inXJSTag;
inXJSTag = <span class="hljs-literal">false</span>;
next();
node.expression = tokType === _braceR ? parseXJSEmptyExpression() : parseExpression();
inXJSTag = origInXJSTag;
expect(_braceR);
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"XJSExpressionContainer"</span>);
}</pre></div></div>
</li>
<li id="section-181">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-181">&#182;</a>
</div>
<p>Parses following JSX attribute name-value pair.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseXJSAttribute</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">if</span> (tokType === _braceL) {
<span class="hljs-keyword">var</span> tokStart1 = tokStart, tokStartLoc1 = tokStartLoc;
<span class="hljs-keyword">var</span> origInXJSTag = inXJSTag;
inXJSTag = <span class="hljs-literal">false</span>;
next();
<span class="hljs-keyword">var</span> node = parseSpread();
inXJSTag = origInXJSTag;
expect(_braceR);
node.type = <span class="hljs-string">"XJSSpreadAttribute"</span>;
node.start = tokStart1;
node.end = lastEnd;
<span class="hljs-keyword">if</span> (options.locations) {
node.loc.start = tokStartLoc1;
node.loc.end = lastEndLoc;
}
<span class="hljs-keyword">if</span> (options.ranges) {
node.range = [tokStart1, lastEnd];
}
<span class="hljs-keyword">return</span> node;
}
<span class="hljs-keyword">var</span> node = startNode();
node.name = parseXJSAttributeName();</pre></div></div>
</li>
<li id="section-182">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-182">&#182;</a>
</div>
<p>HTML empty attribute</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (tokType === _eq) {
next();
node.value = parseXJSAttributeValue();
} <span class="hljs-keyword">else</span> {
node.value = <span class="hljs-literal">null</span>;
}
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"XJSAttribute"</span>);
}</pre></div></div>
</li>
<li id="section-183">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-183">&#182;</a>
</div>
<p>Parses any type of JSX contents (expression, text or another tag).</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseXJSChild</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">switch</span> (tokType) {
<span class="hljs-keyword">case</span> _braceL:
<span class="hljs-keyword">return</span> parseXJSExpressionContainer();
<span class="hljs-keyword">case</span> _xjsText:
<span class="hljs-keyword">return</span> parseExprAtom();
<span class="hljs-keyword">default</span>:
<span class="hljs-keyword">return</span> parseXJSElement();
}
}</pre></div></div>
</li>
<li id="section-184">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-184">&#182;</a>
</div>
<p>Parses JSX open tag.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseXJSOpeningElement</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> node = startNode(), attributes = node.attributes = [];
<span class="hljs-keyword">var</span> origInXJSChild = inXJSChild;
<span class="hljs-keyword">var</span> origInXJSTag = inXJSTag;
inXJSChild = <span class="hljs-literal">false</span>;
inXJSTag = <span class="hljs-literal">true</span>;
next();
node.name = parseXJSElementName();
<span class="hljs-keyword">while</span> (tokType !== _eof &amp;&amp; tokType !== _slash &amp;&amp; tokType !== _gt) {
attributes.push(parseXJSAttribute());
}
inXJSTag = <span class="hljs-literal">false</span>;
<span class="hljs-keyword">if</span> (node.selfClosing = !!eat(_slash)) {
inXJSTag = origInXJSTag;
inXJSChild = origInXJSChild;
} <span class="hljs-keyword">else</span> {
inXJSChild = <span class="hljs-literal">true</span>;
}
expect(_gt);
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"XJSOpeningElement"</span>);
}</pre></div></div>
</li>
<li id="section-185">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-185">&#182;</a>
</div>
<p>Parses JSX closing tag.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseXJSClosingElement</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> node = startNode();
<span class="hljs-keyword">var</span> origInXJSChild = inXJSChild;
<span class="hljs-keyword">var</span> origInXJSTag = inXJSTag;
inXJSChild = <span class="hljs-literal">false</span>;
inXJSTag = <span class="hljs-literal">true</span>;
tokRegexpAllowed = <span class="hljs-literal">false</span>;
expect(_ltSlash);
node.name = parseXJSElementName();
skipSpace();</pre></div></div>
</li>
<li id="section-186">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-186">&#182;</a>
</div>
<p>A valid token is expected after &gt;, so parser needs to know
whether to look for a standard JS token or an XJS text node</p>
</div>
<div class="content"><div class='highlight'><pre> inXJSChild = origInXJSChild;
inXJSTag = origInXJSTag;
tokRegexpAllowed = <span class="hljs-literal">false</span>;
expect(_gt);
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"XJSClosingElement"</span>);
}</pre></div></div>
</li>
<li id="section-187">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-187">&#182;</a>
</div>
<p>Parses entire JSX element, including its opening tag,
attributes, contents and closing tag.</p>
</div>
<div class="content"><div class='highlight'><pre>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseXJSElement</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">var</span> node = startNode();
<span class="hljs-keyword">var</span> children = [];
<span class="hljs-keyword">var</span> origInXJSChild = inXJSChild;
<span class="hljs-keyword">var</span> openingElement = parseXJSOpeningElement();
<span class="hljs-keyword">var</span> closingElement = <span class="hljs-literal">null</span>;
<span class="hljs-keyword">if</span> (!openingElement.selfClosing) {
<span class="hljs-keyword">while</span> (tokType !== _eof &amp;&amp; tokType !== _ltSlash) {
inXJSChild = <span class="hljs-literal">true</span>;
children.push(parseXJSChild());
}
inXJSChild = origInXJSChild;
closingElement = parseXJSClosingElement();
<span class="hljs-keyword">if</span> (getQualifiedXJSName(closingElement.name) !== getQualifiedXJSName(openingElement.name)) {
raise(
closingElement.start,
<span class="hljs-string">"Expected corresponding XJS closing tag for '"</span> + getQualifiedXJSName(openingElement.name) + <span class="hljs-string">"'"</span>
);
}
}</pre></div></div>
</li>
<li id="section-188">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-188">&#182;</a>
</div>
<p>When (erroneously) writing two adjacent tags like</p>
<pre><code><span class="hljs-keyword">var</span> x = <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-title">div</span>&gt;</span>one<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-title">div</span>&gt;</span>two<span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>;</span>
</code></pre><p>the default error message is a bit incomprehensible. Since its
rarely (never?) useful to write a less-than sign after an XJS
element, we disallow it here in the parser in order to provide a
better error message. (In the rare case that the less-than operator
was intended, the left tag can be wrapped in parentheses.)</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (!origInXJSChild &amp;&amp; tokType === _lt) {
raise(tokStart, <span class="hljs-string">"Adjacent XJS elements must be wrapped in an enclosing tag"</span>);
}
node.openingElement = openingElement;
node.closingElement = closingElement;
node.children = children;
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"XJSElement"</span>);
}
});</pre></div></div>
</li>
</ul>
</div>
</body>
</html>