coffeescript
Advanced tools
| # Ensure that the OptionParser handles arguments correctly. | ||
| {OptionParser}: require './../lib/optparse' | ||
| opt: new OptionParser [ | ||
| ['-r', '--required [DIR]', 'desc required'] | ||
| ['-o', '--optional', 'desc optional'] | ||
| ] | ||
| result: opt.parse ['one', 'two', 'three', '-r', 'dir'] | ||
| ok result.arguments.length is 5 | ||
| ok result.arguments[3] is '-r' | ||
| result: opt.parse ['--optional', '-r', 'folder', 'one', 'two'] | ||
| ok result.optional is true | ||
| ok result.required is 'folder' | ||
| ok result.arguments.join(' ') is 'folder one two' | ||
| # Basic exception throwing. | ||
| block: -> (throw 'up') | ||
| throws block, 'up' | ||
| # Basic try/catch. | ||
| result: try | ||
| 10 | ||
| finally | ||
| 15 | ||
| ok result is 10 | ||
| result: try | ||
| throw 'up' | ||
| catch err | ||
| err.length | ||
| ok result is 2 | ||
| result: try throw 'error' catch err then err.length | ||
| ok result is 5 | ||
| # try/catch with empty clauses still compiles. | ||
| try | ||
| # nothing | ||
| catch err | ||
| # nothing | ||
| try | ||
| # nothing | ||
| finally | ||
| # nothing | ||
| ok yes |
@@ -19,3 +19,3 @@ <!DOCTYPE html> <html> <head> <title>coffee-script.coffee</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> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> coffee-script.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>CoffeeScript can be used both on the server, as a command-line compiler based | ||
| <span class="nv">parser: </span> <span class="k">this</span><span class="p">.</span><span class="nx">parser</span> | ||
| <span class="nv">helpers: </span> <span class="k">this</span><span class="p">.</span><span class="nx">helpers</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>The current CoffeeScript version number.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.VERSION: </span><span class="s1">'0.7.0'</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Instantiate a Lexer for our use here.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lexer: </span><span class="k">new</span> <span class="nx">Lexer</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison | ||
| <span class="nv">helpers: </span> <span class="k">this</span><span class="p">.</span><span class="nx">helpers</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>The current CoffeeScript version number.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.VERSION: </span><span class="s1">'0.7.1'</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Instantiate a Lexer for our use here.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lexer: </span><span class="k">new</span> <span class="nx">Lexer</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison | ||
| compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.compile: compile: </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span> | ||
@@ -22,0 +22,0 @@ <span class="nv">options: </span><span class="o">or</span> <span class="p">{}</span> |
@@ -37,4 +37,4 @@ <!DOCTYPE html> <html> <head> <title>command.coffee</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> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> command.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>The <code>coffee</code> utility. Handles command-line compilation of CoffeeScript | ||
| <span class="k">return</span> <span class="nx">require</span> <span class="s1">'./repl'</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">interactive</span> | ||
| <span class="k">return</span> <span class="nx">compileStdio</span><span class="p">()</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">stdio</span> | ||
| <span class="k">return</span> <span class="nx">compileScript</span> <span class="s1">'console'</span><span class="p">,</span> <span class="nx">sources</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nb">eval</span> | ||
| <span class="k">return</span> <span class="nx">compileStdio</span><span class="p">()</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">stdio</span> | ||
| <span class="k">return</span> <span class="nx">compileScript</span> <span class="s1">'console'</span><span class="p">,</span> <span class="nx">sources</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nb">eval</span> | ||
| <span class="k">return</span> <span class="nx">require</span> <span class="s1">'./repl'</span> <span class="nx">unless</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">length</span> | ||
@@ -44,4 +44,7 @@ <span class="nv">separator: </span><span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span> <span class="s1">'--'</span> | ||
| <span class="k">if</span> <span class="nx">separator</span> <span class="o">>=</span> <span class="mi">0</span> | ||
| <span class="nv">flags: </span><span class="nx">sources</span><span class="p">[(</span><span class="nx">separator</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)...</span><span class="nx">sources</span><span class="p">.</span><span class="nx">length</span><span class="p">]</span> | ||
| <span class="nv">flags: </span> <span class="nx">sources</span><span class="p">[(</span><span class="nx">separator</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)...</span><span class="nx">sources</span><span class="p">.</span><span class="nx">length</span><span class="p">]</span> | ||
| <span class="nv">sources: </span><span class="nx">sources</span><span class="p">[</span><span class="mi">0</span><span class="p">...</span><span class="nx">separator</span><span class="p">]</span> | ||
| <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">run</span> | ||
| <span class="nv">flags: </span> <span class="nx">sources</span><span class="p">[</span><span class="mi">1</span><span class="p">..</span><span class="nx">sources</span><span class="p">.</span><span class="nx">length</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">flags</span> | ||
| <span class="nv">sources: </span><span class="p">[</span><span class="nx">sources</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span> | ||
| <span class="nv">process.ARGV: process.argv: </span><span class="nx">flags</span> | ||
@@ -117,7 +120,7 @@ <span class="nx">compileScripts</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Asynchronously read in each CoffeeScript in a list of source files and | ||
| <code>process.argv</code> that are specified in <code>SWITCHES</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">parseOptions: </span><span class="o">-></span> | ||
| <span class="nv">optionParser: </span><span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">SWITCHES</span><span class="p">,</span> <span class="nx">BANNER</span> | ||
| <span class="nv">o: options: </span> <span class="nx">optionParser</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">)</span> | ||
| <span class="nv">optionParser: </span> <span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">SWITCHES</span><span class="p">,</span> <span class="nx">BANNER</span> | ||
| <span class="nv">o: options: </span> <span class="nx">optionParser</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">...</span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">.</span><span class="nx">length</span><span class="p">])</span> | ||
| <span class="nv">options.run: </span> <span class="o">not</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">lint</span><span class="p">)</span> | ||
| <span class="nv">options.print: </span><span class="o">!!</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nb">eval</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">stdio</span> <span class="o">and</span> <span class="nx">o</span><span class="p">.</span><span class="nx">compile</span><span class="p">))</span> | ||
| <span class="nv">sources: </span> <span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span><span class="p">[</span><span class="mi">2</span><span class="p">...</span><span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span><span class="p">.</span><span class="nx">length</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>The compile-time options to pass to the CoffeeScript compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileOptions: </span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">-></span> | ||
| <span class="nv">sources: </span> <span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>The compile-time options to pass to the CoffeeScript compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileOptions: </span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">-></span> | ||
| <span class="nv">o: </span><span class="p">{</span><span class="nx">source</span><span class="p">}</span> | ||
@@ -124,0 +127,0 @@ <span class="nv">o.noWrap: </span><span class="nx">options</span><span class="p">[</span><span class="s1">'no-wrap'</span><span class="p">]</span> |
@@ -6,4 +6,7 @@ <!DOCTYPE html> <html> <head> <title>optparse.coffee</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> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> optparse.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>A simple <strong>OptionParser</strong> class to parse option flags from the command-line. | ||
| options: parser.parse process.argv | ||
| </code></pre> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.OptionParser: </span><span class="nx">class</span> <span class="nx">OptionParser</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-2">#</a> </div> <p>Initialize with a list of valid options, in the form:</p> | ||
| </code></pre> | ||
| <p>The first non-option is considered to be the start of the file (and file | ||
| option) list, and all subsequent arguments are left unparsed.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.OptionParser: </span><span class="nx">class</span> <span class="nx">OptionParser</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-2">#</a> </div> <p>Initialize with a list of valid options, in the form:</p> | ||
| <pre><code>[short-flag, long-flag, description] | ||
@@ -21,3 +24,3 @@ </code></pre> | ||
| <span class="nv">args: </span><span class="nx">normalizeArguments</span> <span class="nx">args</span> | ||
| <span class="k">while</span> <span class="p">(</span><span class="nv">arg: </span><span class="nx">args</span><span class="p">.</span><span class="nx">shift</span><span class="p">())</span> | ||
| <span class="k">for</span> <span class="nx">arg</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">args</span> | ||
| <span class="nv">isOption: </span><span class="o">!!</span><span class="p">(</span><span class="nx">arg</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">LONG_FLAG</span><span class="p">)</span> <span class="o">or</span> <span class="nx">arg</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">SHORT_FLAG</span><span class="p">))</span> | ||
@@ -27,7 +30,9 @@ <span class="nv">matchedRule: </span><span class="kc">no</span> | ||
| <span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">shortFlag</span> <span class="o">is</span> <span class="nx">arg</span> <span class="o">or</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">longFlag</span> <span class="o">is</span> <span class="nx">arg</span> | ||
| <span class="nx">options</span><span class="p">[</span><span class="nx">rule</span><span class="p">.</span><span class="nx">name</span><span class="p">]</span><span class="o">:</span> <span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">hasArgument</span> <span class="k">then</span> <span class="nx">args</span><span class="p">.</span><span class="nx">shift</span><span class="p">()</span> <span class="k">else</span> <span class="kc">true</span> | ||
| <span class="nx">options</span><span class="p">[</span><span class="nx">rule</span><span class="p">.</span><span class="nx">name</span><span class="p">]</span><span class="o">:</span> <span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">hasArgument</span> <span class="k">then</span> <span class="nx">args</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="k">else</span> <span class="kc">true</span> | ||
| <span class="nv">matchedRule: </span><span class="kc">yes</span> | ||
| <span class="k">break</span> | ||
| <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"unrecognized option: $arg"</span> <span class="k">if</span> <span class="nx">isOption</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">matchedRule</span> | ||
| <span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">arg</span> <span class="nx">unless</span> <span class="nx">isOption</span> | ||
| <span class="k">if</span> <span class="o">not</span> <span class="nx">isOption</span> | ||
| <span class="nv">options.arguments: </span><span class="nx">args</span><span class="p">[</span><span class="nx">i</span><span class="p">...</span><span class="nx">args</span><span class="p">.</span><span class="nx">length</span><span class="p">]</span> | ||
| <span class="k">break</span> | ||
| <span class="nx">options</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Return the help text for this <strong>OptionParser</strong>, listing and describing all | ||
@@ -34,0 +39,0 @@ of the valid options, for <code>--help</code> and such.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">help: </span><span class="o">-></span> |
@@ -17,2 +17,3 @@ <!DOCTYPE html> <html> <head> <title>rewriter.coffee</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> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> rewriter.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>The CoffeeScript language has a good deal of optional syntax, implicit syntax, | ||
| <span class="vi">@tokens: </span><span class="nx">tokens</span> | ||
| <span class="nx">@adjustComments</span><span class="p">()</span> | ||
| <span class="nx">@removeLeadingNewlines</span><span class="p">()</span> | ||
@@ -35,5 +36,23 @@ <span class="nx">@removeMidExpressionNewlines</span><span class="p">()</span> | ||
| <span class="nv">i: </span><span class="o">+</span> <span class="nx">move</span> | ||
| <span class="kc">true</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Leading newlines would introduce an ambiguity in the grammar, so we | ||
| <span class="kc">true</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Massage newlines and indentations so that comments don't have to be | ||
| correctly indented, or appear on a line of their own.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">adjustComments: </span><span class="o">-></span> | ||
| <span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">post</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=></span> | ||
| <span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'HERECOMMENT'</span> | ||
| <span class="p">[</span><span class="nx">before</span><span class="p">,</span> <span class="nx">after</span><span class="p">]</span><span class="o">:</span> <span class="p">[</span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">],</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]]</span> | ||
| <span class="k">if</span> <span class="nx">after</span> <span class="o">and</span> <span class="nx">after</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'INDENT'</span> | ||
| <span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span> | ||
| <span class="k">if</span> <span class="nx">before</span> <span class="o">and</span> <span class="nx">before</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'OUTDENT'</span> <span class="o">and</span> <span class="nx">post</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="nx">post</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span> | ||
| <span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span> | ||
| <span class="k">else</span> | ||
| <span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">after</span> | ||
| <span class="k">else</span> <span class="k">if</span> <span class="nx">prev</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">not</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'INDENT'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">]</span> | ||
| <span class="k">if</span> <span class="nx">post</span> <span class="o">and</span> <span class="nx">post</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span> <span class="o">and</span> <span class="nx">after</span> <span class="o">and</span> <span class="nx">after</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'OUTDENT'</span> | ||
| <span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="mi">2</span><span class="p">)...)</span> | ||
| <span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s2">"\n"</span><span class="p">,</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">2</span><span class="p">]])</span> | ||
| <span class="k">else</span> | ||
| <span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s2">"\n"</span><span class="p">,</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span> | ||
| <span class="k">return</span> <span class="mi">2</span> | ||
| <span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Leading newlines would introduce an ambiguity in the grammar, so we | ||
| dispatch them here.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">removeLeadingNewlines: </span><span class="o">-></span> | ||
| <span class="nx">@tokens</span><span class="p">.</span><span class="nx">shift</span><span class="p">()</span> <span class="k">while</span> <span class="nx">@tokens</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">and</span> <span class="nx">@tokens</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="o">is</span> <span class="s1">'TERMINATOR'</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Some blocks occur in the middle of expressions -- when we're expecting | ||
| <span class="nx">@tokens</span><span class="p">.</span><span class="nx">shift</span><span class="p">()</span> <span class="k">while</span> <span class="nx">@tokens</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">and</span> <span class="nx">@tokens</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="o">is</span> <span class="s1">'TERMINATOR'</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Some blocks occur in the middle of expressions -- when we're expecting | ||
| this, remove their trailing newlines.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">removeMidExpressionNewlines: </span><span class="o">-></span> | ||
@@ -43,3 +62,3 @@ <span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">post</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=></span> | ||
| <span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">1</span> | ||
| <span class="k">return</span> <span class="mi">0</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>The lexer has tagged the opening parenthesis of a method call, and the | ||
| <span class="k">return</span> <span class="mi">0</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>The lexer has tagged the opening parenthesis of a method call, and the | ||
| opening bracket of an indexing operation. Match them with their paired | ||
@@ -67,3 +86,3 @@ close.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">closeOpenCallsAndIndexes: </span><span class="o">-></span> | ||
| <span class="nx">brackets</span><span class="p">[</span><span class="nx">brackets</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="o">:</span> <span class="o">-</span> <span class="mi">1</span> | ||
| <span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Methods may be optionally called without parentheses, for simple cases. | ||
| <span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Methods may be optionally called without parentheses, for simple cases. | ||
| Insert the implicit parentheses here, so that the parser doesn't have to | ||
@@ -95,3 +114,3 @@ deal with them.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">addImplicitParentheses: </span><span class="o">-></span> | ||
| <span class="k">return</span> <span class="mi">1</span> | ||
| <span class="k">if</span> <span class="nx">open</span> <span class="o">and</span> <span class="o">!</span><span class="nx">token</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="p">(</span><span class="o">!</span><span class="nx">post</span> <span class="o">or</span> <span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_END</span><span class="p">,</span> <span class="nx">tag</span><span class="p">))</span> | ||
| <span class="k">if</span> <span class="nx">open</span> <span class="o">and</span> <span class="o">!</span><span class="nx">token</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">','</span> <span class="o">and</span> <span class="p">(</span><span class="o">!</span><span class="nx">post</span> <span class="o">or</span> <span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_END</span><span class="p">,</span> <span class="nx">tag</span><span class="p">))</span> | ||
| <span class="nv">j: </span><span class="mi">1</span><span class="p">;</span> <span class="nx">j</span><span class="o">++</span> <span class="k">while</span> <span class="p">(</span><span class="nv">nx: </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="nx">j</span><span class="p">])</span><span class="o">?</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_END</span><span class="p">,</span> <span class="nx">nx</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> | ||
@@ -107,3 +126,3 @@ <span class="k">if</span> <span class="nx">nx</span><span class="o">?</span> <span class="o">and</span> <span class="nx">nx</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">','</span> | ||
| <span class="k">return</span> <span class="mi">1</span> | ||
| <span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Because our grammar is LALR(1), it can't handle some single-line | ||
| <span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>Because our grammar is LALR(1), it can't handle some single-line | ||
| expressions that lack ending delimiters. The <strong>Rewriter</strong> adds the implicit | ||
@@ -114,4 +133,7 @@ blocks, so it doesn't need to. ')' can close a single-line block, | ||
| <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'ELSE'</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'OUTDENT'</span> | ||
| <span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">'INDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]],</span> <span class="p">[</span><span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span> | ||
| <span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">@indentation</span><span class="p">(</span><span class="nx">token</span><span class="p">)...</span> | ||
| <span class="k">return</span> <span class="mi">2</span> | ||
| <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'CATCH'</span> <span class="o">and</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span> | ||
| <span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">@indentation</span><span class="p">(</span><span class="nx">token</span><span class="p">)...</span> | ||
| <span class="k">return</span> <span class="mi">4</span> | ||
| <span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">include</span><span class="p">(</span><span class="nx">SINGLE_LINERS</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">and</span> | ||
@@ -121,4 +143,4 @@ <span class="nx">post</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'INDENT'</span> <span class="o">and</span> | ||
| <span class="nv">starter: </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> | ||
| <span class="nv">indent: </span><span class="p">[</span><span class="s1">'INDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span> | ||
| <span class="nv">indent.generated: </span><span class="kc">true</span> | ||
| <span class="p">[</span><span class="nx">indent</span><span class="p">,</span> <span class="nx">outdent</span><span class="p">]</span><span class="o">:</span> <span class="nx">@indentation</span> <span class="nx">token</span> | ||
| <span class="nv">indent.generated: outdent.generated: </span><span class="kc">true</span> | ||
| <span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">indent</span> | ||
@@ -136,4 +158,2 @@ <span class="nv">idx: </span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span> | ||
| <span class="nv">insertion: </span><span class="k">if</span> <span class="nx">pre</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s2">","</span> <span class="k">then</span> <span class="nx">idx</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">else</span> <span class="nx">idx</span> | ||
| <span class="nv">outdent: </span><span class="p">[</span><span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span> | ||
| <span class="nv">outdent.generated: </span><span class="kc">true</span> | ||
| <span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">insertion</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">outdent</span> | ||
@@ -145,3 +165,3 @@ <span class="k">break</span> | ||
| <span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">1</span> | ||
| <span class="k">return</span> <span class="mi">0</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>Ensure that all listed pairs of tokens are correctly balanced throughout | ||
| <span class="k">return</span> <span class="mi">0</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>Ensure that all listed pairs of tokens are correctly balanced throughout | ||
| the course of the token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ensureBalance: </span><span class="p">(</span><span class="nx">pairs</span><span class="p">)</span> <span class="o">-></span> | ||
@@ -164,3 +184,3 @@ <span class="nv">levels: </span><span class="p">{}</span> | ||
| <span class="nv">line: </span><span class="nx">openLine</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span> | ||
| <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"unclosed $open on line $line"</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>We'd like to support syntax like this:</p> | ||
| <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"unclosed $open on line $line"</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</a> </div> <p>We'd like to support syntax like this:</p> | ||
@@ -212,12 +232,13 @@ <pre><code>el.click((event) -> | ||
| <span class="k">else</span> | ||
| <span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>List of the token pairs that must be balanced.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BALANCED_PAIRS: </span><span class="p">[[</span><span class="s1">'('</span><span class="p">,</span> <span class="s1">')'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'['</span><span class="p">,</span> <span class="s1">']'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'{'</span><span class="p">,</span> <span class="s1">'}'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'INDENT'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">],</span> | ||
| <span class="p">[</span><span class="s1">'PARAM_START'</span><span class="p">,</span> <span class="s1">'PARAM_END'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'CALL_START'</span><span class="p">,</span> <span class="s1">'CALL_END'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'INDEX_START'</span><span class="p">,</span> <span class="s1">'INDEX_END'</span><span class="p">]]</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</a> </div> <p>The inverse mappings of <code>BALANCED_PAIRS</code> we're trying to fix up, so we can | ||
| <span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>Generate the indentation tokens, based on another token on the same line.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">indentation: </span><span class="p">(</span><span class="nx">token</span><span class="p">)</span> <span class="o">-></span> | ||
| <span class="p">[[</span><span class="s1">'INDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]],</span> <span class="p">[</span><span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]]</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>List of the token pairs that must be balanced.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BALANCED_PAIRS: </span><span class="p">[[</span><span class="s1">'('</span><span class="p">,</span> <span class="s1">')'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'['</span><span class="p">,</span> <span class="s1">']'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'{'</span><span class="p">,</span> <span class="s1">'}'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'INDENT'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">],</span> | ||
| <span class="p">[</span><span class="s1">'PARAM_START'</span><span class="p">,</span> <span class="s1">'PARAM_END'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'CALL_START'</span><span class="p">,</span> <span class="s1">'CALL_END'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'INDEX_START'</span><span class="p">,</span> <span class="s1">'INDEX_END'</span><span class="p">]]</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-18">#</a> </div> <p>The inverse mappings of <code>BALANCED_PAIRS</code> we're trying to fix up, so we can | ||
| look things up from either end.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">INVERSES: </span><span class="p">{}</span> | ||
| <span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span> | ||
| <span class="nx">INVERSES</span><span class="p">[</span><span class="nx">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span><span class="o">:</span> <span class="nx">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> | ||
| <span class="nx">INVERSES</span><span class="p">[</span><span class="nx">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]]</span><span class="o">:</span> <span class="nx">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>The tokens that signal the start of a balanced pair.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_START: </span><span class="nx">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-18">#</a> </div> <p>The tokens that signal the end of a balanced pair.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_END: </span> <span class="nx">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-19">#</a> </div> <p>Tokens that indicate the close of a clause of an expression.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_CLOSE: </span><span class="p">[</span><span class="s1">'CATCH'</span><span class="p">,</span> <span class="s1">'WHEN'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">,</span> <span class="s1">'FINALLY'</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">EXPRESSION_END</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-20">#</a> </div> <p>Tokens that, if followed by an <code>IMPLICIT_CALL</code>, indicate a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_FUNC: </span> <span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'SUPER'</span><span class="p">,</span> <span class="s1">')'</span><span class="p">,</span> <span class="s1">'CALL_END'</span><span class="p">,</span> <span class="s1">']'</span><span class="p">,</span> <span class="s1">'INDEX_END'</span><span class="p">,</span> <span class="s1">'@'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-21">#</a> </div> <p>If preceded by an <code>IMPLICIT_FUNC</code>, indicates a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_CALL: </span> <span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'NUMBER'</span><span class="p">,</span> <span class="s1">'STRING'</span><span class="p">,</span> <span class="s1">'JS'</span><span class="p">,</span> <span class="s1">'REGEX'</span><span class="p">,</span> <span class="s1">'NEW'</span><span class="p">,</span> <span class="s1">'PARAM_START'</span><span class="p">,</span> | ||
| <span class="nx">INVERSES</span><span class="p">[</span><span class="nx">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]]</span><span class="o">:</span> <span class="nx">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-19">#</a> </div> <p>The tokens that signal the start of a balanced pair.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_START: </span><span class="nx">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-20">#</a> </div> <p>The tokens that signal the end of a balanced pair.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_END: </span> <span class="nx">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-21">#</a> </div> <p>Tokens that indicate the close of a clause of an expression.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_CLOSE: </span><span class="p">[</span><span class="s1">'CATCH'</span><span class="p">,</span> <span class="s1">'WHEN'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">,</span> <span class="s1">'FINALLY'</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">EXPRESSION_END</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-22">#</a> </div> <p>Tokens that, if followed by an <code>IMPLICIT_CALL</code>, indicate a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_FUNC: </span> <span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'SUPER'</span><span class="p">,</span> <span class="s1">')'</span><span class="p">,</span> <span class="s1">'CALL_END'</span><span class="p">,</span> <span class="s1">']'</span><span class="p">,</span> <span class="s1">'INDEX_END'</span><span class="p">,</span> <span class="s1">'@'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-23">#</a> </div> <p>If preceded by an <code>IMPLICIT_FUNC</code>, indicates a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_CALL: </span> <span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'NUMBER'</span><span class="p">,</span> <span class="s1">'STRING'</span><span class="p">,</span> <span class="s1">'JS'</span><span class="p">,</span> <span class="s1">'REGEX'</span><span class="p">,</span> <span class="s1">'NEW'</span><span class="p">,</span> <span class="s1">'PARAM_START'</span><span class="p">,</span> | ||
| <span class="s1">'TRY'</span><span class="p">,</span> <span class="s1">'DELETE'</span><span class="p">,</span> <span class="s1">'TYPEOF'</span><span class="p">,</span> <span class="s1">'SWITCH'</span><span class="p">,</span> | ||
| <span class="s1">'TRUE'</span><span class="p">,</span> <span class="s1">'FALSE'</span><span class="p">,</span> <span class="s1">'YES'</span><span class="p">,</span> <span class="s1">'NO'</span><span class="p">,</span> <span class="s1">'ON'</span><span class="p">,</span> <span class="s1">'OFF'</span><span class="p">,</span> <span class="s1">'!'</span><span class="p">,</span> <span class="s1">'!!'</span><span class="p">,</span> | ||
| <span class="s1">'THIS'</span><span class="p">,</span> <span class="s1">'NULL'</span><span class="p">,</span> | ||
| <span class="s1">'@'</span><span class="p">,</span> <span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">,</span> <span class="s1">'['</span><span class="p">,</span> <span class="s1">'('</span><span class="p">,</span> <span class="s1">'{'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-22">#</a> </div> <p>Tokens indicating that the implicit call must enclose a block of expressions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_BLOCK: </span><span class="p">[</span><span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">,</span> <span class="s1">'{'</span><span class="p">,</span> <span class="s1">'['</span><span class="p">,</span> <span class="s1">','</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-23">#</a> </div> <p>Tokens that always mark the end of an implicit call for single-liners.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_END: </span> <span class="p">[</span><span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'UNLESS'</span><span class="p">,</span> <span class="s1">'FOR'</span><span class="p">,</span> <span class="s1">'WHILE'</span><span class="p">,</span> <span class="s1">'UNTIL'</span><span class="p">,</span> <span class="s1">'LOOP'</span><span class="p">,</span> <span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'INDENT'</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">EXPRESSION_END</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-24">#</a> </div> <p>Single-line flavors of block expressions that have unclosed endings. | ||
| <span class="s1">'@'</span><span class="p">,</span> <span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">,</span> <span class="s1">'['</span><span class="p">,</span> <span class="s1">'('</span><span class="p">,</span> <span class="s1">'{'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-24">#</a> </div> <p>Tokens indicating that the implicit call must enclose a block of expressions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_BLOCK: </span><span class="p">[</span><span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">,</span> <span class="s1">'{'</span><span class="p">,</span> <span class="s1">'['</span><span class="p">,</span> <span class="s1">','</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-25">#</a> </div> <p>Tokens that always mark the end of an implicit call for single-liners.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_END: </span> <span class="p">[</span><span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'UNLESS'</span><span class="p">,</span> <span class="s1">'FOR'</span><span class="p">,</span> <span class="s1">'WHILE'</span><span class="p">,</span> <span class="s1">'UNTIL'</span><span class="p">,</span> <span class="s1">'LOOP'</span><span class="p">,</span> <span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'INDENT'</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">EXPRESSION_END</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-26">#</a> </div> <p>Single-line flavors of block expressions that have unclosed endings. | ||
| The grammar can't disambiguate them, so we insert the implicit indentation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">SINGLE_LINERS: </span><span class="p">[</span><span class="s1">'ELSE'</span><span class="p">,</span> <span class="s2">"->"</span><span class="p">,</span> <span class="s2">"=>"</span><span class="p">,</span> <span class="s1">'TRY'</span><span class="p">,</span> <span class="s1">'FINALLY'</span><span class="p">,</span> <span class="s1">'THEN'</span><span class="p">]</span> | ||
@@ -224,0 +245,0 @@ <span class="nv">SINGLE_CLOSERS: </span><span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'CATCH'</span><span class="p">,</span> <span class="s1">'FINALLY'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="s1">'LEADING_WHEN'</span><span class="p">]</span> |
@@ -132,3 +132,3 @@ <% | ||
| <b>Latest Version:</b> | ||
| <a href="http://github.com/jashkenas/coffee-script/tarball/0.7.0">0.7.0</a> | ||
| <a href="http://github.com/jashkenas/coffee-script/tarball/0.7.1">0.7.1</a> | ||
| </p> | ||
@@ -179,3 +179,3 @@ | ||
| from GitHub, or download the latest | ||
| release: <a href="http://github.com/jashkenas/coffee-script/tarball/0.7.0">0.7.0</a>. | ||
| release: <a href="http://github.com/jashkenas/coffee-script/tarball/0.7.1">0.7.1</a>. | ||
| To install the CoffeeScript compiler system-wide | ||
@@ -189,3 +189,12 @@ under <tt>/usr/local</tt>, open the directory and run: | ||
| <p> | ||
| This provides the <tt>coffee</tt> command, which will execute CoffeeScripts | ||
| Alternatively, if you already have the | ||
| <a href="http://npmjs.org/">Node Package Manager</a> installed, | ||
| you can use that to grab the latest CoffeeScript: | ||
| </p> | ||
| <pre> | ||
| sudo npm install coffee-script</pre> | ||
| <p> | ||
| Both of these provide the <tt>coffee</tt> command, which will execute CoffeeScripts | ||
| under Node.js by default, but is also used to compile CoffeeScript | ||
@@ -886,2 +895,6 @@ <tt>.coffee</tt> files into JavaScript, or to run an an interactive REPL. | ||
| <li> | ||
| <b>wavded</b>'s <a href="http://github.com/wavded/gedit-coffeescript">gedit-coffeescript</a> | ||
| — a CoffeeScript syntax highlighter for the gedit text editor. | ||
| </li> | ||
| <li> | ||
| <b>yeungda</b>'s <a href="http://yeungda.github.com/coffeescript-idea/">coffeescript-idea</a> | ||
@@ -901,2 +914,7 @@ — a plugin for IntelliJ IDEA and RubyMine providing syntax highlighting. | ||
| <li> | ||
| <b>dsc</b>'s <a href="http://github.com/dsc/coffeecup">CoffeeCup</a> | ||
| — A Python WSGI middleware that compiles CoffeeScript to JavaScript | ||
| on-demand during development. | ||
| </li> | ||
| <li> | ||
| <b>sutto</b>'s <a href="http://github.com/Sutto/barista">Barista</a> | ||
@@ -939,2 +957,10 @@ — a BistroCar alternative that integrates well with | ||
| <p> | ||
| <b class="header" style="margin-top: 20px;">0.7.1</b> | ||
| Block-style comments are now passed through and printed as JavaScript block | ||
| comments -- making them useful for licenses and copyright headers. Better | ||
| support for running coffee scripts standalone via hashbangs. | ||
| Improved syntax errors for tokens that are not in the grammar. | ||
| </p> | ||
| <p> | ||
| <b class="header" style="margin-top: 20px;">0.7.0</b> | ||
@@ -946,3 +972,3 @@ Official CoffeeScript variable style is now camelCase, as in JavaScript. | ||
| improved from the previous release. Running <tt>coffee</tt> with no arguments | ||
| now launches the REPL, with Readline support. The <tt>&-</tt> bind operator | ||
| now launches the REPL, with Readline support. The <tt><-</tt> bind operator | ||
| has been removed from CoffeeScript. The <tt>loop</tt> keyword was added, | ||
@@ -949,0 +975,0 @@ which is equivalent to a <tt>while true</tt> loop. Comprehensions that contain |
@@ -36,3 +36,3 @@ # After wycats' http://yehudakatz.com/2010/02/07/the-building-blocks-of-ruby/ | ||
| write: (location, data) -> | ||
| path = new Pathname location | ||
| path: new Pathname location | ||
| raise "Location does not exist" unless path.exists() | ||
@@ -39,0 +39,0 @@ |
@@ -22,3 +22,3 @@ # Functions: | ||
| regex: /match[ing](every|thing|\/)/gi | ||
| three: new Idea() | ||
| three: new Idea | ||
@@ -25,0 +25,0 @@ inner_obj: { |
@@ -93,3 +93,3 @@ # "Classic" linked list implementation that doesn't keep track of its size. | ||
| # Tests. | ||
| list: new LinkedList() | ||
| list: new LinkedList | ||
@@ -101,3 +101,3 @@ list.add("Hi") | ||
| list: new LinkedList() | ||
| list: new LinkedList | ||
| list.add("zero").add("one").add("two") | ||
@@ -104,0 +104,0 @@ puts(list.size() is 3) |
@@ -63,3 +63,3 @@ # Examples from _why's Potion, the Readme and "Potion: A Short Pamphlet". | ||
| p: new Person() | ||
| p: new Person | ||
| print p.name | ||
@@ -192,5 +192,5 @@ | ||
| BTree: -> | ||
| b: new BTree() | ||
| b.left: new BTree() | ||
| b.right: new BTree() | ||
| b: new BTree | ||
| b.left: new BTree | ||
| b.right: new BTree | ||
@@ -205,4 +205,4 @@ | ||
| BTree: -> | ||
| b: new BTree() | ||
| b: new BTree | ||
| print('left path found!') if b.left? |
@@ -18,3 +18,3 @@ (function(){ | ||
| } | ||
| exports.VERSION = '0.7.0'; | ||
| exports.VERSION = '0.7.1'; | ||
| lexer = new Lexer(); | ||
@@ -21,0 +21,0 @@ exports.compile = (compile = function(code, options) { |
+7
-7
@@ -42,2 +42,6 @@ (function(){ | ||
| } | ||
| if (options.run) { | ||
| flags = sources.slice(1, sources.length + 1).concat(flags); | ||
| sources = [sources[0]]; | ||
| } | ||
| process.ARGV = (process.argv = flags); | ||
@@ -157,7 +161,3 @@ return compileScripts(); | ||
| return path.exists(dir, function(exists) { | ||
| if (exists) { | ||
| return compile(); | ||
| } else { | ||
| return exec(("mkdir -p " + dir), compile); | ||
| } | ||
| return exists ? compile() : exec(("mkdir -p " + dir), compile); | ||
| }); | ||
@@ -196,6 +196,6 @@ }; | ||
| optionParser = new optparse.OptionParser(SWITCHES, BANNER); | ||
| o = (options = optionParser.parse(process.argv)); | ||
| o = (options = optionParser.parse(process.argv.slice(2, process.argv.length))); | ||
| options.run = !(o.compile || o.print || o.lint); | ||
| options.print = !!(o.print || (o.eval || o.stdio && o.compile)); | ||
| sources = options.arguments.slice(2, options.arguments.length); | ||
| sources = options.arguments; | ||
| return sources; | ||
@@ -202,0 +202,0 @@ }; |
+16
-11
@@ -37,3 +37,3 @@ (function(){ | ||
| ], | ||
| Expression: [o("Value"), o("Call"), o("Code"), o("Operation"), o("Assign"), o("If"), o("Try"), o("While"), o("For"), o("Switch"), o("Extends"), o("Class"), o("Splat"), o("Existence")], | ||
| Expression: [o("Value"), o("Call"), o("Code"), o("Operation"), o("Assign"), o("If"), o("Try"), o("While"), o("For"), o("Switch"), o("Extends"), o("Class"), o("Splat"), o("Existence"), o("Comment")], | ||
| Block: [ | ||
@@ -44,2 +44,4 @@ o("INDENT Body OUTDENT", function() { | ||
| return new Expressions(); | ||
| }), o("TERMINATOR Comment", function() { | ||
| return Expressions.wrap([$2]); | ||
| }) | ||
@@ -90,3 +92,3 @@ ], | ||
| return new AssignNode(new ValueNode($1), $3, 'object'); | ||
| }) | ||
| }), o("Comment") | ||
| ], | ||
@@ -100,2 +102,7 @@ Return: [ | ||
| ], | ||
| Comment: [ | ||
| o("HERECOMMENT", function() { | ||
| return new CommentNode($1); | ||
| }) | ||
| ], | ||
| Existence: [ | ||
@@ -239,5 +246,7 @@ o("Expression ?", function() { | ||
| Call: [ | ||
| o("Invocation"), o("NEW Invocation", function() { | ||
| o("Invocation"), o("Super"), o("NEW Invocation", function() { | ||
| return $2.newInstance(); | ||
| }), o("Super") | ||
| }), o("NEW Value", function() { | ||
| return (new CallNode($2, [])).newInstance(); | ||
| }) | ||
| ], | ||
@@ -312,7 +321,3 @@ Extends: [ | ||
| o("Expression"), o("SimpleArgs , Expression", function() { | ||
| if ($1 instanceof Array) { | ||
| return $1.concat([$3]); | ||
| } else { | ||
| return [$1].concat([$3]); | ||
| } | ||
| return $1 instanceof Array ? $1.concat([$3]) : [$1].concat([$3]); | ||
| }) | ||
@@ -569,3 +574,3 @@ ], | ||
| return new OpNode('||', $1, $3); | ||
| }), o("Expression ? Expression", function() { | ||
| }), o("Expression OP? Expression", function() { | ||
| return new OpNode('?', $1, $3); | ||
@@ -601,3 +606,3 @@ }), o("Expression -= Expression", function() { | ||
| }; | ||
| operators = [["left", '?'], ["nonassoc", 'UMINUS', 'UPLUS', '!', '!!', '~', '++', '--'], ["left", '*', '/', '%'], ["left", '+', '-'], ["left", '<<', '>>', '>>>'], ["left", '&', '|', '^'], ["left", '<=', '<', '>', '>='], ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'], ["left", '==', '!='], ["left", '&&', '||'], ["right", '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?='], ["left", '.'], ["right", 'INDENT'], ["left", 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY', 'THROW'], ["right", 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'NEW', 'SUPER', 'CLASS'], ["left", 'EXTENDS'], ["right", 'ASSIGN', 'RETURN'], ["right", '->', '=>', 'UNLESS', 'IF', 'ELSE']]; | ||
| operators = [["left", '?'], ["nonassoc", 'UMINUS', 'UPLUS', '!', '!!', '~', '++', '--'], ["left", '*', '/', '%'], ["left", '+', '-'], ["left", '<<', '>>', '>>>'], ["left", '&', '|', '^'], ["left", '<=', '<', '>', '>='], ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'], ["left", '==', '!='], ["left", '&&', '||', 'OP?'], ["right", '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?='], ["left", '.'], ["right", 'INDENT'], ["left", 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY', 'THROW'], ["right", 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'NEW', 'SUPER', 'CLASS'], ["left", 'EXTENDS'], ["right", 'ASSIGN', 'RETURN'], ["right", '->', '=>', 'UNLESS', 'IF', 'ELSE']]; | ||
| tokens = []; | ||
@@ -604,0 +609,0 @@ _a = grammar; |
+26
-21
@@ -155,3 +155,3 @@ (function(){ | ||
| Lexer.prototype.commentToken = function() { | ||
| var match; | ||
| var comment, match; | ||
| if (!(match = this.chunk.match(COMMENT))) { | ||
@@ -162,2 +162,9 @@ return false; | ||
| this.i += match[1].length; | ||
| if (match[2]) { | ||
| comment = this.sanitizeHeredoc(match[2], { | ||
| herecomment: true | ||
| }); | ||
| this.token('HERECOMMENT', comment.split(MULTILINER)); | ||
| this.token('TERMINATOR', '\n'); | ||
| } | ||
| return true; | ||
@@ -304,2 +311,4 @@ }; | ||
| tag = 'TERMINATOR'; | ||
| } else if (value === '?' && prevSpaced) { | ||
| tag = 'OP?'; | ||
| } else if (include(CALLABLE, this.tag()) && !prevSpaced) { | ||
@@ -344,7 +353,3 @@ if (value === '(') { | ||
| }).call(this); | ||
| if (accessor) { | ||
| return 'accessor'; | ||
| } else { | ||
| return false; | ||
| } | ||
| return accessor ? 'accessor' : false; | ||
| }; | ||
@@ -359,6 +364,13 @@ Lexer.prototype.sanitizeHeredoc = function(doc, options) { | ||
| } | ||
| return doc.replace(new RegExp("^" + indent, 'gm'), '').replace(MULTILINER, "\\n").replace(new RegExp(options.quote, 'g'), ("\\" + options.quote)); | ||
| doc = doc.replace(new RegExp("^" + indent, 'gm'), ''); | ||
| if (options.herecomment) { | ||
| return doc; | ||
| } | ||
| return doc.replace(MULTILINER, "\\n").replace(new RegExp(options.quote, 'g'), ("\\" + options.quote)); | ||
| }; | ||
| Lexer.prototype.tagHalfAssignment = function(tag) { | ||
| var last; | ||
| if (tag === 'OP?') { | ||
| tag = '?'; | ||
| } | ||
| last = this.tokens.pop(); | ||
@@ -441,7 +453,3 @@ this.tokens.push([("" + tag + "="), ("" + tag + "="), last[2]]); | ||
| } | ||
| if (!i) { | ||
| return false; | ||
| } else { | ||
| return str.substring(0, i); | ||
| } | ||
| return !i ? false : str.substring(0, i); | ||
| }; | ||
@@ -481,2 +489,3 @@ Lexer.prototype.interpolateString = function(str, escapeQuotes) { | ||
| if (inner.length) { | ||
| inner = inner.replace(new RegExp('\\\\' + quote, 'g'), quote); | ||
| nested = lexer.tokenize(("(" + inner + ")"), { | ||
@@ -567,7 +576,3 @@ line: this.line | ||
| } | ||
| if (m) { | ||
| return m[index]; | ||
| } else { | ||
| return false; | ||
| } | ||
| return m ? m[index] : false; | ||
| }; | ||
@@ -590,5 +595,5 @@ Lexer.prototype.unfinished = function() { | ||
| INTERPOLATION = /^\$([a-zA-Z_@]\w*(\.\w+)*)/; | ||
| OPERATOR = /^([+\*&|\/\-%=<>:!?]+)([ \t]*)/; | ||
| OPERATOR = /^(-[\-=>]?|\+[+=]?|[*&|\/%=<>:!?]+)([ \t]*)/; | ||
| WHITESPACE = /^([ \t]+)/; | ||
| COMMENT = /^(\s*#{3}(?!#)[ \t]*\n+([\s\S]*?)[ \t]*\n+[ \t]*#{3}|(\s*#[^\n]*)+)/; | ||
| COMMENT = /^(\s*#{3}(?!#)[ \t]*\n+([\s\S]*?)[ \t]*\n+[ \t]*#{3}|(\s*#(?!##[^#])[^\n]*)+)/; | ||
| CODE = /^((-|=)>)/; | ||
@@ -608,3 +613,3 @@ MULTI_DENT = /^((\n([ \t]*))+)(\.)?/; | ||
| HEREDOC_INDENT = /(\n+([ \t]*)|^([ \t]+))/g; | ||
| ASSIGNED = /^([a-zA-Z\$_]\w*[ \t]*?[:=])/; | ||
| ASSIGNED = /^([a-zA-Z\$_]\w*[ \t]*?[:=][^=])/; | ||
| NEXT_CHARACTER = /^\s*(\S)/; | ||
@@ -614,3 +619,3 @@ NOT_REGEX = ['NUMBER', 'REGEX', '++', '--', 'FALSE', 'NULL', 'TRUE', ']']; | ||
| LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR']; | ||
| HALF_ASSIGNMENTS = ['-', '+', '/', '*', '%', '||', '&&', '?']; | ||
| HALF_ASSIGNMENTS = ['-', '+', '/', '*', '%', '||', '&&', '?', 'OP?']; | ||
| CONVERSIONS = { | ||
@@ -617,0 +622,0 @@ 'and': '&&', |
+117
-133
| (function(){ | ||
| var AccessorNode, ArrayNode, AssignNode, BaseNode, CallNode, ClassNode, ClosureNode, CodeNode, DOUBLE_PARENS, ExistenceNode, Expressions, ExtendsNode, ForNode, IDENTIFIER, IS_STRING, IfNode, InNode, IndexNode, LiteralNode, NUMBER, ObjectNode, OpNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, Scope, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThrowNode, TryNode, UTILITIES, ValueNode, WhileNode, _a, compact, del, flatten, helpers, include, indexOf, literal, merge, starts, utility; | ||
| var AccessorNode, ArrayNode, AssignNode, BaseNode, CallNode, ClassNode, ClosureNode, CodeNode, CommentNode, DOUBLE_PARENS, ExistenceNode, Expressions, ExtendsNode, ForNode, IDENTIFIER, IS_STRING, IfNode, InNode, IndexNode, LiteralNode, NUMBER, ObjectNode, OpNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, Scope, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThrowNode, TryNode, UTILITIES, ValueNode, WhileNode, _a, compact, del, flatten, helpers, include, indexOf, literal, merge, starts, utility; | ||
| var __extends = function(child, parent) { | ||
@@ -39,8 +39,4 @@ var ctor = function(){ }; | ||
| top = this.topSensitive() ? this.options.top : del(this.options, 'top'); | ||
| closure = this.isStatement() && !this.isPureStatement() && !top && !this.options.asStatement && !this.containsPureStatement(); | ||
| if (closure) { | ||
| return this.compileClosure(this.options); | ||
| } else { | ||
| return this.compileNode(this.options); | ||
| } | ||
| closure = this.isStatement() && !this.isPureStatement() && !top && !this.options.asStatement && !(this instanceof CommentNode) && !this.containsPureStatement(); | ||
| return closure ? this.compileClosure(this.options) : this.compileNode(this.options); | ||
| }; | ||
@@ -104,6 +100,6 @@ BaseNode.prototype.compileClosure = function(o) { | ||
| }; | ||
| BaseNode.prototype.toString = function(idt) { | ||
| var _b, _c, _d, _e, child; | ||
| BaseNode.prototype.toString = function(idt, override) { | ||
| var _b, _c, _d, _e, child, children; | ||
| idt = idt || ''; | ||
| return '\n' + idt + this['class'] + (function() { | ||
| children = (function() { | ||
| _b = []; _d = this.collectChildren(); | ||
@@ -116,2 +112,3 @@ for (_c = 0, _e = _d.length; _c < _e; _c++) { | ||
| }).call(this).join(''); | ||
| return '\n' + idt + (override || this['class']) + children; | ||
| }; | ||
@@ -190,7 +187,3 @@ BaseNode.prototype.eachChild = function(func) { | ||
| Expressions.prototype.unwrap = function() { | ||
| if (this.expressions.length === 1) { | ||
| return this.expressions[0]; | ||
| } else { | ||
| return this; | ||
| } | ||
| return this.expressions.length === 1 ? this.expressions[0] : this; | ||
| }; | ||
@@ -204,2 +197,5 @@ Expressions.prototype.empty = function() { | ||
| last = this.expressions[idx]; | ||
| if (last instanceof CommentNode) { | ||
| last = this.expressions[idx -= 1]; | ||
| } | ||
| if (!last || last instanceof ReturnNode) { | ||
@@ -213,7 +209,3 @@ return this; | ||
| o = o || {}; | ||
| if (o.scope) { | ||
| return Expressions.__superClass__.compile.call(this, o); | ||
| } else { | ||
| return this.compileRoot(o); | ||
| } | ||
| return o.scope ? Expressions.__superClass__.compile.call(this, o) : this.compileRoot(o); | ||
| }; | ||
@@ -235,10 +227,6 @@ Expressions.prototype.compileNode = function(o) { | ||
| o.scope = new Scope(null, this, null); | ||
| code = o.globals ? this.compileNode(o) : this.compileWithDeclarations(o); | ||
| code = this.compileWithDeclarations(o); | ||
| code = code.replace(TRAILING_WHITESPACE, ''); | ||
| code = code.replace(DOUBLE_PARENS, '($1)'); | ||
| if (o.noWrap) { | ||
| return code; | ||
| } else { | ||
| return "(function(){\n" + code + "\n})();\n"; | ||
| } | ||
| return o.noWrap ? code : ("(function(){\n" + code + "\n})();\n"); | ||
| }; | ||
@@ -251,3 +239,3 @@ Expressions.prototype.compileWithDeclarations = function(o) { | ||
| } | ||
| if (o.scope.hasDeclarations(this)) { | ||
| if (!o.globals && o.scope.hasDeclarations(this)) { | ||
| code = ("" + (this.tab) + "var " + (o.scope.compiledDeclarations()) + ";\n" + code); | ||
@@ -263,7 +251,3 @@ } | ||
| })); | ||
| if (node.isStatement()) { | ||
| return compiledNode; | ||
| } else { | ||
| return "" + (this.idt()) + compiledNode + ";"; | ||
| } | ||
| return node.isStatement() ? compiledNode : ("" + (this.idt()) + compiledNode + ";"); | ||
| }; | ||
@@ -314,9 +298,6 @@ return Expressions; | ||
| ReturnNode.prototype.children = ['expression']; | ||
| ReturnNode.prototype.topSensitive = function() { | ||
| return true; | ||
| }; | ||
| ReturnNode.prototype.makeReturn = function() { | ||
| return this; | ||
| }; | ||
| ReturnNode.prototype.compileNode = function(o) { | ||
| ReturnNode.prototype.compile = function(o) { | ||
| var expr; | ||
@@ -327,3 +308,5 @@ expr = this.expression.makeReturn(); | ||
| } | ||
| del(o, 'top'); | ||
| return ReturnNode.__superClass__.compile.call(this, o); | ||
| }; | ||
| ReturnNode.prototype.compileNode = function(o) { | ||
| if (this.expression.isStatement()) { | ||
@@ -363,14 +346,6 @@ o.asStatement = true; | ||
| ValueNode.prototype.makeReturn = function() { | ||
| if (this.hasProperties()) { | ||
| return ValueNode.__superClass__.makeReturn.call(this); | ||
| } else { | ||
| return this.base.makeReturn(); | ||
| } | ||
| return this.hasProperties() ? ValueNode.__superClass__.makeReturn.call(this) : this.base.makeReturn(); | ||
| }; | ||
| ValueNode.prototype.unwrap = function() { | ||
| if (this.properties.length) { | ||
| return this; | ||
| } else { | ||
| return this.base; | ||
| } | ||
| return this.properties.length ? this : this.base; | ||
| }; | ||
@@ -394,2 +369,5 @@ ValueNode.prototype.isStatement = function() { | ||
| }; | ||
| ValueNode.prototype.compile = function(o) { | ||
| return !o.top || this.properties.length ? ValueNode.__superClass__.compile.call(this, o) : this.base.compile(o); | ||
| }; | ||
| ValueNode.prototype.compileNode = function(o) { | ||
@@ -426,10 +404,26 @@ var _b, _c, baseline, complete, i, only, op, part, prop, props, temp; | ||
| } | ||
| if (op && this.wrapped) { | ||
| return "(" + complete + ")"; | ||
| } else { | ||
| return complete; | ||
| } | ||
| return op && this.wrapped ? ("(" + complete + ")") : complete; | ||
| }; | ||
| return ValueNode; | ||
| })(); | ||
| exports.CommentNode = (function() { | ||
| CommentNode = function(lines) { | ||
| this.lines = lines; | ||
| return this; | ||
| }; | ||
| __extends(CommentNode, BaseNode); | ||
| CommentNode.prototype['class'] = 'CommentNode'; | ||
| CommentNode.prototype.isStatement = function() { | ||
| return true; | ||
| }; | ||
| CommentNode.prototype.makeReturn = function() { | ||
| return this; | ||
| }; | ||
| CommentNode.prototype.compileNode = function(o) { | ||
| var sep; | ||
| sep = ("\n" + this.tab); | ||
| return "" + this.tab + "/*" + sep + (this.lines.join(sep)) + "\n" + this.tab + "*/"; | ||
| }; | ||
| return CommentNode; | ||
| })(); | ||
| exports.CallNode = (function() { | ||
@@ -454,7 +448,3 @@ CallNode = function(variable, args) { | ||
| CallNode.prototype.prefix = function() { | ||
| if (this.isNew) { | ||
| return 'new '; | ||
| } else { | ||
| return ''; | ||
| } | ||
| return this.isNew ? 'new ' : ''; | ||
| }; | ||
@@ -496,7 +486,3 @@ CallNode.prototype.superReference = function(o) { | ||
| } | ||
| if (o.operation && this.wrapped) { | ||
| return "(" + compilation + ")"; | ||
| } else { | ||
| return compilation; | ||
| } | ||
| return o.operation && this.wrapped ? ("(" + compilation + ")") : compilation; | ||
| }; | ||
@@ -596,7 +582,3 @@ CallNode.prototype.compileSuper = function(args, o) { | ||
| } | ||
| if (parts.length) { | ||
| return "" + (parts.join('; ')) + ";\n" + o.indent; | ||
| } else { | ||
| return ''; | ||
| } | ||
| return parts.length ? ("" + (parts.join('; ')) + ";") : ''; | ||
| }; | ||
@@ -617,3 +599,3 @@ RangeNode.prototype.compileNode = function(o) { | ||
| RangeNode.prototype.compileArray = function(o) { | ||
| var body, clause, equals, from, idt, post, pre, to, vars; | ||
| var body, clause, equals, from, i, idt, post, pre, result, to, vars; | ||
| idt = this.idt(1); | ||
@@ -626,7 +608,9 @@ vars = this.compileVariables(merge(o, { | ||
| to = this.toVar.compile(o); | ||
| result = o.scope.freeVariable(); | ||
| i = o.scope.freeVariable(); | ||
| clause = ("" + from + " <= " + to + " ?"); | ||
| pre = ("\n" + (idt) + "a = [];" + (vars)); | ||
| body = ("var i = " + from + "; (" + clause + " i <" + equals + " " + to + " : i >" + equals + " " + to + "); (" + clause + " i += 1 : i -= 1)"); | ||
| post = ("a.push(i);\n" + (idt) + "return a;\n" + o.indent); | ||
| return "(function(){" + (pre) + "for (" + body + ") " + post + "}).call(this)"; | ||
| pre = ("\n" + (idt) + (result) + " = []; " + (vars)); | ||
| body = ("var " + i + " = " + from + "; " + clause + " " + i + " <" + equals + " " + to + " : " + i + " >" + equals + " " + to + "; " + clause + " " + i + " += 1 : " + i + " -= 1"); | ||
| post = ("{ " + (result) + ".push(" + i + ") };\n" + (idt) + "return " + result + ";\n" + o.indent); | ||
| return "(function(){" + (pre) + "\n" + (idt) + "for (" + body + ")" + post + "}).call(this)"; | ||
| }; | ||
@@ -661,18 +645,33 @@ return RangeNode; | ||
| ObjectNode.prototype.compileNode = function(o) { | ||
| var _b, _c, _d, i, inner, join, last, prop, props; | ||
| var _b, _c, _d, _e, _f, _g, _h, i, indent, inner, join, lastNoncom, nonComments, prop, props; | ||
| o.indent = this.idt(1); | ||
| last = this.properties.length - 1; | ||
| nonComments = (function() { | ||
| _b = []; _d = this.properties; | ||
| for (_c = 0, _e = _d.length; _c < _e; _c++) { | ||
| prop = _d[_c]; | ||
| !(prop instanceof CommentNode) ? _b.push(prop) : null; | ||
| } | ||
| return _b; | ||
| }).call(this); | ||
| lastNoncom = nonComments[nonComments.length - 1]; | ||
| props = (function() { | ||
| _b = []; _c = this.properties; | ||
| for (i = 0, _d = _c.length; i < _d; i++) { | ||
| prop = _c[i]; | ||
| _b.push((function() { | ||
| join = i === last ? '' : ',\n'; | ||
| if (!(prop instanceof AssignNode)) { | ||
| _f = []; _g = this.properties; | ||
| for (i = 0, _h = _g.length; i < _h; i++) { | ||
| prop = _g[i]; | ||
| _f.push((function() { | ||
| join = ",\n"; | ||
| if ((prop === lastNoncom) || (prop instanceof CommentNode)) { | ||
| join = "\n"; | ||
| } | ||
| if (i === this.properties.length - 1) { | ||
| join = ''; | ||
| } | ||
| indent = prop instanceof CommentNode ? '' : this.idt(1); | ||
| if (!(prop instanceof AssignNode || prop instanceof CommentNode)) { | ||
| prop = new AssignNode(prop, prop, 'object'); | ||
| } | ||
| return this.idt(1) + prop.compile(o) + join; | ||
| return indent + prop.compile(o) + join; | ||
| }).call(this)); | ||
| } | ||
| return _b; | ||
| return _f; | ||
| }).call(this); | ||
@@ -706,2 +705,4 @@ props = props.join(''); | ||
| return this.compileSplatLiteral(this.objects, o); | ||
| } else if (obj instanceof CommentNode) { | ||
| objects.push("\n" + code + "\n" + o.indent); | ||
| } else if (i === this.objects.length - 1) { | ||
@@ -714,7 +715,3 @@ objects.push(code); | ||
| objects = objects.join(''); | ||
| if (indexOf(objects, '\n') >= 0) { | ||
| return "[\n" + (this.idt(1)) + objects + "\n" + this.tab + "]"; | ||
| } else { | ||
| return "[" + objects + "]"; | ||
| } | ||
| return indexOf(objects, '\n') >= 0 ? ("[\n" + (this.idt(1)) + objects + "\n" + this.tab + "]") : ("[" + objects + "]"); | ||
| }; | ||
@@ -762,2 +759,5 @@ return ArrayNode; | ||
| if (pvar && pvar.base.value === 'constructor' && func instanceof CodeNode) { | ||
| if (func.bound) { | ||
| throw new Error("cannot define a constructor as a bound function."); | ||
| } | ||
| func.name = className; | ||
@@ -857,7 +857,3 @@ func.body.push(new ReturnNode(literal('this'))); | ||
| } | ||
| if (top) { | ||
| return val; | ||
| } else { | ||
| return "(" + val + ")"; | ||
| } | ||
| return top ? val : ("(" + val + ")"); | ||
| }; | ||
@@ -1018,7 +1014,3 @@ AssignNode.prototype.compilePatternMatch = function(o) { | ||
| var _b; | ||
| if ((typeof (_b = this.index) !== "undefined" && _b !== null)) { | ||
| return this.compileParam(o); | ||
| } else { | ||
| return this.name.compile(o); | ||
| } | ||
| return (typeof (_b = this.index) !== "undefined" && _b !== null) ? this.compileParam(o) : this.name.compile(o); | ||
| }; | ||
@@ -1151,2 +1143,5 @@ SplatNode.prototype.compileParam = function(o) { | ||
| }; | ||
| OpNode.prototype.toString = function(idt) { | ||
| return OpNode.__superClass__.toString.call(this, idt, this['class'] + ' ' + this.operator); | ||
| }; | ||
| OpNode.prototype.compileNode = function(o) { | ||
@@ -1233,7 +1228,3 @@ o.operation = true; | ||
| this.obj2 = _b[1]; | ||
| if (this.isArray()) { | ||
| return this.compileOrTest(o); | ||
| } else { | ||
| return this.compileLoopTest(o); | ||
| } | ||
| return this.isArray() ? this.compileOrTest(o) : this.compileLoopTest(o); | ||
| }; | ||
@@ -1263,3 +1254,3 @@ InNode.prototype.compileOrTest = function(o) { | ||
| prefix = this.obj1 !== this.obj2 ? this.obj1 + '; ' : ''; | ||
| return "!!(function(){ " + (prefix) + "for (var " + i + "=0, " + l + "=" + (this.arr1) + ".length; " + i + "<" + l + "; " + i + "++) if (" + (this.arr2) + "[" + i + "] === " + this.obj2 + ") return true; })()"; | ||
| return "!!(function(){ " + (prefix) + "for (var " + i + "=0, " + l + "=" + (this.arr1) + ".length; " + i + "<" + l + "; " + i + "++) if (" + (this.arr2) + "[" + i + "] === " + this.obj2 + ") return true; }).call(this)"; | ||
| }; | ||
@@ -1356,7 +1347,11 @@ return InNode; | ||
| }; | ||
| ParentheticalNode.prototype.topSensitive = function() { | ||
| return true; | ||
| }; | ||
| ParentheticalNode.prototype.compileNode = function(o) { | ||
| var code, l; | ||
| var code, l, top; | ||
| top = del(o, 'top'); | ||
| code = this.expression.compile(o); | ||
| if (this.isStatement()) { | ||
| return code; | ||
| return (top ? ("" + this.tab + code + ";") : code); | ||
| } | ||
@@ -1367,7 +1362,3 @@ l = code.length; | ||
| } | ||
| if (this.expression instanceof AssignNode) { | ||
| return code; | ||
| } else { | ||
| return "(" + code + ")"; | ||
| } | ||
| return this.expression instanceof AssignNode ? code : ("(" + code + ")"); | ||
| }; | ||
@@ -1453,2 +1444,5 @@ return ParentheticalNode; | ||
| sourcePart = source.compileVariables(o); | ||
| if (sourcePart) { | ||
| sourcePart += ("\n" + o.indent); | ||
| } | ||
| forPart = source.compile(merge(o, { | ||
@@ -1465,3 +1459,3 @@ index: ivar, | ||
| top: true | ||
| })) + "\n"; | ||
| })) + '\n'; | ||
| } else { | ||
@@ -1494,5 +1488,3 @@ if (name) { | ||
| } else { | ||
| if (namePart) { | ||
| varPart = ("" + (this.idt(1)) + namePart + ";\n"); | ||
| } | ||
| varPart = (namePart || '') && (this.pattern ? namePart : ("" + (this.idt(1)) + namePart + ";\n")); | ||
| } | ||
@@ -1590,19 +1582,15 @@ this.object ? (forPart = ("" + ivar + " in " + svar + ") { if (" + (utility('hasProp')) + ".call(" + svar + ", " + ivar + ")")) : null; | ||
| IfNode.prototype.compileNode = function(o) { | ||
| return this.isStatement() ? this.compileStatement(o) : this.compileTernary(o); | ||
| }; | ||
| IfNode.prototype.makeReturn = function() { | ||
| if (this.isStatement()) { | ||
| return this.compileStatement(o); | ||
| this.body = this.body && this.ensureExpressions(this.body.makeReturn()); | ||
| this.elseBody = this.elseBody && this.ensureExpressions(this.elseBody.makeReturn()); | ||
| return this; | ||
| } else { | ||
| return this.compileTernary(o); | ||
| return new ReturnNode(this); | ||
| } | ||
| }; | ||
| IfNode.prototype.makeReturn = function() { | ||
| this.body = this.body && this.ensureExpressions(this.body.makeReturn()); | ||
| this.elseBody = this.elseBody && this.ensureExpressions(this.elseBody.makeReturn()); | ||
| return this; | ||
| }; | ||
| IfNode.prototype.ensureExpressions = function(node) { | ||
| if (node instanceof Expressions) { | ||
| return node; | ||
| } else { | ||
| return new Expressions([node]); | ||
| } | ||
| return node instanceof Expressions ? node : new Expressions([node]); | ||
| }; | ||
@@ -1658,6 +1646,6 @@ IfNode.prototype.compileStatement = function(o) { | ||
| mentionsArgs = expressions.contains(function(n) { | ||
| return (n instanceof LiteralNode) && (n.value === 'arguments'); | ||
| return n instanceof LiteralNode && (n.value === 'arguments'); | ||
| }); | ||
| mentionsThis = expressions.contains(function(n) { | ||
| return (n instanceof LiteralNode) && (n.value === 'this'); | ||
| return (n instanceof LiteralNode && (n.value === 'this')) || (n instanceof CodeNode && n.bound); | ||
| }); | ||
@@ -1673,7 +1661,3 @@ if (mentionsArgs || mentionsThis) { | ||
| call = new CallNode(func, args); | ||
| if (statement) { | ||
| return Expressions.wrap([call]); | ||
| } else { | ||
| return call; | ||
| } | ||
| return statement ? Expressions.wrap([call]) : call; | ||
| } | ||
@@ -1680,0 +1664,0 @@ }); |
+11
-8
@@ -10,3 +10,3 @@ (function(){ | ||
| OptionParser.prototype.parse = function(args) { | ||
| var _a, _b, _c, arg, isOption, matchedRule, options, rule; | ||
| var _a, _b, _c, _d, _e, arg, i, isOption, matchedRule, options, rule; | ||
| options = { | ||
@@ -16,10 +16,12 @@ arguments: [] | ||
| args = normalizeArguments(args); | ||
| while ((arg = args.shift())) { | ||
| _a = args; | ||
| for (i = 0, _b = _a.length; i < _b; i++) { | ||
| arg = _a[i]; | ||
| isOption = !!(arg.match(LONG_FLAG) || arg.match(SHORT_FLAG)); | ||
| matchedRule = false; | ||
| _b = this.rules; | ||
| for (_a = 0, _c = _b.length; _a < _c; _a++) { | ||
| rule = _b[_a]; | ||
| _d = this.rules; | ||
| for (_c = 0, _e = _d.length; _c < _e; _c++) { | ||
| rule = _d[_c]; | ||
| if (rule.shortFlag === arg || rule.longFlag === arg) { | ||
| options[rule.name] = rule.hasArgument ? args.shift() : true; | ||
| options[rule.name] = rule.hasArgument ? args[i + 1] : true; | ||
| matchedRule = true; | ||
@@ -32,4 +34,5 @@ break; | ||
| } | ||
| if (!(isOption)) { | ||
| options.arguments.push(arg); | ||
| if (!isOption) { | ||
| options.arguments = args.slice(i, args.length); | ||
| break; | ||
| } | ||
@@ -36,0 +39,0 @@ } |
+44
-7
@@ -17,2 +17,3 @@ (function(){ | ||
| this.tokens = tokens; | ||
| this.adjustComments(); | ||
| this.removeLeadingNewlines(); | ||
@@ -39,2 +40,31 @@ this.removeMidExpressionNewlines(); | ||
| }; | ||
| Rewriter.prototype.adjustComments = function() { | ||
| return this.scanTokens((function(__this) { | ||
| var __func = function(prev, token, post, i) { | ||
| var _c, _d, after, before; | ||
| if (!(token[0] === 'HERECOMMENT')) { | ||
| return 1; | ||
| } | ||
| _c = [this.tokens[i - 2], this.tokens[i + 2]]; | ||
| before = _c[0]; | ||
| after = _c[1]; | ||
| if (after && after[0] === 'INDENT') { | ||
| this.tokens.splice(i + 2, 1); | ||
| before && before[0] === 'OUTDENT' && post && (prev[0] === post[0]) && (post[0] === 'TERMINATOR') ? this.tokens.splice(i - 2, 1) : this.tokens.splice(i, 0, after); | ||
| } else if (prev && !('TERMINATOR' === (_d = prev[0]) || 'INDENT' === _d || 'OUTDENT' === _d)) { | ||
| if (post && post[0] === 'TERMINATOR' && after && after[0] === 'OUTDENT') { | ||
| this.tokens.splice.apply(this.tokens, [i + 3, 0].concat(this.tokens.splice(i, 2))); | ||
| this.tokens.splice(i + 3, 0, ['TERMINATOR', "\n", prev[2]]); | ||
| } else { | ||
| this.tokens.splice(i, 0, ['TERMINATOR', "\n", prev[2]]); | ||
| } | ||
| return 2; | ||
| } | ||
| return 1; | ||
| }; | ||
| return (function() { | ||
| return __func.apply(__this, arguments); | ||
| }); | ||
| })(this)); | ||
| }; | ||
| Rewriter.prototype.removeLeadingNewlines = function() { | ||
@@ -143,3 +173,3 @@ var _c; | ||
| } | ||
| if (open && !token.generated && (!post || include(IMPLICIT_END, tag))) { | ||
| if (open && !token.generated && prev[0] !== ',' && (!post || include(IMPLICIT_END, tag))) { | ||
| j = 1; | ||
@@ -175,7 +205,11 @@ while ((typeof (_d = (nx = this.tokens[i + j])) !== "undefined" && _d !== null) && include(IMPLICIT_END, nx[0])) { | ||
| var __func = function(prev, token, post, i) { | ||
| var idx, indent, insertion, outdent, parens, pre, starter, tok; | ||
| var _c, idx, indent, insertion, outdent, parens, pre, starter, tok; | ||
| if (token[0] === 'ELSE' && prev[0] !== 'OUTDENT') { | ||
| this.tokens.splice(i, 0, ['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]]); | ||
| this.tokens.splice.apply(this.tokens, [i, 0].concat(this.indentation(token))); | ||
| return 2; | ||
| } | ||
| if (token[0] === 'CATCH' && this.tokens[i + 2][0] === 'TERMINATOR') { | ||
| this.tokens.splice.apply(this.tokens, [i + 2, 0].concat(this.indentation(token))); | ||
| return 4; | ||
| } | ||
| if (!(include(SINGLE_LINERS, token[0]) && post[0] !== 'INDENT' && !(token[0] === 'ELSE' && post[0] === 'IF'))) { | ||
@@ -185,4 +219,6 @@ return 1; | ||
| starter = token[0]; | ||
| indent = ['INDENT', 2, token[2]]; | ||
| indent.generated = true; | ||
| _c = this.indentation(token); | ||
| indent = _c[0]; | ||
| outdent = _c[1]; | ||
| indent.generated = (outdent.generated = true); | ||
| this.tokens.splice(i + 1, 0, indent); | ||
@@ -197,4 +233,2 @@ idx = i + 1; | ||
| insertion = pre[0] === "," ? idx - 1 : idx; | ||
| outdent = ['OUTDENT', 2, token[2]]; | ||
| outdent.generated = true; | ||
| this.tokens.splice(insertion, 0, outdent); | ||
@@ -316,2 +350,5 @@ break; | ||
| }; | ||
| Rewriter.prototype.indentation = function(token) { | ||
| return [['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]]]; | ||
| }; | ||
| return Rewriter; | ||
@@ -318,0 +355,0 @@ })(); |
+1
-1
@@ -6,3 +6,3 @@ { | ||
| "author": "Jeremy Ashkenas", | ||
| "version": "0.7.0", | ||
| "version": "0.7.1", | ||
| "licenses": [{ | ||
@@ -9,0 +9,0 @@ "type": "MIT", |
+1
-1
@@ -9,3 +9,3 @@ require 'erb' | ||
| /** | ||
| * CoffeeScript Compiler v0.7.0 | ||
| * CoffeeScript Compiler v0.7.1 | ||
| * http://coffeescript.org | ||
@@ -12,0 +12,0 @@ * |
+3
-0
@@ -28,2 +28,5 @@ = | ||
| Or, if you have the Node Package Manager installed: | ||
| sudo npm install coffee-script | ||
| Compile a script: | ||
@@ -30,0 +33,0 @@ coffee /path/to/script.coffee |
@@ -25,6 +25,6 @@ # CoffeeScript can be used both on the server, as a command-line compiler based | ||
| # The current CoffeeScript version number. | ||
| exports.VERSION: '0.7.0' | ||
| exports.VERSION: '0.7.1' | ||
| # Instantiate a Lexer for our use here. | ||
| lexer: new Lexer() | ||
| lexer: new Lexer | ||
@@ -31,0 +31,0 @@ # Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison |
@@ -52,4 +52,4 @@ # The `coffee` utility. Handles command-line compilation of CoffeeScript | ||
| return require './repl' if options.interactive | ||
| return compileStdio() if options.stdio | ||
| return compileScript 'console', sources[0] if options.eval | ||
| return compileStdio() if options.stdio | ||
| return compileScript 'console', sources[0] if options.eval | ||
| return require './repl' unless sources.length | ||
@@ -59,4 +59,7 @@ separator: sources.indexOf '--' | ||
| if separator >= 0 | ||
| flags: sources[(separator + 1)...sources.length] | ||
| flags: sources[(separator + 1)...sources.length] | ||
| sources: sources[0...separator] | ||
| if options.run | ||
| flags: sources[1..sources.length].concat flags | ||
| sources: [sources[0]] | ||
| process.ARGV: process.argv: flags | ||
@@ -156,7 +159,7 @@ compileScripts() | ||
| parseOptions: -> | ||
| optionParser: new optparse.OptionParser SWITCHES, BANNER | ||
| o: options: optionParser.parse(process.argv) | ||
| optionParser: new optparse.OptionParser SWITCHES, BANNER | ||
| o: options: optionParser.parse(process.argv[2...process.argv.length]) | ||
| options.run: not (o.compile or o.print or o.lint) | ||
| options.print: !! (o.print or (o.eval or o.stdio and o.compile)) | ||
| sources: options.arguments[2...options.arguments.length] | ||
| sources: options.arguments | ||
@@ -163,0 +166,0 @@ # The compile-time options to pass to the CoffeeScript compiler. |
+15
-6
@@ -56,4 +56,4 @@ # The CoffeeScript parser is generated by [Jison](http://github.com/zaach/jison) | ||
| Root: [ | ||
| o "", -> new Expressions() | ||
| o "TERMINATOR", -> new Expressions() | ||
| o "", -> new Expressions | ||
| o "TERMINATOR", -> new Expressions | ||
| o "Body" | ||
@@ -103,2 +103,3 @@ o "Block TERMINATOR" | ||
| o "Existence" | ||
| o "Comment" | ||
| ] | ||
@@ -111,3 +112,4 @@ | ||
| o "INDENT Body OUTDENT", -> $2 | ||
| o "INDENT OUTDENT", -> new Expressions() | ||
| o "INDENT OUTDENT", -> new Expressions | ||
| o "TERMINATOR Comment", -> Expressions.wrap [$2] | ||
| ] | ||
@@ -153,2 +155,3 @@ | ||
| o "AlphaNumeric ASSIGN Expression", -> new AssignNode new ValueNode($1), $3, 'object' | ||
| o "Comment" | ||
| ] | ||
@@ -162,2 +165,7 @@ | ||
| # A block comment. | ||
| Comment: [ | ||
| o "HERECOMMENT", -> new CommentNode $1 | ||
| ] | ||
| # [The existential operator](http://jashkenas.github.com/coffee-script/#existence). | ||
@@ -293,4 +301,5 @@ Existence: [ | ||
| o "Invocation" | ||
| o "Super" | ||
| o "NEW Invocation", -> $2.newInstance() | ||
| o "Super" | ||
| o "NEW Value", -> (new CallNode($2, [])).newInstance() | ||
| ] | ||
@@ -538,3 +547,3 @@ | ||
| o "Expression || Expression", -> new OpNode '||', $1, $3 | ||
| o "Expression ? Expression", -> new OpNode '?', $1, $3 | ||
| o "Expression OP? Expression", -> new OpNode '?', $1, $3 | ||
@@ -580,3 +589,3 @@ o "Expression -= Expression", -> new OpNode '-=', $1, $3 | ||
| ["left", '==', '!='] | ||
| ["left", '&&', '||'] | ||
| ["left", '&&', '||', 'OP?'] | ||
| ["right", '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?='] | ||
@@ -583,0 +592,0 @@ ["left", '.'] |
+20
-11
@@ -57,3 +57,3 @@ # The CoffeeScript Lexer. Uses a series of token-matching regexes to attempt | ||
| return @tokens if o.rewrite is off | ||
| (new Rewriter()).rewrite @tokens | ||
| (new Rewriter).rewrite @tokens | ||
@@ -102,4 +102,4 @@ # At every position, run through this list of attempted matches, | ||
| unless forcedIdentifier | ||
| tag: id: CONVERSIONS[id] if include COFFEE_ALIASES, id | ||
| return @tagHalfAssignment tag if @prev() and @prev()[0] is 'ASSIGN' and include HALF_ASSIGNMENTS, tag | ||
| tag: id: CONVERSIONS[id] if include COFFEE_ALIASES, id | ||
| return @tagHalfAssignment tag if @prev() and @prev()[0] is 'ASSIGN' and include HALF_ASSIGNMENTS, tag | ||
| @token tag, id | ||
@@ -146,2 +146,6 @@ @token ']', ']' if close_index | ||
| @i: + match[1].length | ||
| if match[2] | ||
| comment: @sanitizeHeredoc match[2], {herecomment: true} | ||
| @token 'HERECOMMENT', comment.split MULTILINER | ||
| @token 'TERMINATOR', '\n' | ||
| true | ||
@@ -266,2 +270,4 @@ | ||
| tag: 'TERMINATOR' | ||
| else if value is '?' and prevSpaced | ||
| tag: 'OP?' | ||
| else if include(CALLABLE, @tag()) and not prevSpaced | ||
@@ -299,3 +305,3 @@ if value is '(' | ||
| # Sanitize a heredoc by escaping internal double quotes and | ||
| # Sanitize a heredoc or herecomment by escaping internal double quotes and | ||
| # erasing all external indentation on the left-hand side. | ||
@@ -306,4 +312,5 @@ sanitizeHeredoc: (doc, options) -> | ||
| indent: attempt if not indent or attempt.length < indent.length | ||
| doc.replace(new RegExp("^" +indent, 'gm'), '') | ||
| .replace(MULTILINER, "\\n") | ||
| doc: doc.replace(new RegExp("^" +indent, 'gm'), '') | ||
| return doc if options.herecomment | ||
| doc.replace(MULTILINER, "\\n") | ||
| .replace(new RegExp(options.quote, 'g'), "\\$options.quote") | ||
@@ -313,2 +320,3 @@ | ||
| tagHalfAssignment: (tag) -> | ||
| tag: '?' if tag is 'OP?' | ||
| last: @tokens.pop() | ||
@@ -393,3 +401,3 @@ @tokens.push ["$tag=", "$tag=", last[2]] | ||
| else | ||
| lexer: new Lexer() | ||
| lexer: new Lexer | ||
| tokens: [] | ||
@@ -412,2 +420,3 @@ quote: str.substring 0, 1 | ||
| if inner.length | ||
| inner: inner.replace new RegExp('\\\\' + quote, 'g'), quote | ||
| nested: lexer.tokenize "($inner)", {line: @line} | ||
@@ -516,5 +525,5 @@ (tok[0]: ')') for tok, idx in nested when tok[0] is 'CALL_END' | ||
| INTERPOLATION : /^\$([a-zA-Z_@]\w*(\.\w+)*)/ | ||
| OPERATOR : /^([+\*&|\/\-%=<>:!?]+)([ \t]*)/ | ||
| OPERATOR : /^(-[\-=>]?|\+[+=]?|[*&|\/%=<>:!?]+)([ \t]*)/ | ||
| WHITESPACE : /^([ \t]+)/ | ||
| COMMENT : /^(\s*#{3}(?!#)[ \t]*\n+([\s\S]*?)[ \t]*\n+[ \t]*#{3}|(\s*#[^\n]*)+)/ | ||
| COMMENT : /^(\s*#{3}(?!#)[ \t]*\n+([\s\S]*?)[ \t]*\n+[ \t]*#{3}|(\s*#(?!##[^#])[^\n]*)+)/ | ||
| CODE : /^((-|=)>)/ | ||
@@ -538,3 +547,3 @@ MULTI_DENT : /^((\n([ \t]*))+)(\.)?/ | ||
| HEREDOC_INDENT : /(\n+([ \t]*)|^([ \t]+))/g | ||
| ASSIGNED : /^([a-zA-Z\$_]\w*[ \t]*?[:=])/ | ||
| ASSIGNED : /^([a-zA-Z\$_]\w*[ \t]*?[:=][^=])/ | ||
| NEXT_CHARACTER : /^\s*(\S)/ | ||
@@ -563,3 +572,3 @@ | ||
| # Half-assignments... | ||
| HALF_ASSIGNMENTS: ['-', '+', '/', '*', '%', '||', '&&', '?'] | ||
| HALF_ASSIGNMENTS: ['-', '+', '/', '*', '%', '||', '&&', '?', 'OP?'] | ||
@@ -566,0 +575,0 @@ # Conversions from CoffeeScript operators into JavaScript ones. |
+88
-40
@@ -50,3 +50,3 @@ # `nodes.coffee` contains all of the node classes for the syntax tree. Most | ||
| closure: @isStatement() and not @isPureStatement() and not top and | ||
| not @options.asStatement and | ||
| not @options.asStatement and not (this instanceof CommentNode) and | ||
| not @containsPureStatement() | ||
@@ -115,5 +115,6 @@ if closure then @compileClosure(@options) else @compileNode(@options) | ||
| # This is what `coffee --nodes` prints out. | ||
| toString: (idt) -> | ||
| toString: (idt, override) -> | ||
| idt: or '' | ||
| '\n' + idt + @class + (child.toString(idt + TAB) for child in @collectChildren()).join('') | ||
| children: (child.toString idt + TAB for child in @collectChildren()).join('') | ||
| '\n' + idt + (override or @class) + children | ||
@@ -141,5 +142,5 @@ eachChild: (func) -> | ||
| unwrap: -> this | ||
| unwrap: -> this | ||
| isStatement: -> no | ||
| isPureStatement: -> no | ||
| isPureStatement: -> no | ||
| topSensitive: -> no | ||
@@ -185,2 +186,3 @@ | ||
| last: @expressions[idx] | ||
| last: @expressions[idx: - 1] if last instanceof CommentNode | ||
| return this if not last or last instanceof ReturnNode | ||
@@ -205,3 +207,3 @@ @expressions[idx]: last.makeReturn() | ||
| o.scope: new Scope(null, this, null) | ||
| code: if o.globals then @compileNode(o) else @compileWithDeclarations(o) | ||
| code: @compileWithDeclarations(o) | ||
| code: code.replace(TRAILING_WHITESPACE, '') | ||
@@ -216,3 +218,3 @@ code: code.replace(DOUBLE_PARENS, '($1)') | ||
| code: "${@tab}var ${o.scope.compiledAssignments()};\n$code" if o.scope.hasAssignments(this) | ||
| code: "${@tab}var ${o.scope.compiledDeclarations()};\n$code" if o.scope.hasDeclarations(this) | ||
| code: "${@tab}var ${o.scope.compiledDeclarations()};\n$code" if not o.globals and o.scope.hasDeclarations(this) | ||
| code | ||
@@ -274,12 +276,11 @@ | ||
| topSensitive: -> | ||
| true | ||
| makeReturn: -> | ||
| this | ||
| compile: (o) -> | ||
| expr: @expression.makeReturn() | ||
| return expr.compile o unless expr instanceof ReturnNode | ||
| super o | ||
| compileNode: (o) -> | ||
| expr: @expression.makeReturn() | ||
| return expr.compile(o) unless expr instanceof ReturnNode | ||
| del o, 'top' | ||
| o.asStatement: true if @expression.isStatement() | ||
@@ -345,2 +346,6 @@ "${@tab}return ${@expression.compile(o)};" | ||
| # Override compile to unwrap the value when possible. | ||
| compile: (o) -> | ||
| if not o.top or @properties.length then super(o) else @base.compile(o) | ||
| # We compile a value to JavaScript by compiling and joining each property. | ||
@@ -351,6 +356,6 @@ # Things get much more insteresting if the chain of properties has *soak* | ||
| compileNode: (o) -> | ||
| only: del(o, 'onlyFirst') | ||
| op: del(o, 'operation') | ||
| only: del o, 'onlyFirst' | ||
| op: del o, 'operation' | ||
| props: if only then @properties[0...@properties.length - 1] else @properties | ||
| o.chainRoot: or this | ||
| o.chainRoot: or this | ||
| baseline: @base.compile o | ||
@@ -376,2 +381,21 @@ baseline: "($baseline)" if @hasProperties() and (@base instanceof ObjectNode or @isNumber()) | ||
| #### CommentNode | ||
| # CoffeeScript passes through block comments as JavaScript block comments | ||
| # at the same position. | ||
| exports.CommentNode: class CommentNode extends BaseNode | ||
| class: 'CommentNode' | ||
| isStatement: -> yes | ||
| constructor: (lines) -> | ||
| @lines: lines | ||
| makeReturn: -> | ||
| this | ||
| compileNode: (o) -> | ||
| sep: "\n$@tab" | ||
| "$@tab/*$sep${ @lines.join(sep) }\n$@tab*/" | ||
| #### CallNode | ||
@@ -517,3 +541,3 @@ | ||
| parts.push @to.compile o if @to isnt @toVar | ||
| if parts.length then "${parts.join('; ')};\n$o.indent" else '' | ||
| if parts.length then "${parts.join('; ')};" else '' | ||
@@ -539,7 +563,9 @@ # When compiled normally, the range returns the contents of the *for loop* | ||
| to: @toVar.compile o | ||
| result: o.scope.freeVariable() | ||
| i: o.scope.freeVariable() | ||
| clause: "$from <= $to ?" | ||
| pre: "\n${idt}a = [];${vars}" | ||
| body: "var i = $from; ($clause i <$equals $to : i >$equals $to); ($clause i += 1 : i -= 1)" | ||
| post: "a.push(i);\n${idt}return a;\n$o.indent" | ||
| "(function(){${pre}for ($body) $post}).call(this)" | ||
| pre: "\n${idt}${result} = []; ${vars}" | ||
| body: "var $i = $from; $clause $i <$equals $to : $i >$equals $to; $clause $i += 1 : $i -= 1" | ||
| post: "{ ${result}.push($i) };\n${idt}return $result;\n$o.indent" | ||
| "(function(){${pre}\n${idt}for ($body)$post}).call(this)" | ||
@@ -578,7 +604,11 @@ #### SliceNode | ||
| o.indent: @idt 1 | ||
| last: @properties.length - 1 | ||
| nonComments: prop for prop in @properties when not (prop instanceof CommentNode) | ||
| lastNoncom: nonComments[nonComments.length - 1] | ||
| props: for prop, i in @properties | ||
| join: if i is last then '' else ',\n' | ||
| prop: new AssignNode prop, prop, 'object' unless prop instanceof AssignNode | ||
| @idt(1) + prop.compile(o) + join | ||
| join: ",\n" | ||
| join: "\n" if (prop is lastNoncom) or (prop instanceof CommentNode) | ||
| join: '' if i is @properties.length - 1 | ||
| indent: if prop instanceof CommentNode then '' else @idt 1 | ||
| prop: new AssignNode prop, prop, 'object' unless prop instanceof AssignNode or prop instanceof CommentNode | ||
| indent + prop.compile(o) + join | ||
| props: props.join('') | ||
@@ -608,2 +638,4 @@ inner: if props then '\n' + props + '\n' + @idt() else '' | ||
| return @compileSplatLiteral @objects, o | ||
| else if obj instanceof CommentNode | ||
| objects.push "\n$code\n$o.indent" | ||
| else if i is @objects.length - 1 | ||
@@ -645,3 +677,3 @@ objects.push code | ||
| extension: @parent and new ExtendsNode(@variable, @parent) | ||
| props: new Expressions() | ||
| props: new Expressions | ||
| o.top: true | ||
@@ -658,3 +690,3 @@ me: null | ||
| else | ||
| constructor: new CodeNode() | ||
| constructor: new CodeNode | ||
@@ -664,2 +696,3 @@ for prop in @properties | ||
| if pvar and pvar.base.value is 'constructor' and func instanceof CodeNode | ||
| throw new Error "cannot define a constructor as a bound function." if func.bound | ||
| func.name: className | ||
@@ -805,3 +838,3 @@ func.body.push new ReturnNode literal 'this' | ||
| @params: params or [] | ||
| @body: body or new Expressions() | ||
| @body: body or new Expressions | ||
| @bound: tag is 'boundfunc' | ||
@@ -1003,2 +1036,5 @@ | ||
| toString: (idt) -> | ||
| super(idt, @class + ' ' + @operator) | ||
| compileNode: (o) -> | ||
@@ -1072,3 +1108,3 @@ o.operation: true | ||
| prefix: if @obj1 isnt @obj2 then @obj1 + '; ' else '' | ||
| "!!(function(){ ${prefix}for (var $i=0, $l=${@arr1}.length; $i<$l; $i++) if (${@arr2}[$i] === $@obj2) return true; })()" | ||
| "!!(function(){ ${prefix}for (var $i=0, $l=${@arr1}.length; $i<$l; $i++) if (${@arr2}[$i] === $@obj2) return true; }).call(this)" | ||
@@ -1169,5 +1205,10 @@ #### TryNode | ||
| topSensitive: -> | ||
| yes | ||
| compileNode: (o) -> | ||
| top: del o, 'top' | ||
| code: @expression.compile(o) | ||
| return code if @isStatement() | ||
| if @isStatement() | ||
| return (if top then "$@tab$code;" else code) | ||
| l: code.length | ||
@@ -1236,3 +1277,4 @@ code: code.substr(o, l-1) if code.substr(l-1, 1) is ';' | ||
| if range | ||
| sourcePart: source.compileVariables o | ||
| sourcePart: source.compileVariables(o) | ||
| sourcePart: + "\n$o.indent" if sourcePart | ||
| forPart: source.compile merge o, {index: ivar, step: @step} | ||
@@ -1243,3 +1285,3 @@ else | ||
| if @pattern | ||
| namePart: new AssignNode(@name, literal("$svar[$ivar]")).compile(merge o, {indent: @idt(1), top: true}) + "\n" | ||
| namePart: new AssignNode(@name, literal("$svar[$ivar]")).compile(merge o, {indent: @idt(1), top: true}) + '\n' | ||
| else | ||
@@ -1263,3 +1305,3 @@ namePart: "$name = $svar[$ivar]" if name | ||
| else | ||
| varPart: "${@idt(1)}$namePart;\n" if namePart | ||
| varPart: (namePart or '') and (if @pattern then namePart else "${@idt(1)}$namePart;\n") | ||
| if @object | ||
@@ -1287,6 +1329,6 @@ forPart: "$ivar in $svar) { if (${utility('hasProp')}.call($svar, $ivar)" | ||
| @body: body | ||
| @elseBody: null | ||
| @elseBody: null | ||
| @tags: tags or {} | ||
| @condition: new OpNode('!', new ParentheticalNode(@condition)) if @tags.invert | ||
| @isChain: false | ||
| @isChain: false | ||
@@ -1343,5 +1385,8 @@ bodyNode: -> @body?.unwrap() | ||
| makeReturn: -> | ||
| @body: and @ensureExpressions(@body.makeReturn()) | ||
| @elseBody: and @ensureExpressions(@elseBody.makeReturn()) | ||
| this | ||
| if @isStatement() | ||
| @body: and @ensureExpressions(@body.makeReturn()) | ||
| @elseBody: and @ensureExpressions(@elseBody.makeReturn()) | ||
| this | ||
| else | ||
| new ReturnNode this | ||
@@ -1408,4 +1453,7 @@ ensureExpressions: (node) -> | ||
| args: [] | ||
| mentionsArgs: expressions.contains (n) -> (n instanceof LiteralNode) and (n.value is 'arguments') | ||
| mentionsThis: expressions.contains (n) -> (n instanceof LiteralNode) and (n.value is 'this') | ||
| mentionsArgs: expressions.contains (n) -> | ||
| n instanceof LiteralNode and (n.value is 'arguments') | ||
| mentionsThis: expressions.contains (n) -> | ||
| (n instanceof LiteralNode and (n.value is 'this')) or | ||
| (n instanceof CodeNode and n.bound) | ||
| if mentionsArgs or mentionsThis | ||
@@ -1412,0 +1460,0 @@ meth: literal(if mentionsArgs then 'apply' else 'call') |
@@ -6,2 +6,5 @@ # A simple **OptionParser** class to parse option flags from the command-line. | ||
| # options: parser.parse process.argv | ||
| # | ||
| # The first non-option is considered to be the start of the file (and file | ||
| # option) list, and all subsequent arguments are left unparsed. | ||
| exports.OptionParser: class OptionParser | ||
@@ -26,3 +29,3 @@ | ||
| args: normalizeArguments args | ||
| while (arg: args.shift()) | ||
| for arg, i in args | ||
| isOption: !!(arg.match(LONG_FLAG) or arg.match(SHORT_FLAG)) | ||
@@ -32,7 +35,9 @@ matchedRule: no | ||
| if rule.shortFlag is arg or rule.longFlag is arg | ||
| options[rule.name]: if rule.hasArgument then args.shift() else true | ||
| options[rule.name]: if rule.hasArgument then args[i + 1] else true | ||
| matchedRule: yes | ||
| break | ||
| throw new Error "unrecognized option: $arg" if isOption and not matchedRule | ||
| options.arguments.push arg unless isOption | ||
| if not isOption | ||
| options.arguments: args[i...args.length] | ||
| break | ||
| options | ||
@@ -39,0 +44,0 @@ |
+33
-6
@@ -29,2 +29,3 @@ # The CoffeeScript language has a good deal of optional syntax, implicit syntax, | ||
| @tokens: tokens | ||
| @adjustComments() | ||
| @removeLeadingNewlines() | ||
@@ -52,2 +53,23 @@ @removeMidExpressionNewlines() | ||
| # Massage newlines and indentations so that comments don't have to be | ||
| # correctly indented, or appear on a line of their own. | ||
| adjustComments: -> | ||
| @scanTokens (prev, token, post, i) => | ||
| return 1 unless token[0] is 'HERECOMMENT' | ||
| [before, after]: [@tokens[i - 2], @tokens[i + 2]] | ||
| if after and after[0] is 'INDENT' | ||
| @tokens.splice i + 2, 1 | ||
| if before and before[0] is 'OUTDENT' and post and prev[0] is post[0] is 'TERMINATOR' | ||
| @tokens.splice i - 2, 1 | ||
| else | ||
| @tokens.splice i, 0, after | ||
| else if prev and prev[0] not in ['TERMINATOR', 'INDENT', 'OUTDENT'] | ||
| if post and post[0] is 'TERMINATOR' and after and after[0] is 'OUTDENT' | ||
| @tokens.splice(i + 3, 0, @tokens.splice(i, 2)...) | ||
| @tokens.splice(i + 3, 0, ['TERMINATOR', "\n", prev[2]]) | ||
| else | ||
| @tokens.splice i, 0, ['TERMINATOR', "\n", prev[2]] | ||
| return 2 | ||
| return 1 | ||
| # Leading newlines would introduce an ambiguity in the grammar, so we | ||
@@ -120,3 +142,3 @@ # dispatch them here. | ||
| return 1 | ||
| if open and !token.generated and (!post or include(IMPLICIT_END, tag)) | ||
| if open and !token.generated and prev[0] isnt ',' and (!post or include(IMPLICIT_END, tag)) | ||
| j: 1; j++ while (nx: @tokens[i + j])? and include(IMPLICIT_END, nx[0]) | ||
@@ -141,4 +163,7 @@ if nx? and nx[0] is ',' | ||
| if token[0] is 'ELSE' and prev[0] isnt 'OUTDENT' | ||
| @tokens.splice i, 0, ['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]] | ||
| @tokens.splice i, 0, @indentation(token)... | ||
| return 2 | ||
| if token[0] is 'CATCH' and @tokens[i + 2][0] is 'TERMINATOR' | ||
| @tokens.splice i + 2, 0, @indentation(token)... | ||
| return 4 | ||
| return 1 unless include(SINGLE_LINERS, token[0]) and | ||
@@ -148,4 +173,4 @@ post[0] isnt 'INDENT' and | ||
| starter: token[0] | ||
| indent: ['INDENT', 2, token[2]] | ||
| indent.generated: true | ||
| [indent, outdent]: @indentation token | ||
| indent.generated: outdent.generated: true | ||
| @tokens.splice i + 1, 0, indent | ||
@@ -163,4 +188,2 @@ idx: i + 1 | ||
| insertion: if pre[0] is "," then idx - 1 else idx | ||
| outdent: ['OUTDENT', 2, token[2]] | ||
| outdent.generated: true | ||
| @tokens.splice insertion, 0, outdent | ||
@@ -242,2 +265,6 @@ break | ||
| # Generate the indentation tokens, based on another token on the same line. | ||
| indentation: (token) -> | ||
| [['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]]] | ||
| # Constants | ||
@@ -244,0 +271,0 @@ # --------- |
@@ -25,3 +25,3 @@ # Test classes with a four-level inheritance chain. | ||
| result: (new ThirdChild()).func 'four' | ||
| result: (new ThirdChild).func 'four' | ||
@@ -44,3 +44,3 @@ ok result is 'zero/one/two/three/four' | ||
| ok (new SubClass()).prop is 'top-super-sub' | ||
| ok (new SubClass).prop is 'top-super-sub' | ||
@@ -80,7 +80,7 @@ | ||
| result: (new ThirdChild()).func 'four' | ||
| result: (new ThirdChild).func 'four' | ||
| ok result is 'zero/one/two/three/four' | ||
| ok (new ThirdChild())['func-func']('thing') is 'dynamic-thing' | ||
| ok (new ThirdChild)['func-func']('thing') is 'dynamic-thing' | ||
@@ -103,3 +103,3 @@ | ||
| ok (new SubClass()).prop is 'top-super-sub' | ||
| ok (new SubClass).prop is 'top-super-sub' | ||
@@ -112,3 +112,3 @@ | ||
| obj: new ClassName() | ||
| obj: new ClassName | ||
| ok obj.amI() | ||
@@ -133,3 +133,3 @@ | ||
| instance: new Class() | ||
| instance: new Class | ||
| ok instance.class is 'class' | ||
@@ -153,1 +153,13 @@ ok instance.name() is 'class' | ||
| ok fido.bark() is 'Spark woofs!' | ||
| # Testing a bound function in a bound function. | ||
| class Mini | ||
| num: 10 | ||
| generate: => | ||
| for i in [1..3] | ||
| => | ||
| @num | ||
| m: new Mini | ||
| ok (func() for func in m.generate()).join(' ') is '10 10 10' |
@@ -0,1 +1,8 @@ | ||
| # comment before a ... | ||
| ### | ||
| ... block comment. | ||
| ### | ||
| # comment | ||
@@ -69,3 +76,35 @@ func: -> | ||
| func: -> | ||
| one: -> | ||
| two: -> | ||
| three: -> | ||
| ### | ||
| block. | ||
| ### | ||
| four: -> | ||
| fn1: -> | ||
| oneLevel: null | ||
| ### | ||
| This isn't fine. | ||
| ### | ||
| ok ok | ||
| obj: { | ||
| a: 'b' | ||
| ### | ||
| comment | ||
| ### | ||
| c: 'd' | ||
| } | ||
| arr: [ | ||
| 1, 2, 3, | ||
| ### | ||
| four | ||
| ### | ||
| 5, 6, 7 | ||
| ] | ||
| # Spaced comments in if / elses. | ||
@@ -72,0 +111,0 @@ result: if false |
@@ -9,1 +9,7 @@ # Ensure that carriage returns don't break compilation on Windows. | ||
| global.resultArray: [] | ||
| CoffeeScript.run("resultArray.push i for i of global", {noWrap: on, globals: on, source: 'tests'}) | ||
| ok 'setInterval' in global.resultArray | ||
@@ -81,1 +81,6 @@ ok(if mySpecialVariable? then false else true) | ||
| ok result is undefined | ||
| # Assign to the result of an exsitential operation with a minus. | ||
| x: null ? - 1 | ||
| ok x is - 1 |
@@ -160,2 +160,9 @@ x: 1 | ||
| # Implicit call with a trailing if statement as a param. | ||
| func: -> arguments[1] | ||
| result: func 'one', if false then 100 else 13 | ||
| ok result is 13 | ||
| # Test more function passing: | ||
@@ -162,0 +169,0 @@ result: sum( -> |
@@ -63,1 +63,8 @@ a: b: d: true | ||
| ok result is undefined | ||
| # Return an if with no else. | ||
| func: -> | ||
| return (if false then callback()) | ||
| ok func() is null |
@@ -117,1 +117,8 @@ a: [((x) -> x), ((x) -> x * x)] | ||
| ok obj.class + obj.function is 'hötdog' | ||
| # But keyword assignment should be smart enough not to stringify variables. | ||
| func: -> | ||
| this == 'this' | ||
| ok func() is false |
@@ -52,2 +52,17 @@ # CoffeeScript's operations should be chainable, like Python's. | ||
| result: if list[2] in [7, 10] then 100 else -1 | ||
| ok result is 100 | ||
| ok result is 100 | ||
| # And with array presence on an instance variable. | ||
| obj: { | ||
| list: [1, 2, 3, 4, 5] | ||
| in_list: (value) -> value in @list | ||
| } | ||
| ok obj.in_list 4 | ||
| ok not obj.in_list 0 | ||
| # Non-spaced values still work. | ||
| x: 10 | ||
| y: -5 | ||
| ok x*-y is 50 | ||
| ok x*+y is -50 |
@@ -15,7 +15,16 @@ # Slice. | ||
| # Range. | ||
| # Ranges. | ||
| countdown: [10..1].join(' ') | ||
| ok countdown is "10 9 8 7 6 5 4 3 2 1" | ||
| a: 1 | ||
| b: 5 | ||
| nums: [a...b] | ||
| ok nums.join(' ') is '1 2 3 4' | ||
| b: -5 | ||
| nums: [a..b] | ||
| ok nums.join(' ') is '1 0 -1 -2 -3 -4 -5' | ||
| # Expression-based range. | ||
@@ -22,0 +31,0 @@ array: [(1+5)..1+9] |
@@ -92,3 +92,3 @@ func: (first, second, rest...) -> | ||
| ok (new Child()).meth().join(' ') is '3 2 1' | ||
| ok (new Child).meth().join(' ') is '3 2 1' | ||
@@ -95,0 +95,0 @@ |
@@ -67,2 +67,7 @@ hello: 'Hello' | ||
| a: """ | ||
| Hello ${ "Joe" } | ||
| """ | ||
| ok a is "Hello Joe" | ||
| a: 1 | ||
@@ -69,0 +74,0 @@ b: 2 |
| # Basic exception throwing. | ||
| block: -> (throw 'up') | ||
| throws block, 'up' | ||
| # Basic try/catch. | ||
| result: try | ||
| 10 | ||
| finally | ||
| 15 | ||
| ok result is 10 | ||
| result: try | ||
| throw 'up' | ||
| catch err | ||
| err.length | ||
| ok result is 2 |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Potential vulnerability
Supply chain riskInitial human review suggests the presence of a vulnerability in this package. It is pending further analysis and confirmation.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Potential vulnerability
Supply chain riskInitial human review suggests the presence of a vulnerability in this package. It is pending further analysis and confirmation.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
1904999
2.78%178
0.56%6538
1.1%65
4.84%7
-12.5%