1295 lines
302 KiB
HTML
1295 lines
302 KiB
HTML
<!DOCTYPE html> <html> <head> <title>acorn.js</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> acorn.js </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <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://marijnhaverbeke.nl/git/acorn
|
|
https://github.com/marijnh/acorn.git
|
|
</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> </td> <td class="code"> <div class="highlight"><pre><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">root</span><span class="p">,</span> <span class="nx">mod</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">exports</span> <span class="o">==</span> <span class="s2">"object"</span> <span class="o">&&</span> <span class="k">typeof</span> <span class="nx">module</span> <span class="o">==</span> <span class="s2">"object"</span><span class="p">)</span> <span class="k">return</span> <span class="nx">mod</span><span class="p">(</span><span class="nx">exports</span><span class="p">);</span> <span class="c1">// CommonJS</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">define</span> <span class="o">==</span> <span class="s2">"function"</span> <span class="o">&&</span> <span class="nx">define</span><span class="p">.</span><span class="nx">amd</span><span class="p">)</span> <span class="k">return</span> <span class="nx">define</span><span class="p">([</span><span class="s2">"exports"</span><span class="p">],</span> <span class="nx">mod</span><span class="p">);</span> <span class="c1">// AMD</span>
|
|
<span class="nx">mod</span><span class="p">(</span><span class="nx">root</span><span class="p">.</span><span class="nx">acorn</span> <span class="o">||</span> <span class="p">(</span><span class="nx">root</span><span class="p">.</span><span class="nx">acorn</span> <span class="o">=</span> <span class="p">{}));</span> <span class="c1">// Plain browser env</span>
|
|
<span class="p">})(</span><span class="k">this</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">exports</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="s2">"use strict"</span><span class="p">;</span>
|
|
|
|
<span class="nx">exports</span><span class="p">.</span><span class="nx">version</span> <span class="o">=</span> <span class="s2">"0.3.2"</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">options</span><span class="p">,</span> <span class="nx">input</span><span class="p">,</span> <span class="nx">inputLen</span><span class="p">,</span> <span class="nx">sourceFile</span><span class="p">;</span>
|
|
|
|
<span class="nx">exports</span><span class="p">.</span><span class="nx">parse</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">inpt</span><span class="p">,</span> <span class="nx">opts</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">input</span> <span class="o">=</span> <span class="nb">String</span><span class="p">(</span><span class="nx">inpt</span><span class="p">);</span> <span class="nx">inputLen</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
|
|
<span class="nx">setOptions</span><span class="p">(</span><span class="nx">opts</span><span class="p">);</span>
|
|
<span class="nx">initTokenState</span><span class="p">();</span>
|
|
<span class="k">return</span> <span class="nx">parseTopLevel</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">program</span><span class="p">);</span>
|
|
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">defaultOptions</span> <span class="o">=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">defaultOptions</span> <span class="o">=</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <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. This
|
|
influences support for strict mode, the set of reserved words, and
|
|
support for getters and setter.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ecmaVersion</span><span class="o">:</span> <span class="mi">5</span><span class="p">,</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <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> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">strictSemicolons</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <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> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">allowTrailingCommas</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <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.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">forbidReserved</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">locations</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</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.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">onComment</span><span class="o">:</span> <span class="kc">null</span><span class="p">,</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ranges</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">program</span><span class="o">:</span> <span class="kc">null</span><span class="p">,</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>When <code>location</code> is on, you can pass this to record the source
|
|
file in every node's <code>loc</code> object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">sourceFile</span><span class="o">:</span> <span class="kc">null</span>
|
|
<span class="p">};</span>
|
|
|
|
<span class="kd">function</span> <span class="nx">setOptions</span><span class="p">(</span><span class="nx">opts</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">options</span> <span class="o">=</span> <span class="nx">opts</span> <span class="o">||</span> <span class="p">{};</span>
|
|
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">opt</span> <span class="k">in</span> <span class="nx">defaultOptions</span><span class="p">)</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nb">Object</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">hasOwnProperty</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="nx">options</span><span class="p">,</span> <span class="nx">opt</span><span class="p">))</span>
|
|
<span class="nx">options</span><span class="p">[</span><span class="nx">opt</span><span class="p">]</span> <span class="o">=</span> <span class="nx">defaultOptions</span><span class="p">[</span><span class="nx">opt</span><span class="p">];</span>
|
|
<span class="nx">sourceFile</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sourceFile</span> <span class="o">||</span> <span class="kc">null</span><span class="p">;</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">getLineInfo</span> <span class="o">=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">getLineInfo</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">input</span><span class="p">,</span> <span class="nx">offset</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">line</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">cur</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;;)</span> <span class="p">{</span>
|
|
<span class="nx">lineBreak</span><span class="p">.</span><span class="nx">lastIndex</span> <span class="o">=</span> <span class="nx">cur</span><span class="p">;</span>
|
|
<span class="kd">var</span> <span class="nx">match</span> <span class="o">=</span> <span class="nx">lineBreak</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="nx">input</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">match</span> <span class="o">&&</span> <span class="nx">match</span><span class="p">.</span><span class="nx">index</span> <span class="o"><</span> <span class="nx">offset</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="o">++</span><span class="nx">line</span><span class="p">;</span>
|
|
<span class="nx">cur</span> <span class="o">=</span> <span class="nx">match</span><span class="p">.</span><span class="nx">index</span> <span class="o">+</span> <span class="nx">match</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">length</span><span class="p">;</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="k">break</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="k">return</span> <span class="p">{</span><span class="nx">line</span><span class="o">:</span> <span class="nx">line</span><span class="p">,</span> <span class="nx">column</span><span class="o">:</span> <span class="nx">offset</span> <span class="o">-</span> <span class="nx">cur</span><span class="p">};</span>
|
|
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">exports</span><span class="p">.</span><span class="nx">tokenize</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">inpt</span><span class="p">,</span> <span class="nx">opts</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">input</span> <span class="o">=</span> <span class="nb">String</span><span class="p">(</span><span class="nx">inpt</span><span class="p">);</span> <span class="nx">inputLen</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
|
|
<span class="nx">setOptions</span><span class="p">(</span><span class="nx">opts</span><span class="p">);</span>
|
|
<span class="nx">initTokenState</span><span class="p">();</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">t</span> <span class="o">=</span> <span class="p">{};</span>
|
|
<span class="kd">function</span> <span class="nx">getToken</span><span class="p">(</span><span class="nx">forceRegexp</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">readToken</span><span class="p">(</span><span class="nx">forceRegexp</span><span class="p">);</span>
|
|
<span class="nx">t</span><span class="p">.</span><span class="nx">start</span> <span class="o">=</span> <span class="nx">tokStart</span><span class="p">;</span> <span class="nx">t</span><span class="p">.</span><span class="nx">end</span> <span class="o">=</span> <span class="nx">tokEnd</span><span class="p">;</span>
|
|
<span class="nx">t</span><span class="p">.</span><span class="nx">startLoc</span> <span class="o">=</span> <span class="nx">tokStartLoc</span><span class="p">;</span> <span class="nx">t</span><span class="p">.</span><span class="nx">endLoc</span> <span class="o">=</span> <span class="nx">tokEndLoc</span><span class="p">;</span>
|
|
<span class="nx">t</span><span class="p">.</span><span class="nx">type</span> <span class="o">=</span> <span class="nx">tokType</span><span class="p">;</span> <span class="nx">t</span><span class="p">.</span><span class="nx">value</span> <span class="o">=</span> <span class="nx">tokVal</span><span class="p">;</span>
|
|
<span class="k">return</span> <span class="nx">t</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="nx">getToken</span><span class="p">.</span><span class="nx">jumpTo</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">pos</span><span class="p">,</span> <span class="nx">reAllowed</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">tokPos</span> <span class="o">=</span> <span class="nx">pos</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">locations</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">tokCurLine</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
|
|
<span class="nx">tokLineStart</span> <span class="o">=</span> <span class="nx">lineBreak</span><span class="p">.</span><span class="nx">lastIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
|
|
<span class="kd">var</span> <span class="nx">match</span><span class="p">;</span>
|
|
<span class="k">while</span> <span class="p">((</span><span class="nx">match</span> <span class="o">=</span> <span class="nx">lineBreak</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="nx">input</span><span class="p">))</span> <span class="o">&&</span> <span class="nx">match</span><span class="p">.</span><span class="nx">index</span> <span class="o"><</span> <span class="nx">pos</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="o">++</span><span class="nx">tokCurLine</span><span class="p">;</span>
|
|
<span class="nx">tokLineStart</span> <span class="o">=</span> <span class="nx">match</span><span class="p">.</span><span class="nx">index</span> <span class="o">+</span> <span class="nx">match</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">length</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="nx">tokRegexpAllowed</span> <span class="o">=</span> <span class="nx">reAllowed</span><span class="p">;</span>
|
|
<span class="nx">skipSpace</span><span class="p">();</span>
|
|
<span class="p">};</span>
|
|
<span class="k">return</span> <span class="nx">getToken</span><span class="p">;</span>
|
|
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</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> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>The current position of the tokenizer in the input.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">tokPos</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>The start and end offsets of the current token.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">tokStart</span><span class="p">,</span> <span class="nx">tokEnd</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <p>When <code>options.locations</code> is true, these hold objects
|
|
containing the tokens start and end line/column pairs.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">tokStartLoc</span><span class="p">,</span> <span class="nx">tokEndLoc</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">tokType</span><span class="p">,</span> <span class="nx">tokVal</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">tokRegexpAllowed</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">tokCurLine</span><span class="p">,</span> <span class="nx">tokLineStart</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">lastStart</span><span class="p">,</span> <span class="nx">lastEnd</span><span class="p">,</span> <span class="nx">lastEndLoc</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">inFunction</span><span class="p">,</span> <span class="nx">labels</span><span class="p">,</span> <span class="nx">strict</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">pos</span><span class="p">,</span> <span class="nx">message</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">loc</span> <span class="o">=</span> <span class="nx">getLineInfo</span><span class="p">(</span><span class="nx">input</span><span class="p">,</span> <span class="nx">pos</span><span class="p">);</span>
|
|
<span class="nx">message</span> <span class="o">+=</span> <span class="s2">" ("</span> <span class="o">+</span> <span class="nx">loc</span><span class="p">.</span><span class="nx">line</span> <span class="o">+</span> <span class="s2">":"</span> <span class="o">+</span> <span class="nx">loc</span><span class="p">.</span><span class="nx">column</span> <span class="o">+</span> <span class="s2">")"</span><span class="p">;</span>
|
|
<span class="kd">var</span> <span class="nx">err</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">SyntaxError</span><span class="p">(</span><span class="nx">message</span><span class="p">);</span>
|
|
<span class="nx">err</span><span class="p">.</span><span class="nx">pos</span> <span class="o">=</span> <span class="nx">pos</span><span class="p">;</span> <span class="nx">err</span><span class="p">.</span><span class="nx">loc</span> <span class="o">=</span> <span class="nx">loc</span><span class="p">;</span> <span class="nx">err</span><span class="p">.</span><span class="nx">raisedAt</span> <span class="o">=</span> <span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="k">throw</span> <span class="nx">err</span><span class="p">;</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">¶</a> </div> <p>Reused empty array added for node fields that are always empty.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">empty</span> <span class="o">=</span> <span class="p">[];</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">¶</a> </div> <h2>Token types</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">¶</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> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">¶</a> </div> <p>All token type variables start with an underscore, to make them
|
|
easy to recognize.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-29">¶</a> </div> <p>These are the general types. The <code>type</code> property is only used to
|
|
make them recognizeable when debugging.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">_num</span> <span class="o">=</span> <span class="p">{</span><span class="nx">type</span><span class="o">:</span> <span class="s2">"num"</span><span class="p">},</span> <span class="nx">_regexp</span> <span class="o">=</span> <span class="p">{</span><span class="nx">type</span><span class="o">:</span> <span class="s2">"regexp"</span><span class="p">},</span> <span class="nx">_string</span> <span class="o">=</span> <span class="p">{</span><span class="nx">type</span><span class="o">:</span> <span class="s2">"string"</span><span class="p">};</span>
|
|
<span class="kd">var</span> <span class="nx">_name</span> <span class="o">=</span> <span class="p">{</span><span class="nx">type</span><span class="o">:</span> <span class="s2">"name"</span><span class="p">},</span> <span class="nx">_eof</span> <span class="o">=</span> <span class="p">{</span><span class="nx">type</span><span class="o">:</span> <span class="s2">"eof"</span><span class="p">};</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-30">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">_break</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"break"</span><span class="p">},</span> <span class="nx">_case</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"case"</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">},</span> <span class="nx">_catch</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"catch"</span><span class="p">};</span>
|
|
<span class="kd">var</span> <span class="nx">_continue</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"continue"</span><span class="p">},</span> <span class="nx">_debugger</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"debugger"</span><span class="p">},</span> <span class="nx">_default</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"default"</span><span class="p">};</span>
|
|
<span class="kd">var</span> <span class="nx">_do</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"do"</span><span class="p">,</span> <span class="nx">isLoop</span><span class="o">:</span> <span class="kc">true</span><span class="p">},</span> <span class="nx">_else</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"else"</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">};</span>
|
|
<span class="kd">var</span> <span class="nx">_finally</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"finally"</span><span class="p">},</span> <span class="nx">_for</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"for"</span><span class="p">,</span> <span class="nx">isLoop</span><span class="o">:</span> <span class="kc">true</span><span class="p">},</span> <span class="nx">_function</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"function"</span><span class="p">};</span>
|
|
<span class="kd">var</span> <span class="nx">_if</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"if"</span><span class="p">},</span> <span class="nx">_return</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"return"</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">},</span> <span class="nx">_switch</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"switch"</span><span class="p">};</span>
|
|
<span class="kd">var</span> <span class="nx">_throw</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"throw"</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">},</span> <span class="nx">_try</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"try"</span><span class="p">},</span> <span class="nx">_var</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"var"</span><span class="p">};</span>
|
|
<span class="kd">var</span> <span class="nx">_while</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"while"</span><span class="p">,</span> <span class="nx">isLoop</span><span class="o">:</span> <span class="kc">true</span><span class="p">},</span> <span class="nx">_with</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"with"</span><span class="p">},</span> <span class="nx">_new</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"new"</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">};</span>
|
|
<span class="kd">var</span> <span class="nx">_this</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"this"</span><span class="p">};</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-31">¶</a> </div> <p>The keywords that denote values.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">_null</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"null"</span><span class="p">,</span> <span class="nx">atomValue</span><span class="o">:</span> <span class="kc">null</span><span class="p">},</span> <span class="nx">_true</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"true"</span><span class="p">,</span> <span class="nx">atomValue</span><span class="o">:</span> <span class="kc">true</span><span class="p">};</span>
|
|
<span class="kd">var</span> <span class="nx">_false</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"false"</span><span class="p">,</span> <span class="nx">atomValue</span><span class="o">:</span> <span class="kc">false</span><span class="p">};</span></pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-32">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">_in</span> <span class="o">=</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"in"</span><span class="p">,</span> <span class="nx">binop</span><span class="o">:</span> <span class="mi">7</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">};</span></pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-33">¶</a> </div> <p>Map keyword names to token types.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">keywordTypes</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"break"</span><span class="o">:</span> <span class="nx">_break</span><span class="p">,</span> <span class="s2">"case"</span><span class="o">:</span> <span class="nx">_case</span><span class="p">,</span> <span class="s2">"catch"</span><span class="o">:</span> <span class="nx">_catch</span><span class="p">,</span>
|
|
<span class="s2">"continue"</span><span class="o">:</span> <span class="nx">_continue</span><span class="p">,</span> <span class="s2">"debugger"</span><span class="o">:</span> <span class="nx">_debugger</span><span class="p">,</span> <span class="s2">"default"</span><span class="o">:</span> <span class="nx">_default</span><span class="p">,</span>
|
|
<span class="s2">"do"</span><span class="o">:</span> <span class="nx">_do</span><span class="p">,</span> <span class="s2">"else"</span><span class="o">:</span> <span class="nx">_else</span><span class="p">,</span> <span class="s2">"finally"</span><span class="o">:</span> <span class="nx">_finally</span><span class="p">,</span> <span class="s2">"for"</span><span class="o">:</span> <span class="nx">_for</span><span class="p">,</span>
|
|
<span class="s2">"function"</span><span class="o">:</span> <span class="nx">_function</span><span class="p">,</span> <span class="s2">"if"</span><span class="o">:</span> <span class="nx">_if</span><span class="p">,</span> <span class="s2">"return"</span><span class="o">:</span> <span class="nx">_return</span><span class="p">,</span> <span class="s2">"switch"</span><span class="o">:</span> <span class="nx">_switch</span><span class="p">,</span>
|
|
<span class="s2">"throw"</span><span class="o">:</span> <span class="nx">_throw</span><span class="p">,</span> <span class="s2">"try"</span><span class="o">:</span> <span class="nx">_try</span><span class="p">,</span> <span class="s2">"var"</span><span class="o">:</span> <span class="nx">_var</span><span class="p">,</span> <span class="s2">"while"</span><span class="o">:</span> <span class="nx">_while</span><span class="p">,</span> <span class="s2">"with"</span><span class="o">:</span> <span class="nx">_with</span><span class="p">,</span>
|
|
<span class="s2">"null"</span><span class="o">:</span> <span class="nx">_null</span><span class="p">,</span> <span class="s2">"true"</span><span class="o">:</span> <span class="nx">_true</span><span class="p">,</span> <span class="s2">"false"</span><span class="o">:</span> <span class="nx">_false</span><span class="p">,</span> <span class="s2">"new"</span><span class="o">:</span> <span class="nx">_new</span><span class="p">,</span> <span class="s2">"in"</span><span class="o">:</span> <span class="nx">_in</span><span class="p">,</span>
|
|
<span class="s2">"instanceof"</span><span class="o">:</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"instanceof"</span><span class="p">,</span> <span class="nx">binop</span><span class="o">:</span> <span class="mi">7</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">},</span> <span class="s2">"this"</span><span class="o">:</span> <span class="nx">_this</span><span class="p">,</span>
|
|
<span class="s2">"typeof"</span><span class="o">:</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"typeof"</span><span class="p">,</span> <span class="nx">prefix</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">},</span>
|
|
<span class="s2">"void"</span><span class="o">:</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"void"</span><span class="p">,</span> <span class="nx">prefix</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">},</span>
|
|
<span class="s2">"delete"</span><span class="o">:</span> <span class="p">{</span><span class="nx">keyword</span><span class="o">:</span> <span class="s2">"delete"</span><span class="p">,</span> <span class="nx">prefix</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">}};</span></pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-34">¶</a> </div> <p>Punctuation token types. Again, the <code>type</code> property is purely for debugging.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">_bracketL</span> <span class="o">=</span> <span class="p">{</span><span class="nx">type</span><span class="o">:</span> <span class="s2">"["</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">},</span> <span class="nx">_bracketR</span> <span class="o">=</span> <span class="p">{</span><span class="nx">type</span><span class="o">:</span> <span class="s2">"]"</span><span class="p">},</span> <span class="nx">_braceL</span> <span class="o">=</span> <span class="p">{</span><span class="nx">type</span><span class="o">:</span> <span class="s2">"{"</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">};</span>
|
|
<span class="kd">var</span> <span class="nx">_braceR</span> <span class="o">=</span> <span class="p">{</span><span class="nx">type</span><span class="o">:</span> <span class="s2">"}"</span><span class="p">},</span> <span class="nx">_parenL</span> <span class="o">=</span> <span class="p">{</span><span class="nx">type</span><span class="o">:</span> <span class="s2">"("</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">},</span> <span class="nx">_parenR</span> <span class="o">=</span> <span class="p">{</span><span class="nx">type</span><span class="o">:</span> <span class="s2">")"</span><span class="p">};</span>
|
|
<span class="kd">var</span> <span class="nx">_comma</span> <span class="o">=</span> <span class="p">{</span><span class="nx">type</span><span class="o">:</span> <span class="s2">","</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">},</span> <span class="nx">_semi</span> <span class="o">=</span> <span class="p">{</span><span class="nx">type</span><span class="o">:</span> <span class="s2">";"</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">};</span>
|
|
<span class="kd">var</span> <span class="nx">_colon</span> <span class="o">=</span> <span class="p">{</span><span class="nx">type</span><span class="o">:</span> <span class="s2">":"</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">},</span> <span class="nx">_dot</span> <span class="o">=</span> <span class="p">{</span><span class="nx">type</span><span class="o">:</span> <span class="s2">"."</span><span class="p">},</span> <span class="nx">_question</span> <span class="o">=</span> <span class="p">{</span><span class="nx">type</span><span class="o">:</span> <span class="s2">"?"</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">};</span></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-35">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">_slash</span> <span class="o">=</span> <span class="p">{</span><span class="nx">binop</span><span class="o">:</span> <span class="mi">10</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">},</span> <span class="nx">_eq</span> <span class="o">=</span> <span class="p">{</span><span class="nx">isAssign</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">};</span>
|
|
<span class="kd">var</span> <span class="nx">_assign</span> <span class="o">=</span> <span class="p">{</span><span class="nx">isAssign</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">},</span> <span class="nx">_plusmin</span> <span class="o">=</span> <span class="p">{</span><span class="nx">binop</span><span class="o">:</span> <span class="mi">9</span><span class="p">,</span> <span class="nx">prefix</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">};</span>
|
|
<span class="kd">var</span> <span class="nx">_incdec</span> <span class="o">=</span> <span class="p">{</span><span class="nx">postfix</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">prefix</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">isUpdate</span><span class="o">:</span> <span class="kc">true</span><span class="p">},</span> <span class="nx">_prefix</span> <span class="o">=</span> <span class="p">{</span><span class="nx">prefix</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">};</span>
|
|
<span class="kd">var</span> <span class="nx">_bin1</span> <span class="o">=</span> <span class="p">{</span><span class="nx">binop</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">},</span> <span class="nx">_bin2</span> <span class="o">=</span> <span class="p">{</span><span class="nx">binop</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">};</span>
|
|
<span class="kd">var</span> <span class="nx">_bin3</span> <span class="o">=</span> <span class="p">{</span><span class="nx">binop</span><span class="o">:</span> <span class="mi">3</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">},</span> <span class="nx">_bin4</span> <span class="o">=</span> <span class="p">{</span><span class="nx">binop</span><span class="o">:</span> <span class="mi">4</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">};</span>
|
|
<span class="kd">var</span> <span class="nx">_bin5</span> <span class="o">=</span> <span class="p">{</span><span class="nx">binop</span><span class="o">:</span> <span class="mi">5</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">},</span> <span class="nx">_bin6</span> <span class="o">=</span> <span class="p">{</span><span class="nx">binop</span><span class="o">:</span> <span class="mi">6</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">};</span>
|
|
<span class="kd">var</span> <span class="nx">_bin7</span> <span class="o">=</span> <span class="p">{</span><span class="nx">binop</span><span class="o">:</span> <span class="mi">7</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">},</span> <span class="nx">_bin8</span> <span class="o">=</span> <span class="p">{</span><span class="nx">binop</span><span class="o">:</span> <span class="mi">8</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">};</span>
|
|
<span class="kd">var</span> <span class="nx">_bin10</span> <span class="o">=</span> <span class="p">{</span><span class="nx">binop</span><span class="o">:</span> <span class="mi">10</span><span class="p">,</span> <span class="nx">beforeExpr</span><span class="o">:</span> <span class="kc">true</span><span class="p">};</span></pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-36">¶</a> </div> <p>Provide access to the token types for external users of the
|
|
tokenizer.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">exports</span><span class="p">.</span><span class="nx">tokTypes</span> <span class="o">=</span> <span class="p">{</span><span class="nx">bracketL</span><span class="o">:</span> <span class="nx">_bracketL</span><span class="p">,</span> <span class="nx">bracketR</span><span class="o">:</span> <span class="nx">_bracketR</span><span class="p">,</span> <span class="nx">braceL</span><span class="o">:</span> <span class="nx">_braceL</span><span class="p">,</span> <span class="nx">braceR</span><span class="o">:</span> <span class="nx">_braceR</span><span class="p">,</span>
|
|
<span class="nx">parenL</span><span class="o">:</span> <span class="nx">_parenL</span><span class="p">,</span> <span class="nx">parenR</span><span class="o">:</span> <span class="nx">_parenR</span><span class="p">,</span> <span class="nx">comma</span><span class="o">:</span> <span class="nx">_comma</span><span class="p">,</span> <span class="nx">semi</span><span class="o">:</span> <span class="nx">_semi</span><span class="p">,</span> <span class="nx">colon</span><span class="o">:</span> <span class="nx">_colon</span><span class="p">,</span>
|
|
<span class="nx">dot</span><span class="o">:</span> <span class="nx">_dot</span><span class="p">,</span> <span class="nx">question</span><span class="o">:</span> <span class="nx">_question</span><span class="p">,</span> <span class="nx">slash</span><span class="o">:</span> <span class="nx">_slash</span><span class="p">,</span> <span class="nx">eq</span><span class="o">:</span> <span class="nx">_eq</span><span class="p">,</span> <span class="nx">name</span><span class="o">:</span> <span class="nx">_name</span><span class="p">,</span> <span class="nx">eof</span><span class="o">:</span> <span class="nx">_eof</span><span class="p">,</span>
|
|
<span class="nx">num</span><span class="o">:</span> <span class="nx">_num</span><span class="p">,</span> <span class="nx">regexp</span><span class="o">:</span> <span class="nx">_regexp</span><span class="p">,</span> <span class="nx">string</span><span class="o">:</span> <span class="nx">_string</span><span class="p">};</span>
|
|
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">kw</span> <span class="k">in</span> <span class="nx">keywordTypes</span><span class="p">)</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">tokTypes</span><span class="p">[</span><span class="s2">"_"</span> <span class="o">+</span> <span class="nx">kw</span><span class="p">]</span> <span class="o">=</span> <span class="nx">keywordTypes</span><span class="p">[</span><span class="nx">kw</span><span class="p">];</span></pre></div> </td> </tr> <tr id="section-37"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-37">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">makePredicate</span><span class="p">(</span><span class="nx">words</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">words</span> <span class="o">=</span> <span class="nx">words</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s2">" "</span><span class="p">);</span>
|
|
<span class="kd">var</span> <span class="nx">f</span> <span class="o">=</span> <span class="s2">""</span><span class="p">,</span> <span class="nx">cats</span> <span class="o">=</span> <span class="p">[];</span>
|
|
<span class="nx">out</span><span class="o">:</span> <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">words</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="o">++</span><span class="nx">i</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">j</span> <span class="o"><</span> <span class="nx">cats</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="o">++</span><span class="nx">j</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">cats</span><span class="p">[</span><span class="nx">j</span><span class="p">][</span><span class="mi">0</span><span class="p">].</span><span class="nx">length</span> <span class="o">==</span> <span class="nx">words</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">length</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">cats</span><span class="p">[</span><span class="nx">j</span><span class="p">].</span><span class="nx">push</span><span class="p">(</span><span class="nx">words</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span>
|
|
<span class="k">continue</span> <span class="nx">out</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="nx">cats</span><span class="p">.</span><span class="nx">push</span><span class="p">([</span><span class="nx">words</span><span class="p">[</span><span class="nx">i</span><span class="p">]]);</span>
|
|
<span class="p">}</span>
|
|
<span class="kd">function</span> <span class="nx">compareTo</span><span class="p">(</span><span class="nx">arr</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">arr</span><span class="p">.</span><span class="nx">length</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="k">return</span> <span class="nx">f</span> <span class="o">+=</span> <span class="s2">"return str === "</span> <span class="o">+</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">arr</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">+</span> <span class="s2">";"</span><span class="p">;</span>
|
|
<span class="nx">f</span> <span class="o">+=</span> <span class="s2">"switch(str){"</span><span class="p">;</span>
|
|
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">arr</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="o">++</span><span class="nx">i</span><span class="p">)</span> <span class="nx">f</span> <span class="o">+=</span> <span class="s2">"case "</span> <span class="o">+</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">arr</span><span class="p">[</span><span class="nx">i</span><span class="p">])</span> <span class="o">+</span> <span class="s2">":"</span><span class="p">;</span>
|
|
<span class="nx">f</span> <span class="o">+=</span> <span class="s2">"return true}return false;"</span><span class="p">;</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-38">¶</a> </div> <p>When there are more than three length categories, an outer
|
|
switch first dispatches on the lengths, to save on comparisons.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nx">cats</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">3</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">cats</span><span class="p">.</span><span class="nx">sort</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">)</span> <span class="p">{</span><span class="k">return</span> <span class="nx">b</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="nx">a</span><span class="p">.</span><span class="nx">length</span><span class="p">;});</span>
|
|
<span class="nx">f</span> <span class="o">+=</span> <span class="s2">"switch(str.length){"</span><span class="p">;</span>
|
|
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">cats</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="o">++</span><span class="nx">i</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">cat</span> <span class="o">=</span> <span class="nx">cats</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
|
|
<span class="nx">f</span> <span class="o">+=</span> <span class="s2">"case "</span> <span class="o">+</span> <span class="nx">cat</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">length</span> <span class="o">+</span> <span class="s2">":"</span><span class="p">;</span>
|
|
<span class="nx">compareTo</span><span class="p">(</span><span class="nx">cat</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="nx">f</span> <span class="o">+=</span> <span class="s2">"}"</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-39"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-39">¶</a> </div> <p>Otherwise, simply generate a flat <code>switch</code> statement.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
|
<span class="nx">compareTo</span><span class="p">(</span><span class="nx">words</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="k">return</span> <span class="k">new</span> <span class="nb">Function</span><span class="p">(</span><span class="s2">"str"</span><span class="p">,</span> <span class="nx">f</span><span class="p">);</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-40">¶</a> </div> <p>The ECMAScript 3 reserved word list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">isReservedWord3</span> <span class="o">=</span> <span class="nx">makePredicate</span><span class="p">(</span><span class="s2">"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><span class="p">);</span></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-41">¶</a> </div> <p>ECMAScript 5 reserved words.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">isReservedWord5</span> <span class="o">=</span> <span class="nx">makePredicate</span><span class="p">(</span><span class="s2">"class enum extends super const export import"</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-42">¶</a> </div> <p>The additional reserved words in strict mode.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">isStrictReservedWord</span> <span class="o">=</span> <span class="nx">makePredicate</span><span class="p">(</span><span class="s2">"implements interface let package private protected public static yield"</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-43">¶</a> </div> <p>The forbidden variable names in strict mode.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">isStrictBadIdWord</span> <span class="o">=</span> <span class="nx">makePredicate</span><span class="p">(</span><span class="s2">"eval arguments"</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-44">¶</a> </div> <p>And the keywords.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">isKeyword</span> <span class="o">=</span> <span class="nx">makePredicate</span><span class="p">(</span><span class="s2">"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="p">);</span></pre></div> </td> </tr> <tr id="section-45"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-45">¶</a> </div> <h2>Character categories</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-46"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-46">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">nonASCIIwhitespace</span> <span class="o">=</span> <span class="sr">/[\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/</span><span class="p">;</span>
|
|
<span class="kd">var</span> <span class="nx">nonASCIIidentifierStartChars</span> <span class="o">=</span> <span class="s2">"\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="p">;</span>
|
|
<span class="kd">var</span> <span class="nx">nonASCIIidentifierChars</span> <span class="o">=</span> <span class="s2">"\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="p">;</span>
|
|
<span class="kd">var</span> <span class="nx">nonASCIIidentifierStart</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="s2">"["</span> <span class="o">+</span> <span class="nx">nonASCIIidentifierStartChars</span> <span class="o">+</span> <span class="s2">"]"</span><span class="p">);</span>
|
|
<span class="kd">var</span> <span class="nx">nonASCIIidentifier</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="s2">"["</span> <span class="o">+</span> <span class="nx">nonASCIIidentifierStartChars</span> <span class="o">+</span> <span class="nx">nonASCIIidentifierChars</span> <span class="o">+</span> <span class="s2">"]"</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-47">¶</a> </div> <p>Whether a single character denotes a newline.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">newline</span> <span class="o">=</span> <span class="sr">/[\n\r\u2028\u2029]/</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-48"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-48">¶</a> </div> <p>Matches a whole line break (where CRLF is considered a single
|
|
line break). Used to count lines.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">lineBreak</span> <span class="o">=</span> <span class="sr">/\r\n|[\n\r\u2028\u2029]/g</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-49">¶</a> </div> <p>Test whether a given character code starts an identifier.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">isIdentifierStart</span> <span class="o">=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">isIdentifierStart</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">code</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">code</span> <span class="o"><</span> <span class="mi">65</span><span class="p">)</span> <span class="k">return</span> <span class="nx">code</span> <span class="o">===</span> <span class="mi">36</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">code</span> <span class="o"><</span> <span class="mi">91</span><span class="p">)</span> <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">code</span> <span class="o"><</span> <span class="mi">97</span><span class="p">)</span> <span class="k">return</span> <span class="nx">code</span> <span class="o">===</span> <span class="mi">95</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">code</span> <span class="o"><</span> <span class="mi">123</span><span class="p">)</span><span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
|
|
<span class="k">return</span> <span class="nx">code</span> <span class="o">>=</span> <span class="mh">0xaa</span> <span class="o">&&</span> <span class="nx">nonASCIIidentifierStart</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nb">String</span><span class="p">.</span><span class="nx">fromCharCode</span><span class="p">(</span><span class="nx">code</span><span class="p">));</span>
|
|
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-50"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-50">¶</a> </div> <p>Test whether a given character is part of an identifier.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">isIdentifierChar</span> <span class="o">=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">isIdentifierChar</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">code</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">code</span> <span class="o"><</span> <span class="mi">48</span><span class="p">)</span> <span class="k">return</span> <span class="nx">code</span> <span class="o">===</span> <span class="mi">36</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">code</span> <span class="o"><</span> <span class="mi">58</span><span class="p">)</span> <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">code</span> <span class="o"><</span> <span class="mi">65</span><span class="p">)</span> <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">code</span> <span class="o"><</span> <span class="mi">91</span><span class="p">)</span> <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">code</span> <span class="o"><</span> <span class="mi">97</span><span class="p">)</span> <span class="k">return</span> <span class="nx">code</span> <span class="o">===</span> <span class="mi">95</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">code</span> <span class="o"><</span> <span class="mi">123</span><span class="p">)</span><span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
|
|
<span class="k">return</span> <span class="nx">code</span> <span class="o">>=</span> <span class="mh">0xaa</span> <span class="o">&&</span> <span class="nx">nonASCIIidentifier</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nb">String</span><span class="p">.</span><span class="nx">fromCharCode</span><span class="p">(</span><span class="nx">code</span><span class="p">));</span>
|
|
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-51">¶</a> </div> <h2>Tokenizer</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-52">¶</a> </div> <p>These are used when <code>options.locations</code> is on, for the
|
|
<code>tokStartLoc</code> and <code>tokEndLoc</code> properties.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">line_loc_t</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">line</span> <span class="o">=</span> <span class="nx">tokCurLine</span><span class="p">;</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">column</span> <span class="o">=</span> <span class="nx">tokPos</span> <span class="o">-</span> <span class="nx">tokLineStart</span><span class="p">;</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-53"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-53">¶</a> </div> <p>Reset the token state. Used at the start of a parse.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">initTokenState</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="nx">tokCurLine</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
|
|
<span class="nx">tokPos</span> <span class="o">=</span> <span class="nx">tokLineStart</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
|
|
<span class="nx">tokRegexpAllowed</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
|
|
<span class="nx">skipSpace</span><span class="p">();</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-54">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">finishToken</span><span class="p">(</span><span class="nx">type</span><span class="p">,</span> <span class="nx">val</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">tokEnd</span> <span class="o">=</span> <span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">locations</span><span class="p">)</span> <span class="nx">tokEndLoc</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">line_loc_t</span><span class="p">;</span>
|
|
<span class="nx">tokType</span> <span class="o">=</span> <span class="nx">type</span><span class="p">;</span>
|
|
<span class="nx">skipSpace</span><span class="p">();</span>
|
|
<span class="nx">tokVal</span> <span class="o">=</span> <span class="nx">val</span><span class="p">;</span>
|
|
<span class="nx">tokRegexpAllowed</span> <span class="o">=</span> <span class="nx">type</span><span class="p">.</span><span class="nx">beforeExpr</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">function</span> <span class="nx">skipBlockComment</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">startLoc</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">onComment</span> <span class="o">&&</span> <span class="nx">options</span><span class="p">.</span><span class="nx">locations</span> <span class="o">&&</span> <span class="k">new</span> <span class="nx">line_loc_t</span><span class="p">;</span>
|
|
<span class="kd">var</span> <span class="nx">start</span> <span class="o">=</span> <span class="nx">tokPos</span><span class="p">,</span> <span class="nx">end</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s2">"*/"</span><span class="p">,</span> <span class="nx">tokPos</span> <span class="o">+=</span> <span class="mi">2</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">end</span> <span class="o">===</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">tokPos</span> <span class="o">-</span> <span class="mi">2</span><span class="p">,</span> <span class="s2">"Unterminated comment"</span><span class="p">);</span>
|
|
<span class="nx">tokPos</span> <span class="o">=</span> <span class="nx">end</span> <span class="o">+</span> <span class="mi">2</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">locations</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">lineBreak</span><span class="p">.</span><span class="nx">lastIndex</span> <span class="o">=</span> <span class="nx">start</span><span class="p">;</span>
|
|
<span class="kd">var</span> <span class="nx">match</span><span class="p">;</span>
|
|
<span class="k">while</span> <span class="p">((</span><span class="nx">match</span> <span class="o">=</span> <span class="nx">lineBreak</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="nx">input</span><span class="p">))</span> <span class="o">&&</span> <span class="nx">match</span><span class="p">.</span><span class="nx">index</span> <span class="o"><</span> <span class="nx">tokPos</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="o">++</span><span class="nx">tokCurLine</span><span class="p">;</span>
|
|
<span class="nx">tokLineStart</span> <span class="o">=</span> <span class="nx">match</span><span class="p">.</span><span class="nx">index</span> <span class="o">+</span> <span class="nx">match</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">length</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">onComment</span><span class="p">)</span>
|
|
<span class="nx">options</span><span class="p">.</span><span class="nx">onComment</span><span class="p">(</span><span class="kc">true</span><span class="p">,</span> <span class="nx">input</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">start</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">end</span><span class="p">),</span> <span class="nx">start</span><span class="p">,</span> <span class="nx">tokPos</span><span class="p">,</span>
|
|
<span class="nx">startLoc</span><span class="p">,</span> <span class="nx">options</span><span class="p">.</span><span class="nx">locations</span> <span class="o">&&</span> <span class="k">new</span> <span class="nx">line_loc_t</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">function</span> <span class="nx">skipLineComment</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">start</span> <span class="o">=</span> <span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="kd">var</span> <span class="nx">startLoc</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">onComment</span> <span class="o">&&</span> <span class="nx">options</span><span class="p">.</span><span class="nx">locations</span> <span class="o">&&</span> <span class="k">new</span> <span class="nx">line_loc_t</span><span class="p">;</span>
|
|
<span class="kd">var</span> <span class="nx">ch</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="o">+=</span><span class="mi">2</span><span class="p">);</span>
|
|
<span class="k">while</span> <span class="p">(</span><span class="nx">tokPos</span> <span class="o"><</span> <span class="nx">inputLen</span> <span class="o">&&</span> <span class="nx">ch</span> <span class="o">!==</span> <span class="mi">10</span> <span class="o">&&</span> <span class="nx">ch</span> <span class="o">!==</span> <span class="mi">13</span> <span class="o">&&</span> <span class="nx">ch</span> <span class="o">!==</span> <span class="mi">8232</span> <span class="o">&&</span> <span class="nx">ch</span> <span class="o">!==</span> <span class="mi">8329</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="nx">ch</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">onComment</span><span class="p">)</span>
|
|
<span class="nx">options</span><span class="p">.</span><span class="nx">onComment</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span> <span class="nx">input</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">start</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">tokPos</span><span class="p">),</span> <span class="nx">start</span><span class="p">,</span> <span class="nx">tokPos</span><span class="p">,</span>
|
|
<span class="nx">startLoc</span><span class="p">,</span> <span class="nx">options</span><span class="p">.</span><span class="nx">locations</span> <span class="o">&&</span> <span class="k">new</span> <span class="nx">line_loc_t</span><span class="p">);</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-55">¶</a> </div> <p>Called at the start of the parse and after every token. Skips
|
|
whitespace and comments, and.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">skipSpace</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">while</span> <span class="p">(</span><span class="nx">tokPos</span> <span class="o"><</span> <span class="nx">inputLen</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">ch</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">ch</span> <span class="o">===</span> <span class="mi">32</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// ' '</span>
|
|
<span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="nx">ch</span> <span class="o">===</span> <span class="mi">13</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="kd">var</span> <span class="nx">next</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">);</span>
|
|
<span class="k">if</span><span class="p">(</span><span class="nx">next</span> <span class="o">===</span> <span class="mi">10</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="k">if</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">locations</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="o">++</span><span class="nx">tokCurLine</span><span class="p">;</span>
|
|
<span class="nx">tokLineStart</span> <span class="o">=</span> <span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">ch</span> <span class="o">===</span> <span class="mi">10</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="o">++</span><span class="nx">tokCurLine</span><span class="p">;</span>
|
|
<span class="nx">tokLineStart</span> <span class="o">=</span> <span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="nx">ch</span> <span class="o"><</span> <span class="mi">14</span> <span class="o">&&</span> <span class="nx">ch</span> <span class="o">></span> <span class="mi">8</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">ch</span> <span class="o">===</span> <span class="mi">47</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// '/'</span>
|
|
<span class="kd">var</span> <span class="nx">next</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">next</span> <span class="o">===</span> <span class="mi">42</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// '*'</span>
|
|
<span class="nx">skipBlockComment</span><span class="p">();</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">next</span> <span class="o">===</span> <span class="mi">47</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// '/'</span>
|
|
<span class="nx">skipLineComment</span><span class="p">();</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="k">break</span><span class="p">;</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">ch</span> <span class="o">===</span> <span class="mi">160</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// '\xa0'</span>
|
|
<span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">ch</span> <span class="o">>=</span> <span class="mi">5760</span> <span class="o">&&</span> <span class="nx">nonASCIIwhitespace</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nb">String</span><span class="p">.</span><span class="nx">fromCharCode</span><span class="p">(</span><span class="nx">ch</span><span class="p">)))</span> <span class="p">{</span>
|
|
<span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
|
<span class="k">break</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-56">¶</a> </div> <h3>Token reading</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-57"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-57">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">readToken_dot</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">next</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">next</span> <span class="o">>=</span> <span class="mi">48</span> <span class="o">&&</span> <span class="nx">next</span> <span class="o"><=</span> <span class="mi">57</span><span class="p">)</span> <span class="k">return</span> <span class="nx">readNumber</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
|
|
<span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="k">return</span> <span class="nx">finishToken</span><span class="p">(</span><span class="nx">_dot</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">function</span> <span class="nx">readToken_slash</span><span class="p">()</span> <span class="p">{</span> <span class="c1">// '/'</span>
|
|
<span class="kd">var</span> <span class="nx">next</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">tokRegexpAllowed</span><span class="p">)</span> <span class="p">{</span><span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span> <span class="k">return</span> <span class="nx">readRegexp</span><span class="p">();}</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">next</span> <span class="o">===</span> <span class="mi">61</span><span class="p">)</span> <span class="k">return</span> <span class="nx">finishOp</span><span class="p">(</span><span class="nx">_assign</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">finishOp</span><span class="p">(</span><span class="nx">_slash</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">function</span> <span class="nx">readToken_mult_modulo</span><span class="p">()</span> <span class="p">{</span> <span class="c1">// '%*'</span>
|
|
<span class="kd">var</span> <span class="nx">next</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">next</span> <span class="o">===</span> <span class="mi">61</span><span class="p">)</span> <span class="k">return</span> <span class="nx">finishOp</span><span class="p">(</span><span class="nx">_assign</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">finishOp</span><span class="p">(</span><span class="nx">_bin10</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">function</span> <span class="nx">readToken_pipe_amp</span><span class="p">(</span><span class="nx">code</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// '|&'</span>
|
|
<span class="kd">var</span> <span class="nx">next</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">next</span> <span class="o">===</span> <span class="nx">code</span><span class="p">)</span> <span class="k">return</span> <span class="nx">finishOp</span><span class="p">(</span><span class="nx">code</span> <span class="o">===</span> <span class="mi">124</span> <span class="o">?</span> <span class="nx">_bin1</span> <span class="o">:</span> <span class="nx">_bin2</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">next</span> <span class="o">===</span> <span class="mi">61</span><span class="p">)</span> <span class="k">return</span> <span class="nx">finishOp</span><span class="p">(</span><span class="nx">_assign</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">finishOp</span><span class="p">(</span><span class="nx">code</span> <span class="o">===</span> <span class="mi">124</span> <span class="o">?</span> <span class="nx">_bin3</span> <span class="o">:</span> <span class="nx">_bin5</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">function</span> <span class="nx">readToken_caret</span><span class="p">()</span> <span class="p">{</span> <span class="c1">// '^'</span>
|
|
<span class="kd">var</span> <span class="nx">next</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">next</span> <span class="o">===</span> <span class="mi">61</span><span class="p">)</span> <span class="k">return</span> <span class="nx">finishOp</span><span class="p">(</span><span class="nx">_assign</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">finishOp</span><span class="p">(</span><span class="nx">_bin4</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">function</span> <span class="nx">readToken_plus_min</span><span class="p">(</span><span class="nx">code</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// '+-'</span>
|
|
<span class="kd">var</span> <span class="nx">next</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">next</span> <span class="o">===</span> <span class="nx">code</span><span class="p">)</span> <span class="k">return</span> <span class="nx">finishOp</span><span class="p">(</span><span class="nx">_incdec</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">next</span> <span class="o">===</span> <span class="mi">61</span><span class="p">)</span> <span class="k">return</span> <span class="nx">finishOp</span><span class="p">(</span><span class="nx">_assign</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">finishOp</span><span class="p">(</span><span class="nx">_plusmin</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">function</span> <span class="nx">readToken_lt_gt</span><span class="p">(</span><span class="nx">code</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// '<>'</span>
|
|
<span class="kd">var</span> <span class="nx">next</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
|
|
<span class="kd">var</span> <span class="nx">size</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">next</span> <span class="o">===</span> <span class="nx">code</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">size</span> <span class="o">=</span> <span class="nx">code</span> <span class="o">===</span> <span class="mi">62</span> <span class="o">&&</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span> <span class="o">===</span> <span class="mi">62</span> <span class="o">?</span> <span class="mi">3</span> <span class="o">:</span> <span class="mi">2</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span> <span class="o">+</span> <span class="nx">size</span><span class="p">)</span> <span class="o">===</span> <span class="mi">61</span><span class="p">)</span> <span class="k">return</span> <span class="nx">finishOp</span><span class="p">(</span><span class="nx">_assign</span><span class="p">,</span> <span class="nx">size</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">finishOp</span><span class="p">(</span><span class="nx">_bin8</span><span class="p">,</span> <span class="nx">size</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">next</span> <span class="o">===</span> <span class="mi">61</span><span class="p">)</span>
|
|
<span class="nx">size</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span> <span class="o">===</span> <span class="mi">61</span> <span class="o">?</span> <span class="mi">3</span> <span class="o">:</span> <span class="mi">2</span><span class="p">;</span>
|
|
<span class="k">return</span> <span class="nx">finishOp</span><span class="p">(</span><span class="nx">_bin7</span><span class="p">,</span> <span class="nx">size</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">function</span> <span class="nx">readToken_eq_excl</span><span class="p">(</span><span class="nx">code</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// '=!'</span>
|
|
<span class="kd">var</span> <span class="nx">next</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">next</span> <span class="o">===</span> <span class="mi">61</span><span class="p">)</span> <span class="k">return</span> <span class="nx">finishOp</span><span class="p">(</span><span class="nx">_bin6</span><span class="p">,</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span> <span class="o">===</span> <span class="mi">61</span> <span class="o">?</span> <span class="mi">3</span> <span class="o">:</span> <span class="mi">2</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">finishOp</span><span class="p">(</span><span class="nx">code</span> <span class="o">===</span> <span class="mi">61</span> <span class="o">?</span> <span class="nx">_eq</span> <span class="o">:</span> <span class="nx">_prefix</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">function</span> <span class="nx">getTokenFromCode</span><span class="p">(</span><span class="nx">code</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">switch</span><span class="p">(</span><span class="nx">code</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-58"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-58">¶</a> </div> <p>The interpretation of a dot depends on whether it is followed
|
|
by a digit.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">case</span> <span class="mi">46</span><span class="o">:</span> <span class="c1">// '.'</span>
|
|
<span class="k">return</span> <span class="nx">readToken_dot</span><span class="p">();</span></pre></div> </td> </tr> <tr id="section-59"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-59">¶</a> </div> <p>Punctuation tokens.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">case</span> <span class="mi">40</span><span class="o">:</span> <span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span> <span class="k">return</span> <span class="nx">finishToken</span><span class="p">(</span><span class="nx">_parenL</span><span class="p">);</span>
|
|
<span class="k">case</span> <span class="mi">41</span><span class="o">:</span> <span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span> <span class="k">return</span> <span class="nx">finishToken</span><span class="p">(</span><span class="nx">_parenR</span><span class="p">);</span>
|
|
<span class="k">case</span> <span class="mi">59</span><span class="o">:</span> <span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span> <span class="k">return</span> <span class="nx">finishToken</span><span class="p">(</span><span class="nx">_semi</span><span class="p">);</span>
|
|
<span class="k">case</span> <span class="mi">44</span><span class="o">:</span> <span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span> <span class="k">return</span> <span class="nx">finishToken</span><span class="p">(</span><span class="nx">_comma</span><span class="p">);</span>
|
|
<span class="k">case</span> <span class="mi">91</span><span class="o">:</span> <span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span> <span class="k">return</span> <span class="nx">finishToken</span><span class="p">(</span><span class="nx">_bracketL</span><span class="p">);</span>
|
|
<span class="k">case</span> <span class="mi">93</span><span class="o">:</span> <span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span> <span class="k">return</span> <span class="nx">finishToken</span><span class="p">(</span><span class="nx">_bracketR</span><span class="p">);</span>
|
|
<span class="k">case</span> <span class="mi">123</span><span class="o">:</span> <span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span> <span class="k">return</span> <span class="nx">finishToken</span><span class="p">(</span><span class="nx">_braceL</span><span class="p">);</span>
|
|
<span class="k">case</span> <span class="mi">125</span><span class="o">:</span> <span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span> <span class="k">return</span> <span class="nx">finishToken</span><span class="p">(</span><span class="nx">_braceR</span><span class="p">);</span>
|
|
<span class="k">case</span> <span class="mi">58</span><span class="o">:</span> <span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span> <span class="k">return</span> <span class="nx">finishToken</span><span class="p">(</span><span class="nx">_colon</span><span class="p">);</span>
|
|
<span class="k">case</span> <span class="mi">63</span><span class="o">:</span> <span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span> <span class="k">return</span> <span class="nx">finishToken</span><span class="p">(</span><span class="nx">_question</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-60"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-60">¶</a> </div> <p>'0x' is a hexadecimal number.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">case</span> <span class="mi">48</span><span class="o">:</span> <span class="c1">// '0'</span>
|
|
<span class="kd">var</span> <span class="nx">next</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">next</span> <span class="o">===</span> <span class="mi">120</span> <span class="o">||</span> <span class="nx">next</span> <span class="o">===</span> <span class="mi">88</span><span class="p">)</span> <span class="k">return</span> <span class="nx">readHexNumber</span><span class="p">();</span></pre></div> </td> </tr> <tr id="section-61"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-61">¶</a> </div> <p>Anything else beginning with a digit is an integer, octal
|
|
number, or float.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">case</span> <span class="mi">49</span><span class="o">:</span> <span class="k">case</span> <span class="mi">50</span><span class="o">:</span> <span class="k">case</span> <span class="mi">51</span><span class="o">:</span> <span class="k">case</span> <span class="mi">52</span><span class="o">:</span> <span class="k">case</span> <span class="mi">53</span><span class="o">:</span> <span class="k">case</span> <span class="mi">54</span><span class="o">:</span> <span class="k">case</span> <span class="mi">55</span><span class="o">:</span> <span class="k">case</span> <span class="mi">56</span><span class="o">:</span> <span class="k">case</span> <span class="mi">57</span><span class="o">:</span> <span class="c1">// 1-9</span>
|
|
<span class="k">return</span> <span class="nx">readNumber</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-62"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-62">¶</a> </div> <p>Quotes produce strings.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">case</span> <span class="mi">34</span><span class="o">:</span> <span class="k">case</span> <span class="mi">39</span><span class="o">:</span> <span class="c1">// '"', "'"</span>
|
|
<span class="k">return</span> <span class="nx">readString</span><span class="p">(</span><span class="nx">code</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-63"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-63">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="k">case</span> <span class="mi">47</span><span class="o">:</span> <span class="c1">// '/'</span>
|
|
<span class="k">return</span> <span class="nx">readToken_slash</span><span class="p">(</span><span class="nx">code</span><span class="p">);</span>
|
|
|
|
<span class="k">case</span> <span class="mi">37</span><span class="o">:</span> <span class="k">case</span> <span class="mi">42</span><span class="o">:</span> <span class="c1">// '%*'</span>
|
|
<span class="k">return</span> <span class="nx">readToken_mult_modulo</span><span class="p">();</span>
|
|
|
|
<span class="k">case</span> <span class="mi">124</span><span class="o">:</span> <span class="k">case</span> <span class="mi">38</span><span class="o">:</span> <span class="c1">// '|&'</span>
|
|
<span class="k">return</span> <span class="nx">readToken_pipe_amp</span><span class="p">(</span><span class="nx">code</span><span class="p">);</span>
|
|
|
|
<span class="k">case</span> <span class="mi">94</span><span class="o">:</span> <span class="c1">// '^'</span>
|
|
<span class="k">return</span> <span class="nx">readToken_caret</span><span class="p">();</span>
|
|
|
|
<span class="k">case</span> <span class="mi">43</span><span class="o">:</span> <span class="k">case</span> <span class="mi">45</span><span class="o">:</span> <span class="c1">// '+-'</span>
|
|
<span class="k">return</span> <span class="nx">readToken_plus_min</span><span class="p">(</span><span class="nx">code</span><span class="p">);</span>
|
|
|
|
<span class="k">case</span> <span class="mi">60</span><span class="o">:</span> <span class="k">case</span> <span class="mi">62</span><span class="o">:</span> <span class="c1">// '<>'</span>
|
|
<span class="k">return</span> <span class="nx">readToken_lt_gt</span><span class="p">(</span><span class="nx">code</span><span class="p">);</span>
|
|
|
|
<span class="k">case</span> <span class="mi">61</span><span class="o">:</span> <span class="k">case</span> <span class="mi">33</span><span class="o">:</span> <span class="c1">// '=!'</span>
|
|
<span class="k">return</span> <span class="nx">readToken_eq_excl</span><span class="p">(</span><span class="nx">code</span><span class="p">);</span>
|
|
|
|
<span class="k">case</span> <span class="mi">126</span><span class="o">:</span> <span class="c1">// '~'</span>
|
|
<span class="k">return</span> <span class="nx">finishOp</span><span class="p">(</span><span class="nx">_prefix</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">function</span> <span class="nx">readToken</span><span class="p">(</span><span class="nx">forceRegexp</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">forceRegexp</span><span class="p">)</span> <span class="nx">tokStart</span> <span class="o">=</span> <span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="k">else</span> <span class="nx">tokPos</span> <span class="o">=</span> <span class="nx">tokStart</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">locations</span><span class="p">)</span> <span class="nx">tokStartLoc</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">line_loc_t</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">forceRegexp</span><span class="p">)</span> <span class="k">return</span> <span class="nx">readRegexp</span><span class="p">();</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">tokPos</span> <span class="o">>=</span> <span class="nx">inputLen</span><span class="p">)</span> <span class="k">return</span> <span class="nx">finishToken</span><span class="p">(</span><span class="nx">_eof</span><span class="p">);</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">code</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-64">¶</a> </div> <p>Identifier or keyword. '\uXXXX' sequences are allowed in
|
|
identifiers, so '\' also dispatches to that.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nx">isIdentifierStart</span><span class="p">(</span><span class="nx">code</span><span class="p">)</span> <span class="o">||</span> <span class="nx">code</span> <span class="o">===</span> <span class="mi">92</span> <span class="cm">/* '\' */</span><span class="p">)</span> <span class="k">return</span> <span class="nx">readWord</span><span class="p">();</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">tok</span> <span class="o">=</span> <span class="nx">getTokenFromCode</span><span class="p">(</span><span class="nx">code</span><span class="p">);</span>
|
|
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">tok</span> <span class="o">===</span> <span class="kc">false</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-65"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-65">¶</a> </div> <p>If we are here, we either found a non-ASCII identifier
|
|
character, or something that's entirely disallowed.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">ch</span> <span class="o">=</span> <span class="nb">String</span><span class="p">.</span><span class="nx">fromCharCode</span><span class="p">(</span><span class="nx">code</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">ch</span> <span class="o">===</span> <span class="s2">"\\"</span> <span class="o">||</span> <span class="nx">nonASCIIidentifierStart</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">ch</span><span class="p">))</span> <span class="k">return</span> <span class="nx">readWord</span><span class="p">();</span>
|
|
<span class="nx">raise</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">,</span> <span class="s2">"Unexpected character '"</span> <span class="o">+</span> <span class="nx">ch</span> <span class="o">+</span> <span class="s2">"'"</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="k">return</span> <span class="nx">tok</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">function</span> <span class="nx">finishOp</span><span class="p">(</span><span class="nx">type</span><span class="p">,</span> <span class="nx">size</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">str</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">,</span> <span class="nx">tokPos</span> <span class="o">+</span> <span class="nx">size</span><span class="p">);</span>
|
|
<span class="nx">tokPos</span> <span class="o">+=</span> <span class="nx">size</span><span class="p">;</span>
|
|
<span class="nx">finishToken</span><span class="p">(</span><span class="nx">type</span><span class="p">,</span> <span class="nx">str</span><span class="p">);</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-66"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-66">¶</a> </div> <p>Parse a regular expression. Some context-awareness is necessary,
|
|
since a '/' inside a '[]' set does not end the expression.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">readRegexp</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">content</span> <span class="o">=</span> <span class="s2">""</span><span class="p">,</span> <span class="nx">escaped</span><span class="p">,</span> <span class="nx">inClass</span><span class="p">,</span> <span class="nx">start</span> <span class="o">=</span> <span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="k">for</span> <span class="p">(;;)</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">tokPos</span> <span class="o">>=</span> <span class="nx">inputLen</span><span class="p">)</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span> <span class="s2">"Unterminated regular expression"</span><span class="p">);</span>
|
|
<span class="kd">var</span> <span class="nx">ch</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">newline</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">ch</span><span class="p">))</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span> <span class="s2">"Unterminated regular expression"</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">escaped</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">ch</span> <span class="o">===</span> <span class="s2">"["</span><span class="p">)</span> <span class="nx">inClass</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">ch</span> <span class="o">===</span> <span class="s2">"]"</span> <span class="o">&&</span> <span class="nx">inClass</span><span class="p">)</span> <span class="nx">inClass</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">ch</span> <span class="o">===</span> <span class="s2">"/"</span> <span class="o">&&</span> <span class="o">!</span><span class="nx">inClass</span><span class="p">)</span> <span class="k">break</span><span class="p">;</span>
|
|
<span class="nx">escaped</span> <span class="o">=</span> <span class="nx">ch</span> <span class="o">===</span> <span class="s2">"\\"</span><span class="p">;</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="nx">escaped</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
<span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="kd">var</span> <span class="nx">content</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span> <span class="nx">tokPos</span><span class="p">);</span>
|
|
<span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-67"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-67">¶</a> </div> <p>Need to use <code>readWord1</code> because '\uXXXX' sequences are allowed
|
|
here (don't ask).</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">mods</span> <span class="o">=</span> <span class="nx">readWord1</span><span class="p">();</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">mods</span> <span class="o">&&</span> <span class="o">!</span><span class="sr">/^[gmsiy]*$/</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">mods</span><span class="p">))</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span> <span class="s2">"Invalid regexp flag"</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">finishToken</span><span class="p">(</span><span class="nx">_regexp</span><span class="p">,</span> <span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="nx">content</span><span class="p">,</span> <span class="nx">mods</span><span class="p">));</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-68"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-68">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">readInt</span><span class="p">(</span><span class="nx">radix</span><span class="p">,</span> <span class="nx">len</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">start</span> <span class="o">=</span> <span class="nx">tokPos</span><span class="p">,</span> <span class="nx">total</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
|
|
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">e</span> <span class="o">=</span> <span class="nx">len</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">?</span> <span class="kc">Infinity</span> <span class="o">:</span> <span class="nx">len</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">e</span><span class="p">;</span> <span class="o">++</span><span class="nx">i</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">code</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">),</span> <span class="nx">val</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">code</span> <span class="o">>=</span> <span class="mi">97</span><span class="p">)</span> <span class="nx">val</span> <span class="o">=</span> <span class="nx">code</span> <span class="o">-</span> <span class="mi">97</span> <span class="o">+</span> <span class="mi">10</span><span class="p">;</span> <span class="c1">// a</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">code</span> <span class="o">>=</span> <span class="mi">65</span><span class="p">)</span> <span class="nx">val</span> <span class="o">=</span> <span class="nx">code</span> <span class="o">-</span> <span class="mi">65</span> <span class="o">+</span> <span class="mi">10</span><span class="p">;</span> <span class="c1">// A</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">code</span> <span class="o">>=</span> <span class="mi">48</span> <span class="o">&&</span> <span class="nx">code</span> <span class="o"><=</span> <span class="mi">57</span><span class="p">)</span> <span class="nx">val</span> <span class="o">=</span> <span class="nx">code</span> <span class="o">-</span> <span class="mi">48</span><span class="p">;</span> <span class="c1">// 0-9</span>
|
|
<span class="k">else</span> <span class="nx">val</span> <span class="o">=</span> <span class="kc">Infinity</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">val</span> <span class="o">>=</span> <span class="nx">radix</span><span class="p">)</span> <span class="k">break</span><span class="p">;</span>
|
|
<span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="nx">total</span> <span class="o">=</span> <span class="nx">total</span> <span class="o">*</span> <span class="nx">radix</span> <span class="o">+</span> <span class="nx">val</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">tokPos</span> <span class="o">===</span> <span class="nx">start</span> <span class="o">||</span> <span class="nx">len</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">&&</span> <span class="nx">tokPos</span> <span class="o">-</span> <span class="nx">start</span> <span class="o">!==</span> <span class="nx">len</span><span class="p">)</span> <span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
|
|
|
|
<span class="k">return</span> <span class="nx">total</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">function</span> <span class="nx">readHexNumber</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="nx">tokPos</span> <span class="o">+=</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 0x</span>
|
|
<span class="kd">var</span> <span class="nx">val</span> <span class="o">=</span> <span class="nx">readInt</span><span class="p">(</span><span class="mi">16</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">val</span> <span class="o">==</span> <span class="kc">null</span><span class="p">)</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">tokStart</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="s2">"Expected hexadecimal number"</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">isIdentifierStart</span><span class="p">(</span><span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">)))</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">,</span> <span class="s2">"Identifier directly after number"</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">finishToken</span><span class="p">(</span><span class="nx">_num</span><span class="p">,</span> <span class="nx">val</span><span class="p">);</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-69"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-69">¶</a> </div> <p>Read an integer, octal integer, or floating-point number.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">readNumber</span><span class="p">(</span><span class="nx">startsWithDot</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">start</span> <span class="o">=</span> <span class="nx">tokPos</span><span class="p">,</span> <span class="nx">isFloat</span> <span class="o">=</span> <span class="kc">false</span><span class="p">,</span> <span class="nx">octal</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">)</span> <span class="o">===</span> <span class="mi">48</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">startsWithDot</span> <span class="o">&&</span> <span class="nx">readInt</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="o">===</span> <span class="kc">null</span><span class="p">)</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span> <span class="s2">"Invalid number"</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">)</span> <span class="o">===</span> <span class="mi">46</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="nx">readInt</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span>
|
|
<span class="nx">isFloat</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="kd">var</span> <span class="nx">next</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">next</span> <span class="o">===</span> <span class="mi">69</span> <span class="o">||</span> <span class="nx">next</span> <span class="o">===</span> <span class="mi">101</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 'eE'</span>
|
|
<span class="nx">next</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="o">++</span><span class="nx">tokPos</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">next</span> <span class="o">===</span> <span class="mi">43</span> <span class="o">||</span> <span class="nx">next</span> <span class="o">===</span> <span class="mi">45</span><span class="p">)</span> <span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span> <span class="c1">// '+-'</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">readInt</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="o">===</span> <span class="kc">null</span><span class="p">)</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span> <span class="s2">"Invalid number"</span><span class="p">);</span>
|
|
<span class="nx">isFloat</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">isIdentifierStart</span><span class="p">(</span><span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">)))</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">,</span> <span class="s2">"Identifier directly after number"</span><span class="p">);</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">str</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span> <span class="nx">tokPos</span><span class="p">),</span> <span class="nx">val</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">isFloat</span><span class="p">)</span> <span class="nx">val</span> <span class="o">=</span> <span class="nb">parseFloat</span><span class="p">(</span><span class="nx">str</span><span class="p">);</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">octal</span> <span class="o">||</span> <span class="nx">str</span><span class="p">.</span><span class="nx">length</span> <span class="o">===</span> <span class="mi">1</span><span class="p">)</span> <span class="nx">val</span> <span class="o">=</span> <span class="nb">parseInt</span><span class="p">(</span><span class="nx">str</span><span class="p">,</span> <span class="mi">10</span><span class="p">);</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="sr">/[89]/</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">str</span><span class="p">)</span> <span class="o">||</span> <span class="nx">strict</span><span class="p">)</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span> <span class="s2">"Invalid number"</span><span class="p">);</span>
|
|
<span class="k">else</span> <span class="nx">val</span> <span class="o">=</span> <span class="nb">parseInt</span><span class="p">(</span><span class="nx">str</span><span class="p">,</span> <span class="mi">8</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">finishToken</span><span class="p">(</span><span class="nx">_num</span><span class="p">,</span> <span class="nx">val</span><span class="p">);</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-70"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-70">¶</a> </div> <p>Read a string value, interpreting backslash-escapes.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">readString</span><span class="p">(</span><span class="nx">quote</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">tokPos</span><span class="o">++</span><span class="p">;</span>
|
|
<span class="kd">var</span> <span class="nx">out</span> <span class="o">=</span> <span class="s2">""</span><span class="p">;</span>
|
|
<span class="k">for</span> <span class="p">(;;)</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">tokPos</span> <span class="o">>=</span> <span class="nx">inputLen</span><span class="p">)</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">tokStart</span><span class="p">,</span> <span class="s2">"Unterminated string constant"</span><span class="p">);</span>
|
|
<span class="kd">var</span> <span class="nx">ch</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">ch</span> <span class="o">===</span> <span class="nx">quote</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="k">return</span> <span class="nx">finishToken</span><span class="p">(</span><span class="nx">_string</span><span class="p">,</span> <span class="nx">out</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">ch</span> <span class="o">===</span> <span class="mi">92</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// '\'</span>
|
|
<span class="nx">ch</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="o">++</span><span class="nx">tokPos</span><span class="p">);</span>
|
|
<span class="kd">var</span> <span class="nx">octal</span> <span class="o">=</span> <span class="sr">/^[0-7]+/</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="nx">input</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">,</span> <span class="nx">tokPos</span> <span class="o">+</span> <span class="mi">3</span><span class="p">));</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">octal</span><span class="p">)</span> <span class="nx">octal</span> <span class="o">=</span> <span class="nx">octal</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
|
|
<span class="k">while</span> <span class="p">(</span><span class="nx">octal</span> <span class="o">&&</span> <span class="nb">parseInt</span><span class="p">(</span><span class="nx">octal</span><span class="p">,</span> <span class="mi">8</span><span class="p">)</span> <span class="o">></span> <span class="mi">255</span><span class="p">)</span> <span class="nx">octal</span> <span class="o">=</span> <span class="nx">octal</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">octal</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">octal</span> <span class="o">===</span> <span class="s2">"0"</span><span class="p">)</span> <span class="nx">octal</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
|
|
<span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">octal</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">strict</span><span class="p">)</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">tokPos</span> <span class="o">-</span> <span class="mi">2</span><span class="p">,</span> <span class="s2">"Octal literal in strict mode"</span><span class="p">);</span>
|
|
<span class="nx">out</span> <span class="o">+=</span> <span class="nb">String</span><span class="p">.</span><span class="nx">fromCharCode</span><span class="p">(</span><span class="nb">parseInt</span><span class="p">(</span><span class="nx">octal</span><span class="p">,</span> <span class="mi">8</span><span class="p">));</span>
|
|
<span class="nx">tokPos</span> <span class="o">+=</span> <span class="nx">octal</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
|
<span class="k">switch</span> <span class="p">(</span><span class="nx">ch</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">case</span> <span class="mi">110</span><span class="o">:</span> <span class="nx">out</span> <span class="o">+=</span> <span class="s2">"\n"</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span> <span class="c1">// 'n' -> '\n'</span>
|
|
<span class="k">case</span> <span class="mi">114</span><span class="o">:</span> <span class="nx">out</span> <span class="o">+=</span> <span class="s2">"\r"</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span> <span class="c1">// 'r' -> '\r'</span>
|
|
<span class="k">case</span> <span class="mi">120</span><span class="o">:</span> <span class="nx">out</span> <span class="o">+=</span> <span class="nb">String</span><span class="p">.</span><span class="nx">fromCharCode</span><span class="p">(</span><span class="nx">readHexChar</span><span class="p">(</span><span class="mi">2</span><span class="p">));</span> <span class="k">break</span><span class="p">;</span> <span class="c1">// 'x'</span>
|
|
<span class="k">case</span> <span class="mi">117</span><span class="o">:</span> <span class="nx">out</span> <span class="o">+=</span> <span class="nb">String</span><span class="p">.</span><span class="nx">fromCharCode</span><span class="p">(</span><span class="nx">readHexChar</span><span class="p">(</span><span class="mi">4</span><span class="p">));</span> <span class="k">break</span><span class="p">;</span> <span class="c1">// 'u'</span>
|
|
<span class="k">case</span> <span class="mi">85</span><span class="o">:</span> <span class="nx">out</span> <span class="o">+=</span> <span class="nb">String</span><span class="p">.</span><span class="nx">fromCharCode</span><span class="p">(</span><span class="nx">readHexChar</span><span class="p">(</span><span class="mi">8</span><span class="p">));</span> <span class="k">break</span><span class="p">;</span> <span class="c1">// 'U'</span>
|
|
<span class="k">case</span> <span class="mi">116</span><span class="o">:</span> <span class="nx">out</span> <span class="o">+=</span> <span class="s2">"\t"</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span> <span class="c1">// 't' -> '\t'</span>
|
|
<span class="k">case</span> <span class="mi">98</span><span class="o">:</span> <span class="nx">out</span> <span class="o">+=</span> <span class="s2">"\b"</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span> <span class="c1">// 'b' -> '\b'</span>
|
|
<span class="k">case</span> <span class="mi">118</span><span class="o">:</span> <span class="nx">out</span> <span class="o">+=</span> <span class="s2">"\u000b"</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span> <span class="c1">// 'v' -> '\u000b'</span>
|
|
<span class="k">case</span> <span class="mi">102</span><span class="o">:</span> <span class="nx">out</span> <span class="o">+=</span> <span class="s2">"\f"</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span> <span class="c1">// 'f' -> '\f'</span>
|
|
<span class="k">case</span> <span class="mi">48</span><span class="o">:</span> <span class="nx">out</span> <span class="o">+=</span> <span class="s2">"\0"</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span> <span class="c1">// 0 -> '\0'</span>
|
|
<span class="k">case</span> <span class="mi">13</span><span class="o">:</span> <span class="k">if</span> <span class="p">(</span><span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">)</span> <span class="o">===</span> <span class="mi">10</span><span class="p">)</span> <span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span> <span class="c1">// '\r\n'</span>
|
|
<span class="k">case</span> <span class="mi">10</span><span class="o">:</span> <span class="c1">// ' \n'</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">locations</span><span class="p">)</span> <span class="p">{</span> <span class="nx">tokLineStart</span> <span class="o">=</span> <span class="nx">tokPos</span><span class="p">;</span> <span class="o">++</span><span class="nx">tokCurLine</span><span class="p">;</span> <span class="p">}</span>
|
|
<span class="k">break</span><span class="p">;</span>
|
|
<span class="k">default</span><span class="o">:</span> <span class="nx">out</span> <span class="o">+=</span> <span class="nb">String</span><span class="p">.</span><span class="nx">fromCharCode</span><span class="p">(</span><span class="nx">ch</span><span class="p">);</span> <span class="k">break</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">ch</span> <span class="o">===</span> <span class="mi">13</span> <span class="o">||</span> <span class="nx">ch</span> <span class="o">===</span> <span class="mi">10</span> <span class="o">||</span> <span class="nx">ch</span> <span class="o">===</span> <span class="mi">8232</span> <span class="o">||</span> <span class="nx">ch</span> <span class="o">===</span> <span class="mi">8329</span><span class="p">)</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">tokStart</span><span class="p">,</span> <span class="s2">"Unterminated string constant"</span><span class="p">);</span>
|
|
<span class="nx">out</span> <span class="o">+=</span> <span class="nb">String</span><span class="p">.</span><span class="nx">fromCharCode</span><span class="p">(</span><span class="nx">ch</span><span class="p">);</span> <span class="c1">// '\'</span>
|
|
<span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-71"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-71">¶</a> </div> <p>Used to read character escape sequences ('\x', '\u', '\U').</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">readHexChar</span><span class="p">(</span><span class="nx">len</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">n</span> <span class="o">=</span> <span class="nx">readInt</span><span class="p">(</span><span class="mi">16</span><span class="p">,</span> <span class="nx">len</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">n</span> <span class="o">===</span> <span class="kc">null</span><span class="p">)</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">tokStart</span><span class="p">,</span> <span class="s2">"Bad character escape sequence"</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">n</span><span class="p">;</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-72"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-72">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">containsEsc</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-73"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-73">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">readWord1</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="nx">containsEsc</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
<span class="kd">var</span> <span class="nx">word</span><span class="p">,</span> <span class="nx">first</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">start</span> <span class="o">=</span> <span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="k">for</span> <span class="p">(;;)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">ch</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">isIdentifierChar</span><span class="p">(</span><span class="nx">ch</span><span class="p">))</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">containsEsc</span><span class="p">)</span> <span class="nx">word</span> <span class="o">+=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">);</span>
|
|
<span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">ch</span> <span class="o">===</span> <span class="mi">92</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// "\"</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">containsEsc</span><span class="p">)</span> <span class="nx">word</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span> <span class="nx">tokPos</span><span class="p">);</span>
|
|
<span class="nx">containsEsc</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">input</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="o">++</span><span class="nx">tokPos</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">117</span><span class="p">)</span> <span class="c1">// "u"</span>
|
|
<span class="nx">raise</span><span class="p">(</span><span class="nx">tokPos</span><span class="p">,</span> <span class="s2">"Expecting Unicode escape sequence \\uXXXX"</span><span class="p">);</span>
|
|
<span class="o">++</span><span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="kd">var</span> <span class="nx">esc</span> <span class="o">=</span> <span class="nx">readHexChar</span><span class="p">(</span><span class="mi">4</span><span class="p">);</span>
|
|
<span class="kd">var</span> <span class="nx">escStr</span> <span class="o">=</span> <span class="nb">String</span><span class="p">.</span><span class="nx">fromCharCode</span><span class="p">(</span><span class="nx">esc</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">escStr</span><span class="p">)</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">tokPos</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="s2">"Invalid Unicode escape"</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="nx">first</span> <span class="o">?</span> <span class="nx">isIdentifierStart</span><span class="p">(</span><span class="nx">esc</span><span class="p">)</span> <span class="o">:</span> <span class="nx">isIdentifierChar</span><span class="p">(</span><span class="nx">esc</span><span class="p">)))</span>
|
|
<span class="nx">raise</span><span class="p">(</span><span class="nx">tokPos</span> <span class="o">-</span> <span class="mi">4</span><span class="p">,</span> <span class="s2">"Invalid Unicode escape"</span><span class="p">);</span>
|
|
<span class="nx">word</span> <span class="o">+=</span> <span class="nx">escStr</span><span class="p">;</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
|
<span class="k">break</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="nx">first</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="k">return</span> <span class="nx">containsEsc</span> <span class="o">?</span> <span class="nx">word</span> <span class="o">:</span> <span class="nx">input</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span> <span class="nx">tokPos</span><span class="p">);</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-74"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-74">¶</a> </div> <p>Read an identifier or keyword token. Will check for reserved
|
|
words when necessary.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">readWord</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">word</span> <span class="o">=</span> <span class="nx">readWord1</span><span class="p">();</span>
|
|
<span class="kd">var</span> <span class="nx">type</span> <span class="o">=</span> <span class="nx">_name</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">containsEsc</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">isKeyword</span><span class="p">(</span><span class="nx">word</span><span class="p">))</span> <span class="nx">type</span> <span class="o">=</span> <span class="nx">keywordTypes</span><span class="p">[</span><span class="nx">word</span><span class="p">];</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">forbidReserved</span> <span class="o">&&</span>
|
|
<span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">ecmaVersion</span> <span class="o">===</span> <span class="mi">3</span> <span class="o">?</span> <span class="nx">isReservedWord3</span> <span class="o">:</span> <span class="nx">isReservedWord5</span><span class="p">)(</span><span class="nx">word</span><span class="p">)</span> <span class="o">||</span>
|
|
<span class="nx">strict</span> <span class="o">&&</span> <span class="nx">isStrictReservedWord</span><span class="p">(</span><span class="nx">word</span><span class="p">))</span>
|
|
<span class="nx">raise</span><span class="p">(</span><span class="nx">tokStart</span><span class="p">,</span> <span class="s2">"The keyword '"</span> <span class="o">+</span> <span class="nx">word</span> <span class="o">+</span> <span class="s2">"' is reserved"</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="k">return</span> <span class="nx">finishToken</span><span class="p">(</span><span class="nx">type</span><span class="p">,</span> <span class="nx">word</span><span class="p">);</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-75"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-75">¶</a> </div> <h2>Parser</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-76"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-76">¶</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> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-77"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-77">¶</a> </div> <h3>Parser utilities</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-78"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-78">¶</a> </div> <p>Continue to the next token.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">next</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="nx">lastStart</span> <span class="o">=</span> <span class="nx">tokStart</span><span class="p">;</span>
|
|
<span class="nx">lastEnd</span> <span class="o">=</span> <span class="nx">tokEnd</span><span class="p">;</span>
|
|
<span class="nx">lastEndLoc</span> <span class="o">=</span> <span class="nx">tokEndLoc</span><span class="p">;</span>
|
|
<span class="nx">readToken</span><span class="p">();</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-79"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-79">¶</a> </div> <p>Enter strict mode. Re-reads the next token to please pedantic
|
|
tests ("use strict"; 010; -- should fail).</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">setStrict</span><span class="p">(</span><span class="nx">strct</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">strict</span> <span class="o">=</span> <span class="nx">strct</span><span class="p">;</span>
|
|
<span class="nx">tokPos</span> <span class="o">=</span> <span class="nx">lastEnd</span><span class="p">;</span>
|
|
<span class="k">while</span> <span class="p">(</span><span class="nx">tokPos</span> <span class="o"><</span> <span class="nx">tokLineStart</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">tokLineStart</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">lastIndexOf</span><span class="p">(</span><span class="s2">"\n"</span><span class="p">,</span> <span class="nx">tokLineStart</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
|
|
<span class="o">--</span><span class="nx">tokCurLine</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="nx">skipSpace</span><span class="p">();</span>
|
|
<span class="nx">readToken</span><span class="p">();</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-80"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-80">¶</a> </div> <p>Start an AST node, attaching a start offset.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">node_t</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">type</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">start</span> <span class="o">=</span> <span class="nx">tokStart</span><span class="p">;</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">end</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">function</span> <span class="nx">node_loc_t</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">start</span> <span class="o">=</span> <span class="nx">tokStartLoc</span><span class="p">;</span>
|
|
<span class="k">this</span><span class="p">.</span><span class="nx">end</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">sourceFile</span> <span class="o">!==</span> <span class="kc">null</span><span class="p">)</span> <span class="k">this</span><span class="p">.</span><span class="nx">source</span> <span class="o">=</span> <span class="nx">sourceFile</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">function</span> <span class="nx">startNode</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">node_t</span><span class="p">();</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">locations</span><span class="p">)</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">loc</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">node_loc_t</span><span class="p">();</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">ranges</span><span class="p">)</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">range</span> <span class="o">=</span> <span class="p">[</span><span class="nx">tokStart</span><span class="p">,</span> <span class="mi">0</span><span class="p">];</span>
|
|
<span class="k">return</span> <span class="nx">node</span><span class="p">;</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-81"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-81">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">startNodeFrom</span><span class="p">(</span><span class="nx">other</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">node_t</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">start</span> <span class="o">=</span> <span class="nx">other</span><span class="p">.</span><span class="nx">start</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">locations</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">loc</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">node_loc_t</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">loc</span><span class="p">.</span><span class="nx">start</span> <span class="o">=</span> <span class="nx">other</span><span class="p">.</span><span class="nx">loc</span><span class="p">.</span><span class="nx">start</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">ranges</span><span class="p">)</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">range</span> <span class="o">=</span> <span class="p">[</span><span class="nx">other</span><span class="p">.</span><span class="nx">range</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="mi">0</span><span class="p">];</span>
|
|
|
|
<span class="k">return</span> <span class="nx">node</span><span class="p">;</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-82"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-82">¶</a> </div> <p>Finish an AST node, adding <code>type</code> and <code>end</code> properties.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">type</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">type</span> <span class="o">=</span> <span class="nx">type</span><span class="p">;</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">end</span> <span class="o">=</span> <span class="nx">lastEnd</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">locations</span><span class="p">)</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">loc</span><span class="p">.</span><span class="nx">end</span> <span class="o">=</span> <span class="nx">lastEndLoc</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">ranges</span><span class="p">)</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">range</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="nx">lastEnd</span><span class="p">;</span>
|
|
<span class="k">return</span> <span class="nx">node</span><span class="p">;</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-83"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-83">¶</a> </div> <p>Test whether a statement node is the string literal <code>"use strict"</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">isUseStrict</span><span class="p">(</span><span class="nx">stmt</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="nx">options</span><span class="p">.</span><span class="nx">ecmaVersion</span> <span class="o">>=</span> <span class="mi">5</span> <span class="o">&&</span> <span class="nx">stmt</span><span class="p">.</span><span class="nx">type</span> <span class="o">===</span> <span class="s2">"ExpressionStatement"</span> <span class="o">&&</span>
|
|
<span class="nx">stmt</span><span class="p">.</span><span class="nx">expression</span><span class="p">.</span><span class="nx">type</span> <span class="o">===</span> <span class="s2">"Literal"</span> <span class="o">&&</span> <span class="nx">stmt</span><span class="p">.</span><span class="nx">expression</span><span class="p">.</span><span class="nx">value</span> <span class="o">===</span> <span class="s2">"use strict"</span><span class="p">;</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-84"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-84">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">eat</span><span class="p">(</span><span class="nx">type</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">tokType</span> <span class="o">===</span> <span class="nx">type</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-85"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-85">¶</a> </div> <p>Test whether a semicolon can be inserted at the current position.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">canInsertSemicolon</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="o">!</span><span class="nx">options</span><span class="p">.</span><span class="nx">strictSemicolons</span> <span class="o">&&</span>
|
|
<span class="p">(</span><span class="nx">tokType</span> <span class="o">===</span> <span class="nx">_eof</span> <span class="o">||</span> <span class="nx">tokType</span> <span class="o">===</span> <span class="nx">_braceR</span> <span class="o">||</span> <span class="nx">newline</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">input</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">lastEnd</span><span class="p">,</span> <span class="nx">tokStart</span><span class="p">)));</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-86"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-86">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">semicolon</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">eat</span><span class="p">(</span><span class="nx">_semi</span><span class="p">)</span> <span class="o">&&</span> <span class="o">!</span><span class="nx">canInsertSemicolon</span><span class="p">())</span> <span class="nx">unexpected</span><span class="p">();</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-87"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-87">¶</a> </div> <p>Expect a token of a given type. If found, consume it, otherwise,
|
|
raise an unexpected token error.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">expect</span><span class="p">(</span><span class="nx">type</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">tokType</span> <span class="o">===</span> <span class="nx">type</span><span class="p">)</span> <span class="nx">next</span><span class="p">();</span>
|
|
<span class="k">else</span> <span class="nx">unexpected</span><span class="p">();</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-88"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-88">¶</a> </div> <p>Raise an unexpected token error.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">unexpected</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="nx">raise</span><span class="p">(</span><span class="nx">tokStart</span><span class="p">,</span> <span class="s2">"Unexpected token"</span><span class="p">);</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-89"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-89">¶</a> </div> <p>Verify that a node is an lval — something that can be assigned
|
|
to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">checkLVal</span><span class="p">(</span><span class="nx">expr</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">expr</span><span class="p">.</span><span class="nx">type</span> <span class="o">!==</span> <span class="s2">"Identifier"</span> <span class="o">&&</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">type</span> <span class="o">!==</span> <span class="s2">"MemberExpression"</span><span class="p">)</span>
|
|
<span class="nx">raise</span><span class="p">(</span><span class="nx">expr</span><span class="p">.</span><span class="nx">start</span><span class="p">,</span> <span class="s2">"Assigning to rvalue"</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">strict</span> <span class="o">&&</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">type</span> <span class="o">===</span> <span class="s2">"Identifier"</span> <span class="o">&&</span> <span class="nx">isStrictBadIdWord</span><span class="p">(</span><span class="nx">expr</span><span class="p">.</span><span class="nx">name</span><span class="p">))</span>
|
|
<span class="nx">raise</span><span class="p">(</span><span class="nx">expr</span><span class="p">.</span><span class="nx">start</span><span class="p">,</span> <span class="s2">"Assigning to "</span> <span class="o">+</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="s2">" in strict mode"</span><span class="p">);</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-90"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-90">¶</a> </div> <h3>Statement parsing</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-91"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-91">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">parseTopLevel</span><span class="p">(</span><span class="nx">program</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">lastStart</span> <span class="o">=</span> <span class="nx">lastEnd</span> <span class="o">=</span> <span class="nx">tokPos</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">locations</span><span class="p">)</span> <span class="nx">lastEndLoc</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">line_loc_t</span><span class="p">;</span>
|
|
<span class="nx">inFunction</span> <span class="o">=</span> <span class="nx">strict</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
|
|
<span class="nx">labels</span> <span class="o">=</span> <span class="p">[];</span>
|
|
<span class="nx">readToken</span><span class="p">();</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">program</span> <span class="o">||</span> <span class="nx">startNode</span><span class="p">(),</span> <span class="nx">first</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">program</span><span class="p">)</span> <span class="nx">node</span><span class="p">.</span><span class="nx">body</span> <span class="o">=</span> <span class="p">[];</span>
|
|
<span class="k">while</span> <span class="p">(</span><span class="nx">tokType</span> <span class="o">!==</span> <span class="nx">_eof</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">stmt</span> <span class="o">=</span> <span class="nx">parseStatement</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">stmt</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">first</span> <span class="o">&&</span> <span class="nx">isUseStrict</span><span class="p">(</span><span class="nx">stmt</span><span class="p">))</span> <span class="nx">setStrict</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
|
|
<span class="nx">first</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"Program"</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">loopLabel</span> <span class="o">=</span> <span class="p">{</span><span class="nx">kind</span><span class="o">:</span> <span class="s2">"loop"</span><span class="p">},</span> <span class="nx">switchLabel</span> <span class="o">=</span> <span class="p">{</span><span class="nx">kind</span><span class="o">:</span> <span class="s2">"switch"</span><span class="p">};</span></pre></div> </td> </tr> <tr id="section-92"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-92">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">parseStatement</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">tokType</span> <span class="o">===</span> <span class="nx">_slash</span> <span class="o">||</span> <span class="nx">tokType</span> <span class="o">===</span> <span class="nx">_assign</span> <span class="o">&&</span> <span class="nx">tokVal</span> <span class="o">==</span> <span class="s2">"/="</span><span class="p">)</span>
|
|
<span class="nx">readToken</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">starttype</span> <span class="o">=</span> <span class="nx">tokType</span><span class="p">,</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">startNode</span><span class="p">();</span></pre></div> </td> </tr> <tr id="section-93"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-93">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="k">switch</span> <span class="p">(</span><span class="nx">starttype</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">case</span> <span class="nx">_break</span><span class="o">:</span> <span class="k">case</span> <span class="nx">_continue</span><span class="o">:</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="kd">var</span> <span class="nx">isBreak</span> <span class="o">=</span> <span class="nx">starttype</span> <span class="o">===</span> <span class="nx">_break</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">eat</span><span class="p">(</span><span class="nx">_semi</span><span class="p">)</span> <span class="o">||</span> <span class="nx">canInsertSemicolon</span><span class="p">())</span> <span class="nx">node</span><span class="p">.</span><span class="nx">label</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">tokType</span> <span class="o">!==</span> <span class="nx">_name</span><span class="p">)</span> <span class="nx">unexpected</span><span class="p">();</span>
|
|
<span class="k">else</span> <span class="p">{</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">label</span> <span class="o">=</span> <span class="nx">parseIdent</span><span class="p">();</span>
|
|
<span class="nx">semicolon</span><span class="p">();</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-94"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-94">¶</a> </div> <p>Verify that there is an actual destination to break or
|
|
continue to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">labels</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="o">++</span><span class="nx">i</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">lab</span> <span class="o">=</span> <span class="nx">labels</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">label</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">||</span> <span class="nx">lab</span><span class="p">.</span><span class="nx">name</span> <span class="o">===</span> <span class="nx">node</span><span class="p">.</span><span class="nx">label</span><span class="p">.</span><span class="nx">name</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">lab</span><span class="p">.</span><span class="nx">kind</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">&&</span> <span class="p">(</span><span class="nx">isBreak</span> <span class="o">||</span> <span class="nx">lab</span><span class="p">.</span><span class="nx">kind</span> <span class="o">===</span> <span class="s2">"loop"</span><span class="p">))</span> <span class="k">break</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">label</span> <span class="o">&&</span> <span class="nx">isBreak</span><span class="p">)</span> <span class="k">break</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">i</span> <span class="o">===</span> <span class="nx">labels</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">start</span><span class="p">,</span> <span class="s2">"Unsyntactic "</span> <span class="o">+</span> <span class="nx">starttype</span><span class="p">.</span><span class="nx">keyword</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">isBreak</span> <span class="o">?</span> <span class="s2">"BreakStatement"</span> <span class="o">:</span> <span class="s2">"ContinueStatement"</span><span class="p">);</span>
|
|
|
|
<span class="k">case</span> <span class="nx">_debugger</span><span class="o">:</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="nx">semicolon</span><span class="p">();</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"DebuggerStatement"</span><span class="p">);</span>
|
|
|
|
<span class="k">case</span> <span class="nx">_do</span><span class="o">:</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="nx">labels</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">loopLabel</span><span class="p">);</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">body</span> <span class="o">=</span> <span class="nx">parseStatement</span><span class="p">();</span>
|
|
<span class="nx">labels</span><span class="p">.</span><span class="nx">pop</span><span class="p">();</span>
|
|
<span class="nx">expect</span><span class="p">(</span><span class="nx">_while</span><span class="p">);</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">test</span> <span class="o">=</span> <span class="nx">parseParenExpression</span><span class="p">();</span>
|
|
<span class="nx">semicolon</span><span class="p">();</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"DoWhileStatement"</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-95"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-95">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="k">case</span> <span class="nx">_for</span><span class="o">:</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="nx">labels</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">loopLabel</span><span class="p">);</span>
|
|
<span class="nx">expect</span><span class="p">(</span><span class="nx">_parenL</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">tokType</span> <span class="o">===</span> <span class="nx">_semi</span><span class="p">)</span> <span class="k">return</span> <span class="nx">parseFor</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="kc">null</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">tokType</span> <span class="o">===</span> <span class="nx">_var</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">init</span> <span class="o">=</span> <span class="nx">startNode</span><span class="p">();</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="nx">parseVar</span><span class="p">(</span><span class="nx">init</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">init</span><span class="p">.</span><span class="nx">declarations</span><span class="p">.</span><span class="nx">length</span> <span class="o">===</span> <span class="mi">1</span> <span class="o">&&</span> <span class="nx">eat</span><span class="p">(</span><span class="nx">_in</span><span class="p">))</span>
|
|
<span class="k">return</span> <span class="nx">parseForIn</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">init</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">parseFor</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">init</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="kd">var</span> <span class="nx">init</span> <span class="o">=</span> <span class="nx">parseExpression</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">eat</span><span class="p">(</span><span class="nx">_in</span><span class="p">))</span> <span class="p">{</span><span class="nx">checkLVal</span><span class="p">(</span><span class="nx">init</span><span class="p">);</span> <span class="k">return</span> <span class="nx">parseForIn</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">init</span><span class="p">);}</span>
|
|
<span class="k">return</span> <span class="nx">parseFor</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">init</span><span class="p">);</span>
|
|
|
|
<span class="k">case</span> <span class="nx">_function</span><span class="o">:</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="k">return</span> <span class="nx">parseFunction</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
|
|
|
|
<span class="k">case</span> <span class="nx">_if</span><span class="o">:</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">test</span> <span class="o">=</span> <span class="nx">parseParenExpression</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">consequent</span> <span class="o">=</span> <span class="nx">parseStatement</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">alternate</span> <span class="o">=</span> <span class="nx">eat</span><span class="p">(</span><span class="nx">_else</span><span class="p">)</span> <span class="o">?</span> <span class="nx">parseStatement</span><span class="p">()</span> <span class="o">:</span> <span class="kc">null</span><span class="p">;</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"IfStatement"</span><span class="p">);</span>
|
|
|
|
<span class="k">case</span> <span class="nx">_return</span><span class="o">:</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">inFunction</span><span class="p">)</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">tokStart</span><span class="p">,</span> <span class="s2">"'return' outside of function"</span><span class="p">);</span>
|
|
<span class="nx">next</span><span class="p">();</span></pre></div> </td> </tr> <tr id="section-96"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-96">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nx">eat</span><span class="p">(</span><span class="nx">_semi</span><span class="p">)</span> <span class="o">||</span> <span class="nx">canInsertSemicolon</span><span class="p">())</span> <span class="nx">node</span><span class="p">.</span><span class="nx">argument</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
|
|
<span class="k">else</span> <span class="p">{</span> <span class="nx">node</span><span class="p">.</span><span class="nx">argument</span> <span class="o">=</span> <span class="nx">parseExpression</span><span class="p">();</span> <span class="nx">semicolon</span><span class="p">();</span> <span class="p">}</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"ReturnStatement"</span><span class="p">);</span>
|
|
|
|
<span class="k">case</span> <span class="nx">_switch</span><span class="o">:</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">discriminant</span> <span class="o">=</span> <span class="nx">parseParenExpression</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">cases</span> <span class="o">=</span> <span class="p">[];</span>
|
|
<span class="nx">expect</span><span class="p">(</span><span class="nx">_braceL</span><span class="p">);</span>
|
|
<span class="nx">labels</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">switchLabel</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-97"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-97">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">cur</span><span class="p">,</span> <span class="nx">sawDefault</span><span class="p">;</span> <span class="nx">tokType</span> <span class="o">!=</span> <span class="nx">_braceR</span><span class="p">;)</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">tokType</span> <span class="o">===</span> <span class="nx">_case</span> <span class="o">||</span> <span class="nx">tokType</span> <span class="o">===</span> <span class="nx">_default</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">isCase</span> <span class="o">=</span> <span class="nx">tokType</span> <span class="o">===</span> <span class="nx">_case</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">cur</span><span class="p">)</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">cur</span><span class="p">,</span> <span class="s2">"SwitchCase"</span><span class="p">);</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">cases</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">cur</span> <span class="o">=</span> <span class="nx">startNode</span><span class="p">());</span>
|
|
<span class="nx">cur</span><span class="p">.</span><span class="nx">consequent</span> <span class="o">=</span> <span class="p">[];</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">isCase</span><span class="p">)</span> <span class="nx">cur</span><span class="p">.</span><span class="nx">test</span> <span class="o">=</span> <span class="nx">parseExpression</span><span class="p">();</span>
|
|
<span class="k">else</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">sawDefault</span><span class="p">)</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">lastStart</span><span class="p">,</span> <span class="s2">"Multiple default clauses"</span><span class="p">);</span> <span class="nx">sawDefault</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
|
|
<span class="nx">cur</span><span class="p">.</span><span class="nx">test</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="nx">expect</span><span class="p">(</span><span class="nx">_colon</span><span class="p">);</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">cur</span><span class="p">)</span> <span class="nx">unexpected</span><span class="p">();</span>
|
|
<span class="nx">cur</span><span class="p">.</span><span class="nx">consequent</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">parseStatement</span><span class="p">());</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">cur</span><span class="p">)</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">cur</span><span class="p">,</span> <span class="s2">"SwitchCase"</span><span class="p">);</span>
|
|
<span class="nx">next</span><span class="p">();</span> <span class="c1">// Closing brace</span>
|
|
<span class="nx">labels</span><span class="p">.</span><span class="nx">pop</span><span class="p">();</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"SwitchStatement"</span><span class="p">);</span>
|
|
|
|
<span class="k">case</span> <span class="nx">_throw</span><span class="o">:</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">newline</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">input</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">lastEnd</span><span class="p">,</span> <span class="nx">tokStart</span><span class="p">)))</span>
|
|
<span class="nx">raise</span><span class="p">(</span><span class="nx">lastEnd</span><span class="p">,</span> <span class="s2">"Illegal newline after throw"</span><span class="p">);</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">argument</span> <span class="o">=</span> <span class="nx">parseExpression</span><span class="p">();</span>
|
|
<span class="nx">semicolon</span><span class="p">();</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"ThrowStatement"</span><span class="p">);</span>
|
|
|
|
<span class="k">case</span> <span class="nx">_try</span><span class="o">:</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">block</span> <span class="o">=</span> <span class="nx">parseBlock</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">handler</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">tokType</span> <span class="o">===</span> <span class="nx">_catch</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">clause</span> <span class="o">=</span> <span class="nx">startNode</span><span class="p">();</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="nx">expect</span><span class="p">(</span><span class="nx">_parenL</span><span class="p">);</span>
|
|
<span class="nx">clause</span><span class="p">.</span><span class="nx">param</span> <span class="o">=</span> <span class="nx">parseIdent</span><span class="p">();</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">strict</span> <span class="o">&&</span> <span class="nx">isStrictBadIdWord</span><span class="p">(</span><span class="nx">clause</span><span class="p">.</span><span class="nx">param</span><span class="p">.</span><span class="nx">name</span><span class="p">))</span>
|
|
<span class="nx">raise</span><span class="p">(</span><span class="nx">clause</span><span class="p">.</span><span class="nx">param</span><span class="p">.</span><span class="nx">start</span><span class="p">,</span> <span class="s2">"Binding "</span> <span class="o">+</span> <span class="nx">clause</span><span class="p">.</span><span class="nx">param</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="s2">" in strict mode"</span><span class="p">);</span>
|
|
<span class="nx">expect</span><span class="p">(</span><span class="nx">_parenR</span><span class="p">);</span>
|
|
<span class="nx">clause</span><span class="p">.</span><span class="nx">guard</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
|
|
<span class="nx">clause</span><span class="p">.</span><span class="nx">body</span> <span class="o">=</span> <span class="nx">parseBlock</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">handler</span> <span class="o">=</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">clause</span><span class="p">,</span> <span class="s2">"CatchClause"</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">guardedHandlers</span> <span class="o">=</span> <span class="nx">empty</span><span class="p">;</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">finalizer</span> <span class="o">=</span> <span class="nx">eat</span><span class="p">(</span><span class="nx">_finally</span><span class="p">)</span> <span class="o">?</span> <span class="nx">parseBlock</span><span class="p">()</span> <span class="o">:</span> <span class="kc">null</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">node</span><span class="p">.</span><span class="nx">handler</span> <span class="o">&&</span> <span class="o">!</span><span class="nx">node</span><span class="p">.</span><span class="nx">finalizer</span><span class="p">)</span>
|
|
<span class="nx">raise</span><span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">start</span><span class="p">,</span> <span class="s2">"Missing catch or finally clause"</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"TryStatement"</span><span class="p">);</span>
|
|
|
|
<span class="k">case</span> <span class="nx">_var</span><span class="o">:</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="nx">node</span> <span class="o">=</span> <span class="nx">parseVar</span><span class="p">(</span><span class="nx">node</span><span class="p">);</span>
|
|
<span class="nx">semicolon</span><span class="p">();</span>
|
|
<span class="k">return</span> <span class="nx">node</span><span class="p">;</span>
|
|
|
|
<span class="k">case</span> <span class="nx">_while</span><span class="o">:</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">test</span> <span class="o">=</span> <span class="nx">parseParenExpression</span><span class="p">();</span>
|
|
<span class="nx">labels</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">loopLabel</span><span class="p">);</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">body</span> <span class="o">=</span> <span class="nx">parseStatement</span><span class="p">();</span>
|
|
<span class="nx">labels</span><span class="p">.</span><span class="nx">pop</span><span class="p">();</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"WhileStatement"</span><span class="p">);</span>
|
|
|
|
<span class="k">case</span> <span class="nx">_with</span><span class="o">:</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">strict</span><span class="p">)</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">tokStart</span><span class="p">,</span> <span class="s2">"'with' in strict mode"</span><span class="p">);</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">object</span> <span class="o">=</span> <span class="nx">parseParenExpression</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">body</span> <span class="o">=</span> <span class="nx">parseStatement</span><span class="p">();</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"WithStatement"</span><span class="p">);</span>
|
|
|
|
<span class="k">case</span> <span class="nx">_braceL</span><span class="o">:</span>
|
|
<span class="k">return</span> <span class="nx">parseBlock</span><span class="p">();</span>
|
|
|
|
<span class="k">case</span> <span class="nx">_semi</span><span class="o">:</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"EmptyStatement"</span><span class="p">);</span></pre></div> </td> </tr> <tr id="section-98"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-98">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="k">default</span><span class="o">:</span>
|
|
<span class="kd">var</span> <span class="nx">maybeName</span> <span class="o">=</span> <span class="nx">tokVal</span><span class="p">,</span> <span class="nx">expr</span> <span class="o">=</span> <span class="nx">parseExpression</span><span class="p">();</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">starttype</span> <span class="o">===</span> <span class="nx">_name</span> <span class="o">&&</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">type</span> <span class="o">===</span> <span class="s2">"Identifier"</span> <span class="o">&&</span> <span class="nx">eat</span><span class="p">(</span><span class="nx">_colon</span><span class="p">))</span> <span class="p">{</span>
|
|
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">labels</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="o">++</span><span class="nx">i</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">labels</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">name</span> <span class="o">===</span> <span class="nx">maybeName</span><span class="p">)</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">expr</span><span class="p">.</span><span class="nx">start</span><span class="p">,</span> <span class="s2">"Label '"</span> <span class="o">+</span> <span class="nx">maybeName</span> <span class="o">+</span> <span class="s2">"' is already declared"</span><span class="p">);</span>
|
|
<span class="kd">var</span> <span class="nx">kind</span> <span class="o">=</span> <span class="nx">tokType</span><span class="p">.</span><span class="nx">isLoop</span> <span class="o">?</span> <span class="s2">"loop"</span> <span class="o">:</span> <span class="nx">tokType</span> <span class="o">===</span> <span class="nx">_switch</span> <span class="o">?</span> <span class="s2">"switch"</span> <span class="o">:</span> <span class="kc">null</span><span class="p">;</span>
|
|
<span class="nx">labels</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="nx">name</span><span class="o">:</span> <span class="nx">maybeName</span><span class="p">,</span> <span class="nx">kind</span><span class="o">:</span> <span class="nx">kind</span><span class="p">});</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">body</span> <span class="o">=</span> <span class="nx">parseStatement</span><span class="p">();</span>
|
|
<span class="nx">labels</span><span class="p">.</span><span class="nx">pop</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">label</span> <span class="o">=</span> <span class="nx">expr</span><span class="p">;</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"LabeledStatement"</span><span class="p">);</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">expression</span> <span class="o">=</span> <span class="nx">expr</span><span class="p">;</span>
|
|
<span class="nx">semicolon</span><span class="p">();</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"ExpressionStatement"</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-99"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-99">¶</a> </div> <p>Used for constructs like <code>switch</code> and <code>if</code> that insist on
|
|
parentheses around their expression.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">parseParenExpression</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="nx">expect</span><span class="p">(</span><span class="nx">_parenL</span><span class="p">);</span>
|
|
<span class="kd">var</span> <span class="nx">val</span> <span class="o">=</span> <span class="nx">parseExpression</span><span class="p">();</span>
|
|
<span class="nx">expect</span><span class="p">(</span><span class="nx">_parenR</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">val</span><span class="p">;</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-100"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-100">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">parseBlock</span><span class="p">(</span><span class="nx">allowStrict</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">startNode</span><span class="p">(),</span> <span class="nx">first</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">strict</span> <span class="o">=</span> <span class="kc">false</span><span class="p">,</span> <span class="nx">oldStrict</span><span class="p">;</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">body</span> <span class="o">=</span> <span class="p">[];</span>
|
|
<span class="nx">expect</span><span class="p">(</span><span class="nx">_braceL</span><span class="p">);</span>
|
|
<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="nx">eat</span><span class="p">(</span><span class="nx">_braceR</span><span class="p">))</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">stmt</span> <span class="o">=</span> <span class="nx">parseStatement</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">stmt</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">first</span> <span class="o">&&</span> <span class="nx">allowStrict</span> <span class="o">&&</span> <span class="nx">isUseStrict</span><span class="p">(</span><span class="nx">stmt</span><span class="p">))</span> <span class="p">{</span>
|
|
<span class="nx">oldStrict</span> <span class="o">=</span> <span class="nx">strict</span><span class="p">;</span>
|
|
<span class="nx">setStrict</span><span class="p">(</span><span class="nx">strict</span> <span class="o">=</span> <span class="kc">true</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="nx">first</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">strict</span> <span class="o">&&</span> <span class="o">!</span><span class="nx">oldStrict</span><span class="p">)</span> <span class="nx">setStrict</span><span class="p">(</span><span class="kc">false</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"BlockStatement"</span><span class="p">);</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-101"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-101">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">parseFor</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">init</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">init</span> <span class="o">=</span> <span class="nx">init</span><span class="p">;</span>
|
|
<span class="nx">expect</span><span class="p">(</span><span class="nx">_semi</span><span class="p">);</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">test</span> <span class="o">=</span> <span class="nx">tokType</span> <span class="o">===</span> <span class="nx">_semi</span> <span class="o">?</span> <span class="kc">null</span> <span class="o">:</span> <span class="nx">parseExpression</span><span class="p">();</span>
|
|
<span class="nx">expect</span><span class="p">(</span><span class="nx">_semi</span><span class="p">);</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">update</span> <span class="o">=</span> <span class="nx">tokType</span> <span class="o">===</span> <span class="nx">_parenR</span> <span class="o">?</span> <span class="kc">null</span> <span class="o">:</span> <span class="nx">parseExpression</span><span class="p">();</span>
|
|
<span class="nx">expect</span><span class="p">(</span><span class="nx">_parenR</span><span class="p">);</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">body</span> <span class="o">=</span> <span class="nx">parseStatement</span><span class="p">();</span>
|
|
<span class="nx">labels</span><span class="p">.</span><span class="nx">pop</span><span class="p">();</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"ForStatement"</span><span class="p">);</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-102"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-102">¶</a> </div> <p>Parse a <code>for</code>/<code>in</code> loop.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">parseForIn</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">init</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">left</span> <span class="o">=</span> <span class="nx">init</span><span class="p">;</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">right</span> <span class="o">=</span> <span class="nx">parseExpression</span><span class="p">();</span>
|
|
<span class="nx">expect</span><span class="p">(</span><span class="nx">_parenR</span><span class="p">);</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">body</span> <span class="o">=</span> <span class="nx">parseStatement</span><span class="p">();</span>
|
|
<span class="nx">labels</span><span class="p">.</span><span class="nx">pop</span><span class="p">();</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"ForInStatement"</span><span class="p">);</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-103"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-103">¶</a> </div> <p>Parse a list of variable declarations.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">parseVar</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">noIn</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">declarations</span> <span class="o">=</span> <span class="p">[];</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">kind</span> <span class="o">=</span> <span class="s2">"var"</span><span class="p">;</span>
|
|
<span class="k">for</span> <span class="p">(;;)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">decl</span> <span class="o">=</span> <span class="nx">startNode</span><span class="p">();</span>
|
|
<span class="nx">decl</span><span class="p">.</span><span class="nx">id</span> <span class="o">=</span> <span class="nx">parseIdent</span><span class="p">();</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">strict</span> <span class="o">&&</span> <span class="nx">isStrictBadIdWord</span><span class="p">(</span><span class="nx">decl</span><span class="p">.</span><span class="nx">id</span><span class="p">.</span><span class="nx">name</span><span class="p">))</span>
|
|
<span class="nx">raise</span><span class="p">(</span><span class="nx">decl</span><span class="p">.</span><span class="nx">id</span><span class="p">.</span><span class="nx">start</span><span class="p">,</span> <span class="s2">"Binding "</span> <span class="o">+</span> <span class="nx">decl</span><span class="p">.</span><span class="nx">id</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="s2">" in strict mode"</span><span class="p">);</span>
|
|
<span class="nx">decl</span><span class="p">.</span><span class="nx">init</span> <span class="o">=</span> <span class="nx">eat</span><span class="p">(</span><span class="nx">_eq</span><span class="p">)</span> <span class="o">?</span> <span class="nx">parseExpression</span><span class="p">(</span><span class="kc">true</span><span class="p">,</span> <span class="nx">noIn</span><span class="p">)</span> <span class="o">:</span> <span class="kc">null</span><span class="p">;</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">declarations</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">finishNode</span><span class="p">(</span><span class="nx">decl</span><span class="p">,</span> <span class="s2">"VariableDeclarator"</span><span class="p">));</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">eat</span><span class="p">(</span><span class="nx">_comma</span><span class="p">))</span> <span class="k">break</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"VariableDeclaration"</span><span class="p">);</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-104"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-104">¶</a> </div> <h3>Expression parsing</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-105"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-105">¶</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> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-106"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-106">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">parseExpression</span><span class="p">(</span><span class="nx">noComma</span><span class="p">,</span> <span class="nx">noIn</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">expr</span> <span class="o">=</span> <span class="nx">parseMaybeAssign</span><span class="p">(</span><span class="nx">noIn</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">noComma</span> <span class="o">&&</span> <span class="nx">tokType</span> <span class="o">===</span> <span class="nx">_comma</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">startNodeFrom</span><span class="p">(</span><span class="nx">expr</span><span class="p">);</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">expressions</span> <span class="o">=</span> <span class="p">[</span><span class="nx">expr</span><span class="p">];</span>
|
|
<span class="k">while</span> <span class="p">(</span><span class="nx">eat</span><span class="p">(</span><span class="nx">_comma</span><span class="p">))</span> <span class="nx">node</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">parseMaybeAssign</span><span class="p">(</span><span class="nx">noIn</span><span class="p">));</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"SequenceExpression"</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="k">return</span> <span class="nx">expr</span><span class="p">;</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-107"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-107">¶</a> </div> <p>Parse an assignment expression. This includes applications of
|
|
operators like <code>+=</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">parseMaybeAssign</span><span class="p">(</span><span class="nx">noIn</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">left</span> <span class="o">=</span> <span class="nx">parseMaybeConditional</span><span class="p">(</span><span class="nx">noIn</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">tokType</span><span class="p">.</span><span class="nx">isAssign</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">startNodeFrom</span><span class="p">(</span><span class="nx">left</span><span class="p">);</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">operator</span> <span class="o">=</span> <span class="nx">tokVal</span><span class="p">;</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">left</span> <span class="o">=</span> <span class="nx">left</span><span class="p">;</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">right</span> <span class="o">=</span> <span class="nx">parseMaybeAssign</span><span class="p">(</span><span class="nx">noIn</span><span class="p">);</span>
|
|
<span class="nx">checkLVal</span><span class="p">(</span><span class="nx">left</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"AssignmentExpression"</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="k">return</span> <span class="nx">left</span><span class="p">;</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-108"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-108">¶</a> </div> <p>Parse a ternary conditional (<code>?:</code>) operator.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">parseMaybeConditional</span><span class="p">(</span><span class="nx">noIn</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">expr</span> <span class="o">=</span> <span class="nx">parseExprOps</span><span class="p">(</span><span class="nx">noIn</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">eat</span><span class="p">(</span><span class="nx">_question</span><span class="p">))</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">startNodeFrom</span><span class="p">(</span><span class="nx">expr</span><span class="p">);</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">test</span> <span class="o">=</span> <span class="nx">expr</span><span class="p">;</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">consequent</span> <span class="o">=</span> <span class="nx">parseExpression</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
|
|
<span class="nx">expect</span><span class="p">(</span><span class="nx">_colon</span><span class="p">);</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">alternate</span> <span class="o">=</span> <span class="nx">parseExpression</span><span class="p">(</span><span class="kc">true</span><span class="p">,</span> <span class="nx">noIn</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"ConditionalExpression"</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="k">return</span> <span class="nx">expr</span><span class="p">;</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-109"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-109">¶</a> </div> <p>Start the precedence parser.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">parseExprOps</span><span class="p">(</span><span class="nx">noIn</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="nx">parseExprOp</span><span class="p">(</span><span class="nx">parseMaybeUnary</span><span class="p">(),</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="nx">noIn</span><span class="p">);</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-110"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-110">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">parseExprOp</span><span class="p">(</span><span class="nx">left</span><span class="p">,</span> <span class="nx">minPrec</span><span class="p">,</span> <span class="nx">noIn</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">prec</span> <span class="o">=</span> <span class="nx">tokType</span><span class="p">.</span><span class="nx">binop</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">prec</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">&&</span> <span class="p">(</span><span class="o">!</span><span class="nx">noIn</span> <span class="o">||</span> <span class="nx">tokType</span> <span class="o">!==</span> <span class="nx">_in</span><span class="p">))</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">prec</span> <span class="o">></span> <span class="nx">minPrec</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">startNodeFrom</span><span class="p">(</span><span class="nx">left</span><span class="p">);</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">left</span> <span class="o">=</span> <span class="nx">left</span><span class="p">;</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">operator</span> <span class="o">=</span> <span class="nx">tokVal</span><span class="p">;</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">right</span> <span class="o">=</span> <span class="nx">parseExprOp</span><span class="p">(</span><span class="nx">parseMaybeUnary</span><span class="p">(),</span> <span class="nx">prec</span><span class="p">,</span> <span class="nx">noIn</span><span class="p">);</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="sr">/&&|\|\|/</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">operator</span><span class="p">)</span> <span class="o">?</span> <span class="s2">"LogicalExpression"</span> <span class="o">:</span> <span class="s2">"BinaryExpression"</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">parseExprOp</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">minPrec</span><span class="p">,</span> <span class="nx">noIn</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="k">return</span> <span class="nx">left</span><span class="p">;</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-111"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-111">¶</a> </div> <p>Parse unary operators, both prefix and postfix.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">parseMaybeUnary</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">tokType</span><span class="p">.</span><span class="nx">prefix</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">startNode</span><span class="p">(),</span> <span class="nx">update</span> <span class="o">=</span> <span class="nx">tokType</span><span class="p">.</span><span class="nx">isUpdate</span><span class="p">;</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">operator</span> <span class="o">=</span> <span class="nx">tokVal</span><span class="p">;</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">prefix</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">argument</span> <span class="o">=</span> <span class="nx">parseMaybeUnary</span><span class="p">();</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">update</span><span class="p">)</span> <span class="nx">checkLVal</span><span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">argument</span><span class="p">);</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">strict</span> <span class="o">&&</span> <span class="nx">node</span><span class="p">.</span><span class="nx">operator</span> <span class="o">===</span> <span class="s2">"delete"</span> <span class="o">&&</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">argument</span><span class="p">.</span><span class="nx">type</span> <span class="o">===</span> <span class="s2">"Identifier"</span><span class="p">)</span>
|
|
<span class="nx">raise</span><span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">start</span><span class="p">,</span> <span class="s2">"Deleting local variable in strict mode"</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">update</span> <span class="o">?</span> <span class="s2">"UpdateExpression"</span> <span class="o">:</span> <span class="s2">"UnaryExpression"</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="kd">var</span> <span class="nx">expr</span> <span class="o">=</span> <span class="nx">parseExprSubscripts</span><span class="p">();</span>
|
|
<span class="k">while</span> <span class="p">(</span><span class="nx">tokType</span><span class="p">.</span><span class="nx">postfix</span> <span class="o">&&</span> <span class="o">!</span><span class="nx">canInsertSemicolon</span><span class="p">())</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">startNodeFrom</span><span class="p">(</span><span class="nx">expr</span><span class="p">);</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">operator</span> <span class="o">=</span> <span class="nx">tokVal</span><span class="p">;</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">prefix</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">argument</span> <span class="o">=</span> <span class="nx">expr</span><span class="p">;</span>
|
|
<span class="nx">checkLVal</span><span class="p">(</span><span class="nx">expr</span><span class="p">);</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="nx">expr</span> <span class="o">=</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"UpdateExpression"</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="k">return</span> <span class="nx">expr</span><span class="p">;</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-112"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-112">¶</a> </div> <p>Parse call, dot, and <code>[]</code>-subscript expressions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">parseExprSubscripts</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">return</span> <span class="nx">parseSubscripts</span><span class="p">(</span><span class="nx">parseExprAtom</span><span class="p">());</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">function</span> <span class="nx">parseSubscripts</span><span class="p">(</span><span class="nx">base</span><span class="p">,</span> <span class="nx">noCalls</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">eat</span><span class="p">(</span><span class="nx">_dot</span><span class="p">))</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">startNodeFrom</span><span class="p">(</span><span class="nx">base</span><span class="p">);</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">object</span> <span class="o">=</span> <span class="nx">base</span><span class="p">;</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">property</span> <span class="o">=</span> <span class="nx">parseIdent</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">computed</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
<span class="k">return</span> <span class="nx">parseSubscripts</span><span class="p">(</span><span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"MemberExpression"</span><span class="p">),</span> <span class="nx">noCalls</span><span class="p">);</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">eat</span><span class="p">(</span><span class="nx">_bracketL</span><span class="p">))</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">startNodeFrom</span><span class="p">(</span><span class="nx">base</span><span class="p">);</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">object</span> <span class="o">=</span> <span class="nx">base</span><span class="p">;</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">property</span> <span class="o">=</span> <span class="nx">parseExpression</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">computed</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
|
|
<span class="nx">expect</span><span class="p">(</span><span class="nx">_bracketR</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">parseSubscripts</span><span class="p">(</span><span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"MemberExpression"</span><span class="p">),</span> <span class="nx">noCalls</span><span class="p">);</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">noCalls</span> <span class="o">&&</span> <span class="nx">eat</span><span class="p">(</span><span class="nx">_parenL</span><span class="p">))</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">startNodeFrom</span><span class="p">(</span><span class="nx">base</span><span class="p">);</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">callee</span> <span class="o">=</span> <span class="nx">base</span><span class="p">;</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">arguments</span> <span class="o">=</span> <span class="nx">parseExprList</span><span class="p">(</span><span class="nx">_parenR</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">parseSubscripts</span><span class="p">(</span><span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"CallExpression"</span><span class="p">),</span> <span class="nx">noCalls</span><span class="p">);</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="k">return</span> <span class="nx">base</span><span class="p">;</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-113"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-113">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">parseExprAtom</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">switch</span> <span class="p">(</span><span class="nx">tokType</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">case</span> <span class="nx">_this</span><span class="o">:</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">startNode</span><span class="p">();</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"ThisExpression"</span><span class="p">);</span>
|
|
<span class="k">case</span> <span class="nx">_name</span><span class="o">:</span>
|
|
<span class="k">return</span> <span class="nx">parseIdent</span><span class="p">();</span>
|
|
<span class="k">case</span> <span class="nx">_num</span><span class="o">:</span> <span class="k">case</span> <span class="nx">_string</span><span class="o">:</span> <span class="k">case</span> <span class="nx">_regexp</span><span class="o">:</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">startNode</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">value</span> <span class="o">=</span> <span class="nx">tokVal</span><span class="p">;</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">raw</span> <span class="o">=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">tokStart</span><span class="p">,</span> <span class="nx">tokEnd</span><span class="p">);</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"Literal"</span><span class="p">);</span>
|
|
|
|
<span class="k">case</span> <span class="nx">_null</span><span class="o">:</span> <span class="k">case</span> <span class="nx">_true</span><span class="o">:</span> <span class="k">case</span> <span class="nx">_false</span><span class="o">:</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">startNode</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">value</span> <span class="o">=</span> <span class="nx">tokType</span><span class="p">.</span><span class="nx">atomValue</span><span class="p">;</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">raw</span> <span class="o">=</span> <span class="nx">tokType</span><span class="p">.</span><span class="nx">keyword</span><span class="p">;</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"Literal"</span><span class="p">);</span>
|
|
|
|
<span class="k">case</span> <span class="nx">_parenL</span><span class="o">:</span>
|
|
<span class="kd">var</span> <span class="nx">tokStartLoc1</span> <span class="o">=</span> <span class="nx">tokStartLoc</span><span class="p">,</span> <span class="nx">tokStart1</span> <span class="o">=</span> <span class="nx">tokStart</span><span class="p">;</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="kd">var</span> <span class="nx">val</span> <span class="o">=</span> <span class="nx">parseExpression</span><span class="p">();</span>
|
|
<span class="nx">val</span><span class="p">.</span><span class="nx">start</span> <span class="o">=</span> <span class="nx">tokStart1</span><span class="p">;</span>
|
|
<span class="nx">val</span><span class="p">.</span><span class="nx">end</span> <span class="o">=</span> <span class="nx">tokEnd</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">locations</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">val</span><span class="p">.</span><span class="nx">loc</span><span class="p">.</span><span class="nx">start</span> <span class="o">=</span> <span class="nx">tokStartLoc1</span><span class="p">;</span>
|
|
<span class="nx">val</span><span class="p">.</span><span class="nx">loc</span><span class="p">.</span><span class="nx">end</span> <span class="o">=</span> <span class="nx">tokEndLoc</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">ranges</span><span class="p">)</span>
|
|
<span class="nx">val</span><span class="p">.</span><span class="nx">range</span> <span class="o">=</span> <span class="p">[</span><span class="nx">tokStart1</span><span class="p">,</span> <span class="nx">tokEnd</span><span class="p">];</span>
|
|
<span class="nx">expect</span><span class="p">(</span><span class="nx">_parenR</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">val</span><span class="p">;</span>
|
|
|
|
<span class="k">case</span> <span class="nx">_bracketL</span><span class="o">:</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">startNode</span><span class="p">();</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">elements</span> <span class="o">=</span> <span class="nx">parseExprList</span><span class="p">(</span><span class="nx">_bracketR</span><span class="p">,</span> <span class="kc">true</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"ArrayExpression"</span><span class="p">);</span>
|
|
|
|
<span class="k">case</span> <span class="nx">_braceL</span><span class="o">:</span>
|
|
<span class="k">return</span> <span class="nx">parseObj</span><span class="p">();</span>
|
|
|
|
<span class="k">case</span> <span class="nx">_function</span><span class="o">:</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">startNode</span><span class="p">();</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="k">return</span> <span class="nx">parseFunction</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
|
|
|
|
<span class="k">case</span> <span class="nx">_new</span><span class="o">:</span>
|
|
<span class="k">return</span> <span class="nx">parseNew</span><span class="p">();</span>
|
|
|
|
<span class="k">default</span><span class="o">:</span>
|
|
<span class="nx">unexpected</span><span class="p">();</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-114"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-114">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">parseNew</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">startNode</span><span class="p">();</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">callee</span> <span class="o">=</span> <span class="nx">parseSubscripts</span><span class="p">(</span><span class="nx">parseExprAtom</span><span class="p">(),</span> <span class="kc">true</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">eat</span><span class="p">(</span><span class="nx">_parenL</span><span class="p">))</span> <span class="nx">node</span><span class="p">.</span><span class="nx">arguments</span> <span class="o">=</span> <span class="nx">parseExprList</span><span class="p">(</span><span class="nx">_parenR</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
|
|
<span class="k">else</span> <span class="nx">node</span><span class="p">.</span><span class="nx">arguments</span> <span class="o">=</span> <span class="nx">empty</span><span class="p">;</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"NewExpression"</span><span class="p">);</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-115"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-115">¶</a> </div> <p>Parse an object literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">parseObj</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">startNode</span><span class="p">(),</span> <span class="nx">first</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">sawGetSet</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">properties</span> <span class="o">=</span> <span class="p">[];</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="nx">eat</span><span class="p">(</span><span class="nx">_braceR</span><span class="p">))</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">first</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">expect</span><span class="p">(</span><span class="nx">_comma</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">allowTrailingCommas</span> <span class="o">&&</span> <span class="nx">eat</span><span class="p">(</span><span class="nx">_braceR</span><span class="p">))</span> <span class="k">break</span><span class="p">;</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="nx">first</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">prop</span> <span class="o">=</span> <span class="p">{</span><span class="nx">key</span><span class="o">:</span> <span class="nx">parsePropertyName</span><span class="p">()},</span> <span class="nx">isGetSet</span> <span class="o">=</span> <span class="kc">false</span><span class="p">,</span> <span class="nx">kind</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">eat</span><span class="p">(</span><span class="nx">_colon</span><span class="p">))</span> <span class="p">{</span>
|
|
<span class="nx">prop</span><span class="p">.</span><span class="nx">value</span> <span class="o">=</span> <span class="nx">parseExpression</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
|
|
<span class="nx">kind</span> <span class="o">=</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">kind</span> <span class="o">=</span> <span class="s2">"init"</span><span class="p">;</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">ecmaVersion</span> <span class="o">>=</span> <span class="mi">5</span> <span class="o">&&</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">key</span><span class="p">.</span><span class="nx">type</span> <span class="o">===</span> <span class="s2">"Identifier"</span> <span class="o">&&</span>
|
|
<span class="p">(</span><span class="nx">prop</span><span class="p">.</span><span class="nx">key</span><span class="p">.</span><span class="nx">name</span> <span class="o">===</span> <span class="s2">"get"</span> <span class="o">||</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">key</span><span class="p">.</span><span class="nx">name</span> <span class="o">===</span> <span class="s2">"set"</span><span class="p">))</span> <span class="p">{</span>
|
|
<span class="nx">isGetSet</span> <span class="o">=</span> <span class="nx">sawGetSet</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
|
|
<span class="nx">kind</span> <span class="o">=</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">kind</span> <span class="o">=</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">key</span><span class="p">.</span><span class="nx">name</span><span class="p">;</span>
|
|
<span class="nx">prop</span><span class="p">.</span><span class="nx">key</span> <span class="o">=</span> <span class="nx">parsePropertyName</span><span class="p">();</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">tokType</span> <span class="o">!==</span> <span class="nx">_parenL</span><span class="p">)</span> <span class="nx">unexpected</span><span class="p">();</span>
|
|
<span class="nx">prop</span><span class="p">.</span><span class="nx">value</span> <span class="o">=</span> <span class="nx">parseFunction</span><span class="p">(</span><span class="nx">startNode</span><span class="p">(),</span> <span class="kc">false</span><span class="p">);</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="nx">unexpected</span><span class="p">();</span></pre></div> </td> </tr> <tr id="section-116"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-116">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nx">prop</span><span class="p">.</span><span class="nx">key</span><span class="p">.</span><span class="nx">type</span> <span class="o">===</span> <span class="s2">"Identifier"</span> <span class="o">&&</span> <span class="p">(</span><span class="nx">strict</span> <span class="o">||</span> <span class="nx">sawGetSet</span><span class="p">))</span> <span class="p">{</span>
|
|
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">node</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="o">++</span><span class="nx">i</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">other</span> <span class="o">=</span> <span class="nx">node</span><span class="p">.</span><span class="nx">properties</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">other</span><span class="p">.</span><span class="nx">key</span><span class="p">.</span><span class="nx">name</span> <span class="o">===</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">key</span><span class="p">.</span><span class="nx">name</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">conflict</span> <span class="o">=</span> <span class="nx">kind</span> <span class="o">==</span> <span class="nx">other</span><span class="p">.</span><span class="nx">kind</span> <span class="o">||</span> <span class="nx">isGetSet</span> <span class="o">&&</span> <span class="nx">other</span><span class="p">.</span><span class="nx">kind</span> <span class="o">===</span> <span class="s2">"init"</span> <span class="o">||</span>
|
|
<span class="nx">kind</span> <span class="o">===</span> <span class="s2">"init"</span> <span class="o">&&</span> <span class="p">(</span><span class="nx">other</span><span class="p">.</span><span class="nx">kind</span> <span class="o">===</span> <span class="s2">"get"</span> <span class="o">||</span> <span class="nx">other</span><span class="p">.</span><span class="nx">kind</span> <span class="o">===</span> <span class="s2">"set"</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">conflict</span> <span class="o">&&</span> <span class="o">!</span><span class="nx">strict</span> <span class="o">&&</span> <span class="nx">kind</span> <span class="o">===</span> <span class="s2">"init"</span> <span class="o">&&</span> <span class="nx">other</span><span class="p">.</span><span class="nx">kind</span> <span class="o">===</span> <span class="s2">"init"</span><span class="p">)</span> <span class="nx">conflict</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">conflict</span><span class="p">)</span> <span class="nx">raise</span><span class="p">(</span><span class="nx">prop</span><span class="p">.</span><span class="nx">key</span><span class="p">.</span><span class="nx">start</span><span class="p">,</span> <span class="s2">"Redefinition of property"</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">prop</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"ObjectExpression"</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">function</span> <span class="nx">parsePropertyName</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">tokType</span> <span class="o">===</span> <span class="nx">_num</span> <span class="o">||</span> <span class="nx">tokType</span> <span class="o">===</span> <span class="nx">_string</span><span class="p">)</span> <span class="k">return</span> <span class="nx">parseExprAtom</span><span class="p">();</span>
|
|
<span class="k">return</span> <span class="nx">parseIdent</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-117"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-117">¶</a> </div> <p>Parse a function declaration or literal (depending on the
|
|
<code>isStatement</code> parameter).</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">parseFunction</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">isStatement</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">tokType</span> <span class="o">===</span> <span class="nx">_name</span><span class="p">)</span> <span class="nx">node</span><span class="p">.</span><span class="nx">id</span> <span class="o">=</span> <span class="nx">parseIdent</span><span class="p">();</span>
|
|
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">isStatement</span><span class="p">)</span> <span class="nx">unexpected</span><span class="p">();</span>
|
|
<span class="k">else</span> <span class="nx">node</span><span class="p">.</span><span class="nx">id</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">params</span> <span class="o">=</span> <span class="p">[];</span>
|
|
<span class="kd">var</span> <span class="nx">first</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
|
|
<span class="nx">expect</span><span class="p">(</span><span class="nx">_parenL</span><span class="p">);</span>
|
|
<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="nx">eat</span><span class="p">(</span><span class="nx">_parenR</span><span class="p">))</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">first</span><span class="p">)</span> <span class="nx">expect</span><span class="p">(</span><span class="nx">_comma</span><span class="p">);</span> <span class="k">else</span> <span class="nx">first</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">params</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">parseIdent</span><span class="p">());</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-118"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-118">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">oldInFunc</span> <span class="o">=</span> <span class="nx">inFunction</span><span class="p">,</span> <span class="nx">oldLabels</span> <span class="o">=</span> <span class="nx">labels</span><span class="p">;</span>
|
|
<span class="nx">inFunction</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span> <span class="nx">labels</span> <span class="o">=</span> <span class="p">[];</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">body</span> <span class="o">=</span> <span class="nx">parseBlock</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
|
|
<span class="nx">inFunction</span> <span class="o">=</span> <span class="nx">oldInFunc</span><span class="p">;</span> <span class="nx">labels</span> <span class="o">=</span> <span class="nx">oldLabels</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-119"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-119">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nx">strict</span> <span class="o">||</span> <span class="nx">node</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">length</span> <span class="o">&&</span> <span class="nx">isUseStrict</span><span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">body</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span> <span class="p">{</span>
|
|
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="nx">node</span><span class="p">.</span><span class="nx">id</span> <span class="o">?</span> <span class="o">-</span><span class="mi">1</span> <span class="o">:</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">node</span><span class="p">.</span><span class="nx">params</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="o">++</span><span class="nx">i</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">id</span> <span class="o">=</span> <span class="nx">i</span> <span class="o"><</span> <span class="mi">0</span> <span class="o">?</span> <span class="nx">node</span><span class="p">.</span><span class="nx">id</span> <span class="o">:</span> <span class="nx">node</span><span class="p">.</span><span class="nx">params</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">isStrictReservedWord</span><span class="p">(</span><span class="nx">id</span><span class="p">.</span><span class="nx">name</span><span class="p">)</span> <span class="o">||</span> <span class="nx">isStrictBadIdWord</span><span class="p">(</span><span class="nx">id</span><span class="p">.</span><span class="nx">name</span><span class="p">))</span>
|
|
<span class="nx">raise</span><span class="p">(</span><span class="nx">id</span><span class="p">.</span><span class="nx">start</span><span class="p">,</span> <span class="s2">"Defining '"</span> <span class="o">+</span> <span class="nx">id</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="s2">"' in strict mode"</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">i</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">)</span> <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">j</span> <span class="o"><</span> <span class="nx">i</span><span class="p">;</span> <span class="o">++</span><span class="nx">j</span><span class="p">)</span> <span class="k">if</span> <span class="p">(</span><span class="nx">id</span><span class="p">.</span><span class="nx">name</span> <span class="o">===</span> <span class="nx">node</span><span class="p">.</span><span class="nx">params</span><span class="p">[</span><span class="nx">j</span><span class="p">].</span><span class="nx">name</span><span class="p">)</span>
|
|
<span class="nx">raise</span><span class="p">(</span><span class="nx">id</span><span class="p">.</span><span class="nx">start</span><span class="p">,</span> <span class="s2">"Argument name clash in strict mode"</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">isStatement</span> <span class="o">?</span> <span class="s2">"FunctionDeclaration"</span> <span class="o">:</span> <span class="s2">"FunctionExpression"</span><span class="p">);</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-120"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-120">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">parseExprList</span><span class="p">(</span><span class="nx">close</span><span class="p">,</span> <span class="nx">allowTrailingComma</span><span class="p">,</span> <span class="nx">allowEmpty</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">elts</span> <span class="o">=</span> <span class="p">[],</span> <span class="nx">first</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
|
|
<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="nx">eat</span><span class="p">(</span><span class="nx">close</span><span class="p">))</span> <span class="p">{</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">first</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="nx">expect</span><span class="p">(</span><span class="nx">_comma</span><span class="p">);</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">allowTrailingComma</span> <span class="o">&&</span> <span class="nx">options</span><span class="p">.</span><span class="nx">allowTrailingCommas</span> <span class="o">&&</span> <span class="nx">eat</span><span class="p">(</span><span class="nx">close</span><span class="p">))</span> <span class="k">break</span><span class="p">;</span>
|
|
<span class="p">}</span> <span class="k">else</span> <span class="nx">first</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
|
|
<span class="k">if</span> <span class="p">(</span><span class="nx">allowEmpty</span> <span class="o">&&</span> <span class="nx">tokType</span> <span class="o">===</span> <span class="nx">_comma</span><span class="p">)</span> <span class="nx">elts</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="kc">null</span><span class="p">);</span>
|
|
<span class="k">else</span> <span class="nx">elts</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">parseExpression</span><span class="p">(</span><span class="kc">true</span><span class="p">));</span>
|
|
<span class="p">}</span>
|
|
<span class="k">return</span> <span class="nx">elts</span><span class="p">;</span>
|
|
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-121"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-121">¶</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> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">function</span> <span class="nx">parseIdent</span><span class="p">(</span><span class="nx">liberal</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="nx">startNode</span><span class="p">();</span>
|
|
<span class="nx">node</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">tokType</span> <span class="o">===</span> <span class="nx">_name</span> <span class="o">?</span> <span class="nx">tokVal</span> <span class="o">:</span> <span class="p">(</span><span class="nx">liberal</span> <span class="o">&&</span> <span class="o">!</span><span class="nx">options</span><span class="p">.</span><span class="nx">forbidReserved</span> <span class="o">&&</span> <span class="nx">tokType</span><span class="p">.</span><span class="nx">keyword</span><span class="p">)</span> <span class="o">||</span> <span class="nx">unexpected</span><span class="p">();</span>
|
|
<span class="nx">tokRegexpAllowed</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
|
|
<span class="nx">next</span><span class="p">();</span>
|
|
<span class="k">return</span> <span class="nx">finishNode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="s2">"Identifier"</span><span class="p">);</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="p">});</span>
|
|
|
|
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html> |