4266 lines
222 KiB
HTML
4266 lines
222 KiB
HTML
<!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">¶</a>
|
||
</div>
|
||
<p>Acorn is a tiny, fast JavaScript parser written in JavaScript.</p>
|
||
<p>Acorn was written by Marijn Haverbeke 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> && <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> && 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.6.1"</span>;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-2">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-2">¶</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 the SpiderMonkey-specific syntax
|
||
(<code>let</code>, <code>yield</code>, inline XML, etc) 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">¶</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">¶</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. ES6 support is only partial.</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">¶</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">¶</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">¶</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">¶</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">¶</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">¶</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-11">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-11">¶</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-12">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-12">¶</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-13">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-13">¶</a>
|
||
</div>
|
||
<p>When <code>locations</code> is on, you can pass this to record the source
|
||
file in every node’s <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-14">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-14">¶</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-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> (!<span class="hljs-built_in">Object</span>.prototype.hasOwnProperty.call(options, opt))
|
||
options[opt] = defaultOptions[opt];
|
||
sourceFile = options.sourceFile || <span class="hljs-literal">null</span>;
|
||
|
||
isKeyword = options.ecmaVersion >= <span class="hljs-number">6</span> ? isEcma6Keyword : isEcma5AndLessKeyword;
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-15">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-15">¶</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 && match.index < 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};
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-16">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-16">¶</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-keyword">var</span> t = {};
|
||
<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);
|
||
t.start = tokStart; t.end = tokEnd;
|
||
t.startLoc = tokStartLoc; t.endLoc = tokEndLoc;
|
||
t.type = tokType; t.value = tokVal;
|
||
<span class="hljs-keyword">return</span> t;
|
||
}
|
||
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)) && match.index < 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-17">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-17">¶</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-18">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-18">¶</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-19">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-19">¶</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-20">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-20">¶</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-21">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-21">¶</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 that’s 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-22">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-22">¶</a>
|
||
</div>
|
||
<p>Interal 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 isn’t it’s 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-23">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-23">¶</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-24">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-24">¶</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-25">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-25">¶</a>
|
||
</div>
|
||
<p>This is the parser’s state. <code>inFunction</code> is used to reject
|
||
<code>return</code> statements outside of functions, <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, labels, strict, inXJSChild, inXJSTag;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-26">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-26">¶</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-27">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-27">¶</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-28">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-28">¶</a>
|
||
</div>
|
||
<h2 id="token-types">Token types</h2>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-29">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-29">¶</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-30">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-30">¶</a>
|
||
</div>
|
||
<p>All token type variables start with an underscore, to make them
|
||
easy to recognize.</p>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-31">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-31">¶</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-32">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-32">¶</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-33">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-33">¶</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>};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-34">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-34">¶</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-35">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-35">¶</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-36">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-36">¶</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>}};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-37">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-37">¶</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>};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-38">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-38">¶</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> _multiplyModulo = {binop: <span class="hljs-number">10</span>, beforeExpr: <span class="hljs-literal">true</span>};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-39">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-39">¶</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,
|
||
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-40">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-40">¶</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 < words.length; ++i) {
|
||
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> j = <span class="hljs-number">0</span>; j < 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 < 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-41">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-41">¶</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 > <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 < 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-42">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-42">¶</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-43">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-43">¶</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-44">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-44">¶</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-45">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-45">¶</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-46">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-46">¶</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-47">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-47">¶</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"</span>);
|
||
|
||
<span class="hljs-keyword">var</span> isKeyword = isEcma5AndLessKeyword;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-48">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-48">¶</a>
|
||
</div>
|
||
<h2 id="character-categories">Character categories</h2>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-49">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-49">¶</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.</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\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\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\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\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-\u0c33\u0c35-\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-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\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-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\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\u0620-\u0649\u0672-\u06d3\u06e7-\u06e8\u06fb-\u06fc\u0730-\u074a\u0800-\u0814\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0840-\u0857\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962-\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09d7\u09df-\u09e0\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\u0b5f-\u0b60\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2-\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d46-\u0d48\u0d57\u0d62-\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e34-\u0e3a\u0e40-\u0e45\u0e50-\u0e59\u0eb4-\u0eb9\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f41-\u0f47\u0f71-\u0f84\u0f86-\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1029\u1040-\u1049\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u170e-\u1710\u1720-\u1730\u1740-\u1750\u1772\u1773\u1780-\u17b2\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1920-\u192b\u1930-\u193b\u1951-\u196d\u19b0-\u19c0\u19c8-\u19c9\u19d0-\u19d9\u1a00-\u1a15\u1a20-\u1a53\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b46-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1bb0-\u1bb9\u1be6-\u1bf3\u1c00-\u1c22\u1c40-\u1c49\u1c5b-\u1c7d\u1cd0-\u1cd2\u1d00-\u1dbe\u1e01-\u1f15\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2d81-\u2d96\u2de0-\u2dff\u3021-\u3028\u3099\u309a\ua640-\ua66d\ua674-\ua67d\ua69f\ua6f0-\ua6f1\ua7f8-\ua800\ua806\ua80b\ua823-\ua827\ua880-\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8f3-\ua8f7\ua900-\ua909\ua926-\ua92d\ua930-\ua945\ua980-\ua983\ua9b3-\ua9c0\uaa00-\uaa27\uaa40-\uaa41\uaa4c-\uaa4d\uaa50-\uaa59\uaa7b\uaae0-\uaae9\uaaf2-\uaaf3\uabc0-\uabe1\uabec\uabed\uabf0-\uabf9\ufb20-\ufb28\ufe00-\ufe0f\ufe20-\ufe26\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-50">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-50">¶</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-51">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-51">¶</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-52">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-52">¶</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 < <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 < <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 < <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 < <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 >= <span class="hljs-number">0xaa</span> && nonASCIIidentifierStart.test(<span class="hljs-built_in">String</span>.fromCharCode(code));
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-53">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-53">¶</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 < <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 < <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 < <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 < <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 < <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 < <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 >= <span class="hljs-number">0xaa</span> && nonASCIIidentifier.test(<span class="hljs-built_in">String</span>.fromCharCode(code));
|
||
};</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-54">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-54">¶</a>
|
||
</div>
|
||
<h2 id="tokenizer">Tokenizer</h2>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-55">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-55">¶</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-56">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-56">¶</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>;
|
||
inXJSChild = inXJSTag = <span class="hljs-literal">false</span>;
|
||
skipSpace();
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-57">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-57">¶</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 one’s <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)</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> (!(inXJSTag && val === <span class="hljs-string">'>'</span>) && !(inXJSChild && tokType !== _braceL)) {
|
||
skipSpace();
|
||
}
|
||
tokVal = val;
|
||
tokRegexpAllowed = type.beforeExpr;
|
||
}
|
||
|
||
<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 && options.locations && <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)) && match.index < 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 && <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">()</span> </span>{
|
||
<span class="hljs-keyword">var</span> start = tokPos;
|
||
<span class="hljs-keyword">var</span> startLoc = options.onComment && options.locations && <span class="hljs-keyword">new</span> Position;
|
||
<span class="hljs-keyword">var</span> ch = input.charCodeAt(tokPos+=<span class="hljs-number">2</span>);
|
||
<span class="hljs-keyword">while</span> (tokPos < inputLen && ch !== <span class="hljs-number">10</span> && ch !== <span class="hljs-number">13</span> && ch !== <span class="hljs-number">8232</span> && 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 + <span class="hljs-number">2</span>, tokPos), start, tokPos,
|
||
startLoc, options.locations && <span class="hljs-keyword">new</span> Position);
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-58">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-58">¶</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 < 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 > <span class="hljs-number">8</span> && ch < <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-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 >= <span class="hljs-number">5760</span> && 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-59">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-59">¶</a>
|
||
</div>
|
||
<h3 id="token-reading">Token reading</h3>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-60">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-60">¶</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 >= <span class="hljs-number">48</span> && next <= <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 >= <span class="hljs-number">6</span> && next === <span class="hljs-number">46</span> && 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">()</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(_multiplyModulo, <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">// '|&'</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> && input.charCodeAt(tokPos + <span class="hljs-number">2</span>) == <span class="hljs-number">62</span> &&
|
||
newline.test(input.slice(lastEnd, tokPos))) {</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-61">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-61">¶</a>
|
||
</div>
|
||
<p>A <code>--></code> line comment</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> tokPos += <span class="hljs-number">3</span>;
|
||
skipLineComment();
|
||
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">// '<>'</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> && 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> && code == <span class="hljs-number">60</span> && input.charCodeAt(tokPos + <span class="hljs-number">2</span>) == <span class="hljs-number">45</span> &&
|
||
input.charCodeAt(tokPos + <span class="hljs-number">3</span>) == <span class="hljs-number">45</span>) {</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-62">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-62">¶</a>
|
||
</div>
|
||
<p><code><!--</code>, an XML-style comment that should be interpreted as a line comment</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> tokPos += <span class="hljs-number">4</span>;
|
||
skipLineComment();
|
||
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-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">// '=!'</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">return</span> finishOp(code === <span class="hljs-number">61</span> ? _eq : _prefix, <span class="hljs-number">1</span>);
|
||
}
|
||
|
||
<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-63">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-63">¶</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-64">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-64">¶</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);</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-65">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-65">¶</a>
|
||
</div>
|
||
<p>‘0x’ is a hexadecimal number.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <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> readHexNumber();</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-66">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-66">¶</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-67">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-67">¶</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-68">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-68">¶</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();
|
||
|
||
<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">// '|&'</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">// '<>'</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 >= 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-69">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-69">¶</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 && tokType !== _braceL && code !== <span class="hljs-number">60</span> && code !== <span class="hljs-number">123</span> && code !== <span class="hljs-number">125</span>) {
|
||
<span class="hljs-keyword">return</span> readXJSText([<span class="hljs-string">'<'</span>, <span class="hljs-string">'{'</span>]);
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-70">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-70">¶</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-71">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-71">¶</a>
|
||
</div>
|
||
<p>If we are here, we either found a non-ASCII identifier
|
||
character, or something that’s 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-72">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-72">¶</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 >= inputLen) raise(start, <span class="hljs-string">"Unterminated regular expression"</span>);
|
||
<span class="hljs-keyword">var</span> ch = input.charAt(tokPos);
|
||
<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> && 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> && !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-73">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-73">¶</a>
|
||
</div>
|
||
<p>Need to use <code>readWord1</code> because ‘\uXXXX’ sequences are allowed
|
||
here (don’t 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 && !<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-74">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-74">¶</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 < e; ++i) {
|
||
<span class="hljs-keyword">var</span> code = input.charCodeAt(tokPos), val;
|
||
<span class="hljs-keyword">if</span> (code >= <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 >= <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 >= <span class="hljs-number">48</span> && code <= <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 >= 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> && 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">readHexNumber</span><span class="hljs-params">()</span> </span>{
|
||
tokPos += <span class="hljs-number">2</span>; <span class="hljs-comment">// 0x</span>
|
||
<span class="hljs-keyword">var</span> val = readInt(<span class="hljs-number">16</span>);
|
||
<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 hexadecimal number"</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">return</span> finishToken(_num, val);
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-75">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-75">¶</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 && 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-76">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-76">¶</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">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 >= 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>
|
||
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 && <span class="hljs-built_in">parseInt</span>(octal, <span class="hljs-number">8</span>) > <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>);
|
||
out += <span class="hljs-built_in">String</span>.fromCharCode(<span class="hljs-built_in">parseInt</span>(octal, <span class="hljs-number">8</span>));
|
||
tokPos += octal.length - <span class="hljs-number">1</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>: out += <span class="hljs-string">"\n"</span>; <span class="hljs-keyword">break</span>; <span class="hljs-comment">// 'n' -> '\n'</span>
|
||
<span class="hljs-keyword">case</span> <span class="hljs-number">114</span>: out += <span class="hljs-string">"\r"</span>; <span class="hljs-keyword">break</span>; <span class="hljs-comment">// 'r' -> '\r'</span>
|
||
<span class="hljs-keyword">case</span> <span class="hljs-number">120</span>: out += <span class="hljs-built_in">String</span>.fromCharCode(readHexChar(<span class="hljs-number">2</span>)); <span class="hljs-keyword">break</span>; <span class="hljs-comment">// 'x'</span>
|
||
<span class="hljs-keyword">case</span> <span class="hljs-number">117</span>: out += <span class="hljs-built_in">String</span>.fromCharCode(readHexChar(<span class="hljs-number">4</span>)); <span class="hljs-keyword">break</span>; <span class="hljs-comment">// 'u'</span>
|
||
<span class="hljs-keyword">case</span> <span class="hljs-number">85</span>: out += <span class="hljs-built_in">String</span>.fromCharCode(readHexChar(<span class="hljs-number">8</span>)); <span class="hljs-keyword">break</span>; <span class="hljs-comment">// 'U'</span>
|
||
<span class="hljs-keyword">case</span> <span class="hljs-number">116</span>: out += <span class="hljs-string">"\t"</span>; <span class="hljs-keyword">break</span>; <span class="hljs-comment">// 't' -> '\t'</span>
|
||
<span class="hljs-keyword">case</span> <span class="hljs-number">98</span>: out += <span class="hljs-string">"\b"</span>; <span class="hljs-keyword">break</span>; <span class="hljs-comment">// 'b' -> '\b'</span>
|
||
<span class="hljs-keyword">case</span> <span class="hljs-number">118</span>: out += <span class="hljs-string">"\u000b"</span>; <span class="hljs-keyword">break</span>; <span class="hljs-comment">// 'v' -> '\u000b'</span>
|
||
<span class="hljs-keyword">case</span> <span class="hljs-number">102</span>: out += <span class="hljs-string">"\f"</span>; <span class="hljs-keyword">break</span>; <span class="hljs-comment">// 'f' -> '\f'</span>
|
||
<span class="hljs-keyword">case</span> <span class="hljs-number">48</span>: out += <span class="hljs-string">"\0"</span>; <span class="hljs-keyword">break</span>; <span class="hljs-comment">// 0 -> '\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">break</span>;
|
||
<span class="hljs-keyword">default</span>: out += <span class="hljs-built_in">String</span>.fromCharCode(ch); <span class="hljs-keyword">break</span>;
|
||
}
|
||
}
|
||
} <span class="hljs-keyword">else</span> {
|
||
<span class="hljs-keyword">if</span> (ch === <span class="hljs-number">13</span> || ch === <span class="hljs-number">10</span> || ch === <span class="hljs-number">8232</span> || ch === <span class="hljs-number">8233</span>) 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>
|
||
++tokPos;
|
||
}
|
||
}
|
||
}
|
||
|
||
<span class="hljs-keyword">var</span> XHTMLEntities = {
|
||
quot: <span class="hljs-string">'\u0022'</span>,
|
||
amp: <span class="hljs-string">'&'</span>,
|
||
apos: <span class="hljs-string">'\u0027'</span>,
|
||
lt: <span class="hljs-string">'<'</span>,
|
||
gt: <span class="hljs-string">'>'</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">'&'</span>) raise(tokPos, <span class="hljs-string">"Entity must start with an ampersand"</span>);
|
||
tokPos++;
|
||
<span class="hljs-keyword">while</span> (tokPos < inputLen && count++ <span class="xml"><span class="hljs-tag">< <span class="hljs-attribute">10</span>) {
|
||
<span class="hljs-attribute">ch</span> = <span class="hljs-attribute">input.charAt</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> '#' && <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> < <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> '&') {
|
||
<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>' && <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>' && <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> && <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-77">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-77">¶</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-78">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-78">¶</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-79">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-79">¶</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 && ch === <span class="hljs-number">45</span>)) {
|
||
<span class="hljs-keyword">if</span> (containsEsc) word += input.charAt(tokPos);
|
||
++tokPos;
|
||
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (ch === <span class="hljs-number">92</span> && !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-80">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-80">¶</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 && isKeyword(word))
|
||
type = keywordTypes[word];
|
||
<span class="hljs-keyword">return</span> finishToken(type, word);
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-81">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-81">¶</a>
|
||
</div>
|
||
<h2 id="parser">Parser</h2>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-82">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-82">¶</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, it’ll 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-83">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-83">¶</a>
|
||
</div>
|
||
<h3 id="parser-utilities">Parser utilities</h3>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-84">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-84">¶</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-85">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-85">¶</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 < 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-86">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-86">¶</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-87">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-87">¶</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-88">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-88">¶</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-89">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-89">¶</a>
|
||
</div>
|
||
<p>Test whether a statement node is the string literal <code>"use strict"</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 >= <span class="hljs-number">5</span> && stmt.type === <span class="hljs-string">"ExpressionStatement"</span> &&
|
||
stmt.expression.type === <span class="hljs-string">"Literal"</span> && stmt.expression.value === <span class="hljs-string">"use strict"</span>;
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-90">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-90">¶</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>;
|
||
}
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-91">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-91">¶</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 &&
|
||
(tokType === _eof || tokType === _braceR || newline.test(input.slice(lastEnd, tokStart)));
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-92">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-92">¶</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) && !canInsertSemicolon()) unexpected();
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-93">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-93">¶</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>{
|
||
<span class="hljs-keyword">if</span> (tokType === type) next();
|
||
<span class="hljs-keyword">else</span> unexpected();
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-94">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-94">¶</a>
|
||
</div>
|
||
<p>Expect a char. 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">expectChar</span><span class="hljs-params">(ch)</span> </span>{
|
||
<span class="hljs-keyword">if</span> (tokVal === ch) next();
|
||
<span class="hljs-keyword">else</span> unexpected();
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-95">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-95">¶</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-96">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-96">¶</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">()</span> </span>{
|
||
raise(tokStart, <span class="hljs-string">"Unexpected token"</span>);
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-97">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-97">¶</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)</span> </span>{
|
||
<span class="hljs-keyword">if</span> (expr.type !== <span class="hljs-string">"Identifier"</span> && expr.type !== <span class="hljs-string">"MemberExpression"</span>)
|
||
raise(expr.start, <span class="hljs-string">"Assigning to rvalue"</span>);
|
||
<span class="hljs-keyword">if</span> (strict && expr.type === <span class="hljs-string">"Identifier"</span> && isStrictBadIdWord(expr.name))
|
||
raise(expr.start, <span class="hljs-string">"Assigning to "</span> + expr.name + <span class="hljs-string">" in strict mode"</span>);
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-98">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-98">¶</a>
|
||
</div>
|
||
<h3 id="statement-parsing">Statement parsing</h3>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-99">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-99">¶</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 = 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 && 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-100">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-100">¶</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 && 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-101">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-101">¶</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> _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);</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-102">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-102">¶</a>
|
||
</div>
|
||
<p>If the statement does not start with a statement keyword or a
|
||
brace, it’s 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 && expr.type === <span class="hljs-string">"Identifier"</span> && 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-103">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-103">¶</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 < 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> && (isBreak || lab.kind === <span class="hljs-string">"loop"</span>)) <span class="hljs-keyword">break</span>;
|
||
<span class="hljs-keyword">if</span> (node.label && 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-104">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-104">¶</a>
|
||
</div>
|
||
<p>Disambiguating between a <code>for</code> and a <code>for</code>/<code>in</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>. 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;
|
||
next();
|
||
parseVar(init, <span class="hljs-literal">true</span>, varKind);
|
||
finishNode(init, <span class="hljs-string">"VariableDeclaration"</span>);
|
||
<span class="hljs-keyword">if</span> (init.declarations.length === <span class="hljs-number">1</span> && eat(_in))
|
||
<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> (eat(_in)) {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 && !options.allowReturnOutsideFunction)
|
||
raise(tokStart, <span class="hljs-string">"'return' outside of function"</span>);
|
||
next();</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-105">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-105">¶</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-106">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-106">¶</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>);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 && 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 && !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 < 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-107">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-107">¶</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-108">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-108">¶</a>
|
||
</div>
|
||
<p>Parse a semicolon-enclosed block of statements, handling <code>"use
|
||
strict"</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 && allowStrict && 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 && !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-109">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-109">¶</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-110">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-110">¶</a>
|
||
</div>
|
||
<p>Parse a <code>for</code>/<code>in</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">parseForIn</span><span class="hljs-params">(node, init)</span> </span>{
|
||
node.left = init;
|
||
node.right = parseExpression();
|
||
expect(_parenR);
|
||
node.body = parseStatement();
|
||
labels.pop();
|
||
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"ForInStatement"</span>);
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-111">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-111">¶</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 = parseIdent();
|
||
<span class="hljs-keyword">if</span> (strict && isStrictBadIdWord(decl.id.name))
|
||
raise(decl.id.start, <span class="hljs-string">"Binding "</span> + decl.id.name + <span class="hljs-string">" in strict mode"</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-112">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-112">¶</a>
|
||
</div>
|
||
<h3 id="expression-parsing">Expression parsing</h3>
|
||
|
||
</div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-113">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-113">¶</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-114">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-114">¶</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 && 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-115">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-115">¶</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 = left;
|
||
next();
|
||
node.right = parseMaybeAssign(noIn);
|
||
checkLVal(left);
|
||
<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-116">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-116">¶</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-117">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-117">¶</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-118">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-118">¶</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> && (!noIn || tokType !== _in)) {
|
||
<span class="hljs-keyword">if</span> (prec > 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-119">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-119">¶</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 && node.operator === <span class="hljs-string">"delete"</span> &&
|
||
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 && !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-120">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-120">¶</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 && 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">return</span> base;
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-121">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-121">¶</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> _name:
|
||
<span class="hljs-keyword">return</span> parseIdent();
|
||
<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;
|
||
next();
|
||
<span class="hljs-keyword">var</span> val = parseExpression();
|
||
val.start = tokStart1;
|
||
val.end = tokEnd;
|
||
<span class="hljs-keyword">if</span> (options.locations) {
|
||
val.loc.start = tokStartLoc1;
|
||
val.loc.end = tokEndLoc;
|
||
}
|
||
<span class="hljs-keyword">if</span> (options.ranges)
|
||
val.range = [tokStart1, tokEnd];
|
||
expect(_parenR);
|
||
<span class="hljs-keyword">return</span> val;
|
||
|
||
<span class="hljs-keyword">case</span> _bracketL:
|
||
<span class="hljs-keyword">var</span> node = startNode();
|
||
next();
|
||
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> _new:
|
||
<span class="hljs-keyword">return</span> parseNew();
|
||
|
||
<span class="hljs-keyword">case</span> _relational:
|
||
<span class="hljs-keyword">if</span> (tokVal === <span class="hljs-string">'<'</span>) {
|
||
<span class="hljs-keyword">return</span> parseXJSElement();
|
||
}
|
||
|
||
<span class="hljs-keyword">default</span>:
|
||
unexpected();
|
||
}
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-122">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-122">¶</a>
|
||
</div>
|
||
<p>New’s 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-123">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-123">¶</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>, sawGetSet = <span class="hljs-literal">false</span>;
|
||
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 && 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 = {key: parsePropertyName()}, isGetSet = <span class="hljs-literal">false</span>, kind;
|
||
<span class="hljs-keyword">if</span> (eat(_colon)) {
|
||
prop.value = parseExpression(<span class="hljs-literal">true</span>);
|
||
kind = prop.kind = <span class="hljs-string">"init"</span>;
|
||
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (options.ecmaVersion >= <span class="hljs-number">5</span> && prop.key.type === <span class="hljs-string">"Identifier"</span> &&
|
||
(prop.key.name === <span class="hljs-string">"get"</span> || prop.key.name === <span class="hljs-string">"set"</span>)) {
|
||
isGetSet = sawGetSet = <span class="hljs-literal">true</span>;
|
||
kind = prop.kind = prop.key.name;
|
||
prop.key = parsePropertyName();
|
||
<span class="hljs-keyword">if</span> (tokType !== _parenL) unexpected();
|
||
prop.value = parseFunction(startNode(), <span class="hljs-literal">false</span>);
|
||
} <span class="hljs-keyword">else</span> unexpected();</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-124">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-124">¶</a>
|
||
</div>
|
||
<p>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-keyword">if</span> (prop.key.type === <span class="hljs-string">"Identifier"</span> && (strict || sawGetSet)) {
|
||
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i < node.properties.length; ++i) {
|
||
<span class="hljs-keyword">var</span> other = node.properties[i];
|
||
<span class="hljs-keyword">if</span> (other.key.name === prop.key.name) {
|
||
<span class="hljs-keyword">var</span> conflict = kind == other.kind || isGetSet && other.kind === <span class="hljs-string">"init"</span> ||
|
||
kind === <span class="hljs-string">"init"</span> && (other.kind === <span class="hljs-string">"get"</span> || other.kind === <span class="hljs-string">"set"</span>);
|
||
<span class="hljs-keyword">if</span> (conflict && !strict && kind === <span class="hljs-string">"init"</span> && other.kind === <span class="hljs-string">"init"</span>) conflict = <span class="hljs-literal">false</span>;
|
||
<span class="hljs-keyword">if</span> (conflict) raise(prop.key.start, <span class="hljs-string">"Redefinition of property"</span>);
|
||
}
|
||
}
|
||
}
|
||
node.properties.push(prop);
|
||
}
|
||
<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">()</span> </span>{
|
||
<span class="hljs-keyword">if</span> (tokType === _num || tokType === _string) <span class="hljs-keyword">return</span> parseExprAtom();
|
||
<span class="hljs-keyword">return</span> parseIdent(<span class="hljs-literal">true</span>);
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-125">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-125">¶</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)</span> </span>{
|
||
<span class="hljs-keyword">if</span> (tokType === _name) node.id = parseIdent();
|
||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (isStatement) unexpected();
|
||
<span class="hljs-keyword">else</span> node.id = <span class="hljs-literal">null</span>;
|
||
node.params = [];
|
||
node.rest = <span class="hljs-literal">null</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 >= <span class="hljs-number">6</span> && eat(_ellipsis)) {
|
||
node.rest = parseIdent();
|
||
expect(_parenR);
|
||
<span class="hljs-keyword">break</span>;
|
||
} <span class="hljs-keyword">else</span> {
|
||
node.params.push(parseIdent());
|
||
<span class="hljs-keyword">if</span> (!eat(_comma)) {
|
||
expect(_parenR);
|
||
<span class="hljs-keyword">break</span>;
|
||
}
|
||
}
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-126">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-126">¶</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, oldLabels = labels;
|
||
inFunction = <span class="hljs-literal">true</span>; labels = [];
|
||
node.body = parseBlock(<span class="hljs-literal">true</span>);
|
||
inFunction = oldInFunc; labels = oldLabels;</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-127">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-127">¶</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 || node.body.body.length && isUseStrict(node.body.body[<span class="hljs-number">0</span>])) {</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-128">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-128">¶</a>
|
||
</div>
|
||
<p>Negative indices are used to reuse loop body for node.rest and node.id</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">2</span>, id; i < node.params.length; ++i) {
|
||
<span class="hljs-keyword">if</span> (i >= <span class="hljs-number">0</span>) {
|
||
id = node.params[i];
|
||
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (i == -<span class="hljs-number">2</span>) {
|
||
<span class="hljs-keyword">if</span> (node.rest) id = node.rest;
|
||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">continue</span>;
|
||
} <span class="hljs-keyword">else</span> {
|
||
<span class="hljs-keyword">if</span> (node.id) id = node.id;
|
||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">continue</span>;
|
||
}
|
||
<span class="hljs-keyword">if</span> (isStrictReservedWord(id.name) || isStrictBadIdWord(id.name))
|
||
raise(id.start, <span class="hljs-string">"Defining '"</span> + id.name + <span class="hljs-string">"' in strict mode"</span>);
|
||
<span class="hljs-keyword">if</span> (i >= <span class="hljs-number">0</span>) <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> j = <span class="hljs-number">0</span>; j < i; ++j) <span class="hljs-keyword">if</span> (id.name === node.params[j].name)
|
||
raise(id.start, <span class="hljs-string">"Argument name clash in strict mode"</span>);
|
||
}
|
||
}
|
||
|
||
<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-129">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-129">¶</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 && options.allowTrailingCommas && 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 && 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-130">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-130">¶</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 && 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 &&
|
||
(options.forbidReserved &&
|
||
(options.ecmaVersion === <span class="hljs-number">3</span> ? isReservedWord3 : isReservedWord5)(tokVal) ||
|
||
strict && isStrictReservedWord(tokVal)) &&
|
||
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 && 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-131">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-131">¶</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-132">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-132">¶</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-133">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-133">¶</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-134">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-134">¶</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-135">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-135">¶</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-136">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-136">¶</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-137">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-137">¶</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">var</span> node;
|
||
<span class="hljs-keyword">if</span> (tokType === _braceL) {
|
||
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">else</span> <span class="hljs-keyword">if</span> (tokVal === <span class="hljs-string">'<'</span>) {
|
||
node = parseXJSElement();
|
||
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (tokType === _xjsText) {
|
||
node = parseExprAtom();
|
||
} <span class="hljs-keyword">else</span> {
|
||
raise(tokStart, <span class="hljs-string">"XJS value should be either an expression or a quoted XJS text"</span>);
|
||
}
|
||
<span class="hljs-keyword">return</span> node;
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-138">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-138">¶</a>
|
||
</div>
|
||
<p>XJSEmptyExpression is unique type since it doesn’t 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-139">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-139">¶</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>;
|
||
|
||
expect(_braceL);
|
||
|
||
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-140">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-140">¶</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">var</span> node = startNode();
|
||
|
||
node.name = parseXJSAttributeName();</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-141">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-141">¶</a>
|
||
</div>
|
||
<p>HTML empty attribute</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (tokVal === <span class="hljs-string">"="</span>) {
|
||
next();
|
||
node.value = parseXJSAttributeValue();
|
||
}
|
||
|
||
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"XJSAttribute"</span>);
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-142">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-142">¶</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-143">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-143">¶</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>;
|
||
|
||
expectChar(<span class="hljs-string">'<'</span>);
|
||
|
||
node.name = parseXJSElementName();
|
||
|
||
<span class="hljs-keyword">while</span> (tokType !== _eof && tokType !== _slash && tokVal !== <span class="hljs-string">'>'</span>) {
|
||
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>;
|
||
}
|
||
|
||
expectChar(<span class="hljs-string">'>'</span>);
|
||
|
||
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"XJSOpeningElement"</span>);
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-144">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-144">¶</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>;
|
||
expectChar(<span class="hljs-string">'<'</span>);
|
||
expect(_slash);
|
||
node.name = parseXJSElementName();
|
||
skipSpace();</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-145">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-145">¶</a>
|
||
</div>
|
||
<p>A valid token is expected after >, 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>;
|
||
expectChar(<span class="hljs-string">'>'</span>);
|
||
<span class="hljs-keyword">return</span> finishNode(node, <span class="hljs-string">"XJSClosingElement"</span>);
|
||
}</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-146">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-146">¶</a>
|
||
</div>
|
||
<p>Parses entire JSX element, including it’s 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">if</span> (!openingElement.selfClosing) {
|
||
<span class="hljs-keyword">while</span> (tokType !== _eof && !(tokVal === <span class="hljs-string">'<'</span> && nextChar() === <span class="hljs-string">'/'</span>)) {
|
||
inXJSChild = <span class="hljs-literal">true</span>;
|
||
children.push(parseXJSChild());
|
||
}
|
||
inXJSChild = origInXJSChild;
|
||
<span class="hljs-keyword">var</span> 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-147">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-147">¶</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"><<span class="hljs-title">div</span>></span>one<span class="hljs-tag"></<span class="hljs-title">div</span>></span><span class="hljs-tag"><<span class="hljs-title">div</span>></span>two<span class="hljs-tag"></<span class="hljs-title">div</span>></span>;</span>
|
||
</code></pre><p>the default error message is a bit incomprehensible. Since it’s
|
||
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 && tokVal === <span class="hljs-string">'<'</span>) {
|
||
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>
|