Compare commits

..

91 Commits
0.5.6 ... 0.6.1

Author SHA1 Message Date
Jeremy Ashkenas
92540d5e85 CoffeeScript 0.6.1, for Node.js v0.1.90 2010-04-12 21:20:00 -04:00
Jeremy Ashkenas
ea982a627e adding coffee-haml-filter to the docs 2010-04-11 17:57:29 -04:00
Jeremy Ashkenas
835ecac8db simplifying some unecessary interpolated expressions into interpolated values. 2010-04-11 16:57:53 -04:00
Jeremy Ashkenas
c3bbb48041 adding a test case for issue 309, interpolations with implicit calls. 2010-04-11 09:37:48 -04:00
Jeremy Ashkenas
2e842f0146 merging Stan's recursive tokenizing fix for interpolations. 2010-04-11 09:26:21 -04:00
Jeremy Ashkenas
8de2fb9009 Merge commit 'StanAngeloff/issue_309' 2010-04-11 09:22:31 -04:00
Stan Angeloff
17e177405a FIXES #309: Optional parens and interpolation. 2010-04-11 12:22:54 +03:00
Dr Nic Williams
ef67561fb3 Using anonymous callback for 'exit' event when running tests 2010-04-11 19:05:49 +10:00
Jeremy Ashkenas
df97effb9c fixing implicit-call-in-function-in-parens bug. 2010-04-10 18:56:46 -04:00
Jeremy Ashkenas
8317960f81 Battery of patches for compatibility with Node v0.1.90 2010-04-10 18:05:35 -04:00
Jeremy Ashkenas
065bf54094 generated closures should only call() or apply() when necessary. 2010-04-10 14:40:05 -04:00
Jeremy Ashkenas
f36acc27e5 safely preserving the arguments object through generated closure wrappers. 2010-04-10 14:20:32 -04:00
Jeremy Ashkenas
491ad6de95 adding webchat to the doc page 2010-04-10 13:42:39 -04:00
Jeremy Ashkenas
3eedf8ed1b Adding noonat to the contributor list 2010-04-06 21:09:23 -04:00
Jeremy Ashkenas
75b260e495 Merge branch 'master' of git://github.com/noonat/coffee-script 2010-04-06 21:08:29 -04:00
noonat
2351948291 Renamed Lexer.tag() argument to new_tag, due to Rhino scope confusion 2010-04-05 22:58:56 -07:00
Tim Jones
538e518d76 Realigning function arrows. 2010-04-06 02:29:38 +12:00
Tim Jones
de955dacc4 Added Statement to the grammar. 2010-04-06 02:26:23 +12:00
Chris Lloyd
19ed63129e Interpolated strings are expressions. 2010-04-04 17:05:52 +10:00
Chris Lloyd
2e744a1c1b Failing test for string interpolation. Interpolated strings need to be expressions, not values. 2010-04-04 16:54:59 +10:00
Jeremy Ashkenas
89534b88b1 merging in Chris Lloyd's fix for optional descriptions on Cake tasks. 2010-04-04 00:20:17 -04:00
Jeremy Ashkenas
c067808b54 CoffeeScript 0.6.0 is on the books. 2010-04-03 20:43:50 -04:00
Jeremy Ashkenas
59ae79d8fb rebuilding the docs with the fixed highlighter for '@' and regexes. 2010-04-03 19:10:26 -04:00
Jeremy Ashkenas
ad1c5e1884 merging non-func-constructor-fix, but a little more forgiving. 2010-04-03 14:53:26 -04:00
Stan Angeloff
9958cedd89 Throwing proper error when "constructor" is not a function within a class body. 2010-04-03 21:43:42 +03:00
Jeremy Ashkenas
d1aaed4430 Merge branch 'master' of git://github.com/Tesco/coffee-script 2010-04-03 12:21:31 -04:00
Tim Jones
89debc87b2 Removing {@prop: value} from the grammar. 2010-04-04 04:18:29 +12:00
Jeremy Ashkenas
9d2c81ea54 rebuilding the docs with new pygments, no errors on '@' 2010-04-03 12:01:46 -04:00
Jeremy Ashkenas
44765907b3 tiny tweak 2010-04-03 11:16:49 -04:00
Jeremy Ashkenas
4a85f3d499 cleaning up tests ... consolidation, consistency... 2010-04-03 10:39:32 -04:00
Jeremy Ashkenas
f99b5ad463 Merging Tesco's invoking-this-fix 2010-04-03 09:58:45 -04:00
Tim Jones
8fc631269b Added a rule to prevent invoking THIS. 2010-04-03 14:14:16 +13:00
Tim Jones
a1975583a7 Added THIS to CALLABLE. 2010-04-03 13:58:21 +13:00
Jeremy Ashkenas
1c628e7883 fixing parens-around-implicit-function-with-multiline-chained-chaser bug 2010-04-01 23:38:20 -04:00
Jeremy Ashkenas
3605168e85 fixing single evaluation of functions used in chained comparisons wrapped in parentheses. 2010-03-31 22:48:47 -04:00
Jeremy Ashkenas
f86fca2739 merged tanob's fix for installing outside of /usr/local without a /bin 2010-03-31 21:30:14 -04:00
Adriano Bonat
0410748e2d Merge remote branch 'upstream/master' 2010-03-31 22:14:26 -03:00
Adriano Bonat
2172878f21 When installing in different prefixes, prefix + '/bin' may not exist. 2010-03-31 09:38:05 -03:00
Jeremy Ashkenas
d3a51fbfa1 stylistics: removing a bunch of unecessary parentheses 2010-03-31 00:17:49 -04:00
Jeremy Ashkenas
aae2405de4 removing all of the 'type' tags from the Nodes. Simply using constructor.name instead. 2010-03-31 00:04:14 -04:00
Jeremy Ashkenas
2b578367a9 rebuilding the source documentation with the new utility refactors 2010-03-30 23:53:02 -04:00
Jeremy Ashkenas
f9b028b78c __extend back to __extends, as is the correct name. 2010-03-30 20:15:51 -04:00
Jeremy Ashkenas
572aa4e98f reverting the grammar to the pre-slice notation. 2010-03-30 20:11:40 -04:00
Jeremy Ashkenas
864275f07e removing __range, and all the slice behavior it enabled. If you can't do array[-1], then you shouldn't be able to do array[0..-1] -- it's just too inconsistent. 2010-03-30 20:06:44 -04:00
Jeremy Ashkenas
998a7c8cb0 more cleanups, added a utility helper function to the codegen 2010-03-30 19:48:37 -04:00
Jeremy Ashkenas
6d7a04228f another reshuffle ... removed utilities.coffee entirely. 2010-03-30 19:42:09 -04:00
Jeremy Ashkenas
4a8c2e8a13 more refactors to utilities ... removing dependencies and the namespacing 2010-03-30 19:27:38 -04:00
Jeremy Ashkenas
f3a60edc5d simplifying the lookup of the top-level scope object 2010-03-30 19:21:14 -04:00
Jeremy Ashkenas
1e1146d61d more utility simplifications 2010-03-30 19:17:40 -04:00
Jeremy Ashkenas
832e1d8cb8 Utilities doesn't need to be a class, and removing __utilities.keys 2010-03-30 19:00:59 -04:00
Jeremy Ashkenas
4936211a9c modified shorter imlementation of bind 2010-03-30 18:49:55 -04:00
Jeremy Ashkenas
f0d731009f merged matehat's utility branch, arraySlice -> slice, removed dead dependency... 2010-03-30 18:27:53 -04:00
Jeremy Ashkenas
a6248d03e5 Merge branch 'slice' of git://github.com/matehat/coffee-script 2010-03-30 18:19:41 -04:00
Jeremy Ashkenas
a934cf4947 make JSLint happy about the while condition 2010-03-30 18:19:09 -04:00
matehat
c498b7090e Removed __splice in the same manner 2010-03-30 18:14:51 -04:00
matehat
ca9e45e8af Removed the __slice method, in favor of the native array slice method 2010-03-30 17:57:23 -04:00
matehat
97096696a2 Put back every utility functions on the global scope, automatically prefixed with __ and set them dynamically as reserved on the lexer. 2010-03-30 16:48:43 -04:00
matehat
27fb3763b4 A set of improvements on previous code 2010-03-30 16:14:07 -04:00
matehat
da43c70488 Merged in StanAngeloff excellent slice branch, applying recent factoring of utility functions 2010-03-30 15:43:30 -04:00
Stan Angeloff
76ade0cb4d Removing vendor specific files for measurement tests. 2010-03-30 14:33:57 -04:00
Stan Angeloff
09e1526bca Removing commented code in compile_splice -- this is working correctly now. 2010-03-30 14:33:57 -04:00
Stan Angeloff
7d1fbeb708 Re-compiling the core using the new __slice and __splice functions. 2010-03-30 14:32:37 -04:00
Stan Angeloff
15217c705e Allowing for negative indices in slice literals. 2010-03-30 14:30:15 -04:00
matehat
9f108e87eb Removed unused __hasProp assignment and declared Coffeescript a reserved name 2010-03-30 11:20:53 -04:00
matehat
1e786d6d8b Removed unnecessary check 2010-03-30 10:58:21 -04:00
matehat
0557eb9b93 Removed hard-coding of utility object name 2010-03-30 09:08:16 -04:00
matehat
241f6f3068 Applied the utility factoring into a "Coffeescript" object to the core. All tests pass fast. 2010-03-30 09:02:51 -04:00
Jeremy Ashkenas
326656245a using the new static properties of class definitions in the CoffeeScript compiler -- it's hardly used. 2010-03-29 21:49:20 -04:00
Jeremy Ashkenas
177ec92c39 adding class methods to class definition syntax, using '@' 2010-03-29 21:43:12 -04:00
Jeremy Ashkenas
711dacae5f more little documentation for the rewriter ... moving along 2010-03-29 21:22:12 -04:00
Jeremy Ashkenas
c19183118e removing a case from Rewriter#add_implicit_parentheses that apparently never happens... 2010-03-29 20:52:22 -04:00
Jeremy Ashkenas
0af132d0c6 update internal documentation ... it's been a while 2010-03-29 20:48:41 -04:00
Jeremy Ashkenas
83c0e77ca8 making the Rewriter's add_implicit_calls more sensitive of parenthetical arguments. 2010-03-28 17:12:30 -04:00
Jeremy Ashkenas
1e315b5a33 fixing single-line implicit call wrapped around function with trailing arguments 2010-03-28 16:44:41 -04:00
Tim Jones
6e0e0767f9 Removed unprocessed values on a for loop from the grammar. 2010-03-29 07:32:01 +13:00
Tim Jones
6df50399a9 Restricted class and extends values to simple assignments. 2010-03-29 06:14:35 +13:00
Tim Jones
7b9a8998cf Addressing some assignment issues. 2010-03-29 06:06:16 +13:00
Jeremy Ashkenas
7de5253318 removing unused reserved variable 'source var' from range comprehensions 2010-03-27 16:04:47 -04:00
Jeremy Ashkenas
eaf4a71d32 Revert "Added Unix-like piping. Allows chaining of function calls where every succeeding call receives as first argument the result of all preceding expressions."
This reverts commit 7ee10e06be.
2010-03-27 15:25:34 -04:00
Jeremy Ashkenas
4dd40034ed Revert "removing the special case for | or"
This reverts commit 9763839ed1.
2010-03-27 15:25:27 -04:00
Jeremy Ashkenas
030476d335 Revert "typo for @compile_bitwise_or"
This reverts commit 45aae5e322.
2010-03-27 15:25:19 -04:00
Jeremy Ashkenas
45aae5e322 typo for @compile_bitwise_or 2010-03-27 12:13:24 -04:00
Jeremy Ashkenas
9763839ed1 removing the special case for | or 2010-03-27 10:28:08 -04:00
Stan Angeloff
7ee10e06be Added Unix-like piping. Allows chaining of function calls where every succeeding call receives as first argument the result of all preceding expressions. 2010-03-27 15:49:33 +02:00
matehat
8f3ea1d0c5 Fixed a small bug that happened when having a trailing comma in multiline array and object literals 2010-03-26 14:11:34 -04:00
matehat
b9b87f7d8e Minor modifications to the grammar to allow a single trailing comma for function call arguments, array literal and object literals. Adjusted tests accordingly 2010-03-26 11:44:25 -04:00
Chris Lloyd
c9b6e82e2c Optional sentence descriptions for cake tasks. 2010-03-26 20:25:17 +11:00
Jeremy Ashkenas
c8f969b4a2 adding a test case for the explicit returns 2010-03-25 18:54:17 -04:00
Jeremy Ashkenas
ecd1c77f48 fixing explicit returns of comprehensions (and probably other things as well) 2010-03-25 18:51:24 -04:00
Jeremy Ashkenas
ad93d2fe4d added another language extension test for a << b into a.push(b) 2010-03-23 20:42:40 -04:00
Jeremy Ashkenas
5a4d401582 make sure that the source-hacking docs mention to 'git checkout lib' 2010-03-23 00:25:37 -04:00
93 changed files with 2778 additions and 2348 deletions

View File

@@ -1,10 +1,11 @@
fs: require 'fs'
helpers: require('./lib/helpers').helpers
fs: require 'fs'
helpers: require('./lib/helpers').helpers
CoffeeScript: require './lib/coffee-script'
{spawn: spawn, exec: exec}: require('child_process')
# Run a CoffeeScript through our node/coffee interpreter.
run: (args) ->
proc: process.createChildProcess 'bin/coffee', args
proc: spawn 'bin/coffee', args
proc.addListener 'error', (err) -> if err then puts err
@@ -12,12 +13,13 @@ option '-p', '--prefix [DIR]', 'set the installation prefix for `cake install`'
task 'install', 'install CoffeeScript into /usr/local (or --prefix)', (options) ->
base: options.prefix or '/usr/local'
lib: base + '/lib/coffee-script'
lib: "$base/lib/coffee-script"
bin: "$base/bin"
exec([
'mkdir -p ' + lib
'cp -rf bin lib LICENSE README package.json src vendor ' + lib
'ln -sf ' + lib + '/bin/coffee ' + base + '/bin/coffee'
'ln -sf ' + lib + '/bin/cake ' + base + '/bin/cake'
"mkdir -p $lib $bin"
"cp -rf bin lib LICENSE README package.json src vendor $lib"
"ln -sf $lib/bin/coffee $base/bin/coffee"
"ln -sf $lib/bin/cake $base/bin/cake"
].join(' && '), (err, stdout, stderr) ->
if err then print stderr
)
@@ -72,8 +74,8 @@ task 'doc:underscore', 'rebuild the Underscore.coffee documentation page', ->
task 'test', 'run the CoffeeScript language test suite', ->
helpers.extend global, require 'assert'
passed_tests: failed_tests: 0
start_time: new Date()
original_ok: ok
start_time: new Date()
original_ok: ok
helpers.extend global, {
ok: (args...) -> passed_tests += 1; original_ok(args...)
CoffeeScript: CoffeeScript
@@ -81,11 +83,10 @@ task 'test', 'run the CoffeeScript language test suite', ->
red: '\033[0;31m'
green: '\033[0;32m'
reset: '\033[0m'
on_exit: ->
process.addListener 'exit', ->
time: ((new Date() - start_time) / 1000).toFixed(2)
message: "passed $passed_tests tests in $time seconds$reset"
puts(if failed_tests then "${red}failed $failed_tests and $message" else "$green$message")
process.addListener 'exit', on_exit
fs.readdir 'test', (err, files) ->
files.forEach (file) ->
return unless file.match(/\.coffee$/i)

22
README
View File

@@ -39,4 +39,24 @@
The source repository:
git://github.com/jashkenas/coffee-script.git
Contributors:
Stan Angeloff (StanAngeloff)
Jeremy Ashkenas (jashkenas)
Zach Carter (zaach)
Tim Cuthbertson (gfxmonk)
Mathieu D'Amours (matehat)
Chris Hoffman (cehoffman)
Jason Huggins (hugs)
Tim Jones (Tesco)
Chris Lloyd (chrislloyd)
Matt Lyon (mattly)
Jeff Olson (olsonjeffery)
Nathan Ostgard (noonat)
Samuel Reis (grgh)
Tom Robinson (tlrobinson)
Tim Smart (Tim-Smart)
Dr. Nic Williams (drnic)

View File

@@ -11,8 +11,9 @@ current directory's Cakefile.</p> </td> <td class="code"
<span class="nv">CoffeeScript: </span><span class="nx">require</span> <span class="s1">&#39;./coffee-script&#39;</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>Keep track of the list of defined tasks, the accepted options, and so on.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">tasks: </span><span class="p">{}</span>
<span class="nv">options: </span><span class="p">{}</span>
<span class="nv">switches: </span><span class="p">[]</span>
<span class="nv">oparse: </span><span class="kc">null</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Mixin the top-level Cake functions for Cakefiles to use directly.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">helpers</span><span class="p">.</span><span class="nx">extend</span> <span class="nx">global</span><span class="p">,</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>Define a Cake task with a short name, a sentence description,
<span class="nv">oparse: </span><span class="kc">null</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Mixin the top-level Cake functions for Cakefiles to use directly.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">helpers</span><span class="p">.</span><span class="nx">extend</span> <span class="nx">global</span><span class="p">,</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>Define a Cake task with a short name, an optional sentence description,
and the function to run as the action itself.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">task: </span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">description</span><span class="p">,</span> <span class="nx">action</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="p">[</span><span class="nx">action</span><span class="p">,</span> <span class="nx">description</span><span class="p">]</span><span class="o">:</span> <span class="p">[</span><span class="nx">description</span><span class="p">,</span> <span class="nx">action</span><span class="p">]</span> <span class="nx">unless</span> <span class="nx">action</span>
<span class="nx">tasks</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span><span class="o">:</span> <span class="p">{</span><span class="nv">name: </span><span class="nx">name</span><span class="p">,</span> <span class="nv">description: </span><span class="nx">description</span><span class="p">,</span> <span class="nv">action: </span><span class="nx">action</span><span class="p">}</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Define an option that the Cakefile accepts. The parsed options hash,
containing all of the command-line options passed, will be made available
as the first argument to the action.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">option: </span><span class="p">(</span><span class="nx">letter</span><span class="p">,</span> <span class="nx">flag</span><span class="p">,</span> <span class="nx">description</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -35,9 +36,10 @@ If no tasks are passed, print the help screen.</p> </td>
<span class="k">for</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">task</span> <span class="k">of</span> <span class="nx">tasks</span>
<span class="nv">spaces: </span><span class="mi">20</span> <span class="o">-</span> <span class="nx">name</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">spaces: </span><span class="k">if</span> <span class="nx">spaces</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="k">then</span> <span class="p">(</span><span class="s1">&#39; &#39;</span> <span class="k">for</span> <span class="nx">i</span> <span class="k">in</span> <span class="p">[</span><span class="mi">0</span><span class="p">..</span><span class="nx">spaces</span><span class="p">]).</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="nx">puts</span> <span class="s2">&quot;cake $name$spaces # ${task.description}&quot;</span>
<span class="nv">desc: </span> <span class="k">if</span> <span class="nx">task</span><span class="p">.</span><span class="nx">description</span> <span class="k">then</span> <span class="s2">&quot;# $task.description&quot;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="nx">puts</span> <span class="s2">&quot;cake $name$spaces $desc&quot;</span>
<span class="nx">puts</span> <span class="nx">oparse</span><span class="p">.</span><span class="nx">help</span><span class="p">()</span> <span class="k">if</span> <span class="nx">switches</span><span class="p">.</span><span class="nx">length</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Print an error and exit when attempting to all an undefined task.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">no_such_task: </span><span class="p">(</span><span class="nx">task</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">stdio</span><span class="p">.</span><span class="nx">writeError</span> <span class="s2">&quot;No such task: \&quot;$task\&quot;\n&quot;</span>
<span class="nx">puts</span> <span class="s2">&quot;No such task: \&quot;$task\&quot;\n&quot;</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

View File

@@ -16,13 +16,13 @@ execute all scripts present in <code>text/coffeescript</code> tags.</p>
<span class="k">this</span><span class="p">.</span><span class="nv">exports: </span><span class="k">this</span><span class="p">.</span><span class="nv">CoffeeScript: </span><span class="p">{}</span>
<span class="nv">Lexer: </span> <span class="k">this</span><span class="p">.</span><span class="nx">Lexer</span>
<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">&#39;0.5.6&#39;</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">&#39;0.6.1&#39;</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
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">-&gt;</span>
<span class="nv">options: </span><span class="o">or</span> <span class="p">{}</span>
<span class="k">try</span>
<span class="p">(</span><span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="nx">code</span><span class="p">).</span><span class="nx">compile</span> <span class="nx">options</span>
<span class="k">catch</span> <span class="nx">err</span>
<span class="nv">err.message: </span><span class="s2">&quot;In ${options.source}, ${err.message}&quot;</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">source</span>
<span class="nv">err.message: </span><span class="s2">&quot;In $options.source, $err.message&quot;</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">source</span>
<span class="k">throw</span> <span class="nx">err</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Tokenize a string of CoffeeScript code, and return the array of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.tokens: </span><span class="p">(</span><span class="nx">code</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="nx">code</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Tokenize and parse a string of CoffeeScript code, and return the AST. You can
then compile it by calling <code>.compile()</code> on the root, or traverse it by using
@@ -30,7 +30,7 @@ then compile it by calling <code>.compile()</code> on the root, or traverse it b
<span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="nx">code</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Compile and execute a string of CoffeeScript (on the server), correctly
setting <code>__filename</code>, <code>__dirname</code>, and relative <code>require()</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run: </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">-&gt;</span>
<span class="nv">module.filename: __filename: </span><span class="nx">options</span><span class="p">.</span><span class="nx">source</span>
<span class="nv">__dirname: </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">__filename</span>
<span class="nv">__dirname: </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span><span class="p">(</span><span class="nx">__filename</span><span class="p">)</span>
<span class="nb">eval</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span>
<span class="p">)</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Extend CoffeeScript with a custom language extension. It should hook in to
the <strong>Lexer</strong> (as a peer of any of the lexer's tokenizing methods), and
@@ -40,16 +40,16 @@ peer of the nodes in <a href="nodes.html">nodes.coffee</a>).</p> </t
thin wrapper around it, compatible with the Jison API. We can then pass it
directly as a "Jison lexer".</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">parser.lexer: </span><span class="p">{</span>
<span class="nv">lex: </span><span class="o">-&gt;</span>
<span class="nv">token: </span><span class="err">@</span><span class="nx">tokens</span><span class="p">[</span><span class="err">@</span><span class="nx">pos</span><span class="p">]</span> <span class="o">or</span> <span class="p">[</span><span class="s2">&quot;&quot;</span><span class="p">]</span>
<span class="err">@</span><span class="nv">pos: </span><span class="o">+</span> <span class="mi">1</span>
<span class="nv">token: </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">@pos</span><span class="p">]</span> <span class="o">or</span> <span class="p">[</span><span class="s2">&quot;&quot;</span><span class="p">]</span>
<span class="vi">@pos: </span><span class="o">+</span> <span class="mi">1</span>
<span class="k">this</span><span class="p">.</span><span class="nv">yylineno: </span><span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
<span class="k">this</span><span class="p">.</span><span class="nv">yytext: </span> <span class="nx">token</span><span class="p">[</span><span class="mi">1</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="nv">setInput: </span><span class="p">(</span><span class="nx">tokens</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nv">tokens: </span><span class="nx">tokens</span>
<span class="err">@</span><span class="nv">pos: </span><span class="mi">0</span>
<span class="vi">@tokens: </span><span class="nx">tokens</span>
<span class="vi">@pos: </span><span class="mi">0</span>
<span class="nv">upcomingInput: </span><span class="o">-&gt;</span> <span class="s2">&quot;&quot;</span>
<span class="nv">showPosition: </span><span class="o">-&gt;</span> <span class="err">@</span><span class="nx">pos</span>
<span class="nv">showPosition: </span><span class="o">-&gt;</span> <span class="nx">@pos</span>
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Activate CoffeeScript in the browser by having it compile and evaluate
all script tags with a content-type of <code>text/coffeescript</code>. This happens
on page load. Unfortunately, the text contents of remote scripts cannot be

View File

@@ -5,7 +5,8 @@ saved, printed as a token stream or as the syntax tree, or launch an
interactive REPL.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-2">#</a> </div> <p>External dependencies.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">fs: </span> <span class="nx">require</span> <span class="s1">&#39;fs&#39;</span>
<span class="nv">path: </span> <span class="nx">require</span> <span class="s1">&#39;path&#39;</span>
<span class="nv">optparse: </span> <span class="nx">require</span> <span class="s1">&#39;./optparse&#39;</span>
<span class="nv">CoffeeScript: </span><span class="nx">require</span> <span class="s1">&#39;./coffee-script&#39;</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 help banner that is printed when <code>coffee</code> is called without arguments.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BANNER: </span><span class="s1">&#39;&#39;&#39;</span>
<span class="nv">CoffeeScript: </span><span class="nx">require</span> <span class="s1">&#39;./coffee-script&#39;</span>
<span class="p">{</span><span class="nv">spawn: </span><span class="nx">spawn</span><span class="p">,</span> <span class="nv">exec: </span><span class="nx">exec</span><span class="p">}</span><span class="o">:</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;child_process&#39;</span><span class="p">)</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 help banner that is printed when <code>coffee</code> is called without arguments.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BANNER: </span><span class="s1">&#39;&#39;&#39;</span>
<span class="s1"> coffee compiles CoffeeScript source files into JavaScript.</span>
<span class="s1"> Usage:</span>
@@ -49,7 +50,9 @@ compile them.</p> </td> <td class="code">
<span class="nx">path</span><span class="p">.</span><span class="nx">exists</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">exists</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">&quot;File not found: $source&quot;</span> <span class="nx">unless</span> <span class="nx">exists</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">code</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">compile_script</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">code</span><span class="p">)</span>
<span class="nx">compile</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="k">for</span> <span class="nx">source</span> <span class="k">in</span> <span class="nx">sources</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Compile a single source script, containing the given code, according to the
<span class="nv">run: </span><span class="o">-&gt;</span> <span class="nx">compile</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="k">for</span> <span class="nx">source</span> <span class="k">in</span> <span class="nx">sources</span>
<span class="k">return</span> <span class="nx">run</span><span class="p">()</span> <span class="nx">unless</span> <span class="nx">options</span><span class="p">.</span><span class="nx">output</span> <span class="o">and</span> <span class="nx">options</span><span class="p">.</span><span class="nx">compile</span>
<span class="nx">exec</span> <span class="s2">&quot;mkdir -p $options.output&quot;</span><span class="p">,</span> <span class="nx">run</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Compile a single source script, containing the given code, according to the
requested options. Both compile_scripts and watch_scripts share this method
in common. If evaluating the script directly sets <code>__filename</code>, <code>__dirname</code>
and <code>module.filename</code> to be correct relative to the script's path.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compile_script: </span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">code</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -61,17 +64,17 @@ and <code>module.filename</code> to be correct relative to the script's path.</p
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">run</span> <span class="k">then</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">code_opts</span>
<span class="k">else</span>
<span class="nv">js: </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">code_opts</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="k">then</span> <span class="nx">process</span><span class="p">.</span><span class="nx">stdio</span><span class="p">.</span><span class="nx">write</span> <span class="nx">js</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="k">then</span> <span class="nx">print</span> <span class="nx">js</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="k">then</span> <span class="nx">write_js</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">js</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">lint</span> <span class="k">then</span> <span class="nx">lint</span> <span class="nx">js</span>
<span class="k">catch</span> <span class="nx">err</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">watch</span> <span class="k">then</span> <span class="nx">puts</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span> <span class="k">else</span> <span class="k">throw</span> <span class="nx">err</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Attach the appropriate listeners to compile scripts incoming over <strong>stdin</strong>,
and write them back to <strong>stdout</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compile_stdio: </span><span class="o">-&gt;</span>
<span class="nv">code: </span><span class="s1">&#39;&#39;</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">stdio</span><span class="p">.</span><span class="nx">open</span><span class="p">()</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">stdio</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">&#39;data&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">string</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">code: </span><span class="o">+</span> <span class="nx">string</span> <span class="k">if</span> <span class="nx">string</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">stdio</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">&#39;close&#39;</span><span class="p">,</span> <span class="o">-&gt;</span>
<span class="nv">stdin: </span><span class="nx">process</span><span class="p">.</span><span class="nx">openStdin</span><span class="p">()</span>
<span class="nx">stdin</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">&#39;data&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">code: </span><span class="o">+</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span> <span class="k">if</span> <span class="nx">buffer</span>
<span class="nx">stdin</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">&#39;end&#39;</span><span class="p">,</span> <span class="o">-&gt;</span>
<span class="nx">compile_script</span> <span class="s1">&#39;stdio&#39;</span><span class="p">,</span> <span class="nx">code</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Watch a list of source CoffeeScript files using <code>fs.watchFile</code>, recompiling
them every time the files are updated. May be used in combination with other
options, such as <code>--lint</code> or <code>--print</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">watch_scripts: </span><span class="o">-&gt;</span>
@@ -87,13 +90,12 @@ directory can be customized with <code>--output</code>.</p> </td>
<span class="nv">js_path: </span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">dir</span><span class="p">,</span> <span class="nx">filename</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">writeFile</span> <span class="nx">js_path</span><span class="p">,</span> <span class="nx">js</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>Pipe compiled JS through JSLint (requires a working <code>jsl</code> command), printing
any errors or warnings that arise.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lint: </span><span class="p">(</span><span class="nx">js</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">jsl: </span><span class="nx">process</span><span class="p">.</span><span class="nx">createChildProcess</span><span class="p">(</span><span class="s1">&#39;jsl&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;-nologo&#39;</span><span class="p">,</span> <span class="s1">&#39;-stdin&#39;</span><span class="p">])</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">&#39;output&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">result</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">puts</span> <span class="nx">result</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\n/g</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="k">if</span> <span class="nx">result</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">&#39;error&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">result</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">puts</span> <span class="nx">result</span> <span class="k">if</span> <span class="nx">result</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">write</span> <span class="nx">js</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">close</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>Pretty-print a stream of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">print_tokens: </span><span class="p">(</span><span class="nx">tokens</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">print_it: </span><span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">puts</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span>
<span class="nv">jsl: </span><span class="nx">spawn</span> <span class="s1">&#39;jsl&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;-nologo&#39;</span><span class="p">,</span> <span class="s1">&#39;-stdin&#39;</span><span class="p">]</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">&#39;data&#39;</span><span class="p">,</span> <span class="nx">print_it</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stderr</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">&#39;data&#39;</span><span class="p">,</span> <span class="nx">print_it</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdin</span><span class="p">.</span><span class="nx">write</span> <span class="nx">js</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdin</span><span class="p">.</span><span class="nx">end</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>Pretty-print a stream of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">print_tokens: </span><span class="p">(</span><span class="nx">tokens</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">strings: </span><span class="k">for</span> <span class="nx">token</span> <span class="k">in</span> <span class="nx">tokens</span>
<span class="p">[</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span><span class="p">]</span><span class="o">:</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="nx">token</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">toString</span><span class="p">().</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\n/</span><span class="p">,</span> <span class="s1">&#39;\\n&#39;</span><span class="p">)]</span>
<span class="s2">&quot;[$tag $value]&quot;</span>
@@ -109,7 +111,7 @@ any errors or warnings that arise.</p> </td> <td class="
<span class="nx">o</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</a> </div> <p>Print the <code>--help</code> usage message and exit.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">usage: </span><span class="o">-&gt;</span>
<span class="nx">puts</span> <span class="nx">option_parser</span><span class="p">.</span><span class="nx">help</span><span class="p">()</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">0</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>Print the <code>--version</code> message and exit.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">version: </span><span class="o">-&gt;</span>
<span class="nx">puts</span> <span class="s2">&quot;CoffeeScript version ${CoffeeScript.VERSION}&quot;</span>
<span class="nx">puts</span> <span class="s2">&quot;CoffeeScript version $CoffeeScript.VERSION&quot;</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">0</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

View File

@@ -124,7 +124,7 @@ td.linenos { background-color: #f0f0f0; padding-right: 10px; }
span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
body .hll { background-color: #ffffcc }
body .c { color: #408080; font-style: italic } /* Comment */
/*body .err { border: 1px solid #FF0000 } /* Error */
body .err { border: 1px solid #FF0000 } /* Error */
body .k { color: #954121 } /* Keyword */
body .o { color: #666666 } /* Operator */
body .cm { color: #408080; font-style: italic } /* Comment.Multiline */

View File

@@ -33,19 +33,28 @@ their numeric position, so in this rule:</p>
for the <code>UNLESS</code> terminal, and <code>$3</code> would be the value of the second
<code>Expression</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">grammar: </span><span class="p">{</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>The <strong>Root</strong> is the top-level node in the syntax tree. Since we parse bottom-up,
all parsing must end here.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Root: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Expressions</span><span class="p">()</span>
<span class="nx">o</span> <span class="s2">&quot;TERMINATOR&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Expressions</span><span class="p">()</span>
<span class="nx">o</span> <span class="s2">&quot;Expressions&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Expressions</span><span class="p">()</span>
<span class="nx">o</span> <span class="s2">&quot;TERMINATOR&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Expressions</span><span class="p">()</span>
<span class="nx">o</span> <span class="s2">&quot;Body&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Block TERMINATOR&quot;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Any list of expressions or method body, seperated by line breaks or
semicolons.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Expressions: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;Expressions TERMINATOR Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">push</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expressions TERMINATOR&quot;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>All the different types of expressions in our language. The basic unit of
CoffeeScript is the <strong>Expression</strong> -- you'll notice that there is no
"statement" nonterminal. Expressions serve as the building blocks
of many other rules, making them somewhat circular.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Expression: </span><span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Any list of statements and expressions, seperated by line breaks or semicolons.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Body: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Line&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;Body TERMINATOR Line&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">push</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Body TERMINATOR&quot;</span>
<span class="p">]</span>
</pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Expressions and statements, which make up a line in a body.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Line: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Expression&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Statement&quot;</span>
<span class="p">]</span>
</pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Pure statements which cannot be expressions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Statement: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Return&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Throw&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;BREAK&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">yytext</span>
<span class="nx">o</span> <span class="s2">&quot;CONTINUE&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">yytext</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>All the different types of expressions in our language. The basic unit of
CoffeeScript is the <strong>Expression</strong> -- everything that can be an expression
is one. Expressions serve as the building blocks of many other rules, making
them somewhat circular.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Expression: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Value&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Call&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Curry&quot;</span>
@@ -54,8 +63,6 @@ of many other rules, making them somewhat circular.</p> </td>
<span class="nx">o</span> <span class="s2">&quot;Assign&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;If&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Try&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Throw&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Return&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;While&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;For&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Switch&quot;</span>
@@ -65,78 +72,82 @@ of many other rules, making them somewhat circular.</p> </td>
<span class="nx">o</span> <span class="s2">&quot;Existence&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Comment&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Extension&quot;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>A an indented block of expressions. Note that the <a href="rewriter.html">Rewriter</a>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>A an indented block of expressions. Note that the <a href="rewriter.html">Rewriter</a>
will convert some postfix forms into blocks for us, by adjusting the
token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Block: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;INDENT Expressions OUTDENT&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;INDENT Body OUTDENT&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;INDENT OUTDENT&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">Expressions</span><span class="p">()</span>
<span class="nx">o</span> <span class="s2">&quot;TERMINATOR Comment&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$2</span><span class="p">]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>A literal identifier, a variable name or property.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Identifier: </span><span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</a> </div> <p>A literal identifier, a variable name or property.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Identifier: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;IDENTIFIER&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">yytext</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>Alphanumerics are separated from the other <strong>Literal</strong> matchers because
<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>Alphanumerics are separated from the other <strong>Literal</strong> matchers because
they can also serve as keys in object literals.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">AlphaNumeric: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;NUMBER&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">yytext</span>
<span class="nx">o</span> <span class="s2">&quot;STRING&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">yytext</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</a> </div> <p>All of our immediate values. These can (in general), be passed straight
<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>All of our immediate values. These can (in general), be passed straight
through and printed to JavaScript.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Literal: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;AlphaNumeric&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;JS&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">yytext</span>
<span class="nx">o</span> <span class="s2">&quot;REGEX&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">yytext</span>
<span class="nx">o</span> <span class="s2">&quot;BREAK&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">yytext</span>
<span class="nx">o</span> <span class="s2">&quot;CONTINUE&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">yytext</span>
<span class="nx">o</span> <span class="s2">&quot;TRUE&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s2">&quot;FALSE&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="kc">false</span>
<span class="nx">o</span> <span class="s2">&quot;YES&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s2">&quot;NO&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="kc">false</span>
<span class="nx">o</span> <span class="s2">&quot;ON&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s2">&quot;OFF&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="kc">false</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>Assignment of a variable, property, or index to a value.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Assign: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Value ASSIGN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">AssignNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</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>Assignment when it happens within an object literal. The difference from
<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>Assignment of a variable, property, or index to a value.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Assign: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Assignable ASSIGN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">AssignNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</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>Assignment when it happens within an object literal. The difference from
the ordinary <strong>Assign</strong> is that these allow numbers and strings as keys.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">AssignObj: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Identifier ASSIGN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">AssignNode</span> <span class="k">new</span> <span class="nx">ValueNode</span><span class="p">(</span><span class="nx">$1</span><span class="p">),</span> <span class="nx">$3</span><span class="p">,</span> <span class="s1">&#39;object&#39;</span>
<span class="nx">o</span> <span class="s2">&quot;AlphaNumeric ASSIGN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">AssignNode</span> <span class="k">new</span> <span class="nx">ValueNode</span><span class="p">(</span><span class="nx">$1</span><span class="p">),</span> <span class="nx">$3</span><span class="p">,</span> <span class="s1">&#39;object&#39;</span>
<span class="nx">o</span> <span class="s2">&quot;Comment&quot;</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>A return statement from a function body.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Return: </span><span class="p">[</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>A return statement from a function body.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Return: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;RETURN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ReturnNode</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;RETURN&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ReturnNode</span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="s1">&#39;null&#39;</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>A comment. Because CoffeeScript passes comments through to JavaScript, we
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-20">#</a> </div> <p>A comment. Because CoffeeScript passes comments through to JavaScript, we
have to parse comments like any other construct, and identify all of the
positions in which they can occur in the grammar.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Comment: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;COMMENT&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">CommentNode</span> <span class="nx">yytext</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><a href="http://jashkenas.github.com/coffee-script/#existence">The existential operator</a>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Existence: </span><span class="p">[</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><a href="http://jashkenas.github.com/coffee-script/#existence">The existential operator</a>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Existence: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Expression ?&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ExistenceNode</span> <span class="nx">$1</span>
<span class="p">]</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 <strong>Code</strong> node is the function literal. It's defined by an indented block
<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>The <strong>Code</strong> node is the function literal. It's defined by an indented block
of <strong>Expressions</strong> preceded by a function arrow, with an optional parameter
list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Code: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;PARAM_START ParamList PARAM_END FuncGlyph Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">CodeNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$5</span><span class="p">,</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s2">&quot;FuncGlyph Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">CodeNode</span> <span class="p">[],</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</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>CoffeeScript has two different symbols for functions. <code>-&gt;</code> is for ordinary
<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>CoffeeScript has two different symbols for functions. <code>-&gt;</code> is for ordinary
functions, and <code>=&gt;</code> is for functions bound to the current value of <em>this</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">FuncGlyph: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;-&gt;&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="s1">&#39;func&#39;</span>
<span class="nx">o</span> <span class="s2">&quot;=&gt;&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="s1">&#39;boundfunc&#39;</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>The list of parameters that a function accepts can be of any length.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ParamList: </span><span class="p">[</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>The list of parameters that a function accepts can be of any length.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ParamList: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[]</span>
<span class="nx">o</span> <span class="s2">&quot;Param&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;ParamList , Param&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[</span><span class="nx">$3</span><span class="p">]</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>A single parameter in a function definition can be ordinary, or a splat
<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>A single parameter in a function definition can be ordinary, or a splat
that hoovers up the remaining arguments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Param: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;PARAM&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">yytext</span>
<span class="nx">o</span> <span class="s2">&quot;Param . . .&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">SplatNode</span> <span class="nx">$1</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>A splat that occurs outside of a parameter list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Splat: </span><span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-26">#</a> </div> <p>A splat that occurs outside of a parameter list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Splat: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Expression . . .&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">SplatNode</span> <span class="nx">$1</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>The types of things that can be treated as values -- assigned to, invoked
as functions, indexed into, named as a class, etc.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Value: </span><span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-27">#</a> </div> <p>Variables and properties that can be assigned to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">SimpleAssignable: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Identifier&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s2">&quot;Literal&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s2">&quot;Value Accessor&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">push</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;Invocation Accessor&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="p">[</span><span class="nx">$2</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;ThisProperty&quot;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-28">#</a> </div> <p>Everything that can be assigned to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Assignable: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;SimpleAssignable&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Array&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s2">&quot;Object&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-29">#</a> </div> <p>The types of things that can be treated as values -- assigned to, invoked
as functions, indexed into, named as a class, etc.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Value: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Assignable&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Literal&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s2">&quot;Parenthetical&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s2">&quot;Range&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s2">&quot;This&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Value Accessor&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">push</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;Invocation Accessor&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="p">[</span><span class="nx">$2</span><span class="p">]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-26">#</a> </div> <p>The general group of accessors into an object, by property, by prototype
<span class="nx">o</span> <span class="s2">&quot;NULL&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="s1">&#39;null&#39;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-30">#</a> </div> <p>The general group of accessors into an object, by property, by prototype
or by array index or slice.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Accessor: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;PROPERTY_ACCESS Identifier&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">AccessorNode</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;PROTOTYPE_ACCESS Identifier&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">AccessorNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="s1">&#39;prototype&#39;</span>
@@ -144,58 +155,71 @@ or by array index or slice.</p> </td> <td class="code">
<span class="nx">o</span> <span class="s2">&quot;SOAK_ACCESS Identifier&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">AccessorNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="s1">&#39;soak&#39;</span>
<span class="nx">o</span> <span class="s2">&quot;Index&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Slice&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">SliceNode</span> <span class="nx">$1</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-27">#</a> </div> <p>Indexing into an object or array using bracket notation.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Index: </span><span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-31">#</a> </div> <p>Indexing into an object or array using bracket notation.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Index: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;INDEX_START Expression INDEX_END&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IndexNode</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;SOAKED_INDEX_START Expression SOAKED_INDEX_END&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IndexNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="s1">&#39;soak&#39;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-28">#</a> </div> <p>In CoffeeScript, an object literal is simply a list of assignments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nb">Object</span><span class="o">:</span> <span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-32">#</a> </div> <p>In CoffeeScript, an object literal is simply a list of assignments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nb">Object</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;{ AssignList }&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ObjectNode</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;{ IndentedAssignList }&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ObjectNode</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-29">#</a> </div> <p>Class definitions have optional bodies of prototype property assignments,
and optional references to the superclass.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Class: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;CLASS Value&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ClassNode</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;CLASS Value EXTENDS Value&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ClassNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s2">&quot;CLASS Value IndentedAssignList&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ClassNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;CLASS Value EXTENDS Value IndentedAssignList&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ClassNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$5</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-30">#</a> </div> <p>Assignment of properties within an object literal can be separated by
<span class="nx">o</span> <span class="s2">&quot;{ AssignList , }&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ObjectNode</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;{ IndentedAssignList , }&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ObjectNode</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-33">#</a> </div> <p>Assignment of properties within an object literal can be separated by
comma, as in JavaScript, or simply by newline.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">AssignList: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[]</span>
<span class="nx">o</span> <span class="s2">&quot;AssignObj&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;AssignList , AssignObj&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[</span><span class="nx">$3</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;AssignList TERMINATOR AssignObj&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[</span><span class="nx">$3</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;AssignList , TERMINATOR AssignObj&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[</span><span class="nx">$4</span><span class="p">]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-31">#</a> </div> <p>An <strong>AssignList</strong> within a block indentation.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">IndentedAssignList: </span><span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-34">#</a> </div> <p>An <strong>AssignList</strong> within a block indentation.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">IndentedAssignList: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;INDENT AssignList OUTDENT&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-32">#</a> </div> <p>The three flavors of function call: normal, object instantiation with <code>new</code>,
<span class="nx">o</span> <span class="s2">&quot;INDENT AssignList , OUTDENT&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-35">#</a> </div> <p>Class definitions have optional bodies of prototype property assignments,
and optional references to the superclass.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Class: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;CLASS SimpleAssignable&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ClassNode</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;CLASS SimpleAssignable EXTENDS Value&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ClassNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s2">&quot;CLASS SimpleAssignable INDENT ClassBody OUTDENT&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ClassNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s2">&quot;CLASS SimpleAssignable EXTENDS Value INDENT ClassBody OUTDENT&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ClassNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$6</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-36">#</a> </div> <p>Assignments that can happen directly inside a class declaration.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ClassAssign: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;AssignObj&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s2">&quot;ThisProperty ASSIGN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">AssignNode</span> <span class="k">new</span> <span class="nx">ValueNode</span><span class="p">(</span><span class="nx">$1</span><span class="p">),</span> <span class="nx">$3</span><span class="p">,</span> <span class="s1">&#39;this&#39;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-37"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-37">#</a> </div> <p>A list of assignments to a class.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ClassBody: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[]</span>
<span class="nx">o</span> <span class="s2">&quot;ClassAssign&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;ClassBody TERMINATOR ClassAssign&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$3</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-38">#</a> </div> <p>The three flavors of function call: normal, object instantiation with <code>new</code>,
and calling <code>super()</code></p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Call: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Invocation&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;NEW Invocation&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$2</span><span class="p">.</span><span class="nx">new_instance</span><span class="p">()</span>
<span class="nx">o</span> <span class="s2">&quot;Super&quot;</span>
<span class="p">]</span>
<span class="nv">Curry: </span><span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-39"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-39">#</a> </div> <p>Binds a function call to a context and/or arguments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Curry: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Value &lt;- Arguments&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">CurryNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-33">#</a> </div> <p>Extending an object by setting its prototype chain to reference a parent
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-40">#</a> </div> <p>Extending an object by setting its prototype chain to reference a parent
object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Extends: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Value EXTENDS Value&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ExtendsNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-34">#</a> </div> <p>Ordinary function invocation, or a chained series of calls.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Invocation: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;SimpleAssignable EXTENDS Value&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ExtendsNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-41">#</a> </div> <p>Ordinary function invocation, or a chained series of calls.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Invocation: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Value Arguments&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">CallNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;Invocation Arguments&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">CallNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-35">#</a> </div> <p>The list of arguments to a function call.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Arguments: </span><span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-42">#</a> </div> <p>The list of arguments to a function call.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Arguments: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;CALL_START ArgList CALL_END&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-36">#</a> </div> <p>Calling super.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Super: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;CALL_START ArgList , CALL_END&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-43">#</a> </div> <p>Calling super.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Super: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;SUPER CALL_START ArgList CALL_END&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">CallNode</span> <span class="s1">&#39;super&#39;</span><span class="p">,</span> <span class="nx">$3</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-37"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-37">#</a> </div> <p>A reference to the <em>this</em> current object, either naked or to a property.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">This: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;SUPER CALL_START ArgList , CALL_END&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">CallNode</span> <span class="s1">&#39;super&#39;</span><span class="p">,</span> <span class="nx">$3</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-44">#</a> </div> <p>A reference to the <em>this</em> current object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">This: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;THIS&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="s1">&#39;this&#39;</span>
<span class="nx">o</span> <span class="s2">&quot;@&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="s1">&#39;this&#39;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-45"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-45">#</a> </div> <p>A reference to a property on <em>this</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ThisProperty: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;@ Identifier&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="k">new</span> <span class="nx">LiteralNode</span><span class="p">(</span><span class="s1">&#39;this&#39;</span><span class="p">),</span> <span class="p">[</span><span class="k">new</span> <span class="nx">AccessorNode</span><span class="p">(</span><span class="nx">$2</span><span class="p">)]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-38">#</a> </div> <p>The CoffeeScript range literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Range: </span><span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-46"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-46">#</a> </div> <p>The CoffeeScript range literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Range: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;[ Expression . . Expression ]&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">RangeNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$5</span>
<span class="nx">o</span> <span class="s2">&quot;[ Expression . . . Expression ]&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">RangeNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$6</span><span class="p">,</span> <span class="kc">true</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-39"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-39">#</a> </div> <p>The slice literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Slice: </span><span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-47">#</a> </div> <p>The slice literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Slice: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;INDEX_START Expression . . Expression INDEX_END&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">RangeNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$5</span>
<span class="nx">o</span> <span class="s2">&quot;INDEX_START Expression . . . Expression INDEX_END&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">RangeNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$6</span><span class="p">,</span> <span class="kc">true</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-40">#</a> </div> <p>The array literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nb">Array</span><span class="o">:</span> <span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-48"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-48">#</a> </div> <p>The array literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nb">Array</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;[ ArgList ]&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ArrayNode</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-41">#</a> </div> <p>The <strong>ArgList</strong> is both the list of objects passed into a function call,
<span class="nx">o</span> <span class="s2">&quot;[ ArgList , ]&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ArrayNode</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-49">#</a> </div> <p>The <strong>ArgList</strong> is both the list of objects passed into a function call,
as well as the contents of an array literal
(i.e. comma-separated expressions). Newlines work as well.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ArgList: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[]</span>
@@ -206,80 +230,88 @@ as well as the contents of an array literal
<span class="nx">o</span> <span class="s2">&quot;ArgList , TERMINATOR Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[</span><span class="nx">$4</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;ArgList , INDENT Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[</span><span class="nx">$4</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;ArgList OUTDENT&quot;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-42">#</a> </div> <p>Just simple, comma-separated, required arguments (no fancy syntax). We need
<span class="nx">o</span> <span class="s2">&quot;ArgList , OUTDENT&quot;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-50"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-50">#</a> </div> <p>Just simple, comma-separated, required arguments (no fancy syntax). We need
this to be separate from the <strong>ArgList</strong> for use in <strong>Switch</strong> blocks, where
having the newlines wouldn't make sense.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">SimpleArgs: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Expression&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;SimpleArgs , Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">$1</span> <span class="k">instanceof</span> <span class="nb">Array</span> <span class="k">then</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span><span class="p">([</span><span class="nx">$3</span><span class="p">])</span> <span class="k">else</span> <span class="p">[</span><span class="nx">$1</span><span class="p">].</span><span class="nx">concat</span><span class="p">([</span><span class="nx">$3</span><span class="p">])</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-43">#</a> </div> <p>The variants of <em>try/catch/finally</em> exception handling blocks.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Try: </span><span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-51">#</a> </div> <p>The variants of <em>try/catch/finally</em> exception handling blocks.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Try: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;TRY Block Catch&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">TryNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;TRY Block FINALLY Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">TryNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s2">&quot;TRY Block Catch FINALLY Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">TryNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="nx">$5</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-44">#</a> </div> <p>A catch clause names its error and runs a block of code.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Catch: </span><span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-52">#</a> </div> <p>A catch clause names its error and runs a block of code.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Catch: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;CATCH Identifier Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-45"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-45">#</a> </div> <p>Throw an exception object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Throw: </span><span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-53"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-53">#</a> </div> <p>Throw an exception object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Throw: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;THROW Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ThrowNode</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-46"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-46">#</a> </div> <p>Parenthetical expressions. Note that the <strong>Parenthetical</strong> is a <strong>Value</strong>,
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-54">#</a> </div> <p>Parenthetical expressions. Note that the <strong>Parenthetical</strong> is a <strong>Value</strong>,
not an <strong>Expression</strong>, so if you need to use an expression in a place
where only values are accepted, wrapping it in parentheses will always do
the trick.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Parenthetical: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;( Expression )&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ParentheticalNode</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-47">#</a> </div> <p>A language extension to CoffeeScript from the outside. We simply pass
<span class="nx">o</span> <span class="s2">&quot;( Line )&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ParentheticalNode</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-55">#</a> </div> <p>A language extension to CoffeeScript from the outside. We simply pass
it through unaltered.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Extension: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;EXTENSION&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">yytext</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-48"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-48">#</a> </div> <p>The condition portion of a while loop.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">WhileSource: </span><span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-56">#</a> </div> <p>The condition portion of a while loop.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">WhileSource: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;WHILE Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">WhileNode</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;WHILE Expression WHEN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">WhileNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="p">{</span><span class="nx">filter</span> <span class="o">:</span> <span class="nx">$4</span><span class="p">}</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-49">#</a> </div> <p>The while loop can either be normal, with a block of expressions to execute,
<span class="nx">o</span> <span class="s2">&quot;WHILE Expression WHEN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">WhileNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="p">{</span><span class="nv">filter : </span><span class="nx">$4</span><span class="p">}</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-57"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-57">#</a> </div> <p>The while loop can either be normal, with a block of expressions to execute,
or postfix, with a single expression. There is no do..while.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">While: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;WhileSource Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">add_body</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;Statement WhileSource&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$2</span><span class="p">.</span><span class="nx">add_body</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;Expression WhileSource&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$2</span><span class="p">.</span><span class="nx">add_body</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-50"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-50">#</a> </div> <p>Array, object, and range comprehensions, at the most generic level.
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-58"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-58">#</a> </div> <p>Array, object, and range comprehensions, at the most generic level.
Comprehensions can either be normal, with a block of expressions to execute,
or postfix, with a single expression.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">For: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Statement FOR ForVariables ForSource&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ForNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;Expression FOR ForVariables ForSource&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ForNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;FOR ForVariables ForSource Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ForNode</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-51">#</a> </div> <p>An array or range comprehension has variables for the current element and
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-59"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-59">#</a> </div> <p>An array or range comprehension has variables for the current element and
(optional) reference to the current index. Or, <em>key, value</em>, in the case
of object comprehensions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ForVariables: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Identifier&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;Identifier , Identifier&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-52">#</a> </div> <p>The source of a comprehension is an array or object with an optional filter
clause. If it's an array comprehension, you can also choose to step throug
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-60"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-60">#</a> </div> <p>The source of a comprehension is an array or object with an optional filter
clause. If it's an array comprehension, you can also choose to step through
in fixed-size increments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ForSource: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;IN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">{</span><span class="nv">source: </span> <span class="nx">$2</span><span class="p">}</span>
<span class="nx">o</span> <span class="s2">&quot;OF Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">{</span><span class="nv">source: </span> <span class="nx">$2</span><span class="p">,</span> <span class="nv">object: </span><span class="kc">true</span><span class="p">}</span>
<span class="nx">o</span> <span class="s2">&quot;ForSource WHEN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nv">$1.filter: </span><span class="nx">$3</span><span class="p">;</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s2">&quot;ForSource BY Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nv">$1.step: </span> <span class="nx">$3</span><span class="p">;</span> <span class="nx">$1</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-53"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-53">#</a> </div> <p>The CoffeeScript switch/when/else block replaces the JavaScript
<span class="nx">o</span> <span class="s2">&quot;IN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">}</span>
<span class="nx">o</span> <span class="s2">&quot;OF Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">object: </span><span class="kc">true</span><span class="p">}</span>
<span class="nx">o</span> <span class="s2">&quot;IN Expression WHEN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">filter: </span><span class="nx">$4</span><span class="p">}</span>
<span class="nx">o</span> <span class="s2">&quot;OF Expression WHEN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">filter: </span><span class="nx">$4</span><span class="p">,</span> <span class="nv">object: </span><span class="kc">true</span><span class="p">}</span>
<span class="nx">o</span> <span class="s2">&quot;IN Expression BY Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">step: </span> <span class="nx">$4</span><span class="p">}</span>
<span class="nx">o</span> <span class="s2">&quot;IN Expression WHEN Expression BY Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">filter: </span><span class="nx">$4</span><span class="p">;</span> <span class="nv">step: </span> <span class="nx">$6</span><span class="p">}</span>
<span class="nx">o</span> <span class="s2">&quot;IN Expression BY Expression WHEN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">step: </span> <span class="nx">$4</span><span class="p">,</span> <span class="nv">filter: </span><span class="nx">$6</span><span class="p">}</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-61"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-61">#</a> </div> <p>The CoffeeScript switch/when/else block replaces the JavaScript
switch/case/default by compiling into an if-else chain.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Switch: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;SWITCH Expression INDENT Whens OUTDENT&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$4</span><span class="p">.</span><span class="nx">rewrite_condition</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;SWITCH Expression INDENT Whens ELSE Block OUTDENT&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$4</span><span class="p">.</span><span class="nx">rewrite_condition</span><span class="p">(</span><span class="nx">$2</span><span class="p">).</span><span class="nx">add_else</span> <span class="nx">$6</span><span class="p">,</span> <span class="kc">true</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-54">#</a> </div> <p>The inner list of whens is left recursive. At code-generation time, the
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-62"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-62">#</a> </div> <p>The inner list of whens is left recursive. At code-generation time, the
IfNode will rewrite them into a proper chain.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Whens: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;When&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Whens When&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">push</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-55">#</a> </div> <p>An individual <strong>When</strong> clause, with action.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">When: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;LEADING_WHEN SimpleArgs Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="p">{</span><span class="nv">statement: </span><span class="kc">true</span><span class="p">}</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-63"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-63">#</a> </div> <p>An individual <strong>When</strong> clause, with action.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">When: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;LEADING_WHEN SimpleArgs Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="p">{</span><span class="nv">statement: </span><span class="kc">true</span><span class="p">}</span>
<span class="nx">o</span> <span class="s2">&quot;LEADING_WHEN SimpleArgs Block TERMINATOR&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="p">{</span><span class="nv">statement: </span><span class="kc">true</span><span class="p">}</span>
<span class="nx">o</span> <span class="s2">&quot;Comment TERMINATOR When&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nv">$3.comment: </span><span class="nx">$1</span><span class="p">;</span> <span class="nx">$3</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-56">#</a> </div> <p>The most basic form of <em>if</em> is a condition and an action. The following
<span class="nx">o</span> <span class="s2">&quot;Comment TERMINATOR When&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nv">$3.comment: </span><span class="nx">$1</span><span class="p">;</span> <span class="nx">$3</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-64">#</a> </div> <p>The most basic form of <em>if</em> is a condition and an action. The following
if-related rules are broken up along these lines in order to avoid
ambiguity.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">IfStart: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;IF Expression Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;IfStart ElsIf&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">add_else</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-57"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-57">#</a> </div> <p>An <strong>IfStart</strong> can optionally be followed by an else block.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">IfBlock: </span><span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-65"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-65">#</a> </div> <p>An <strong>IfStart</strong> can optionally be followed by an else block.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">IfBlock: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;IfStart&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;IfStart ELSE Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">add_else</span> <span class="nx">$3</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-58"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-58">#</a> </div> <p>An <em>else if</em> continuation of the <em>if</em> expression.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ElsIf: </span><span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-66"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-66">#</a> </div> <p>An <em>else if</em> continuation of the <em>if</em> expression.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ElsIf: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;ELSE IF Expression Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="k">new</span> <span class="nx">IfNode</span><span class="p">(</span><span class="nx">$3</span><span class="p">,</span> <span class="nx">$4</span><span class="p">)).</span><span class="nx">force_statement</span><span class="p">()</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-59"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-59">#</a> </div> <p>The full complement of <em>if</em> expressions, including postfix one-liner
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-67"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-67">#</a> </div> <p>The full complement of <em>if</em> expressions, including postfix one-liner
<em>if</em> and <em>unless</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">If: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;IfBlock&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Statement IF Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="nx">$1</span><span class="p">]),</span> <span class="kc">null</span><span class="p">,</span> <span class="p">{</span><span class="nv">statement: </span><span class="kc">true</span><span class="p">}</span>
<span class="nx">o</span> <span class="s2">&quot;Expression IF Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="nx">$1</span><span class="p">]),</span> <span class="kc">null</span><span class="p">,</span> <span class="p">{</span><span class="nv">statement: </span><span class="kc">true</span><span class="p">}</span>
<span class="nx">o</span> <span class="s2">&quot;Statement UNLESS Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="nx">$1</span><span class="p">]),</span> <span class="kc">null</span><span class="p">,</span> <span class="p">{</span><span class="nv">statement: </span><span class="kc">true</span><span class="p">,</span> <span class="nv">invert: </span><span class="kc">true</span><span class="p">}</span>
<span class="nx">o</span> <span class="s2">&quot;Expression UNLESS Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="nx">$1</span><span class="p">]),</span> <span class="kc">null</span><span class="p">,</span> <span class="p">{</span><span class="nv">statement: </span><span class="kc">true</span><span class="p">,</span> <span class="nv">invert: </span><span class="kc">true</span><span class="p">}</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-60"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-60">#</a> </div> <p>Arithmetic and logical operators, working on one or more operands.
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-68"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-68">#</a> </div> <p>Arithmetic and logical operators, working on one or more operands.
Here they are grouped by order of precedence. The actual precedence rules
are defined at the bottom of the page. It would be shorter if we could
combine most of these rules into a single generic <em>Operand OpSymbol Operand</em>
@@ -336,7 +368,7 @@ rules are necessary.</p> </td> <td class="code">
<span class="nx">o</span> <span class="s2">&quot;Expression IN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;in&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="p">]</span>
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-61"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-61">#</a> </div> <h2>Precedence</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-62"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-62">#</a> </div> <p>Operators at the top of this list have higher precedence than the ones lower
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-69"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-69">#</a> </div> <h2>Precedence</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-70"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-70">#</a> </div> <p>Operators at the top of this list have higher precedence than the ones lower
down. Following these rules is what makes <code>2 + 3 * 4</code> parse as:</p>
<pre><code>2 + (3 * 4)
@@ -351,37 +383,12 @@ down. Following these rules is what makes <code>2 + 3 * 4</code> parse as:</p>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;*&#39;</span><span class="p">,</span> <span class="s1">&#39;/&#39;</span><span class="p">,</span> <span class="s1">&#39;%&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;+&#39;</span><span class="p">,</span> <span class="s1">&#39;-&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;&lt;&lt;&#39;</span><span class="p">,</span> <span class="s1">&#39;&gt;&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;&gt;&gt;&gt;&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;&amp;&#39;</span><span class="p">,</span> <span class="s1">&#39;|&#39;</span><span class="p">,</span> <span class="s1">&#39;^&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;&lt;=&#39;</span><span class="p">,</span> <span class="s1">&#39;&lt;&#39;</span><span class="p">,</span> <span class="s1">&#39;&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;&gt;=&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;right&quot;</span><span class="p">,</span> <span class="s1">&#39;DELETE&#39;</span><span class="p">,</span> <span class="s1">&#39;INSTANCEOF&#39;</span><span class="p">,</span> <span class="s1">&#39;TYPEOF&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;==&#39;</span><span class="p">,</span> <span class="s1">&#39;!=&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;&amp;&amp;&#39;</span><span class="p">,</span> <span class="s1">&#39;||&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;right&quot;</span><span class="p">,</span> <span class="s1">&#39;-=&#39;</span><span class="p">,</span> <span class="s1">&#39;+=&#39;</span><span class="p">,</span> <span class="s1">&#39;/=&#39;</span><span class="p">,</span> <span class="s1">&#39;*=&#39;</span><span class="p">,</span> <span class="s1">&#39;%=&#39;</span><span class="p">,</span> <span class="s1">&#39;||=&#39;</span><span class="p">,</span> <span class="s1">&#39;&amp;&amp;=&#39;</span><span class="p">,</span> <span class="s1">&#39;?=&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;.&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;right&quot;</span><span class="p">,</span> <span class="s1">&#39;INDENT&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;OUTDENT&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;right&quot;</span><span class="p">,</span> <span class="s1">&#39;WHEN&#39;</span><span class="p">,</span> <span class="s1">&#39;LEADING_WHEN&#39;</span><span class="p">,</span> <span class="s1">&#39;IN&#39;</span><span class="p">,</span> <span class="s1">&#39;OF&#39;</span><span class="p">,</span> <span class="s1">&#39;BY&#39;</span><span class="p">,</span> <span class="s1">&#39;THROW&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;right&quot;</span><span class="p">,</span> <span class="s1">&#39;FOR&#39;</span><span class="p">,</span> <span class="s1">&#39;NEW&#39;</span><span class="p">,</span> <span class="s1">&#39;SUPER&#39;</span><span class="p">,</span> <span class="s1">&#39;CLASS&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;EXTENDS&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;right&quot;</span><span class="p">,</span> <span class="s1">&#39;ASSIGN&#39;</span><span class="p">,</span> <span class="s1">&#39;RETURN&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;right&quot;</span><span class="p">,</span> <span class="s1">&#39;-&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;=&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;&lt;-&#39;</span><span class="p">,</span> <span class="s1">&#39;UNLESS&#39;</span><span class="p">,</span> <span class="s1">&#39;IF&#39;</span><span class="p">,</span> <span class="s1">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s1">&#39;WHILE&#39;</span><span class="p">]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-63"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-63">#</a> </div> <h2>Wrapping Up</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-64">#</a> </div> <p>Finally, now what we have our <strong>grammar</strong> and our <strong>operators</strong>, we can create
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;&amp;&#39;</span><span class="p">,</span> <span class="s1">&#39;|&#39;</span><span class="p">,</span> <span class="s1">&#39;^&#39;</span>
</pre></div> </td> </tr> <tr id="section-71"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-71">#</a> </div> <h2>Wrapping Up</h2> </td> <td class="code"> <div class="highlight"><pre>undefined</pre></div> </td> </tr> <tr id="section-72"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-72">#</a> </div> <p>Finally, now what we have our <strong>grammar</strong> and our <strong>operators</strong>, we can create
our <strong>Jison.Parser</strong>. We do this by processing all of our rules, recording all
terminals (every symbol which does not appear as the name of a rule above)
as "tokens".</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">tokens: </span><span class="p">[]</span>
<span class="k">for</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">alternatives</span> <span class="k">of</span> <span class="nx">grammar</span>
<span class="nx">grammar</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span><span class="o">:</span> <span class="k">for</span> <span class="nx">alt</span> <span class="k">in</span> <span class="nx">alternatives</span>
<span class="k">for</span> <span class="nx">token</span> <span class="k">in</span> <span class="nx">alt</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">split</span> <span class="s1">&#39; &#39;</span>
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="nx">token</span> <span class="nx">unless</span> <span class="nx">grammar</span><span class="p">[</span><span class="nx">token</span><span class="p">]</span>
<span class="nx">alt</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&quot;return ${alt[1]}&quot;</span> <span class="k">if</span> <span class="nx">name</span> <span class="o">is</span> <span class="s1">&#39;Root&#39;</span>
<span class="nx">alt</span></pre></div> </td> </tr> <tr id="section-65"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-65">#</a> </div> <p>Initialize the <strong>Parser</strong> with our list of terminal <strong>tokens</strong>, our <strong>grammar</strong>
as "tokens".</p> </td> <td class="code"> <div class="highlight"><pre>undefined</pre></div> </td> </tr> <tr id="section-73"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-73">#</a> </div> <p>Initialize the <strong>Parser</strong> with our list of terminal <strong>tokens</strong>, our <strong>grammar</strong>
rules, and the name of the root. Reverse the operators because Jison orders
precedence from low to high, and we have it high to low
(as in <a href="http://dinosaur.compilertools.net/yacc/index.html">Yacc</a>).</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.parser: </span><span class="k">new</span> <span class="nx">Parser</span> <span class="p">{</span>
<span class="nv">tokens: </span> <span class="nx">tokens</span><span class="p">.</span><span class="nx">join</span> <span class="s1">&#39; &#39;</span>
<span class="nv">bnf: </span> <span class="nx">grammar</span>
<span class="nv">operators: </span> <span class="nx">operators</span><span class="p">.</span><span class="nx">reverse</span><span class="p">()</span>
<span class="nv">startSymbol: </span> <span class="s1">&#39;Root&#39;</span>
<span class="p">}</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
(as in <a href="http://dinosaur.compilertools.net/yacc/index.html">Yacc</a>).</p> </td> <td class="code"> <div class="highlight"><pre>undefined</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

View File

@@ -30,33 +30,33 @@ of source.</p>
<p>Before returning the token stream, run it through the <a href="rewriter.html">Rewriter</a>
unless explicitly asked not to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tokenize: </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">-&gt;</span>
<span class="nx">code</span> <span class="o">:</span> <span class="nx">code</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/(\r|\s+$)/g</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span>
<span class="nx">o</span> <span class="o">:</span> <span class="nx">options</span> <span class="o">or</span> <span class="p">{}</span>
<span class="err">@</span><span class="nx">code</span> <span class="o">:</span> <span class="nx">code</span> <span class="c1"># The remainder of the source code.</span>
<span class="err">@</span><span class="nx">i</span> <span class="o">:</span> <span class="mi">0</span> <span class="c1"># Current character position we&#39;re parsing.</span>
<span class="err">@</span><span class="nx">line</span> <span class="o">:</span> <span class="nx">o</span><span class="p">.</span><span class="nx">line</span> <span class="o">or</span> <span class="mi">0</span> <span class="c1"># The current line.</span>
<span class="err">@</span><span class="nx">indent</span> <span class="o">:</span> <span class="mi">0</span> <span class="c1"># The current indentation level.</span>
<span class="err">@</span><span class="nx">indents</span> <span class="o">:</span> <span class="p">[]</span> <span class="c1"># The stack of all current indentation levels.</span>
<span class="err">@</span><span class="nx">tokens</span> <span class="o">:</span> <span class="p">[]</span> <span class="c1"># Stream of parsed tokens in the form [&#39;TYPE&#39;, value, line]</span>
<span class="k">while</span> <span class="err">@</span><span class="nx">i</span> <span class="o">&lt;</span> <span class="err">@</span><span class="nx">code</span><span class="p">.</span><span class="nx">length</span>
<span class="err">@</span><span class="nv">chunk: </span><span class="err">@</span><span class="nx">code</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="err">@</span><span class="nx">i</span><span class="p">)</span>
<span class="err">@</span><span class="nx">extract_next_token</span><span class="p">()</span>
<span class="err">@</span><span class="nx">close_indentation</span><span class="p">()</span>
<span class="k">return</span> <span class="err">@</span><span class="nx">tokens</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">rewrite</span> <span class="o">is</span> <span class="kc">off</span>
<span class="p">(</span><span class="k">new</span> <span class="nx">Rewriter</span><span class="p">()).</span><span class="nx">rewrite</span> <span class="err">@</span><span class="nx">tokens</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>At every position, run through this list of attempted matches,
<span class="nv">code : </span><span class="nx">code</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/(\r|\s+$)/g</span><span class="p">,</span> <span class="s1">&#39;&#39;</span>
<span class="nv">o : </span><span class="nx">options</span> <span class="o">or</span> <span class="p">{}</span>
<span class="vi">@code : </span><span class="nx">code</span> <span class="c1"># The remainder of the source code.</span>
<span class="vi">@i : </span><span class="mi">0</span> <span class="c1"># Current character position we&#39;re parsing.</span>
<span class="vi">@line : </span><span class="nx">o</span><span class="p">.</span><span class="nx">line</span> <span class="o">or</span> <span class="mi">0</span> <span class="c1"># The current line.</span>
<span class="vi">@indent : </span><span class="mi">0</span> <span class="c1"># The current indentation level.</span>
<span class="vi">@indents : </span><span class="p">[]</span> <span class="c1"># The stack of all current indentation levels.</span>
<span class="vi">@tokens : </span><span class="p">[]</span> <span class="c1"># Stream of parsed tokens in the form [&#39;TYPE&#39;, value, line]</span>
<span class="k">while</span> <span class="nx">@i</span> <span class="o">&lt;</span> <span class="nx">@code</span><span class="p">.</span><span class="nx">length</span>
<span class="vi">@chunk: </span><span class="nx">@code</span><span class="p">.</span><span class="nx">slice</span> <span class="nx">@i</span>
<span class="nx">@extract_next_token</span><span class="p">()</span>
<span class="nx">@close_indentation</span><span class="p">()</span>
<span class="k">return</span> <span class="nx">@tokens</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">rewrite</span> <span class="o">is</span> <span class="kc">off</span>
<span class="p">(</span><span class="k">new</span> <span class="nx">Rewriter</span><span class="p">()).</span><span class="nx">rewrite</span> <span class="nx">@tokens</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>At every position, run through this list of attempted matches,
short-circuiting if any of them succeed. Their order determines precedence:
<code>@literal_token</code> is the fallback catch-all.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">extract_next_token: </span><span class="o">-&gt;</span>
<span class="k">return</span> <span class="k">if</span> <span class="err">@</span><span class="nx">extension_token</span><span class="p">()</span>
<span class="k">return</span> <span class="k">if</span> <span class="err">@</span><span class="nx">identifier_token</span><span class="p">()</span>
<span class="k">return</span> <span class="k">if</span> <span class="err">@</span><span class="nx">number_token</span><span class="p">()</span>
<span class="k">return</span> <span class="k">if</span> <span class="err">@</span><span class="nx">heredoc_token</span><span class="p">()</span>
<span class="k">return</span> <span class="k">if</span> <span class="err">@</span><span class="nx">regex_token</span><span class="p">()</span>
<span class="k">return</span> <span class="k">if</span> <span class="err">@</span><span class="nx">comment_token</span><span class="p">()</span>
<span class="k">return</span> <span class="k">if</span> <span class="err">@</span><span class="nx">line_token</span><span class="p">()</span>
<span class="k">return</span> <span class="k">if</span> <span class="err">@</span><span class="nx">whitespace_token</span><span class="p">()</span>
<span class="k">return</span> <span class="k">if</span> <span class="err">@</span><span class="nx">js_token</span><span class="p">()</span>
<span class="k">return</span> <span class="k">if</span> <span class="err">@</span><span class="nx">string_token</span><span class="p">()</span>
<span class="k">return</span> <span class="err">@</span><span class="nx">literal_token</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <h2>Tokenizers</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Language extensions get the highest priority, first chance to tag tokens
<span class="k">return</span> <span class="k">if</span> <span class="nx">@extension_token</span><span class="p">()</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">@identifier_token</span><span class="p">()</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">@number_token</span><span class="p">()</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">@heredoc_token</span><span class="p">()</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">@regex_token</span><span class="p">()</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">@comment_token</span><span class="p">()</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">@line_token</span><span class="p">()</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">@whitespace_token</span><span class="p">()</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">@js_token</span><span class="p">()</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">@string_token</span><span class="p">()</span>
<span class="k">return</span> <span class="nx">@literal_token</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <h2>Tokenizers</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Language extensions get the highest priority, first chance to tag tokens
as something else.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">extension_token: </span><span class="o">-&gt;</span>
<span class="k">for</span> <span class="nx">extension</span> <span class="k">in</span> <span class="nx">Lexer</span><span class="p">.</span><span class="nx">extensions</span>
<span class="k">return</span> <span class="kc">true</span> <span class="k">if</span> <span class="nx">extension</span><span class="p">.</span><span class="nx">call</span> <span class="k">this</span>
@@ -66,73 +66,73 @@ identifiers. Because CoffeeScript reserves a handful of keywords that are
allowed in JavaScript, we're careful not to tag them as keywords when
referenced as property names here, so you can still do <code>jQuery.is()</code> even
though <code>is</code> means <code>===</code> otherwise.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">identifier_token: </span><span class="o">-&gt;</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">id: </span><span class="err">@</span><span class="nx">match</span> <span class="nx">IDENTIFIER</span><span class="p">,</span> <span class="mi">1</span>
<span class="err">@</span><span class="nx">name_access_type</span><span class="p">()</span>
<span class="nv">accessed: </span><span class="nx">include</span> <span class="nx">ACCESSORS</span><span class="p">,</span> <span class="err">@</span><span class="nx">tag</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">id: </span><span class="nx">@match</span> <span class="nx">IDENTIFIER</span><span class="p">,</span> <span class="mi">1</span>
<span class="nx">@name_access_type</span><span class="p">()</span>
<span class="nv">accessed: </span><span class="nx">include</span> <span class="nx">ACCESSORS</span><span class="p">,</span> <span class="nx">@tag</span> <span class="mi">0</span>
<span class="nv">tag: </span><span class="s1">&#39;IDENTIFIER&#39;</span>
<span class="nv">tag: </span><span class="nx">id</span><span class="p">.</span><span class="nx">toUpperCase</span><span class="p">()</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">accessed</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">KEYWORDS</span><span class="p">,</span> <span class="nx">id</span><span class="p">)</span>
<span class="err">@</span><span class="nx">identifier_error</span> <span class="nx">id</span> <span class="k">if</span> <span class="nx">include</span> <span class="nx">RESERVED</span><span class="p">,</span> <span class="nx">id</span>
<span class="nv">tag: </span><span class="s1">&#39;LEADING_WHEN&#39;</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;WHEN&#39;</span> <span class="o">and</span> <span class="nx">include</span> <span class="nx">LINE_BREAK</span><span class="p">,</span> <span class="err">@</span><span class="nx">tag</span><span class="p">()</span>
<span class="err">@</span><span class="nv">i: </span><span class="o">+</span> <span class="nx">id</span><span class="p">.</span><span class="nx">length</span>
<span class="nx">@identifier_error</span> <span class="nx">id</span> <span class="k">if</span> <span class="nx">include</span> <span class="nx">RESERVED</span><span class="p">,</span> <span class="nx">id</span>
<span class="nv">tag: </span><span class="s1">&#39;LEADING_WHEN&#39;</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;WHEN&#39;</span> <span class="o">and</span> <span class="nx">include</span> <span class="nx">LINE_BREAK</span><span class="p">,</span> <span class="nx">@tag</span><span class="p">()</span>
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">id</span><span class="p">.</span><span class="nx">length</span>
<span class="k">if</span> <span class="o">not</span> <span class="nx">accessed</span>
<span class="nv">tag: id: </span><span class="nx">CONVERSIONS</span><span class="p">[</span><span class="nx">id</span><span class="p">]</span> <span class="k">if</span> <span class="nx">include</span> <span class="nx">COFFEE_ALIASES</span><span class="p">,</span> <span class="nx">id</span>
<span class="k">return</span> <span class="err">@</span><span class="nx">tag_half_assignment</span><span class="p">(</span><span class="nx">tag</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">prev</span><span class="p">()</span> <span class="o">and</span> <span class="err">@</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="s1">&#39;ASSIGN&#39;</span> <span class="o">and</span> <span class="nx">include</span> <span class="nx">HALF_ASSIGNMENTS</span><span class="p">,</span> <span class="nx">tag</span>
<span class="err">@</span><span class="nx">token</span><span class="p">(</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">id</span><span class="p">)</span>
<span class="k">return</span> <span class="nx">@tag_half_assignment</span> <span class="nx">tag</span> <span class="k">if</span> <span class="nx">@prev</span><span class="p">()</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="s1">&#39;ASSIGN&#39;</span> <span class="o">and</span> <span class="nx">include</span> <span class="nx">HALF_ASSIGNMENTS</span><span class="p">,</span> <span class="nx">tag</span>
<span class="nx">@token</span> <span class="nx">tag</span><span class="p">,</span> <span class="nx">id</span>
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Matches numbers, including decimals, hex, and exponential notation.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">number_token: </span><span class="o">-&gt;</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">number: </span><span class="err">@</span><span class="nx">match</span> <span class="nx">NUMBER</span><span class="p">,</span> <span class="mi">1</span>
<span class="err">@</span><span class="nx">token</span> <span class="s1">&#39;NUMBER&#39;</span><span class="p">,</span> <span class="nx">number</span>
<span class="err">@</span><span class="nv">i: </span><span class="o">+</span> <span class="nx">number</span><span class="p">.</span><span class="nx">length</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">number: </span><span class="nx">@match</span> <span class="nx">NUMBER</span><span class="p">,</span> <span class="mi">1</span>
<span class="nx">@token</span> <span class="s1">&#39;NUMBER&#39;</span><span class="p">,</span> <span class="nx">number</span>
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">number</span><span class="p">.</span><span class="nx">length</span>
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>Matches strings, including multi-line strings. Ensures that quotation marks
are balanced within the string's contents, and within nested interpolations.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">string_token: </span><span class="o">-&gt;</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nx">starts</span><span class="p">(</span><span class="err">@</span><span class="nx">chunk</span><span class="p">,</span> <span class="s1">&#39;&quot;&#39;</span><span class="p">)</span> <span class="o">or</span> <span class="nx">starts</span><span class="p">(</span><span class="err">@</span><span class="nx">chunk</span><span class="p">,</span> <span class="s2">&quot;&#39;&quot;</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nx">starts</span><span class="p">(</span><span class="nx">@chunk</span><span class="p">,</span> <span class="s1">&#39;&quot;&#39;</span><span class="p">)</span> <span class="o">or</span> <span class="nx">starts</span><span class="p">(</span><span class="nx">@chunk</span><span class="p">,</span> <span class="s2">&quot;&#39;&quot;</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">string:</span>
<span class="err">@</span><span class="nx">balanced_token</span><span class="p">([</span><span class="s1">&#39;&quot;&#39;</span><span class="p">,</span> <span class="s1">&#39;&quot;&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;${&#39;</span><span class="p">,</span> <span class="s1">&#39;}&#39;</span><span class="p">])</span> <span class="o">or</span>
<span class="err">@</span><span class="nx">balanced_token</span> <span class="p">[</span><span class="s2">&quot;&#39;&quot;</span><span class="p">,</span> <span class="s2">&quot;&#39;&quot;</span><span class="p">]</span>
<span class="err">@</span><span class="nx">interpolate_string</span> <span class="nx">string</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="nx">STRING_NEWLINES</span><span class="p">,</span> <span class="s2">&quot; \\\n&quot;</span><span class="p">)</span>
<span class="err">@</span><span class="nv">line: </span><span class="o">+</span> <span class="nx">count</span> <span class="nx">string</span><span class="p">,</span> <span class="s2">&quot;\n&quot;</span>
<span class="err">@</span><span class="nv">i: </span><span class="o">+</span> <span class="nx">string</span><span class="p">.</span><span class="nx">length</span>
<span class="nx">@balanced_token</span><span class="p">([</span><span class="s1">&#39;&quot;&#39;</span><span class="p">,</span> <span class="s1">&#39;&quot;&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;${&#39;</span><span class="p">,</span> <span class="s1">&#39;}&#39;</span><span class="p">])</span> <span class="o">or</span>
<span class="nx">@balanced_token</span> <span class="p">[</span><span class="s2">&quot;&#39;&quot;</span><span class="p">,</span> <span class="s2">&quot;&#39;&quot;</span><span class="p">]</span>
<span class="nx">@interpolate_string</span> <span class="nx">string</span><span class="p">.</span><span class="nx">replace</span> <span class="nx">STRING_NEWLINES</span><span class="p">,</span> <span class="s2">&quot; \\\n&quot;</span>
<span class="vi">@line: </span><span class="o">+</span> <span class="nx">count</span> <span class="nx">string</span><span class="p">,</span> <span class="s2">&quot;\n&quot;</span>
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">string</span><span class="p">.</span><span class="nx">length</span>
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>Matches heredocs, adjusting indentation to the correct level, as heredocs
preserve whitespace, but ignore indentation to the left.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">heredoc_token: </span><span class="o">-&gt;</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">match: </span><span class="err">@</span><span class="nx">chunk</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">HEREDOC</span><span class="p">)</span>
<span class="nv">quote: </span><span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">substr</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="nv">doc: </span><span class="err">@</span><span class="nx">sanitize_heredoc</span> <span class="nx">match</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">or</span> <span class="nx">match</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="nx">quote</span>
<span class="err">@</span><span class="nx">interpolate_string</span> <span class="s2">&quot;$quote$doc$quote&quot;</span>
<span class="err">@</span><span class="nv">line: </span><span class="o">+</span> <span class="nx">count</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="s2">&quot;\n&quot;</span>
<span class="err">@</span><span class="nv">i: </span><span class="o">+</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">length</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">match: </span><span class="nx">@chunk</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">HEREDOC</span><span class="p">)</span>
<span class="nv">quote: </span><span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">substr</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span>
<span class="nv">doc: </span><span class="nx">@sanitize_heredoc</span> <span class="nx">match</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">or</span> <span class="nx">match</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="nx">quote</span>
<span class="nx">@interpolate_string</span> <span class="s2">&quot;$quote$doc$quote&quot;</span>
<span class="vi">@line: </span><span class="o">+</span> <span class="nx">count</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="s2">&quot;\n&quot;</span>
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">length</span>
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</a> </div> <p>Matches JavaScript interpolated directly into the source via backticks.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">js_token: </span><span class="o">-&gt;</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nx">starts</span> <span class="err">@</span><span class="nx">chunk</span><span class="p">,</span> <span class="s1">&#39;`&#39;</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">script: </span><span class="err">@</span><span class="nx">balanced_token</span> <span class="p">[</span><span class="s1">&#39;`&#39;</span><span class="p">,</span> <span class="s1">&#39;`&#39;</span><span class="p">]</span>
<span class="err">@</span><span class="nx">token</span> <span class="s1">&#39;JS&#39;</span><span class="p">,</span> <span class="nx">script</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="nx">JS_CLEANER</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span>
<span class="err">@</span><span class="nv">i: </span><span class="o">+</span> <span class="nx">script</span><span class="p">.</span><span class="nx">length</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nx">starts</span> <span class="nx">@chunk</span><span class="p">,</span> <span class="s1">&#39;`&#39;</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">script: </span><span class="nx">@balanced_token</span> <span class="p">[</span><span class="s1">&#39;`&#39;</span><span class="p">,</span> <span class="s1">&#39;`&#39;</span><span class="p">]</span>
<span class="nx">@token</span> <span class="s1">&#39;JS&#39;</span><span class="p">,</span> <span class="nx">script</span><span class="p">.</span><span class="nx">replace</span> <span class="nx">JS_CLEANER</span><span class="p">,</span> <span class="s1">&#39;&#39;</span>
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">script</span><span class="p">.</span><span class="nx">length</span>
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>Matches regular expression literals. Lexing regular expressions is difficult
to distinguish from division, so we borrow some basic heuristics from
JavaScript and Ruby, borrow slash balancing from <code>@balanced_token</code>, and
borrow interpolation from <code>@interpolate_string</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">regex_token: </span><span class="o">-&gt;</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="err">@</span><span class="nx">chunk</span><span class="p">.</span><span class="nx">match</span> <span class="nx">REGEX_START</span>
<span class="k">return</span> <span class="kc">false</span> <span class="k">if</span> <span class="nx">include</span> <span class="nx">NOT_REGEX</span><span class="p">,</span> <span class="err">@</span><span class="nx">tag</span><span class="p">()</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">regex: </span><span class="err">@</span><span class="nx">balanced_token</span> <span class="p">[</span><span class="s1">&#39;/&#39;</span><span class="p">,</span> <span class="s1">&#39;/&#39;</span><span class="p">]</span>
<span class="nv">regex: </span><span class="o">+</span> <span class="p">(</span><span class="nv">flags: </span><span class="err">@</span><span class="nx">chunk</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="nx">regex</span><span class="p">.</span><span class="nx">length</span><span class="p">).</span><span class="nx">match</span><span class="p">(</span><span class="nx">REGEX_FLAGS</span><span class="p">))</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nx">@chunk</span><span class="p">.</span><span class="nx">match</span> <span class="nx">REGEX_START</span>
<span class="k">return</span> <span class="kc">false</span> <span class="k">if</span> <span class="nx">include</span> <span class="nx">NOT_REGEX</span><span class="p">,</span> <span class="nx">@tag</span><span class="p">()</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">regex: </span><span class="nx">@balanced_token</span> <span class="p">[</span><span class="s1">&#39;/&#39;</span><span class="p">,</span> <span class="s1">&#39;/&#39;</span><span class="p">]</span>
<span class="nv">regex: </span><span class="o">+</span> <span class="p">(</span><span class="nv">flags: </span><span class="nx">@chunk</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="nx">regex</span><span class="p">.</span><span class="nx">length</span><span class="p">).</span><span class="nx">match</span> <span class="nx">REGEX_FLAGS</span><span class="p">)</span>
<span class="k">if</span> <span class="nx">regex</span><span class="p">.</span><span class="nx">match</span> <span class="nx">REGEX_INTERPOLATION</span>
<span class="nv">str: </span><span class="nx">regex</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">1</span><span class="p">).</span><span class="nx">split</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="nv">str: </span><span class="nx">str</span><span class="p">.</span><span class="nx">replace</span> <span class="nx">REGEX_ESCAPE</span><span class="p">,</span> <span class="p">(</span><span class="nx">escaped</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="s1">&#39;\\&#39;</span> <span class="o">+</span> <span class="nx">escaped</span>
<span class="err">@</span><span class="nv">tokens: </span><span class="err">@</span><span class="nx">tokens</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[[</span><span class="s1">&#39;(&#39;</span><span class="p">,</span> <span class="s1">&#39;(&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;NEW&#39;</span><span class="p">,</span> <span class="s1">&#39;new&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;IDENTIFIER&#39;</span><span class="p">,</span> <span class="s1">&#39;RegExp&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;CALL_START&#39;</span><span class="p">,</span> <span class="s1">&#39;(&#39;</span><span class="p">]]</span>
<span class="err">@</span><span class="nx">interpolate_string</span> <span class="s2">&quot;\&quot;$str\&quot;&quot;</span><span class="p">,</span> <span class="kc">yes</span>
<span class="err">@</span><span class="nv">tokens: </span><span class="err">@</span><span class="nx">tokens</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[[</span><span class="s1">&#39;,&#39;</span><span class="p">,</span> <span class="s1">&#39;,&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;STRING&#39;</span><span class="p">,</span> <span class="s2">&quot;\&quot;$flags\&quot;&quot;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;)&#39;</span><span class="p">,</span> <span class="s1">&#39;)&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;)&#39;</span><span class="p">,</span> <span class="s1">&#39;)&#39;</span><span class="p">]]</span>
<span class="vi">@tokens: </span><span class="nx">@tokens</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[[</span><span class="s1">&#39;(&#39;</span><span class="p">,</span> <span class="s1">&#39;(&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;NEW&#39;</span><span class="p">,</span> <span class="s1">&#39;new&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;IDENTIFIER&#39;</span><span class="p">,</span> <span class="s1">&#39;RegExp&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;CALL_START&#39;</span><span class="p">,</span> <span class="s1">&#39;(&#39;</span><span class="p">]]</span>
<span class="nx">@interpolate_string</span> <span class="s2">&quot;\&quot;$str\&quot;&quot;</span><span class="p">,</span> <span class="kc">yes</span>
<span class="vi">@tokens: </span><span class="nx">@tokens</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[[</span><span class="s1">&#39;,&#39;</span><span class="p">,</span> <span class="s1">&#39;,&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;STRING&#39;</span><span class="p">,</span> <span class="s2">&quot;\&quot;$flags\&quot;&quot;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;)&#39;</span><span class="p">,</span> <span class="s1">&#39;)&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;)&#39;</span><span class="p">,</span> <span class="s1">&#39;)&#39;</span><span class="p">]]</span>
<span class="k">else</span>
<span class="err">@</span><span class="nx">token</span> <span class="s1">&#39;REGEX&#39;</span><span class="p">,</span> <span class="nx">regex</span>
<span class="err">@</span><span class="nv">i: </span><span class="o">+</span> <span class="nx">regex</span><span class="p">.</span><span class="nx">length</span>
<span class="nx">@token</span> <span class="s1">&#39;REGEX&#39;</span><span class="p">,</span> <span class="nx">regex</span>
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">regex</span><span class="p">.</span><span class="nx">length</span>
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</a> </div> <p>Matches a token in which which the passed delimiter pairs must be correctly
balanced (ie. strings, JS literals).</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">balanced_token: </span><span class="p">(</span><span class="nx">delimited</span><span class="p">...)</span> <span class="o">-&gt;</span>
<span class="nx">balanced_string</span> <span class="err">@</span><span class="nx">chunk</span><span class="p">,</span> <span class="nx">delimited</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>Matches and conumes comments. We pass through comments into JavaScript,
<span class="nx">balanced_string</span> <span class="nx">@chunk</span><span class="p">,</span> <span class="nx">delimited</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>Matches and conumes comments. We pass through comments into JavaScript,
so they're treated as real tokens, like any other part of the language.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">comment_token: </span><span class="o">-&gt;</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">comment: </span><span class="err">@</span><span class="nx">match</span> <span class="nx">COMMENT</span><span class="p">,</span> <span class="mi">1</span>
<span class="err">@</span><span class="nv">line: </span><span class="o">+</span> <span class="p">(</span><span class="nx">comment</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">MULTILINER</span><span class="p">)</span> <span class="o">or</span> <span class="p">[]).</span><span class="nx">length</span>
<span class="nv">lines: </span><span class="nx">compact</span> <span class="nx">comment</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="nx">COMMENT_CLEANER</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">).</span><span class="nx">split</span><span class="p">(</span><span class="nx">MULTILINER</span><span class="p">)</span>
<span class="nv">i: </span><span class="err">@</span><span class="nx">tokens</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
<span class="k">if</span> <span class="err">@</span><span class="nx">unfinished</span><span class="p">()</span>
<span class="nv">i: </span><span class="o">-</span> <span class="mi">1</span> <span class="k">while</span> <span class="err">@</span><span class="nx">tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">include</span> <span class="nx">LINE_BREAK</span><span class="p">,</span> <span class="err">@</span><span class="nx">tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
<span class="err">@</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">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;COMMENT&#39;</span><span class="p">,</span> <span class="nx">lines</span><span class="p">,</span> <span class="err">@</span><span class="nx">line</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s1">&#39;\n&#39;</span><span class="p">,</span> <span class="err">@</span><span class="nx">line</span><span class="p">])</span>
<span class="err">@</span><span class="nv">i: </span><span class="o">+</span> <span class="nx">comment</span><span class="p">.</span><span class="nx">length</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">comment: </span><span class="nx">@match</span> <span class="nx">COMMENT</span><span class="p">,</span> <span class="mi">1</span>
<span class="vi">@line: </span><span class="o">+</span> <span class="p">(</span><span class="nx">comment</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">MULTILINER</span><span class="p">)</span> <span class="o">or</span> <span class="p">[]).</span><span class="nx">length</span>
<span class="nv">lines: </span><span class="nx">compact</span> <span class="nx">comment</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="nx">COMMENT_CLEANER</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">).</span><span class="nx">split</span> <span class="nx">MULTILINER</span>
<span class="nv">i: </span><span class="nx">@tokens</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
<span class="k">if</span> <span class="nx">@unfinished</span><span class="p">()</span>
<span class="nv">i: </span><span class="o">-</span> <span class="mi">1</span> <span class="k">while</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">include</span> <span class="nx">LINE_BREAK</span><span class="p">,</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</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="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;COMMENT&#39;</span><span class="p">,</span> <span class="nx">lines</span><span class="p">,</span> <span class="nx">@line</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s1">&#39;\n&#39;</span><span class="p">,</span> <span class="nx">@line</span><span class="p">])</span>
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">comment</span><span class="p">.</span><span class="nx">length</span>
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-18">#</a> </div> <p>Matches newlines, indents, and outdents, and determines which is which.
If we can detect that the current line is continued onto the the next line,
then the newline is suppressed:</p>
@@ -144,103 +144,103 @@ then the newline is suppressed:</p>
<p>Keeps track of the level of indentation, because a single outdent token
can close multiple indents, so we need to know how far in we happen to be.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">line_token: </span><span class="o">-&gt;</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">indent: </span><span class="err">@</span><span class="nx">match</span> <span class="nx">MULTI_DENT</span><span class="p">,</span> <span class="mi">1</span>
<span class="err">@</span><span class="nv">line: </span><span class="o">+</span> <span class="nx">indent</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">MULTILINER</span><span class="p">).</span><span class="nx">length</span>
<span class="err">@</span><span class="nx">i</span> <span class="o">:</span> <span class="o">+</span> <span class="nx">indent</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">prev: </span><span class="err">@</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="kc">false</span> <span class="nx">unless</span> <span class="nv">indent: </span><span class="nx">@match</span> <span class="nx">MULTI_DENT</span><span class="p">,</span> <span class="mi">1</span>
<span class="vi">@line: </span><span class="o">+</span> <span class="nx">indent</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">MULTILINER</span><span class="p">).</span><span class="nx">length</span>
<span class="vi">@i : </span><span class="o">+</span> <span class="nx">indent</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">prev: </span><span class="nx">@prev</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="nv">size: </span><span class="nx">indent</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">LAST_DENTS</span><span class="p">).</span><span class="nx">reverse</span><span class="p">()[</span><span class="mi">0</span><span class="p">].</span><span class="nx">match</span><span class="p">(</span><span class="nx">LAST_DENT</span><span class="p">)[</span><span class="mi">1</span><span class="p">].</span><span class="nx">length</span>
<span class="nv">next_character: </span><span class="err">@</span><span class="nx">chunk</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">MULTI_DENT</span><span class="p">)[</span><span class="mi">4</span><span class="p">]</span>
<span class="nv">no_newlines: </span><span class="nx">next_character</span> <span class="o">is</span> <span class="s1">&#39;.&#39;</span> <span class="o">or</span> <span class="err">@</span><span class="nx">unfinished</span><span class="p">()</span>
<span class="k">if</span> <span class="nx">size</span> <span class="o">is</span> <span class="err">@</span><span class="nx">indent</span>
<span class="k">return</span> <span class="err">@</span><span class="nx">suppress_newlines</span><span class="p">()</span> <span class="k">if</span> <span class="nx">no_newlines</span>
<span class="k">return</span> <span class="err">@</span><span class="nx">newline_token</span><span class="p">(</span><span class="nx">indent</span><span class="p">)</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">size</span> <span class="o">&gt;</span> <span class="err">@</span><span class="nx">indent</span>
<span class="k">return</span> <span class="err">@</span><span class="nx">suppress_newlines</span><span class="p">()</span> <span class="k">if</span> <span class="nx">no_newlines</span>
<span class="nv">diff: </span><span class="nx">size</span> <span class="o">-</span> <span class="err">@</span><span class="nx">indent</span>
<span class="err">@</span><span class="nx">token</span> <span class="s1">&#39;INDENT&#39;</span><span class="p">,</span> <span class="nx">diff</span>
<span class="err">@</span><span class="nx">indents</span><span class="p">.</span><span class="nx">push</span> <span class="nx">diff</span>
<span class="nv">next_character: </span><span class="nx">@chunk</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">MULTI_DENT</span><span class="p">)[</span><span class="mi">4</span><span class="p">]</span>
<span class="nv">no_newlines: </span><span class="nx">next_character</span> <span class="o">is</span> <span class="s1">&#39;.&#39;</span> <span class="o">or</span> <span class="nx">@unfinished</span><span class="p">()</span>
<span class="k">if</span> <span class="nx">size</span> <span class="o">is</span> <span class="nx">@indent</span>
<span class="k">return</span> <span class="nx">@suppress_newlines</span><span class="p">()</span> <span class="k">if</span> <span class="nx">no_newlines</span>
<span class="k">return</span> <span class="nx">@newline_token</span> <span class="nx">indent</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">size</span> <span class="o">&gt;</span> <span class="nx">@indent</span>
<span class="k">return</span> <span class="nx">@suppress_newlines</span><span class="p">()</span> <span class="k">if</span> <span class="nx">no_newlines</span>
<span class="nv">diff: </span><span class="nx">size</span> <span class="o">-</span> <span class="nx">@indent</span>
<span class="nx">@token</span> <span class="s1">&#39;INDENT&#39;</span><span class="p">,</span> <span class="nx">diff</span>
<span class="nx">@indents</span><span class="p">.</span><span class="nx">push</span> <span class="nx">diff</span>
<span class="k">else</span>
<span class="err">@</span><span class="nx">outdent_token</span> <span class="err">@</span><span class="nx">indent</span> <span class="o">-</span> <span class="nx">size</span><span class="p">,</span> <span class="nx">no_newlines</span>
<span class="err">@</span><span class="nv">indent: </span><span class="nx">size</span>
<span class="nx">@outdent_token</span> <span class="nx">@indent</span> <span class="o">-</span> <span class="nx">size</span><span class="p">,</span> <span class="nx">no_newlines</span>
<span class="vi">@indent: </span><span class="nx">size</span>
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-19">#</a> </div> <p>Record an outdent token or multiple tokens, if we happen to be moving back
inwards past several recorded indents.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">outdent_token: </span><span class="p">(</span><span class="nx">move_out</span><span class="p">,</span> <span class="nx">no_newlines</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">while</span> <span class="nx">move_out</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">and</span> <span class="err">@</span><span class="nx">indents</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">last_indent: </span><span class="err">@</span><span class="nx">indents</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
<span class="err">@</span><span class="nx">token</span> <span class="s1">&#39;OUTDENT&#39;</span><span class="p">,</span> <span class="nx">last_indent</span>
<span class="k">while</span> <span class="nx">move_out</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">and</span> <span class="nx">@indents</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">last_indent: </span><span class="nx">@indents</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
<span class="nx">@token</span> <span class="s1">&#39;OUTDENT&#39;</span><span class="p">,</span> <span class="nx">last_indent</span>
<span class="nv">move_out: </span><span class="o">-</span> <span class="nx">last_indent</span>
<span class="err">@</span><span class="nx">token</span> <span class="s1">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s2">&quot;\n&quot;</span> <span class="nx">unless</span> <span class="err">@</span><span class="nx">tag</span><span class="p">()</span> <span class="o">is</span> <span class="s1">&#39;TERMINATOR&#39;</span> <span class="o">or</span> <span class="nx">no_newlines</span>
<span class="nx">@token</span> <span class="s1">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s2">&quot;\n&quot;</span> <span class="nx">unless</span> <span class="nx">@tag</span><span class="p">()</span> <span class="o">is</span> <span class="s1">&#39;TERMINATOR&#39;</span> <span class="o">or</span> <span class="nx">no_newlines</span>
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-20">#</a> </div> <p>Matches and consumes non-meaningful whitespace. Tag the previous token
as being "spaced", because there are some cases where it makes a difference.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">whitespace_token: </span><span class="o">-&gt;</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">space: </span><span class="err">@</span><span class="nx">match</span> <span class="nx">WHITESPACE</span><span class="p">,</span> <span class="mi">1</span>
<span class="nv">prev: </span><span class="err">@</span><span class="nx">prev</span><span class="p">()</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">space: </span><span class="nx">@match</span> <span class="nx">WHITESPACE</span><span class="p">,</span> <span class="mi">1</span>
<span class="nv">prev: </span><span class="nx">@prev</span><span class="p">()</span>
<span class="nv">prev.spaced: </span><span class="kc">true</span> <span class="k">if</span> <span class="nx">prev</span>
<span class="err">@</span><span class="nv">i: </span><span class="o">+</span> <span class="nx">space</span><span class="p">.</span><span class="nx">length</span>
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">space</span><span class="p">.</span><span class="nx">length</span>
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-21">#</a> </div> <p>Generate a newline token. Consecutive newlines get merged together.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">newline_token: </span><span class="p">(</span><span class="nx">newlines</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">token</span> <span class="s1">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s2">&quot;\n&quot;</span> <span class="nx">unless</span> <span class="err">@</span><span class="nx">tag</span><span class="p">()</span> <span class="o">is</span> <span class="s1">&#39;TERMINATOR&#39;</span>
<span class="nx">@token</span> <span class="s1">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s2">&quot;\n&quot;</span> <span class="nx">unless</span> <span class="nx">@tag</span><span class="p">()</span> <span class="o">is</span> <span class="s1">&#39;TERMINATOR&#39;</span>
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-22">#</a> </div> <p>Use a <code>\</code> at a line-ending to suppress the newline.
The slash is removed here once its job is done.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">suppress_newlines: </span><span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">tokens</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span> <span class="k">if</span> <span class="err">@</span><span class="nx">value</span><span class="p">()</span> <span class="o">is</span> <span class="s2">&quot;\\&quot;</span>
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span> <span class="k">if</span> <span class="nx">@value</span><span class="p">()</span> <span class="o">is</span> <span class="s2">&quot;\\&quot;</span>
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-23">#</a> </div> <p>We treat all other single characters as a token. Eg.: <code>( ) , . !</code>
Multi-character operators are also literal tokens, so that Jison can assign
the proper order of operations. There are some symbols that we tag specially
here. <code>;</code> and newlines are both treated as a <code>TERMINATOR</code>, we distinguish
parentheses that indicate a method call from regular parentheses, and so on.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">literal_token: </span><span class="o">-&gt;</span>
<span class="nv">match: </span><span class="err">@</span><span class="nx">chunk</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">OPERATOR</span><span class="p">)</span>
<span class="nv">match: </span><span class="nx">@chunk</span><span class="p">.</span><span class="nx">match</span> <span class="nx">OPERATOR</span>
<span class="nv">value: </span><span class="nx">match</span> <span class="o">and</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="nv">space: </span><span class="nx">match</span> <span class="o">and</span> <span class="nx">match</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
<span class="err">@</span><span class="nx">tag_parameters</span><span class="p">()</span> <span class="k">if</span> <span class="nx">value</span> <span class="o">and</span> <span class="nx">value</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">CODE</span><span class="p">)</span>
<span class="nv">value: </span><span class="o">or</span> <span class="err">@</span><span class="nx">chunk</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="nv">prev_spaced: </span><span class="err">@</span><span class="nx">prev</span><span class="p">()</span> <span class="o">and</span> <span class="err">@</span><span class="nx">prev</span><span class="p">().</span><span class="nx">spaced</span>
<span class="nx">@tag_parameters</span><span class="p">()</span> <span class="k">if</span> <span class="nx">value</span> <span class="o">and</span> <span class="nx">value</span><span class="p">.</span><span class="nx">match</span> <span class="nx">CODE</span>
<span class="nv">value: </span><span class="o">or</span> <span class="nx">@chunk</span><span class="p">.</span><span class="nx">substr</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span>
<span class="nv">prev_spaced: </span><span class="nx">@prev</span><span class="p">()</span> <span class="o">and</span> <span class="nx">@prev</span><span class="p">().</span><span class="nx">spaced</span>
<span class="nv">tag: </span><span class="nx">value</span>
<span class="k">if</span> <span class="nx">value</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">ASSIGNMENT</span><span class="p">)</span>
<span class="k">if</span> <span class="nx">value</span><span class="p">.</span><span class="nx">match</span> <span class="nx">ASSIGNMENT</span>
<span class="nv">tag: </span><span class="s1">&#39;ASSIGN&#39;</span>
<span class="err">@</span><span class="nx">assignment_error</span><span class="p">()</span> <span class="k">if</span> <span class="nx">include</span> <span class="nx">JS_FORBIDDEN</span><span class="p">,</span> <span class="err">@</span><span class="nx">value</span>
<span class="nx">@assignment_error</span><span class="p">()</span> <span class="k">if</span> <span class="nx">include</span> <span class="nx">JS_FORBIDDEN</span><span class="p">,</span> <span class="nx">@value</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">value</span> <span class="o">is</span> <span class="s1">&#39;;&#39;</span>
<span class="nv">tag: </span><span class="s1">&#39;TERMINATOR&#39;</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">value</span> <span class="o">is</span> <span class="s1">&#39;[&#39;</span> <span class="o">and</span> <span class="err">@</span><span class="nx">tag</span><span class="p">()</span> <span class="o">is</span> <span class="s1">&#39;?&#39;</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">prev_spaced</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">value</span> <span class="o">is</span> <span class="s1">&#39;[&#39;</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">()</span> <span class="o">is</span> <span class="s1">&#39;?&#39;</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">prev_spaced</span>
<span class="nv">tag: </span><span class="s1">&#39;SOAKED_INDEX_START&#39;</span>
<span class="err">@</span><span class="nv">soaked_index: </span><span class="kc">true</span>
<span class="err">@</span><span class="nx">tokens</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">value</span> <span class="o">is</span> <span class="s1">&#39;]&#39;</span> <span class="o">and</span> <span class="err">@</span><span class="nx">soaked_index</span>
<span class="vi">@soaked_index: </span><span class="kc">true</span>
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">value</span> <span class="o">is</span> <span class="s1">&#39;]&#39;</span> <span class="o">and</span> <span class="nx">@soaked_index</span>
<span class="nv">tag: </span><span class="s1">&#39;SOAKED_INDEX_END&#39;</span>
<span class="err">@</span><span class="nv">soaked_index: </span><span class="kc">false</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">include</span><span class="p">(</span><span class="nx">CALLABLE</span><span class="p">,</span> <span class="err">@</span><span class="nx">tag</span><span class="p">())</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">prev_spaced</span>
<span class="vi">@soaked_index: </span><span class="kc">false</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">include</span><span class="p">(</span><span class="nx">CALLABLE</span><span class="p">,</span> <span class="nx">@tag</span><span class="p">())</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">prev_spaced</span>
<span class="nv">tag: </span><span class="s1">&#39;CALL_START&#39;</span> <span class="k">if</span> <span class="nx">value</span> <span class="o">is</span> <span class="s1">&#39;(&#39;</span>
<span class="nv">tag: </span><span class="s1">&#39;INDEX_START&#39;</span> <span class="k">if</span> <span class="nx">value</span> <span class="o">is</span> <span class="s1">&#39;[&#39;</span>
<span class="err">@</span><span class="nv">i: </span><span class="o">+</span> <span class="nx">value</span><span class="p">.</span><span class="nx">length</span>
<span class="k">return</span> <span class="err">@</span><span class="nx">tag_half_assignment</span><span class="p">(</span><span class="nx">tag</span><span class="p">)</span> <span class="k">if</span> <span class="nx">space</span> <span class="o">and</span> <span class="nx">prev_spaced</span> <span class="o">and</span> <span class="err">@</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="s1">&#39;ASSIGN&#39;</span> <span class="o">and</span> <span class="nx">include</span> <span class="nx">HALF_ASSIGNMENTS</span><span class="p">,</span> <span class="nx">tag</span>
<span class="err">@</span><span class="nx">token</span> <span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span>
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">value</span><span class="p">.</span><span class="nx">length</span>
<span class="k">return</span> <span class="nx">@tag_half_assignment</span> <span class="nx">tag</span> <span class="k">if</span> <span class="nx">space</span> <span class="o">and</span> <span class="nx">prev_spaced</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="s1">&#39;ASSIGN&#39;</span> <span class="o">and</span> <span class="nx">include</span> <span class="nx">HALF_ASSIGNMENTS</span><span class="p">,</span> <span class="nx">tag</span>
<span class="nx">@token</span> <span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span>
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-24">#</a> </div> <h2>Token Manipulators</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-25">#</a> </div> <p>As we consume a new <code>IDENTIFIER</code>, look at the previous token to determine
if it's a special kind of accessor.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">name_access_type: </span><span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">tag</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s1">&#39;PROTOTYPE_ACCESS&#39;</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">value</span><span class="p">()</span> <span class="o">is</span> <span class="s1">&#39;::&#39;</span>
<span class="k">if</span> <span class="err">@</span><span class="nx">value</span><span class="p">()</span> <span class="o">is</span> <span class="s1">&#39;.&#39;</span> <span class="o">and</span> <span class="o">not</span> <span class="p">(</span><span class="err">@</span><span class="nx">value</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s1">&#39;.&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="err">@</span><span class="nx">tag</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s1">&#39;?&#39;</span>
<span class="err">@</span><span class="nx">tag</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s1">&#39;SOAK_ACCESS&#39;</span><span class="p">)</span>
<span class="err">@</span><span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="nx">@tag</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s1">&#39;PROTOTYPE_ACCESS&#39;</span><span class="p">)</span> <span class="k">if</span> <span class="nx">@value</span><span class="p">()</span> <span class="o">is</span> <span class="s1">&#39;::&#39;</span>
<span class="k">if</span> <span class="nx">@value</span><span class="p">()</span> <span class="o">is</span> <span class="s1">&#39;.&#39;</span> <span class="o">and</span> <span class="o">not</span> <span class="p">(</span><span class="nx">@value</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s1">&#39;.&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="nx">@tag</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s1">&#39;?&#39;</span>
<span class="nx">@tag</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s1">&#39;SOAK_ACCESS&#39;</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="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">else</span>
<span class="err">@</span><span class="nx">tag</span> <span class="mi">1</span><span class="p">,</span> <span class="s1">&#39;PROPERTY_ACCESS&#39;</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-26">#</a> </div> <p>Sanitize a heredoc by escaping internal double quotes and erasing all
<span class="nx">@tag</span> <span class="mi">1</span><span class="p">,</span> <span class="s1">&#39;PROPERTY_ACCESS&#39;</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-26">#</a> </div> <p>Sanitize a heredoc by escaping internal double quotes and erasing all
external indentation on the left-hand side.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">sanitize_heredoc: </span><span class="p">(</span><span class="nx">doc</span><span class="p">,</span> <span class="nx">quote</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">indent: </span><span class="p">(</span><span class="nx">doc</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">HEREDOC_INDENT</span><span class="p">)</span> <span class="o">or</span> <span class="p">[</span><span class="s1">&#39;&#39;</span><span class="p">]).</span><span class="nx">sort</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
<span class="nx">doc</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="s2">&quot;^&quot;</span> <span class="o">+</span><span class="nx">indent</span><span class="p">,</span> <span class="s1">&#39;gm&#39;</span><span class="p">),</span> <span class="s1">&#39;&#39;</span><span class="p">)</span>
<span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="nx">MULTILINER</span><span class="p">,</span> <span class="s2">&quot;\\n&quot;</span><span class="p">)</span>
<span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="nx">quote</span><span class="p">,</span> <span class="s1">&#39;g&#39;</span><span class="p">),</span> <span class="s1">&#39;\\&quot;&#39;</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-27">#</a> </div> <p>Tag a half assignment.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tag_half_assignment: </span><span class="p">(</span><span class="nx">tag</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">last: </span><span class="err">@</span><span class="nx">tokens</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
<span class="err">@</span><span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s2">&quot;$tag=&quot;</span><span class="p">,</span> <span class="s2">&quot;$tag=&quot;</span><span class="p">,</span> <span class="nx">last</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
<span class="nv">last: </span><span class="nx">@tokens</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s2">&quot;$tag=&quot;</span><span class="p">,</span> <span class="s2">&quot;$tag=&quot;</span><span class="p">,</span> <span class="nx">last</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-28">#</a> </div> <p>A source of ambiguity in our grammar used to be parameter lists in function
definitions versus argument lists in function calls. Walk backwards, tagging
parameters specially in order to make things easier for the parser.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tag_parameters: </span><span class="o">-&gt;</span>
<span class="k">return</span> <span class="k">if</span> <span class="err">@</span><span class="nx">tag</span><span class="p">()</span> <span class="o">isnt</span> <span class="s1">&#39;)&#39;</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">@tag</span><span class="p">()</span> <span class="o">isnt</span> <span class="s1">&#39;)&#39;</span>
<span class="nv">i: </span><span class="mi">0</span>
<span class="k">while</span> <span class="kc">true</span>
<span class="nv">i: </span><span class="o">+</span> <span class="mi">1</span>
<span class="nv">tok: </span><span class="err">@</span><span class="nx">prev</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span>
<span class="nv">tok: </span><span class="nx">@prev</span> <span class="nx">i</span>
<span class="k">return</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">tok</span>
<span class="k">switch</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">when</span> <span class="s1">&#39;IDENTIFIER&#39;</span> <span class="k">then</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">:</span> <span class="s1">&#39;PARAM&#39;</span>
<span class="k">when</span> <span class="s1">&#39;)&#39;</span> <span class="k">then</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">:</span> <span class="s1">&#39;PARAM_END&#39;</span>
<span class="k">when</span> <span class="s1">&#39;(&#39;</span> <span class="k">then</span> <span class="k">return</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">:</span> <span class="s1">&#39;PARAM_START&#39;</span>
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-29">#</a> </div> <p>Close up all remaining open blocks at the end of the file.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">close_indentation: </span><span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">outdent_token</span><span class="p">(</span><span class="err">@</span><span class="nx">indent</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-30">#</a> </div> <p>The error for when you try to use a forbidden word in JavaScript as
<span class="nx">@outdent_token</span> <span class="nx">@indent</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-30">#</a> </div> <p>The error for when you try to use a forbidden word in JavaScript as
an identifier.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">identifier_error: </span><span class="p">(</span><span class="nx">word</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">&quot;SyntaxError: Reserved word \&quot;$word\&quot; on line ${@line + 1}&quot;</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-31">#</a> </div> <p>The error for when you try to assign to a reserved word in JavaScript,
like "function" or "default".</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">assignment_error: </span><span class="o">-&gt;</span>
@@ -256,11 +256,11 @@ for substitution of bare variables as well as arbitrary expressions.</p>
new Lexer, tokenize the interpolated contents, and merge them into the
token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">interpolate_string: </span><span class="p">(</span><span class="nx">str</span><span class="p">,</span> <span class="nx">escape_quotes</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">str</span><span class="p">.</span><span class="nx">length</span> <span class="o">&lt;</span> <span class="mi">3</span> <span class="o">or</span> <span class="o">not</span> <span class="nx">starts</span> <span class="nx">str</span><span class="p">,</span> <span class="s1">&#39;&quot;&#39;</span>
<span class="err">@</span><span class="nx">token</span> <span class="s1">&#39;STRING&#39;</span><span class="p">,</span> <span class="nx">str</span>
<span class="nx">@token</span> <span class="s1">&#39;STRING&#39;</span><span class="p">,</span> <span class="nx">str</span>
<span class="k">else</span>
<span class="nv">lexer: </span> <span class="k">new</span> <span class="nx">Lexer</span><span class="p">()</span>
<span class="nv">tokens: </span> <span class="p">[]</span>
<span class="nv">quote: </span> <span class="nx">str</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="nv">quote: </span> <span class="nx">str</span><span class="p">.</span><span class="nx">substring</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span>
<span class="p">[</span><span class="nx">i</span><span class="p">,</span> <span class="nx">pi</span><span class="p">]</span><span class="o">:</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
<span class="k">while</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">str</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
<span class="k">if</span> <span class="nx">starts</span> <span class="nx">str</span><span class="p">,</span> <span class="s1">&#39;\\&#39;</span><span class="p">,</span> <span class="nx">i</span>
@@ -276,7 +276,8 @@ token stream.</p> </td> <td class="code">
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">&#39;STRING&#39;</span><span class="p">,</span> <span class="s2">&quot;$quote${ str.substring(pi, i) }$quote&quot;</span><span class="p">]</span> <span class="k">if</span> <span class="nx">pi</span> <span class="o">&lt;</span> <span class="nx">i</span>
<span class="nv">inner: </span><span class="nx">expr</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">if</span> <span class="nx">inner</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">nested: </span><span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="s2">&quot;($inner)&quot;</span><span class="p">,</span> <span class="p">{</span><span class="nv">rewrite: </span><span class="kc">no</span><span class="p">,</span> <span class="nv">line: </span><span class="err">@</span><span class="nx">line</span><span class="p">}</span>
<span class="nv">nested: </span><span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="s2">&quot;($inner)&quot;</span><span class="p">,</span> <span class="p">{</span><span class="nv">line: </span><span class="nx">@line</span><span class="p">}</span>
<span class="p">(</span><span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">:</span> <span class="s1">&#39;)&#39;</span><span class="p">)</span> <span class="k">for</span> <span class="nx">tok</span><span class="p">,</span> <span class="nx">idx</span> <span class="k">in</span> <span class="nx">nested</span> <span class="k">when</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;CALL_END&#39;</span>
<span class="nx">nested</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">&#39;TOKENS&#39;</span><span class="p">,</span> <span class="nx">nested</span><span class="p">]</span>
<span class="k">else</span>
@@ -286,31 +287,34 @@ token stream.</p> </td> <td class="code">
<span class="nv">i: </span><span class="o">+</span> <span class="mi">1</span>
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">&#39;STRING&#39;</span><span class="p">,</span> <span class="s2">&quot;$quote${ str.substring(pi, i) }$quote&quot;</span><span class="p">]</span> <span class="k">if</span> <span class="nx">pi</span> <span class="o">&lt;</span> <span class="nx">i</span> <span class="o">and</span> <span class="nx">pi</span> <span class="o">&lt;</span> <span class="nx">str</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
<span class="nx">tokens</span><span class="p">.</span><span class="nx">unshift</span> <span class="p">[</span><span class="s1">&#39;STRING&#39;</span><span class="p">,</span> <span class="s1">&#39;&quot;&quot;&#39;</span><span class="p">]</span> <span class="nx">unless</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">&#39;STRING&#39;</span>
<span class="nv">interpolated: </span><span class="nx">tokens</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">1</span>
<span class="nx">@token</span> <span class="s1">&#39;(&#39;</span><span class="p">,</span> <span class="s1">&#39;(&#39;</span> <span class="k">if</span> <span class="nx">interpolated</span>
<span class="k">for</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">tokens</span>
<span class="p">[</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span><span class="p">]</span><span class="o">:</span> <span class="nx">token</span>
<span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;TOKENS&#39;</span>
<span class="err">@</span><span class="nv">tokens: </span><span class="err">@</span><span class="nx">tokens</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">value</span>
<span class="vi">@tokens: </span><span class="nx">@tokens</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">value</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;STRING&#39;</span> <span class="o">and</span> <span class="nx">escape_quotes</span>
<span class="nv">escaped: </span><span class="nx">value</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nx">value</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">).</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/&quot;/g</span><span class="p">,</span> <span class="s1">&#39;\\&quot;&#39;</span><span class="p">)</span>
<span class="err">@</span><span class="nx">token</span> <span class="nx">tag</span><span class="p">,</span> <span class="s2">&quot;\&quot;$escaped\&quot;&quot;</span>
<span class="nx">@token</span> <span class="nx">tag</span><span class="p">,</span> <span class="s2">&quot;\&quot;$escaped\&quot;&quot;</span>
<span class="k">else</span>
<span class="err">@</span><span class="nx">token</span> <span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span>
<span class="err">@</span><span class="nx">token</span> <span class="s1">&#39;+&#39;</span><span class="p">,</span> <span class="s1">&#39;+&#39;</span> <span class="k">if</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">tokens</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
<span class="nx">@token</span> <span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span>
<span class="nx">@token</span> <span class="s1">&#39;+&#39;</span><span class="p">,</span> <span class="s1">&#39;+&#39;</span> <span class="k">if</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">tokens</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
<span class="nx">@token</span> <span class="s1">&#39;)&#39;</span><span class="p">,</span> <span class="s1">&#39;)&#39;</span> <span class="k">if</span> <span class="nx">interpolated</span>
<span class="nx">tokens</span></pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-33">#</a> </div> <h2>Helpers</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-34">#</a> </div> <p>Add a token to the results, taking note of the line number.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">token: </span><span class="p">(</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span><span class="p">([</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="err">@</span><span class="nx">line</span><span class="p">])</span></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-35">#</a> </div> <p>Peek at a tag in the current token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tag: </span><span class="p">(</span><span class="nx">index</span><span class="p">,</span> <span class="nx">tag</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="nx">unless</span> <span class="nv">tok: </span><span class="err">@</span><span class="nx">prev</span><span class="p">(</span><span class="nx">index</span><span class="p">)</span>
<span class="k">return</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">:</span> <span class="nx">tag</span> <span class="k">if</span> <span class="nx">tag</span><span class="o">?</span>
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">@line</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-35">#</a> </div> <p>Peek at a tag in the current token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tag: </span><span class="p">(</span><span class="nx">index</span><span class="p">,</span> <span class="nx">new_tag</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="nx">unless</span> <span class="nv">tok: </span><span class="nx">@prev</span> <span class="nx">index</span>
<span class="k">return</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">:</span> <span class="nx">new_tag</span> <span class="k">if</span> <span class="nx">new_tag</span><span class="o">?</span>
<span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-36">#</a> </div> <p>Peek at a value in the current token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">value: </span><span class="p">(</span><span class="nx">index</span><span class="p">,</span> <span class="nx">val</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="nx">unless</span> <span class="nv">tok: </span><span class="err">@</span><span class="nx">prev</span><span class="p">(</span><span class="nx">index</span><span class="p">)</span>
<span class="k">return</span> <span class="nx">unless</span> <span class="nv">tok: </span><span class="nx">@prev</span> <span class="nx">index</span>
<span class="k">return</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">:</span> <span class="nx">val</span> <span class="k">if</span> <span class="nx">val</span><span class="o">?</span>
<span class="nx">tok</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-37"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-37">#</a> </div> <p>Peek at a previous token, entire.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">prev: </span><span class="p">(</span><span class="nx">index</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">tokens</span><span class="p">[</span><span class="err">@</span><span class="nx">tokens</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="p">(</span><span class="nx">index</span> <span class="o">or</span> <span class="mi">1</span><span class="p">)]</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-38">#</a> </div> <p>Attempt to match a string against the current chunk, returning the indexed
<span class="nx">@tokens</span><span class="p">[</span><span class="nx">@tokens</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="p">(</span><span class="nx">index</span> <span class="o">or</span> <span class="mi">1</span><span class="p">)]</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-38">#</a> </div> <p>Attempt to match a string against the current chunk, returning the indexed
match if successful, and <code>false</code> otherwise.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">match: </span><span class="p">(</span><span class="nx">regex</span><span class="p">,</span> <span class="nx">index</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">m: </span><span class="err">@</span><span class="nx">chunk</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">regex</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">m: </span><span class="nx">@chunk</span><span class="p">.</span><span class="nx">match</span> <span class="nx">regex</span>
<span class="k">if</span> <span class="nx">m</span> <span class="k">then</span> <span class="nx">m</span><span class="p">[</span><span class="nx">index</span><span class="p">]</span> <span class="k">else</span> <span class="kc">false</span></pre></div> </td> </tr> <tr id="section-39"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-39">#</a> </div> <p>Are we in the midst of an unfinished expression?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">unfinished: </span><span class="o">-&gt;</span>
<span class="nv">prev: </span><span class="err">@</span><span class="nx">prev</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="err">@</span><span class="nx">value</span><span class="p">()</span> <span class="o">and</span> <span class="err">@</span><span class="nx">value</span><span class="p">().</span><span class="nx">match</span> <span class="o">and</span> <span class="err">@</span><span class="nx">value</span><span class="p">().</span><span class="nx">match</span><span class="p">(</span><span class="nx">NO_NEWLINE</span><span class="p">)</span> <span class="o">and</span>
<span class="nx">prev</span> <span class="o">and</span> <span class="p">(</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">&#39;.&#39;</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="err">@</span><span class="nx">value</span><span class="p">().</span><span class="nx">match</span><span class="p">(</span><span class="nx">CODE</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-40">#</a> </div> <p>There are no exensions to the core lexer by default.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">Lexer.extensions: </span><span class="p">[]</span></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-41">#</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-42">#</a> </div> <p>Keywords that CoffeeScript shares in common with JavaScript.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">JS_KEYWORDS: </span><span class="p">[</span>
<span class="nv">prev: </span><span class="nx">@prev</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="nx">@value</span><span class="p">()</span> <span class="o">and</span> <span class="nx">@value</span><span class="p">().</span><span class="nx">match</span> <span class="o">and</span> <span class="nx">@value</span><span class="p">().</span><span class="nx">match</span><span class="p">(</span><span class="nx">NO_NEWLINE</span><span class="p">)</span> <span class="o">and</span>
<span class="nx">prev</span> <span class="o">and</span> <span class="p">(</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">&#39;.&#39;</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@value</span><span class="p">().</span><span class="nx">match</span><span class="p">(</span><span class="nx">CODE</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-40">#</a> </div> <h2>Lexer Properties</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-41">#</a> </div> <p>There are no exensions to the core lexer by default.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="vi">@extensions: </span><span class="p">[]</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-42">#</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-43">#</a> </div> <p>Keywords that CoffeeScript shares in common with JavaScript.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">JS_KEYWORDS: </span><span class="p">[</span>
<span class="s2">&quot;if&quot;</span><span class="p">,</span> <span class="s2">&quot;else&quot;</span><span class="p">,</span>
<span class="s2">&quot;true&quot;</span><span class="p">,</span> <span class="s2">&quot;false&quot;</span><span class="p">,</span>
<span class="s2">&quot;new&quot;</span><span class="p">,</span> <span class="s2">&quot;return&quot;</span><span class="p">,</span>
@@ -318,53 +322,53 @@ match if successful, and <code>false</code> otherwise.</p> </td>
<span class="s2">&quot;break&quot;</span><span class="p">,</span> <span class="s2">&quot;continue&quot;</span><span class="p">,</span>
<span class="s2">&quot;for&quot;</span><span class="p">,</span> <span class="s2">&quot;in&quot;</span><span class="p">,</span> <span class="s2">&quot;while&quot;</span><span class="p">,</span>
<span class="s2">&quot;delete&quot;</span><span class="p">,</span> <span class="s2">&quot;instanceof&quot;</span><span class="p">,</span> <span class="s2">&quot;typeof&quot;</span><span class="p">,</span>
<span class="s2">&quot;switch&quot;</span><span class="p">,</span> <span class="s2">&quot;super&quot;</span><span class="p">,</span> <span class="s2">&quot;extends&quot;</span><span class="p">,</span> <span class="s2">&quot;class&quot;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-43">#</a> </div> <p>CoffeeScript-only keywords, which we're more relaxed about allowing. They can't
<span class="s2">&quot;switch&quot;</span><span class="p">,</span> <span class="s2">&quot;super&quot;</span><span class="p">,</span> <span class="s2">&quot;extends&quot;</span><span class="p">,</span> <span class="s2">&quot;class&quot;</span><span class="p">,</span>
<span class="s2">&quot;this&quot;</span><span class="p">,</span> <span class="s2">&quot;null&quot;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-44">#</a> </div> <p>CoffeeScript-only keywords, which we're more relaxed about allowing. They can't
be used standalone, but you can reference them as an attached property.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">COFFEE_ALIASES: </span> <span class="p">[</span><span class="s2">&quot;and&quot;</span><span class="p">,</span> <span class="s2">&quot;or&quot;</span><span class="p">,</span> <span class="s2">&quot;is&quot;</span><span class="p">,</span> <span class="s2">&quot;isnt&quot;</span><span class="p">,</span> <span class="s2">&quot;not&quot;</span><span class="p">]</span>
<span class="nv">COFFEE_KEYWORDS: </span><span class="nx">COFFEE_ALIASES</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[</span>
<span class="s2">&quot;then&quot;</span><span class="p">,</span> <span class="s2">&quot;unless&quot;</span><span class="p">,</span>
<span class="s2">&quot;yes&quot;</span><span class="p">,</span> <span class="s2">&quot;no&quot;</span><span class="p">,</span> <span class="s2">&quot;on&quot;</span><span class="p">,</span> <span class="s2">&quot;off&quot;</span><span class="p">,</span>
<span class="s2">&quot;of&quot;</span><span class="p">,</span> <span class="s2">&quot;by&quot;</span><span class="p">,</span> <span class="s2">&quot;where&quot;</span><span class="p">,</span> <span class="s2">&quot;when&quot;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-44">#</a> </div> <p>The combined list of keywords is the superset that gets passed verbatim to
the parser.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">KEYWORDS: </span><span class="nx">JS_KEYWORDS</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">COFFEE_KEYWORDS</span></pre></div> </td> </tr> <tr id="section-45"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-45">#</a> </div> <p>The list of keywords that are reserved by JavaScript, but not used, or are
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-45"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-45">#</a> </div> <p>The combined list of keywords is the superset that gets passed verbatim to
the parser.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">KEYWORDS: </span><span class="nx">JS_KEYWORDS</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">COFFEE_KEYWORDS</span></pre></div> </td> </tr> <tr id="section-46"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-46">#</a> </div> <p>The list of keywords that are reserved by JavaScript, but not used, or are
used by CoffeeScript internally. We throw an error when these are encountered,
to avoid having a JavaScript error at runtime.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">RESERVED: </span><span class="p">[</span>
<span class="s2">&quot;case&quot;</span><span class="p">,</span> <span class="s2">&quot;default&quot;</span><span class="p">,</span> <span class="s2">&quot;do&quot;</span><span class="p">,</span> <span class="s2">&quot;function&quot;</span><span class="p">,</span> <span class="s2">&quot;var&quot;</span><span class="p">,</span> <span class="s2">&quot;void&quot;</span><span class="p">,</span> <span class="s2">&quot;with&quot;</span>
<span class="s2">&quot;const&quot;</span><span class="p">,</span> <span class="s2">&quot;let&quot;</span><span class="p">,</span> <span class="s2">&quot;debugger&quot;</span><span class="p">,</span> <span class="s2">&quot;enum&quot;</span><span class="p">,</span> <span class="s2">&quot;export&quot;</span><span class="p">,</span> <span class="s2">&quot;import&quot;</span><span class="p">,</span> <span class="s2">&quot;native&quot;</span><span class="p">,</span>
<span class="s2">&quot;__extends&quot;</span><span class="p">,</span> <span class="s2">&quot;__hasProp&quot;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-46"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-46">#</a> </div> <p>The superset of both JavaScript keywords and reserved words, none of which may
be used as identifiers or properties.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">JS_FORBIDDEN: </span><span class="nx">JS_KEYWORDS</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">RESERVED</span></pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-47">#</a> </div> <p>Token matching regexes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">IDENTIFIER</span> <span class="o">:</span> <span class="sr">/^([a-zA-Z\$_](\w|\$)*)/</span>
<span class="nx">NUMBER</span> <span class="o">:</span> <span class="sr">/^(\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?(e[+\-]?[0-9]+)?)))\b/i</span>
<span class="nx">HEREDOC</span> <span class="o">:</span> <span class="sr">/^(&quot;{6}|&#39;{6}|&quot;{3}\n?([\s\S]*?)\n?([ \t]*)&quot;{3}|&#39;{3}\n?([\s\S]*?)\n?([ \t]*)&#39;{3})/</span>
<span class="nx">INTERPOLATION</span> <span class="o">:</span> <span class="sr">/^\$([a-zA-Z_@]\w*(\.\w+)*)/</span>
<span class="nx">OPERATOR</span> <span class="o">:</span> <span class="sr">/^([+\*&amp;|\/\-%=&lt;&gt;:!?]+)([ \t]*)/</span>
<span class="nx">WHITESPACE</span> <span class="o">:</span> <span class="sr">/^([ \t]+)/</span>
<span class="nx">COMMENT</span> <span class="o">:</span> <span class="sr">/^(((\n?[ \t]*)?#[^\n]*)+)/</span>
<span class="nx">CODE</span> <span class="o">:</span> <span class="sr">/^((-|=)&gt;)/</span>
<span class="nx">MULTI_DENT</span> <span class="o">:</span> <span class="sr">/^((\n([ \t]*))+)(\.)?/</span>
<span class="nx">LAST_DENTS</span> <span class="o">:</span> <span class="sr">/\n([ \t]*)/g</span>
<span class="nx">LAST_DENT</span> <span class="o">:</span> <span class="sr">/\n([ \t]*)/</span>
<span class="nx">ASSIGNMENT</span> <span class="o">:</span> <span class="sr">/^(:|=)$/</span></pre></div> </td> </tr> <tr id="section-48"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-48">#</a> </div> <p>Regex-matching-regexes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">REGEX_START</span> <span class="o">:</span> <span class="sr">/^\/[^\/ ]/</span>
<span class="s2">&quot;const&quot;</span><span class="p">,</span> <span class="s2">&quot;let&quot;</span><span class="p">,</span> <span class="s2">&quot;debugger&quot;</span><span class="p">,</span> <span class="s2">&quot;enum&quot;</span><span class="p">,</span> <span class="s2">&quot;export&quot;</span><span class="p">,</span> <span class="s2">&quot;import&quot;</span><span class="p">,</span> <span class="s2">&quot;native&quot;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-47">#</a> </div> <p>The superset of both JavaScript keywords and reserved words, none of which may
be used as identifiers or properties.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">JS_FORBIDDEN: </span><span class="nx">JS_KEYWORDS</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">RESERVED</span></pre></div> </td> </tr> <tr id="section-48"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-48">#</a> </div> <p>Token matching regexes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IDENTIFIER : </span><span class="sr">/^([a-zA-Z\$_](\w|\$)*)/</span>
<span class="nv">NUMBER : </span><span class="sr">/^(\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?(e[+\-]?[0-9]+)?)))\b/i</span>
<span class="nv">HEREDOC : </span><span class="sr">/^(&quot;{6}|&#39;{6}|&quot;{3}\n?([\s\S]*?)\n?([ \t]*)&quot;{3}|&#39;{3}\n?([\s\S]*?)\n?([ \t]*)&#39;{3})/</span>
<span class="nv">INTERPOLATION : </span><span class="sr">/^\$([a-zA-Z_@]\w*(\.\w+)*)/</span>
<span class="nv">OPERATOR : </span><span class="sr">/^([+\*&amp;|\/\-%=&lt;&gt;:!?]+)([ \t]*)/</span>
<span class="nv">WHITESPACE : </span><span class="sr">/^([ \t]+)/</span>
<span class="nv">COMMENT : </span><span class="sr">/^(((\n?[ \t]*)?#[^\n]*)+)/</span>
<span class="nv">CODE : </span><span class="sr">/^((-|=)&gt;)/</span>
<span class="nv">MULTI_DENT : </span><span class="sr">/^((\n([ \t]*))+)(\.)?/</span>
<span class="nv">LAST_DENTS : </span><span class="sr">/\n([ \t]*)/g</span>
<span class="nv">LAST_DENT : </span><span class="sr">/\n([ \t]*)/</span>
<span class="nv">ASSIGNMENT : </span><span class="sr">/^(:|=)$/</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-49">#</a> </div> <p>Regex-matching-regexes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">REGEX_START : </span><span class="sr">/^\/[^\/ ]/</span>
<span class="nv">REGEX_INTERPOLATION: </span><span class="sr">/([^\\]\$[a-zA-Z_@]|[^\\]\$\{.*[^\\]\})/</span>
<span class="nx">REGEX_FLAGS</span> <span class="o">:</span> <span class="sr">/^[imgy]{0,4}/</span>
<span class="nx">REGEX_ESCAPE</span> <span class="o">:</span> <span class="sr">/\\[^\$]/g</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-49">#</a> </div> <p>Token cleaning regexes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">JS_CLEANER</span> <span class="o">:</span> <span class="sr">/(^`|`$)/g</span>
<span class="nx">MULTILINER</span> <span class="o">:</span> <span class="sr">/\n/g</span>
<span class="nx">STRING_NEWLINES</span> <span class="o">:</span> <span class="sr">/\n[ \t]*/g</span>
<span class="nx">COMMENT_CLEANER</span> <span class="o">:</span> <span class="sr">/(^[ \t]*#|\n[ \t]*$)/mg</span>
<span class="nx">NO_NEWLINE</span> <span class="o">:</span> <span class="sr">/^([+\*&amp;|\/\-%=&lt;&gt;:!.\\][&lt;&gt;=&amp;|]*|and|or|is|isnt|not|delete|typeof|instanceof)$/</span>
<span class="nx">HEREDOC_INDENT</span> <span class="o">:</span> <span class="sr">/^[ \t]+/mg</span></pre></div> </td> </tr> <tr id="section-50"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-50">#</a> </div> <p>Tokens which a regular expression will never immediately follow, but which
<span class="nv">REGEX_FLAGS : </span><span class="sr">/^[imgy]{0,4}/</span>
<span class="nv">REGEX_ESCAPE : </span><span class="sr">/\\[^\$]/g</span></pre></div> </td> </tr> <tr id="section-50"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-50">#</a> </div> <p>Token cleaning regexes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">JS_CLEANER : </span><span class="sr">/(^`|`$)/g</span>
<span class="nv">MULTILINER : </span><span class="sr">/\n/g</span>
<span class="nv">STRING_NEWLINES : </span><span class="sr">/\n[ \t]*/g</span>
<span class="nv">COMMENT_CLEANER : </span><span class="sr">/(^[ \t]*#|\n[ \t]*$)/mg</span>
<span class="nv">NO_NEWLINE : </span><span class="sr">/^([+\*&amp;|\/\-%=&lt;&gt;:!.\\][&lt;&gt;=&amp;|]*|and|or|is|isnt|not|delete|typeof|instanceof)$/</span>
<span class="nv">HEREDOC_INDENT : </span><span class="sr">/^[ \t]+/mg</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-51">#</a> </div> <p>Tokens which a regular expression will never immediately follow, but which
a division operator might.</p>
<p>See: <a href='http://www.mozilla.org/js/language/js20-2002-04/rationale/syntax.html#regular-expressions'>http://www.mozilla.org/js/language/js20-2002-04/rationale/syntax.html#regular-expressions</a></p>
<p>Our list is shorter, due to sans-parentheses method calls.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">NOT_REGEX: </span><span class="p">[</span>
<span class="s1">&#39;NUMBER&#39;</span><span class="p">,</span> <span class="s1">&#39;REGEX&#39;</span><span class="p">,</span> <span class="s1">&#39;++&#39;</span><span class="p">,</span> <span class="s1">&#39;--&#39;</span><span class="p">,</span> <span class="s1">&#39;FALSE&#39;</span><span class="p">,</span> <span class="s1">&#39;NULL&#39;</span><span class="p">,</span> <span class="s1">&#39;TRUE&#39;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-51">#</a> </div> <p>Tokens which could legitimately be invoked or indexed. A opening
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-52">#</a> </div> <p>Tokens which could legitimately be invoked or indexed. A opening
parentheses or bracket following these tokens will be recorded as the start
of a function invocation or indexing operation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CALLABLE: </span><span class="p">[</span><span class="s1">&#39;IDENTIFIER&#39;</span><span class="p">,</span> <span class="s1">&#39;SUPER&#39;</span><span class="p">,</span> <span class="s1">&#39;)&#39;</span><span class="p">,</span> <span class="s1">&#39;]&#39;</span><span class="p">,</span> <span class="s1">&#39;}&#39;</span><span class="p">,</span> <span class="s1">&#39;STRING&#39;</span><span class="p">,</span> <span class="s1">&#39;@&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-52">#</a> </div> <p>Tokens that indicate an access -- keywords immediately following will be
treated as identifiers.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">ACCESSORS: </span><span class="p">[</span><span class="s1">&#39;PROPERTY_ACCESS&#39;</span><span class="p">,</span> <span class="s1">&#39;PROTOTYPE_ACCESS&#39;</span><span class="p">,</span> <span class="s1">&#39;SOAK_ACCESS&#39;</span><span class="p">,</span> <span class="s1">&#39;@&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-53"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-53">#</a> </div> <p>Tokens that, when immediately preceding a <code>WHEN</code>, indicate that the <code>WHEN</code>
of a function invocation or indexing operation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CALLABLE: </span><span class="p">[</span><span class="s1">&#39;IDENTIFIER&#39;</span><span class="p">,</span> <span class="s1">&#39;SUPER&#39;</span><span class="p">,</span> <span class="s1">&#39;)&#39;</span><span class="p">,</span> <span class="s1">&#39;]&#39;</span><span class="p">,</span> <span class="s1">&#39;}&#39;</span><span class="p">,</span> <span class="s1">&#39;STRING&#39;</span><span class="p">,</span> <span class="s1">&#39;@&#39;</span><span class="p">,</span> <span class="s1">&#39;THIS&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-53"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-53">#</a> </div> <p>Tokens that indicate an access -- keywords immediately following will be
treated as identifiers.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">ACCESSORS: </span><span class="p">[</span><span class="s1">&#39;PROPERTY_ACCESS&#39;</span><span class="p">,</span> <span class="s1">&#39;PROTOTYPE_ACCESS&#39;</span><span class="p">,</span> <span class="s1">&#39;SOAK_ACCESS&#39;</span><span class="p">,</span> <span class="s1">&#39;@&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-54">#</a> </div> <p>Tokens that, when immediately preceding a <code>WHEN</code>, indicate that the <code>WHEN</code>
occurs at the start of a line. We disambiguate these from trailing whens to
avoid an ambiguity in the grammar.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">LINE_BREAK: </span><span class="p">[</span><span class="s1">&#39;INDENT&#39;</span><span class="p">,</span> <span class="s1">&#39;OUTDENT&#39;</span><span class="p">,</span> <span class="s1">&#39;TERMINATOR&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-54">#</a> </div> <p>Half-assignments...</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">HALF_ASSIGNMENTS: </span><span class="p">[</span><span class="s1">&#39;-&#39;</span><span class="p">,</span> <span class="s1">&#39;+&#39;</span><span class="p">,</span> <span class="s1">&#39;/&#39;</span><span class="p">,</span> <span class="s1">&#39;*&#39;</span><span class="p">,</span> <span class="s1">&#39;%&#39;</span><span class="p">,</span> <span class="s1">&#39;||&#39;</span><span class="p">,</span> <span class="s1">&#39;&amp;&amp;&#39;</span><span class="p">,</span> <span class="s1">&#39;?&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-55">#</a> </div> <p>Conversions from CoffeeScript operators into JavaScript ones.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CONVERSIONS: </span><span class="p">{</span>
avoid an ambiguity in the grammar.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">LINE_BREAK: </span><span class="p">[</span><span class="s1">&#39;INDENT&#39;</span><span class="p">,</span> <span class="s1">&#39;OUTDENT&#39;</span><span class="p">,</span> <span class="s1">&#39;TERMINATOR&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-55">#</a> </div> <p>Half-assignments...</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">HALF_ASSIGNMENTS: </span><span class="p">[</span><span class="s1">&#39;-&#39;</span><span class="p">,</span> <span class="s1">&#39;+&#39;</span><span class="p">,</span> <span class="s1">&#39;/&#39;</span><span class="p">,</span> <span class="s1">&#39;*&#39;</span><span class="p">,</span> <span class="s1">&#39;%&#39;</span><span class="p">,</span> <span class="s1">&#39;||&#39;</span><span class="p">,</span> <span class="s1">&#39;&amp;&amp;&#39;</span><span class="p">,</span> <span class="s1">&#39;?&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-56">#</a> </div> <p>Conversions from CoffeeScript operators into JavaScript ones.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CONVERSIONS: </span><span class="p">{</span>
<span class="s1">&#39;and&#39;</span><span class="o">:</span> <span class="s1">&#39;&amp;&amp;&#39;</span>
<span class="s1">&#39;or&#39;</span><span class="o">:</span> <span class="s1">&#39;||&#39;</span>
<span class="s1">&#39;is&#39;</span><span class="o">:</span> <span class="s1">&#39;==&#39;</span>

File diff suppressed because it is too large Load Diff

View File

@@ -9,18 +9,18 @@ options: parser.parse process.argv
</code></pre>
<p>Along with an an optional banner for the usage help.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">rules</span><span class="p">,</span> <span class="nx">banner</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nv">banner: </span> <span class="nx">banner</span>
<span class="err">@</span><span class="nv">rules: </span> <span class="nx">build_rules</span><span class="p">(</span><span class="nx">rules</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>Parse the list of arguments, populating an <code>options</code> object with all of the
<span class="vi">@banner: </span> <span class="nx">banner</span>
<span class="vi">@rules: </span> <span class="nx">build_rules</span><span class="p">(</span><span class="nx">rules</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>Parse the list of arguments, populating an <code>options</code> object with all of the
specified options, and returning it. <code>options.arguments</code> will be an array
containing the remaning non-option arguments. This is a simpler API than
many option parsers that allow you to attach callback actions for every
flag. Instead, you're responsible for interpreting the options object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">parse: </span><span class="p">(</span><span class="nx">args</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">options: </span><span class="p">{</span><span class="nv">arguments: </span><span class="p">[]}</span>
<span class="nv">args: </span><span class="nx">normalize_arguments</span> <span class="nx">args</span>
<span class="k">while</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">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="nv">is_option: </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>
<span class="nv">matched_rule: </span><span class="kc">no</span>
<span class="k">for</span> <span class="nx">rule</span> <span class="k">in</span> <span class="err">@</span><span class="nx">rules</span>
<span class="k">for</span> <span class="nx">rule</span> <span class="k">in</span> <span class="nx">@rules</span>
<span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">short_flag</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">long_flag</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">has_argument</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="nv">matched_rule: </span><span class="kc">yes</span>
@@ -30,12 +30,12 @@ flag. Instead, you're responsible for interpreting the options object.</p>
<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
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">-&gt;</span>
<span class="nv">lines: </span><span class="p">[</span><span class="s1">&#39;Available options:&#39;</span><span class="p">]</span>
<span class="nx">lines</span><span class="p">.</span><span class="nx">unshift</span> <span class="s2">&quot;$@banner\n&quot;</span> <span class="k">if</span> <span class="err">@</span><span class="nx">banner</span>
<span class="k">for</span> <span class="nx">rule</span> <span class="k">in</span> <span class="err">@</span><span class="nx">rules</span>
<span class="nx">lines</span><span class="p">.</span><span class="nx">unshift</span> <span class="s2">&quot;$@banner\n&quot;</span> <span class="k">if</span> <span class="nx">@banner</span>
<span class="k">for</span> <span class="nx">rule</span> <span class="k">in</span> <span class="nx">@rules</span>
<span class="nv">spaces: </span> <span class="mi">15</span> <span class="o">-</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">long_flag</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">spaces: </span> <span class="k">if</span> <span class="nx">spaces</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="k">then</span> <span class="p">(</span><span class="s1">&#39; &#39;</span> <span class="k">for</span> <span class="nx">i</span> <span class="k">in</span> <span class="p">[</span><span class="mi">0</span><span class="p">..</span><span class="nx">spaces</span><span class="p">]).</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="nv">let_part: </span><span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">short_flag</span> <span class="k">then</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">short_flag</span> <span class="o">+</span> <span class="s1">&#39;, &#39;</span> <span class="k">else</span> <span class="s1">&#39; &#39;</span>
<span class="nx">lines</span><span class="p">.</span><span class="nx">push</span> <span class="s2">&quot; $let_part${rule.long_flag}$spaces${rule.description}&quot;</span>
<span class="nx">lines</span><span class="p">.</span><span class="nx">push</span> <span class="s2">&quot; $let_part$rule.long_flag$spaces$rule.description&quot;</span>
<span class="s2">&quot;\n${ lines.join(&#39;\n&#39;) }\n&quot;</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <h2>Helpers</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Regex matchers for option flags.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">LONG_FLAG: </span> <span class="sr">/^(--\w[\w\-]+)/</span>
<span class="nv">SHORT_FLAG: </span><span class="sr">/^(-\w)/</span>
<span class="nv">MULTI_FLAG: </span><span class="sr">/^-(\w{2,})/</span>

View File

@@ -8,14 +8,14 @@ Using it looks like this:</p>
<span class="nv">quit: </span><span class="o">-&gt;</span> <span class="nx">process</span><span class="p">.</span><span class="nx">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</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>The main REPL function. <strong>run</strong> is called every time a line of code is entered.
Attempt to evaluate the command. If there's an exception, print it out instead
of exiting.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">run: </span><span class="p">(</span><span class="nx">code</span><span class="p">)</span> <span class="o">-&gt;</span>
of exiting.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">run: </span><span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">try</span>
<span class="nv">val: </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">code</span><span class="p">,</span> <span class="p">{</span><span class="nv">no_wrap: </span><span class="kc">true</span><span class="p">,</span> <span class="nv">globals: </span><span class="kc">true</span><span class="p">,</span> <span class="nv">source: </span><span class="s1">&#39;repl&#39;</span><span class="p">}</span>
<span class="nv">val: </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">(),</span> <span class="p">{</span><span class="nv">no_wrap: </span><span class="kc">true</span><span class="p">,</span> <span class="nv">globals: </span><span class="kc">true</span><span class="p">,</span> <span class="nv">source: </span><span class="s1">&#39;repl&#39;</span><span class="p">}</span>
<span class="nx">p</span> <span class="nx">val</span> <span class="k">if</span> <span class="nx">val</span> <span class="o">isnt</span> <span class="kc">undefined</span>
<span class="k">catch</span> <span class="nx">err</span>
<span class="nx">puts</span> <span class="nx">err</span><span class="p">.</span><span class="nx">stack</span> <span class="o">or</span> <span class="nx">err</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span>
<span class="nx">print</span> <span class="nx">prompt</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Start up the REPL by opening <strong>stdio</strong> and listening for input.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">process</span><span class="p">.</span><span class="nx">stdio</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">&#39;data&#39;</span><span class="p">,</span> <span class="nx">run</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">stdio</span><span class="p">.</span><span class="nx">open</span><span class="p">()</span>
<span class="nx">print</span> <span class="nx">prompt</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Start up the REPL by opening <strong>stdin</strong> and listening for input.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">stdin: </span><span class="nx">process</span><span class="p">.</span><span class="nx">openStdin</span><span class="p">()</span>
<span class="nx">stdin</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">&#39;data&#39;</span><span class="p">,</span> <span class="nx">run</span>
<span class="nx">print</span> <span class="nx">prompt</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

View File

@@ -13,54 +13,54 @@ a time. This could certainly be changed into a single pass through the
stream, with a big ol' efficient switch, but it's much nicer to work with
like this. The order of these passes matters -- indentation must be
corrected before implicit parentheses can be wrapped around blocks of code.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">rewrite: </span><span class="p">(</span><span class="nx">tokens</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nv">tokens: </span><span class="nx">tokens</span>
<span class="err">@</span><span class="nx">adjust_comments</span><span class="p">()</span>
<span class="err">@</span><span class="nx">remove_leading_newlines</span><span class="p">()</span>
<span class="err">@</span><span class="nx">remove_mid_expression_newlines</span><span class="p">()</span>
<span class="err">@</span><span class="nx">close_open_calls_and_indexes</span><span class="p">()</span>
<span class="err">@</span><span class="nx">add_implicit_indentation</span><span class="p">()</span>
<span class="err">@</span><span class="nx">add_implicit_parentheses</span><span class="p">()</span>
<span class="err">@</span><span class="nx">ensure_balance</span><span class="p">(</span><span class="nx">BALANCED_PAIRS</span><span class="p">)</span>
<span class="err">@</span><span class="nx">rewrite_closing_parens</span><span class="p">()</span>
<span class="err">@</span><span class="nx">tokens</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Rewrite the token stream, looking one token ahead and behind.
<span class="vi">@tokens: </span><span class="nx">tokens</span>
<span class="nx">@adjust_comments</span><span class="p">()</span>
<span class="nx">@remove_leading_newlines</span><span class="p">()</span>
<span class="nx">@remove_mid_expression_newlines</span><span class="p">()</span>
<span class="nx">@close_open_calls_and_indexes</span><span class="p">()</span>
<span class="nx">@add_implicit_indentation</span><span class="p">()</span>
<span class="nx">@add_implicit_parentheses</span><span class="p">()</span>
<span class="nx">@ensure_balance</span> <span class="nx">BALANCED_PAIRS</span>
<span class="nx">@rewrite_closing_parens</span><span class="p">()</span>
<span class="nx">@tokens</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Rewrite the token stream, looking one token ahead and behind.
Allow the return value of the block to tell us how many tokens to move
forwards (or backwards) in the stream, to make sure we don't miss anything
as tokens are inserted and removed, and the stream changes length under
our feet.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">scan_tokens: </span><span class="p">(</span><span class="nx">block</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">i: </span><span class="mi">0</span>
<span class="k">while</span> <span class="kc">true</span>
<span class="k">break</span> <span class="nx">unless</span> <span class="err">@</span><span class="nx">tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>
<span class="nv">move: </span><span class="nx">block</span><span class="p">(</span><span class="err">@</span><span class="nx">tokens</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="err">@</span><span class="nx">tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span> <span class="err">@</span><span class="nx">tokens</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="nx">i</span><span class="p">)</span>
<span class="k">break</span> <span class="nx">unless</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>
<span class="nv">move: </span><span class="nx">block</span> <span class="nx">@tokens</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="nx">@tokens</span><span class="p">[</span><span class="nx">i</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">1</span><span class="p">],</span> <span class="nx">i</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>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">adjust_comments: </span><span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">scan_tokens</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">=&gt;</span>
<span class="nx">@scan_tokens</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">=&gt;</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">&#39;COMMENT&#39;</span>
<span class="nv">after: </span> <span class="err">@</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="nv">after: </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">&#39;INDENT&#39;</span>
<span class="err">@</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="err">@</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="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="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">return</span> <span class="mi">1</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">isnt</span> <span class="s1">&#39;TERMINATOR&#39;</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">&#39;INDENT&#39;</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">&#39;OUTDENT&#39;</span>
<span class="err">@</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">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s2">&quot;\n&quot;</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="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">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s2">&quot;\n&quot;</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">else</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">remove_leading_newlines: </span><span class="o">-&gt;</span>
<span class="err">@</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="err">@</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="err">@</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">&#39;TERMINATOR&#39;</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
<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">&#39;TERMINATOR&#39;</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">remove_mid_expression_newlines: </span><span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">scan_tokens</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">=&gt;</span>
<span class="nx">@scan_tokens</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">=&gt;</span>
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">post</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">EXPRESSION_CLOSE</span><span class="p">,</span> <span class="nx">post</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">and</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">&#39;TERMINATOR&#39;</span>
<span class="err">@</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">1</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">1</span>
<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
close.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">close_open_calls_and_indexes: </span><span class="o">-&gt;</span>
<span class="nv">parens: </span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="nv">brackets: </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="err">@</span><span class="nx">scan_tokens</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">=&gt;</span>
<span class="nx">@scan_tokens</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">=&gt;</span>
<span class="k">switch</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">when</span> <span class="s1">&#39;CALL_START&#39;</span> <span class="k">then</span> <span class="nx">parens</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">when</span> <span class="s1">&#39;INDEX_START&#39;</span> <span class="k">then</span> <span class="nx">brackets</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">when</span> <span class="s1">&#39;CALL_START&#39;</span> <span class="k">then</span> <span class="nx">parens</span><span class="p">.</span><span class="nx">push</span> <span class="mi">0</span>
<span class="k">when</span> <span class="s1">&#39;INDEX_START&#39;</span> <span class="k">then</span> <span class="nx">brackets</span><span class="p">.</span><span class="nx">push</span> <span class="mi">0</span>
<span class="k">when</span> <span class="s1">&#39;(&#39;</span> <span class="k">then</span> <span class="nx">parens</span><span class="p">[</span><span class="nx">parens</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">when</span> <span class="s1">&#39;[&#39;</span> <span class="k">then</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">when</span> <span class="s1">&#39;)&#39;</span>
@@ -79,67 +79,71 @@ close.</p> </td> <td class="code"> <div cl
Insert the implicit parentheses here, so that the parser doesn't have to
deal with them.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">add_implicit_parentheses: </span><span class="o">-&gt;</span>
<span class="nv">stack: </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="nv">calls: </span><span class="mi">0</span>
<span class="err">@</span><span class="nx">scan_tokens</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">=&gt;</span>
<span class="nv">calls: </span> <span class="mi">0</span>
<span class="nv">parens: </span><span class="mi">0</span>
<span class="nv">start_parens: </span><span class="mi">0</span>
<span class="nx">@scan_tokens</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">=&gt;</span>
<span class="nv">tag: </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">switch</span> <span class="nx">tag</span>
<span class="k">when</span> <span class="s1">&#39;CALL_START&#39;</span> <span class="k">then</span> <span class="nv">calls: </span><span class="o">+</span> <span class="mi">1</span>
<span class="k">when</span> <span class="s1">&#39;CALL_END&#39;</span> <span class="k">then</span> <span class="nv">calls: </span><span class="o">-</span> <span class="mi">1</span>
<span class="k">when</span> <span class="s1">&#39;INDENT&#39;</span> <span class="k">then</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">when</span> <span class="s1">&#39;(&#39;</span> <span class="k">then</span> <span class="nv">parens: </span><span class="o">+</span> <span class="mi">1</span>
<span class="k">when</span> <span class="s1">&#39;)&#39;</span> <span class="k">then</span> <span class="nv">parens: </span><span class="o">-</span> <span class="mi">1</span>
<span class="k">when</span> <span class="s1">&#39;INDENT&#39;</span> <span class="k">then</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="mi">0</span>
<span class="k">when</span> <span class="s1">&#39;OUTDENT&#39;</span>
<span class="nv">last: </span><span class="nx">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
<span class="nx">stack</span><span class="p">[</span><span class="nx">stack</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="nx">last</span>
<span class="nv">open: </span><span class="nx">stack</span><span class="p">[</span><span class="nx">stack</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">&gt;</span> <span class="mi">0</span>
<span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;CALL_END&#39;</span> <span class="o">and</span> <span class="nx">calls</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="o">and</span> <span class="nx">open</span>
<span class="nx">stack</span><span class="p">[</span><span class="nx">stack</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="err">@</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">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;CALL_END&#39;</span><span class="p">,</span> <span class="s1">&#39;)&#39;</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="k">return</span> <span class="mi">2</span>
<span class="k">if</span> <span class="o">!</span><span class="nx">post</span><span class="o">?</span> <span class="o">or</span> <span class="nx">include</span> <span class="nx">IMPLICIT_END</span><span class="p">,</span> <span class="nx">tag</span>
<span class="k">if</span> <span class="o">!</span><span class="nx">post</span><span class="o">?</span> <span class="o">or</span> <span class="p">(</span><span class="nx">start_parens</span> <span class="o">&gt;</span> <span class="nx">parens</span><span class="p">)</span> <span class="o">or</span> <span class="p">(</span><span class="nx">start_parens</span> <span class="o">is</span> <span class="nx">parens</span> <span class="o">and</span> <span class="nx">include</span> <span class="nx">IMPLICIT_END</span><span class="p">,</span> <span class="nx">tag</span><span class="p">)</span>
<span class="k">return</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;INDENT&#39;</span> <span class="o">and</span> <span class="nx">prev</span> <span class="o">and</span> <span class="nx">include</span> <span class="nx">IMPLICIT_BLOCK</span><span class="p">,</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">return</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;OUTDENT&#39;</span> <span class="o">and</span> <span class="nx">token</span><span class="p">.</span><span class="nx">generated</span>
<span class="k">if</span> <span class="nx">open</span> <span class="o">or</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;INDENT&#39;</span>
<span class="nv">idx: </span><span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;OUTDENT&#39;</span> <span class="k">then</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span> <span class="k">else</span> <span class="nx">i</span>
<span class="nv">stack_pointer: </span><span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;INDENT&#39;</span> <span class="k">then</span> <span class="mi">2</span> <span class="k">else</span> <span class="mi">1</span>
<span class="k">for</span> <span class="nx">tmp</span> <span class="k">in</span> <span class="p">[</span><span class="mi">0</span><span class="p">...</span><span class="nx">stack</span><span class="p">[</span><span class="nx">stack</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="nx">stack_pointer</span><span class="p">]]</span>
<span class="err">@</span><span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">idx</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;CALL_END&#39;</span><span class="p">,</span> <span class="s1">&#39;)&#39;</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="p">(</span><span class="nx">idx</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;CALL_END&#39;</span><span class="p">,</span> <span class="s1">&#39;)&#39;</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">size: </span><span class="nx">stack</span><span class="p">[</span><span class="nx">stack</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="nx">stack_pointer</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span>
<span class="nx">stack</span><span class="p">[</span><span class="nx">stack</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="nx">stack_pointer</span><span class="p">]</span><span class="o">:</span> <span class="mi">0</span>
<span class="k">return</span> <span class="nx">size</span>
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">prev</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_FUNC</span><span class="p">,</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">and</span> <span class="nx">include</span> <span class="nx">IMPLICIT_CALL</span><span class="p">,</span> <span class="nx">tag</span>
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">prev</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_FUNC</span><span class="p">,</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_CALL</span><span class="p">,</span> <span class="nx">tag</span><span class="p">)</span>
<span class="nv">calls: </span><span class="mi">0</span>
<span class="err">@</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">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;CALL_START&#39;</span><span class="p">,</span> <span class="s1">&#39;(&#39;</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">start_parens: </span><span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;(&#39;</span> <span class="k">then</span> <span class="nx">parens</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">else</span> <span class="nx">parens</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">&#39;CALL_START&#39;</span><span class="p">,</span> <span class="s1">&#39;(&#39;</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">stack</span><span class="p">[</span><span class="nx">stack</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">2</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
blocks, so it doesn't need to. ')' can close a single-line block,
but we need to make sure it's balanced.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">add_implicit_indentation: </span><span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">scan_tokens</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">=&gt;</span>
<span class="nx">@scan_tokens</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">=&gt;</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>
<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">&#39;INDENT&#39;</span> <span class="o">and</span>
<span class="o">not</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">is</span> <span class="s1">&#39;ELSE&#39;</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">&#39;IF&#39;</span><span class="p">)</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="err">@</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">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;INDENT&#39;</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="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;INDENT&#39;</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">idx: </span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span>
<span class="nv">parens: </span><span class="mi">0</span>
<span class="k">while</span> <span class="kc">true</span>
<span class="nv">idx: </span><span class="o">+</span> <span class="mi">1</span>
<span class="nv">tok: </span><span class="err">@</span><span class="nx">tokens</span><span class="p">[</span><span class="nx">idx</span><span class="p">]</span>
<span class="nv">pre: </span><span class="err">@</span><span class="nx">tokens</span><span class="p">[</span><span class="nx">idx</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
<span class="nv">tok: </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">idx</span><span class="p">]</span>
<span class="nv">pre: </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">idx</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
<span class="k">if</span> <span class="p">(</span><span class="o">not</span> <span class="nx">tok</span> <span class="o">or</span>
<span class="p">(</span><span class="nx">include</span><span class="p">(</span><span class="nx">SINGLE_CLOSERS</span><span class="p">,</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">and</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">&#39;;&#39;</span><span class="p">)</span> <span class="o">or</span>
<span class="p">(</span><span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;)&#39;</span> <span class="o">&amp;&amp;</span> <span class="nx">parens</span> <span class="o">is</span> <span class="mi">0</span><span class="p">))</span> <span class="o">and</span>
<span class="p">(</span><span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;)&#39;</span> <span class="o">and</span> <span class="nx">parens</span> <span class="o">is</span> <span class="mi">0</span><span class="p">))</span> <span class="o">and</span>
<span class="o">not</span> <span class="p">(</span><span class="nx">starter</span> <span class="o">is</span> <span class="s1">&#39;ELSE&#39;</span> <span class="o">and</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;ELSE&#39;</span><span class="p">)</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">&quot;,&quot;</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="err">@</span><span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">insertion</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;OUTDENT&#39;</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: </span><span class="p">[</span><span class="s1">&#39;OUTDENT&#39;</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>
<span class="k">break</span>
<span class="nv">parens: </span><span class="o">+</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;(&#39;</span>
<span class="nv">parens: </span><span class="o">-</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;)&#39;</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">&#39;THEN&#39;</span>
<span class="err">@</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">1</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">1</span>
<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">ensure_balance: </span><span class="p">(</span><span class="nx">pairs</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">levels: </span><span class="p">{}</span>
<span class="nv">open_line: </span><span class="p">{}</span>
<span class="err">@</span><span class="nx">scan_tokens</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">=&gt;</span>
<span class="nx">@scan_tokens</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">=&gt;</span>
<span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">pairs</span>
<span class="p">[</span><span class="nx">open</span><span class="p">,</span> <span class="nx">close</span><span class="p">]</span><span class="o">:</span> <span class="nx">pair</span>
<span class="nx">levels</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span><span class="o">:</span> <span class="o">or</span> <span class="mi">0</span>
@@ -164,16 +168,16 @@ inwards, safely. The steps to accomplish this are:</p>
<ol>
<li>Check that all paired tokens are balanced and in order.</li>
<li>Rewrite the stream with a stack: if you see an '(' or INDENT, add it
to the stack. If you see an ')' or OUTDENT, pop the stack and replace
<li>Rewrite the stream with a stack: if you see an <code>EXPRESSION_START</code>, add it
to the stack. If you see an <code>EXPRESSION_END</code>, pop the stack and replace
it with the inverse of what we've just popped.</li>
<li>Keep track of "debt" for tokens that we fake, to make sure we end
<li>Keep track of "debt" for tokens that we manufacture, to make sure we end
up balanced in the end.</li>
</ol> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">rewrite_closing_parens: </span><span class="o">-&gt;</span>
<span class="nv">stack: </span><span class="p">[]</span>
<span class="nv">debt: </span> <span class="p">{}</span>
<span class="p">(</span><span class="nx">debt</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span><span class="o">:</span> <span class="mi">0</span><span class="p">)</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">INVERSES</span>
<span class="err">@</span><span class="nx">scan_tokens</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">=&gt;</span>
<span class="nx">@scan_tokens</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">=&gt;</span>
<span class="nv">tag: </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="nv">inv: </span><span class="nx">INVERSES</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="k">if</span> <span class="nx">include</span> <span class="nx">EXPRESSION_START</span><span class="p">,</span> <span class="nx">tag</span>
@@ -182,7 +186,7 @@ up balanced in the end.</li>
<span class="k">else</span> <span class="k">if</span> <span class="nx">include</span> <span class="nx">EXPRESSION_END</span><span class="p">,</span> <span class="nx">tag</span>
<span class="k">if</span> <span class="nx">debt</span><span class="p">[</span><span class="nx">inv</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span>
<span class="nx">debt</span><span class="p">[</span><span class="nx">inv</span><span class="p">]</span><span class="o">:</span> <span class="o">-</span> <span class="mi">1</span>
<span class="err">@</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="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>
<span class="k">else</span>
<span class="nv">match: </span><span class="nx">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
@@ -190,7 +194,7 @@ up balanced in the end.</li>
<span class="k">return</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="nx">INVERSES</span><span class="p">[</span><span class="nx">mtag</span><span class="p">]</span>
<span class="nx">debt</span><span class="p">[</span><span class="nx">mtag</span><span class="p">]</span><span class="o">:</span> <span class="o">+</span> <span class="mi">1</span>
<span class="nv">val: </span><span class="k">if</span> <span class="nx">mtag</span> <span class="o">is</span> <span class="s1">&#39;INDENT&#39;</span> <span class="k">then</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">else</span> <span class="nx">INVERSES</span><span class="p">[</span><span class="nx">mtag</span><span class="p">]</span>
<span class="err">@</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="nx">INVERSES</span><span class="p">[</span><span class="nx">mtag</span><span class="p">],</span> <span class="nx">val</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="p">[</span><span class="nx">INVERSES</span><span class="p">[</span><span class="nx">mtag</span><span class="p">],</span> <span class="nx">val</span><span class="p">]</span>
<span class="k">return</span> <span class="mi">1</span>
<span class="k">else</span>
<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> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</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">&#39;(&#39;</span><span class="p">,</span> <span class="s1">&#39;)&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;[&#39;</span><span class="p">,</span> <span class="s1">&#39;]&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;{&#39;</span><span class="p">,</span> <span class="s1">&#39;}&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;INDENT&#39;</span><span class="p">,</span> <span class="s1">&#39;OUTDENT&#39;</span><span class="p">],</span>
@@ -202,6 +206,7 @@ look things up from either end.</p> </td> <td class="cod
<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-18"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-18">#</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-19"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-19">#</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-20"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-20">#</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">&#39;CATCH&#39;</span><span class="p">,</span> <span class="s1">&#39;WHEN&#39;</span><span class="p">,</span> <span class="s1">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s1">&#39;FINALLY&#39;</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">EXPRESSION_END</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, 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">&#39;IDENTIFIER&#39;</span><span class="p">,</span> <span class="s1">&#39;SUPER&#39;</span><span class="p">,</span> <span class="s1">&#39;)&#39;</span><span class="p">,</span> <span class="s1">&#39;CALL_END&#39;</span><span class="p">,</span> <span class="s1">&#39;]&#39;</span><span class="p">,</span> <span class="s1">&#39;INDEX_END&#39;</span><span class="p">,</span> <span class="s1">&#39;&lt;-&#39;</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>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">&#39;IDENTIFIER&#39;</span><span class="p">,</span> <span class="s1">&#39;NUMBER&#39;</span><span class="p">,</span> <span class="s1">&#39;STRING&#39;</span><span class="p">,</span> <span class="s1">&#39;JS&#39;</span><span class="p">,</span> <span class="s1">&#39;REGEX&#39;</span><span class="p">,</span> <span class="s1">&#39;NEW&#39;</span><span class="p">,</span> <span class="s1">&#39;PARAM_START&#39;</span><span class="p">,</span>
<span class="s1">&#39;TRY&#39;</span><span class="p">,</span> <span class="s1">&#39;DELETE&#39;</span><span class="p">,</span> <span class="s1">&#39;TYPEOF&#39;</span><span class="p">,</span> <span class="s1">&#39;SWITCH&#39;</span><span class="p">,</span> <span class="s1">&#39;EXTENSION&#39;</span><span class="p">,</span>
<span class="s1">&#39;TRUE&#39;</span><span class="p">,</span> <span class="s1">&#39;FALSE&#39;</span><span class="p">,</span> <span class="s1">&#39;YES&#39;</span><span class="p">,</span> <span class="s1">&#39;NO&#39;</span><span class="p">,</span> <span class="s1">&#39;ON&#39;</span><span class="p">,</span> <span class="s1">&#39;OFF&#39;</span><span class="p">,</span> <span class="s1">&#39;!&#39;</span><span class="p">,</span> <span class="s1">&#39;!!&#39;</span><span class="p">,</span> <span class="s1">&#39;NOT&#39;</span><span class="p">,</span>
<span class="s1">&#39;THIS&#39;</span><span class="p">,</span> <span class="s1">&#39;NULL&#39;</span><span class="p">,</span>
<span class="s1">&#39;@&#39;</span><span class="p">,</span> <span class="s1">&#39;-&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;=&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;[&#39;</span><span class="p">,</span> <span class="s1">&#39;(&#39;</span><span class="p">,</span> <span class="s1">&#39;{&#39;</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 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">&#39;-&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;=&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;{&#39;</span><span class="p">,</span> <span class="s1">&#39;[&#39;</span><span class="p">,</span> <span class="s1">&#39;,&#39;</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 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">&#39;IF&#39;</span><span class="p">,</span> <span class="s1">&#39;UNLESS&#39;</span><span class="p">,</span> <span class="s1">&#39;FOR&#39;</span><span class="p">,</span> <span class="s1">&#39;WHILE&#39;</span><span class="p">,</span> <span class="s1">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s1">&#39;INDENT&#39;</span><span class="p">,</span> <span class="s1">&#39;OUTDENT&#39;</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>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">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s2">&quot;-&gt;&quot;</span><span class="p">,</span> <span class="s2">&quot;=&gt;&quot;</span><span class="p">,</span> <span class="s1">&#39;TRY&#39;</span><span class="p">,</span> <span class="s1">&#39;FINALLY&#39;</span><span class="p">,</span> <span class="s1">&#39;THEN&#39;</span><span class="p">]</span>
<span class="nv">SINGLE_CLOSERS: </span><span class="p">[</span><span class="s1">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s1">&#39;CATCH&#39;</span><span class="p">,</span> <span class="s1">&#39;FINALLY&#39;</span><span class="p">,</span> <span class="s1">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s1">&#39;OUTDENT&#39;</span><span class="p">,</span> <span class="s1">&#39;LEADING_WHEN&#39;</span><span class="p">]</span>

View File

@@ -5,38 +5,44 @@ and has a reference to its parent enclosing scope. In this way, we know which
variables are new and need to be declared with <code>var</code>, and which are shared
with the outside.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-2">#</a> </div> <p>Set up exported variables for both <strong>Node.js</strong> and the browser.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">this</span><span class="p">.</span><span class="nv">exports: </span><span class="k">this</span> <span class="nx">unless</span> <span class="nx">process</span><span class="o">?</span>
<span class="nv">exports.Scope: </span><span class="nx">class</span> <span class="nx">Scope</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>Initialize a scope with its parent, for lookups up the chain,
<span class="nv">exports.Scope: </span><span class="nx">class</span> <span class="nx">Scope</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 top-level <strong>Scope</strong> object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="vi">@root: </span><span class="kc">null</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Initialize a scope with its parent, for lookups up the chain,
as well as a reference to the <strong>Expressions</strong> node is belongs to, which is
where it should declare its variables, and a reference to the function that
it wraps.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">parent</span><span class="p">,</span> <span class="nx">expressions</span><span class="p">,</span> <span class="nx">method</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="p">[</span><span class="err">@</span><span class="nx">parent</span><span class="p">,</span> <span class="err">@</span><span class="nx">expressions</span><span class="p">,</span> <span class="err">@</span><span class="nx">method</span><span class="p">]</span><span class="o">:</span> <span class="p">[</span><span class="nx">parent</span><span class="p">,</span> <span class="nx">expressions</span><span class="p">,</span> <span class="nx">method</span><span class="p">]</span>
<span class="err">@</span><span class="nv">variables: </span><span class="p">{}</span>
<span class="err">@</span><span class="nv">temp_var: </span><span class="k">if</span> <span class="err">@</span><span class="nx">parent</span> <span class="k">then</span> <span class="err">@</span><span class="nx">parent</span><span class="p">.</span><span class="nx">temp_var</span> <span class="k">else</span> <span class="s1">&#39;_a&#39;</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Look up a variable name in lexical scope, and declare it if it does not
<span class="p">[</span><span class="nx">@parent</span><span class="p">,</span> <span class="nx">@expressions</span><span class="p">,</span> <span class="nx">@method</span><span class="p">]</span><span class="o">:</span> <span class="p">[</span><span class="nx">parent</span><span class="p">,</span> <span class="nx">expressions</span><span class="p">,</span> <span class="nx">method</span><span class="p">]</span>
<span class="vi">@variables: </span><span class="p">{}</span>
<span class="k">if</span> <span class="nx">@parent</span>
<span class="vi">@temp_var: </span><span class="nx">@parent</span><span class="p">.</span><span class="nx">temp_var</span>
<span class="k">else</span>
<span class="nv">Scope.root: </span><span class="k">this</span>
<span class="vi">@temp_var: </span><span class="s1">&#39;_a&#39;</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Look up a variable name in lexical scope, and declare it if it does not
already exist.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">find: </span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="kc">true</span> <span class="k">if</span> <span class="err">@</span><span class="nx">check</span> <span class="nx">name</span>
<span class="err">@</span><span class="nx">variables</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span><span class="o">:</span> <span class="s1">&#39;var&#39;</span>
<span class="kc">false</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Reserve a variable name as originating from a function parameter for this
<span class="k">return</span> <span class="kc">true</span> <span class="k">if</span> <span class="nx">@check</span> <span class="nx">name</span>
<span class="nx">@variables</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span><span class="o">:</span> <span class="s1">&#39;var&#39;</span>
<span class="kc">false</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Test variables and return true the first time fn(v, k) returns true</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">any: </span><span class="p">(</span><span class="nx">fn</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">for</span> <span class="nx">v</span><span class="p">,</span> <span class="nx">k</span> <span class="k">of</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">fn</span><span class="p">(</span><span class="nx">v</span><span class="p">,</span> <span class="nx">k</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">true</span>
<span class="k">return</span> <span class="kc">false</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Reserve a variable name as originating from a function parameter for this
scope. No <code>var</code> required for internal references.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">parameter: </span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">variables</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span><span class="o">:</span> <span class="s1">&#39;param&#39;</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Just check to see if a variable has already been declared, without reserving.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">check: </span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="kc">true</span> <span class="k">if</span> <span class="err">@</span><span class="nx">variables</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span>
<span class="o">!!</span><span class="p">(</span><span class="err">@</span><span class="nx">parent</span> <span class="o">and</span> <span class="err">@</span><span class="nx">parent</span><span class="p">.</span><span class="nx">check</span><span class="p">(</span><span class="nx">name</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>If we need to store an intermediate result, find an available name for a
<span class="nx">@variables</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span><span class="o">:</span> <span class="s1">&#39;param&#39;</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Just check to see if a variable has already been declared, without reserving.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">check: </span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="kc">true</span> <span class="k">if</span> <span class="nx">@variables</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span>
<span class="o">!!</span><span class="p">(</span><span class="nx">@parent</span> <span class="o">and</span> <span class="nx">@parent</span><span class="p">.</span><span class="nx">check</span><span class="p">(</span><span class="nx">name</span><span class="p">))</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>If we need to store an intermediate result, find an available name for a
compiler-generated variable. <code>_a</code>, <code>_b</code>, and so on...</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">free_variable: </span><span class="o">-&gt;</span>
<span class="k">while</span> <span class="err">@</span><span class="nx">check</span> <span class="err">@</span><span class="nx">temp_var</span>
<span class="nv">ordinal: </span><span class="mi">1</span> <span class="o">+</span> <span class="nb">parseInt</span> <span class="err">@</span><span class="nx">temp_var</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span> <span class="mi">36</span>
<span class="err">@</span><span class="nv">temp_var: </span><span class="s1">&#39;_&#39;</span> <span class="o">+</span> <span class="nx">ordinal</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="mi">36</span><span class="p">).</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\d/g</span><span class="p">,</span> <span class="s1">&#39;a&#39;</span><span class="p">)</span>
<span class="err">@</span><span class="nx">variables</span><span class="p">[</span><span class="err">@</span><span class="nx">temp_var</span><span class="p">]</span><span class="o">:</span> <span class="s1">&#39;var&#39;</span>
<span class="err">@</span><span class="nx">temp_var</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Ensure that an assignment is made at the top of this scope
(or at the top-level scope, if requested).</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">assign: </span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">top_level</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="err">@</span><span class="nx">parent</span><span class="p">.</span><span class="nx">assign</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">top_level</span><span class="p">)</span> <span class="k">if</span> <span class="nx">top_level</span> <span class="o">and</span> <span class="err">@</span><span class="nx">parent</span>
<span class="err">@</span><span class="nx">variables</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span><span class="o">:</span> <span class="p">{</span><span class="nv">value: </span><span class="nx">value</span><span class="p">,</span> <span class="nv">assigned: </span><span class="kc">true</span><span class="p">}</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Does this scope reference any variables that need to be declared in the
<span class="k">while</span> <span class="nx">@check</span> <span class="nx">@temp_var</span>
<span class="nv">ordinal: </span><span class="mi">1</span> <span class="o">+</span> <span class="nb">parseInt</span> <span class="nx">@temp_var</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span> <span class="mi">36</span>
<span class="vi">@temp_var: </span><span class="s1">&#39;_&#39;</span> <span class="o">+</span> <span class="nx">ordinal</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="mi">36</span><span class="p">).</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\d/g</span><span class="p">,</span> <span class="s1">&#39;a&#39;</span><span class="p">)</span>
<span class="nx">@variables</span><span class="p">[</span><span class="nx">@temp_var</span><span class="p">]</span><span class="o">:</span> <span class="s1">&#39;var&#39;</span>
<span class="nx">@temp_var</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Ensure that an assignment is made at the top of this scope
(or at the top-level scope, if requested).</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">assign: </span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">@variables</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span><span class="o">:</span> <span class="p">{</span><span class="nv">value: </span><span class="nx">value</span><span class="p">,</span> <span class="nv">assigned: </span><span class="kc">true</span><span class="p">}</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Does this scope reference any variables that need to be declared in the
given function body?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">has_declarations: </span><span class="p">(</span><span class="nx">body</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">body</span> <span class="o">is</span> <span class="err">@</span><span class="nx">expressions</span> <span class="o">and</span> <span class="err">@</span><span class="nx">declared_variables</span><span class="p">().</span><span class="nx">length</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Does this scope reference any assignments that need to be declared at the
<span class="nx">body</span> <span class="o">is</span> <span class="nx">@expressions</span> <span class="o">and</span> <span class="nx">@any</span> <span class="p">(</span><span class="nx">k</span><span class="p">,</span> <span class="nx">val</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">val</span> <span class="o">is</span> <span class="s1">&#39;var&#39;</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>Does this scope reference any assignments that need to be declared at the
top of the given function body?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">has_assignments: </span><span class="p">(</span><span class="nx">body</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">body</span> <span class="o">is</span> <span class="err">@</span><span class="nx">expressions</span> <span class="o">and</span> <span class="err">@</span><span class="nx">assigned_variables</span><span class="p">().</span><span class="nx">length</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Return the list of variables first declared in this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">declared_variables: </span><span class="o">-&gt;</span>
<span class="p">(</span><span class="nx">key</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="err">@</span><span class="nx">variables</span> <span class="k">when</span> <span class="nx">val</span> <span class="o">is</span> <span class="s1">&#39;var&#39;</span><span class="p">).</span><span class="nx">sort</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>Return the list of assignments that are supposed to be made at the top
<span class="nx">body</span> <span class="o">is</span> <span class="nx">@expressions</span> <span class="o">and</span> <span class="nx">@any</span> <span class="p">(</span><span class="nx">k</span><span class="p">,</span> <span class="nx">val</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">val</span><span class="p">.</span><span class="nx">assigned</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>Return the list of variables first declared in this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">declared_variables: </span><span class="o">-&gt;</span>
<span class="p">(</span><span class="nx">key</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">val</span> <span class="o">is</span> <span class="s1">&#39;var&#39;</span><span class="p">).</span><span class="nx">sort</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</a> </div> <p>Return the list of assignments that are supposed to be made at the top
of this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">assigned_variables: </span><span class="o">-&gt;</span>
<span class="s2">&quot;$key = ${val.value}&quot;</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="err">@</span><span class="nx">variables</span> <span class="k">when</span> <span class="nx">val</span><span class="p">.</span><span class="nx">assigned</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>Compile the JavaScript for all of the variable declarations in this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compiled_declarations: </span><span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">declared_variables</span><span class="p">().</span><span class="nx">join</span> <span class="s1">&#39;, &#39;</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</a> </div> <p>Compile the JavaScript for all of the variable assignments in this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compiled_assignments: </span><span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">assigned_variables</span><span class="p">().</span><span class="nx">join</span> <span class="s1">&#39;, &#39;</span>
<span class="s2">&quot;$key = $val.value&quot;</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">val</span><span class="p">.</span><span class="nx">assigned</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>Compile the JavaScript for all of the variable declarations in this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compiled_declarations: </span><span class="o">-&gt;</span>
<span class="nx">@declared_variables</span><span class="p">().</span><span class="nx">join</span> <span class="s1">&#39;, &#39;</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</a> </div> <p>Compile the JavaScript for all of the variable assignments in this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compiled_assignments: </span><span class="o">-&gt;</span>
<span class="nx">@assigned_variables</span><span class="p">().</span><span class="nx">join</span> <span class="s1">&#39;, &#39;</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

File diff suppressed because one or more lines are too long

View File

@@ -63,6 +63,7 @@
<a href="#cake">Cake, and Cakefiles</a>
<a href="#scripts">"text/coffeescript" Script Tags</a>
<a href="#resources">Resources</a>
<a href="#webchat">Web Chat (IRC)</a>
<a href="#change_log">Change Log</a>
</div>
</div>
@@ -129,7 +130,7 @@ alert reverse '.eeffoC yrT'</textarea></div>
<p>
<b>Latest Version:</b>
<a href="http://github.com/jashkenas/coffee-script/tarball/0.5.6">0.5.6</a>
<a href="http://github.com/jashkenas/coffee-script/tarball/0.6.1">0.6.1</a>
</p>
<h2>
@@ -170,12 +171,12 @@ alert reverse '.eeffoC yrT'</textarea></div>
</p>
<p>
To install, first make sure you have a working version of
<a href="http://nodejs.org/">Node.js</a> version 0.1.33 or higher.
To install, first make sure you have a working copy of the latest tagged version of
<a href="http://nodejs.org/">Node.js</a>, currently <b>0.1.90</b> or higher.
Then clone the CoffeeScript
<a href="http://github.com/jashkenas/coffee-script">source repository</a>
from GitHub, or download the latest
release: <a href="http://github.com/jashkenas/coffee-script/tarball/0.5.6">0.5.6</a>.
release: <a href="http://github.com/jashkenas/coffee-script/tarball/0.6.1">0.6.1</a>.
To install the CoffeeScript compiler system-wide
under <tt>/usr/local</tt>, open the directory and run:
</p>
@@ -432,7 +433,7 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
<%= code_for('conditionals') %>
<p>
You can assign a variable to a half-expression to perform an operation
like Ruby's <tt>||=</tt>, which only assigns a value to a variable
like Ruby's <tt>||=</tt>, which only assigns a value to a variable
if the variable's current value is falsy.
</p>
@@ -638,6 +639,10 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
is converted into a call against the immediate ancestor's method of the same name.
</p>
<%= code_for('prototypes', '"one_two".dasherize()') %>
<p>
Finally, you may assign Class-level (static) properties within a class
definition by using<br /><tt>@property: value</tt>
</p>
<p>
<span id="pattern_matching" class="bookmark"></span>
@@ -838,7 +843,7 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
<tt>bin/cake build</tt> to rebuild the CoffeeScript compiler, and <br />
<tt>bin/cake build:parser</tt> to regenerate the Jison parser if you're
working on the grammar. <br /><br />
<tt>bin/cake build:full</tt> is a good command to run when you're working
<tt>git checkout lib &amp;&amp; bin/cake build:full</tt> is a good command to run when you're working
on the core language. It'll refresh the lib directory
(in case you broke something), build your altered compiler, use that to
rebuild itself (a good sanity test) and then run all of the tests. If
@@ -856,20 +861,66 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
<li>
<b>defunkt</b>'s <a href="http://github.com/defunkt/coffee-mode">CoffeeScript Major Mode</a>
&mdash; a Emacs major mode that provides syntax highlighting, indentation
support, and some bonus commands. (For Vim and TextMate highlighters,
see the <tt>extras</tt> directory of the main repository.)
support, and some bonus commands.
</li>
<li>
<b>jashkenas</b>'s <a href="http://github.com/jashkenas/coffee-script-tmbundle">CoffeeScript TextMate Bundle</a>
&mdash; which provides syntax highlighting, snippet expansion, and the
ability to run bits of CoffeeScript from within TextMate itself.
</li>
<li>
<b>kchmck</b>'s <a href="http://github.com/kchmck/vim-coffee-script">Vim CoffeeScript</a>
&mdash; which adds Vim syntax highlighting and indentation support.
</li>
<li>
<b>mattly</b>'s <a href="http://github.com/mattly/rack-coffee">rack-coffee</a>
&mdash; a small Rack middleware for serving CoffeeScript files as
compiled JavaScript on the fly.
</li>
<li>
<b>jnicklas</b>'s <a href="http://github.com/jnicklas/bistro_car">BistroCar</a>
&mdash; a plugin that serves and bundles CoffeeScript from within your
Rails application.
</li>
<li>
<b>inem</b> and <b>gerad</b>'s <a href="http://github.com/gerad/coffee-haml-filter">coffee-haml-filter</a>
&mdash; a custom filter for rendering CoffeeScript inline within
<a href="http://haml-lang.com/">HAML</a> templates.
</li>
</ul>
<h2>
<span id="webchat" class="bookmark"></span>
Web Chat (IRC)
</h2>
<p>
Quick help and advice can usually be found in the CoffeeScript IRC room.
Join <tt>#coffeescript</tt> on <tt>irc.freenode.net</tt>, or click the
button below to open a webchat session on this page.
</p>
<p>
<button id="open_webchat">click to open #coffeescript</button>
</p>
<h2>
<span id="change_log" class="bookmark"></span>
Change Log
</h2>
<p>
<b class="header" style="margin-top: 20px;">0.6.1</b>
Upgraded CoffeeScript for compatibility with the new Node.js <b>v0.1.90</b>
series.
</p>
<p>
<b class="header" style="margin-top: 20px;">0.6.0</b>
Trailing commas are now allowed, a-la Python. Static
properties may be assigned directly within class definitions,
using <tt>@property</tt> notation.
</p>
<p>
<b class="header" style="margin-top: 20px;">0.5.6</b>
@@ -1135,6 +1186,9 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
$('.navigation .minimize').click ->
document.body.className: 'minimized'
$('#open_webchat').click ->
$(this).replaceWith $('<iframe src="http://webchat.freenode.net/?channels=coffeescript" width="625" height="400"></iframe>')
compile_source()
</script>

View File

@@ -2,20 +2,20 @@
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, food, lunch, roid, roid2;
// Eat lunch.
lunch = (function() {
_a = []; _b = ['toast', 'cheese', 'wine'];
for (_c = 0, _d = _b.length; _c < _d; _c++) {
food = _b[_c];
_a = []; _c = ['toast', 'cheese', 'wine'];
for (_b = 0, _d = _c.length; _b < _d; _b++) {
food = _c[_b];
_a.push(eat(food));
}
return _a;
}).call(this);
})();
// Naive collision detection.
_e = asteroids;
for (_f = 0, _g = _e.length; _f < _g; _f++) {
roid = _e[_f];
_h = asteroids;
for (_i = 0, _j = _h.length; _i < _j; _i++) {
roid2 = _h[_i];
_f = asteroids;
for (_e = 0, _g = _f.length; _e < _g; _e++) {
roid = _f[_e];
_i = asteroids;
for (_h = 0, _j = _i.length; _h < _j; _h++) {
roid2 = _i[_h];
if (roid !== roid2) {
if (roid.overlaps(roid2)) {
roid.explode();

View File

@@ -1,11 +1,12 @@
(function(){
var get_source, url;
url = "documentation/coffee/binding.coffee";
get_source = (function(func, obj, args) {
var __slice = Array.prototype.slice, __bind = function(func, obj, args) {
return function() {
return func.apply(obj, args.concat(Array.prototype.slice.call(arguments, 0)));
return func.apply(obj || {}, args ? args.concat(__slice.call(arguments, 0)) : arguments);
};
}(jQuery.get, jQuery, [url]));
};
url = "documentation/coffee/binding.coffee";
get_source = __bind(jQuery.get, jQuery, [url]);
get_source(function(response) {
return alert(response);
});

View File

@@ -1,9 +1,9 @@
(function(){
task('test', 'run each of the unit tests', function() {
var _a, _b, _c, _d, test;
_a = []; _b = test_files;
for (_c = 0, _d = _b.length; _c < _d; _c++) {
test = _b[_c];
_a = []; _c = test_files;
for (_b = 0, _d = _c.length; _b < _d; _b++) {
test = _c[_b];
_a.push(fs.readFile(test, function(err, code) {
return eval(coffee.compile(code));
}));

View File

@@ -8,5 +8,5 @@
_a.push(name);
}}
return _a;
}).call(this).slice(0, 10);
})().slice(0, 10);
})();

View File

@@ -5,5 +5,5 @@
} catch (error) {
return "And the error is ... " + error;
}
}).call(this));
})());
})();

View File

@@ -1,15 +1,15 @@
(function(){
var Account;
var __slice = Array.prototype.slice, __bind = function(func, obj, args) {
return function() {
return func.apply(obj || {}, args ? args.concat(__slice.call(arguments, 0)) : arguments);
};
};
Account = function Account(customer, cart) {
this.customer = customer;
this.cart = cart;
return $('.shopping_cart').bind('click', (function(__this) {
var __func = function(event) {
return $('.shopping_cart').bind('click', __bind(function(event) {
return this.customer.purchase(this.cart);
};
return (function() {
return __func.apply(__this, arguments);
});
})(this));
}, this));
};
})();

View File

@@ -1,5 +1,5 @@
(function(){
var author, quote;
author = "Wittgenstein";
quote = "A picture is a fact. -- " + author;
quote = ("A picture is a fact. -- " + author);
})();

View File

@@ -1,6 +1,6 @@
(function(){
var dates, sentence, sep;
sentence = "" + (22 / 7) + " is a decent approximation of π";
sentence = ("" + (22 / 7) + " is a decent approximation of π");
sep = "[.\\/\\- ]";
dates = (new RegExp("\\d+" + sep + "\\d+" + sep + "\\d+", "g"));
dates = (new RegExp(("\\d+" + sep + "\\d+" + sep + "\\d+"), "g"));
})();

View File

@@ -13,5 +13,5 @@
_a.push(child + " is " + age);
}}
return _a;
}).call(this);
})();
})();

View File

@@ -1,5 +1,6 @@
(function(){
var _a, _b, _c, _d, cubed_list, list, math, num, number, opposite_day, race, square;
var __slice = Array.prototype.slice;
// Assignment:
number = 42;
opposite_day = true;
@@ -24,7 +25,7 @@
// Splats:
race = function race(winner) {
var runners;
runners = Array.prototype.slice.call(arguments, 1, arguments.length - 0);
runners = __slice.call(arguments, 1, arguments.length - 0);
return print(winner, runners);
};
// Existence:
@@ -33,11 +34,11 @@
}
// Array comprehensions:
cubed_list = (function() {
_a = []; _b = list;
for (_c = 0, _d = _b.length; _c < _d; _c++) {
num = _b[_c];
_a = []; _c = list;
for (_b = 0, _d = _c.length; _b < _d; _b++) {
num = _c[_b];
_a.push(math.cube(num));
}
return _a;
}).call(this);
})();
})();

View File

@@ -1,8 +1,9 @@
(function(){
var _a, close, contents, open, tag;
var __slice = Array.prototype.slice;
tag = "<impossible>";
_a = tag.split("");
open = _a[0];
contents = Array.prototype.slice.call(_a, 1, _a.length - 1);
contents = __slice.call(_a, 1, _a.length - 1);
close = _a[_a.length - 1];
})();

View File

@@ -1,21 +1,21 @@
(function(){
var _a, _b, _c, _d, _e, countdown, egg_delivery, num;
var _a, _b, _c, _d, countdown, egg_delivery, num;
countdown = (function() {
_a = []; _d = 10; _e = 1;
for (_c = 0, num = _d; (_d <= _e ? num <= _e : num >= _e); (_d <= _e ? num += 1 : num -= 1), _c++) {
_a = []; _c = 10; _d = 1;
for (_b = 0, num = _c; (_c <= _d ? num <= _d : num >= _d); (_c <= _d ? num += 1 : num -= 1), _b++) {
_a.push(num);
}
return _a;
}).call(this);
})();
egg_delivery = function egg_delivery() {
var _f, _g, _h, _i, _j, dozen_eggs, i;
_f = []; _i = 0; _j = eggs.length;
for (_h = 0, i = _i; (_i <= _j ? i < _j : i > _j); (_i <= _j ? i += 12 : i -= 12), _h++) {
_f.push((function() {
var _e, _f, _g, _h, dozen_eggs, i;
_e = []; _g = 0; _h = eggs.length;
for (_f = 0, i = _g; (_g <= _h ? i < _h : i > _h); (_g <= _h ? i += 12 : i -= 12), _f++) {
_e.push((function() {
dozen_eggs = eggs.slice(i, i + 12);
return deliver(new egg_carton(dozen));
}).call(this));
})());
}
return _f;
return _e;
};
})();

View File

@@ -1,9 +1,10 @@
(function(){
var award_medals, contenders, gold, silver, the_field;
var __slice = Array.prototype.slice;
gold = (silver = (the_field = "unknown"));
award_medals = function award_medals(first, second) {
var rest;
rest = Array.prototype.slice.call(arguments, 2, arguments.length - 0);
rest = __slice.call(arguments, 2, arguments.length - 0);
gold = first;
silver = second;
the_field = rest;

View File

@@ -18,5 +18,5 @@
One fell out and bumped his head.");
}
return _a;
}).call(this);
})();
})();

View File

@@ -71,7 +71,7 @@
# Current version.
_.VERSION: '0.6.0'
_.VERSION: '1.0.2'
# Collection Functions
@@ -422,9 +422,10 @@
# Extend a given object with all of the properties in a source object.
_.extend: (destination, source) ->
(destination[key]: val) for key, val of source
destination
_.extend: (obj) ->
for source in _.rest(arguments)
(obj[key]: val) for key, val of source
obj
# Create a (shallow-cloned) duplicate of an object.
@@ -472,7 +473,7 @@
# Different object sizes?
return false if aKeys.length isnt bKeys.length
# Recursive comparison of contents.
(return false) for key, val of a when !_.isEqual(val, b[key])
(return false) for key, val of a when !(key in b) or !_.isEqual(val, b[key])
true
@@ -488,12 +489,11 @@
# Is a given value an array?
_.isArray: nativeIsArray or (obj) -> !!(obj and obj.concat and obj.unshift)
_.isArray: nativeIsArray or (obj) -> !!(obj and obj.concat and obj.unshift and not obj.callee)
# Is a given variable an arguments object?
_.isArguments: (obj) -> obj and _.isNumber(obj.length) and not obj.concat and
not obj.substr and not obj.apply and not propertyIsEnumerable.call(obj, 'length')
_.isArguments: (obj) -> obj and obj.callee
# Is the given value a function?

View File

@@ -6,7 +6,7 @@ http: require 'http'
server: http.createServer (req, res) ->
res.writeHeader 200, {'Content-Type': 'text/plain'}
res.write 'Hello, World!'
res.close()
res.end()
server.listen 3000

View File

@@ -5,19 +5,3 @@ CoffeeScript compiler. To use it in the browser, include the script after any
inline script tags of type "text/coffeescript" on the page. It will compile
and evaluate all of the scripts in order.
This folder also includes a CoffeeScript syntax highlighter for Vim.
To install, copy "coffee.vim" into the "syntax" directory of
your vim72, and enable it in either of the following two ways:
* Manually, by running `:set syntax=coffee`
* Or automatically, by creating a "filetype.vim" file within "~/.vim", which
contains something along these lines:
if exists("did_load_filetypes")
finish
end
augroup filetypedetect
au! BufRead,BufNewFile *.coffee setfiletype coffee
augroup END

File diff suppressed because one or more lines are too long

View File

@@ -1,117 +0,0 @@
" Vim syntax file
" Language: CoffeeScript
" Maintainer: Jeff Olson <olson.jeffery@gmail.com>
" URL: http://github.com/olsonjeffery
" Changes: (jro) initial port from javascript
" Last Change: 2006 Jun 19
" Adaptation of javascript.vim syntax file (distro'd w/ vim72),
" maintained by Claudio Fleiner <claudio@fleiner.com>
" with updates from Scott Shattuck (ss) <ss@technicalpursuit.com>
if !exists("main_syntax")
if version < 600
syntax clear
elseif exists("b:current_syntax")
finish
endif
let main_syntax = 'coffee'
endif
syn case ignore
syn match coffeeLineComment "#.*" contains=@Spell,CoffeeCommentTodo
syn match coffeeSpecial "\\\d\d\d\|\\."
syn region coffeeStringD start=+"+ skip=+\\\\\|\\"+ end=+"\|$+ contains=coffeeSpecial,@htmlPreproc
syn region coffeeStringS start=+'+ skip=+\\\\\|\\'+ end=+'\|$+ contains=coffeeSpecial,@htmlPreproc
syn match coffeeSpecialCharacter "'\\.'"
syn match coffeeNumber "-\=\<\d\+L\=\>\|0[xX][0-9a-fA-F]\+\>"
syn region coffeeRegexpString start=+/[^/*]+me=e-1 skip=+\\\\\|\\/+ end=+/[gi]\{0,2\}\s*$+ end=+/[gi]\{0,2\}\s*[;.,)\]}]+me=e-1 contains=@htmlPreproc oneline
syn match coffeeFunctionParams "([^)]*)\s*->"
syn match coffeeBindFunctionParams "([^)]*)\s*=>"
syn match coffeePrototypeAccess "::"
syn match coffeeBindFunction "=[1]>[1]"
syn match coffeeFunction "->"
syn keyword coffeeExtends extends
syn keyword coffeeConditional if else switch then not
syn keyword coffeeRepeat while for in of
syn keyword coffeeBranch break continue
syn keyword coffeeOperator delete instanceof typeof
syn keyword coffeeType Array Boolean Date Function Number Object String RegExp
syn keyword coffeeStatement return with
syn keyword coffeeBoolean true false
syn keyword coffeeNull null undefined
syn keyword coffeeIdentifier arguments this var
syn keyword coffeeLabel case default
syn keyword coffeeException try catch finally throw
syn keyword coffeeMessage alert confirm prompt status
syn keyword coffeeGlobal self window top parent
syn keyword coffeeMember document event location
syn keyword coffeeDeprecated escape unescape
syn keyword coffeeReserved abstract boolean byte char class const debugger double enum export final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile
syn sync fromstart
syn sync maxlines=100
if main_syntax == "coffee"
syn sync ccomment coffeeComment
endif
" Define the default highlighting.
" For version 5.7 and earlier: only when not done already
" For version 5.8 and later: only when an item doesn't have highlighting yet
if version >= 508 || !exists("did_coffee_syn_inits")
if version < 508
let did_coffee_syn_inits = 1
command -nargs=+ HiLink hi link <args>
else
command -nargs=+ HiLink hi def link <args>
endif
HiLink coffeePrototypeAccess Keyword
HiLink coffeeExtends Keyword
HiLink coffeeLineComment Comment
HiLink coffeeSpecial Special
HiLink coffeeStringS String
HiLink coffeeStringD String
HiLink coffeeCharacter Character
HiLink coffeeSpecialCharacter coffeeSpecial
HiLink coffeeNumber coffeeValue
HiLink coffeeConditional Conditional
HiLink coffeeRepeat Repeat
HiLink coffeeBranch Conditional
HiLink coffeeOperator Operator
HiLink coffeeType Type
HiLink coffeeStatement Statement
HiLink coffeeBindFunctionParams Function
HiLink coffeeFunctionParams Function
HiLink coffeeFunction Function
HiLink coffeeBindFunction Function
HiLink coffeeBraces Function
HiLink coffeeError Error
HiLink coffeeScrParenError coffeeError
HiLink coffeeNull Keyword
HiLink coffeeBoolean Boolean
HiLink coffeeRegexpString String
HiLink coffeeIdentifier Identifier
HiLink coffeeLabel Label
HiLink coffeeException Exception
HiLink coffeeMessage Keyword
HiLink coffeeGlobal Keyword
HiLink coffeeMember Keyword
HiLink coffeeDeprecated Exception
HiLink coffeeReserved Keyword
HiLink coffeeDebug Debug
HiLink coffeeConstant Label
delcommand HiLink
endif
let b:current_syntax = "coffee"
if main_syntax == 'coffee'
unlet main_syntax
endif
" vim: ts=8

View File

@@ -49,6 +49,7 @@
<a href="#cake">Cake, and Cakefiles</a>
<a href="#scripts">"text/coffeescript" Script Tags</a>
<a href="#resources">Resources</a>
<a href="#webchat">Web Chat (IRC)</a>
<a href="#change_log">Change Log</a>
</div>
</div>
@@ -115,7 +116,7 @@ alert reverse '.eeffoC yrT'</textarea></div>
<p>
<b>Latest Version:</b>
<a href="http://github.com/jashkenas/coffee-script/tarball/0.5.6">0.5.6</a>
<a href="http://github.com/jashkenas/coffee-script/tarball/0.6.1">0.6.1</a>
</p>
<h2>
@@ -155,6 +156,7 @@ alert <span class="String"><span class="String">&quot;</span>I knew it!<span cla
<span class="Comment"><span class="Comment">#</span> Array comprehensions:</span>
cubed_list<span class="Keyword">:</span> math.cube num <span class="Keyword">for</span> num <span class="Keyword">in</span> list
</pre><pre class="idle"><span class="Storage">var</span> _a, _b, _c, _d, cubed_list, list, math, num, number, opposite_day, race, square;
<span class="Storage">var</span> __slice <span class="Keyword">=</span> <span class="LibraryClassType">Array</span>.<span class="LibraryConstant">prototype</span>.slice;
<span class="Comment"><span class="Comment">//</span> Assignment:</span>
number <span class="Keyword">=</span> <span class="Number">42</span>;
opposite_day <span class="Keyword">=</span> <span class="BuiltInConstant">true</span>;
@@ -179,7 +181,7 @@ math <span class="Keyword">=</span> {
<span class="Comment"><span class="Comment">//</span> Splats:</span>
race <span class="Keyword">=</span> <span class="Storage">function</span> <span class="FunctionName">race</span>(<span class="FunctionArgument">winner</span>) {
<span class="Storage">var</span> runners;
runners <span class="Keyword">=</span> <span class="LibraryClassType">Array</span>.<span class="LibraryConstant">prototype</span>.slice.<span class="LibraryFunction">call</span>(arguments, <span class="Number">1</span>, arguments.<span class="LibraryConstant">length</span> <span class="Keyword">-</span> <span class="Number">0</span>);
runners <span class="Keyword">=</span> __slice.<span class="LibraryFunction">call</span>(arguments, <span class="Number">1</span>, arguments.<span class="LibraryConstant">length</span> <span class="Keyword">-</span> <span class="Number">0</span>);
<span class="Keyword">return</span> <span class="LibraryFunction">print</span>(winner, runners);
};
<span class="Comment"><span class="Comment">//</span> Existence:</span>
@@ -188,14 +190,15 @@ race <span class="Keyword">=</span> <span class="Storage">function</span> <span
}
<span class="Comment"><span class="Comment">//</span> Array comprehensions:</span>
cubed_list <span class="Keyword">=</span> (<span class="Storage">function</span>() {
_a <span class="Keyword">=</span> []; _b <span class="Keyword">=</span> list;
<span class="Keyword">for</span> (_c <span class="Keyword">=</span> <span class="Number">0</span>, _d <span class="Keyword">=</span> _b.<span class="LibraryConstant">length</span>; _c <span class="Keyword">&lt;</span> _d; _c<span class="Keyword">++</span>) {
num <span class="Keyword">=</span> _b[_c];
_a <span class="Keyword">=</span> []; _c <span class="Keyword">=</span> list;
<span class="Keyword">for</span> (_b <span class="Keyword">=</span> <span class="Number">0</span>, _d <span class="Keyword">=</span> _c.<span class="LibraryConstant">length</span>; _b <span class="Keyword">&lt;</span> _d; _b<span class="Keyword">++</span>) {
num <span class="Keyword">=</span> _c[_b];
_a.<span class="LibraryFunction">push</span>(math.cube(num));
}
<span class="Keyword">return</span> _a;
}).<span class="LibraryFunction">call</span>(<span class="Variable">this</span>);
})();
</pre><button onclick='javascript: var _a, _b, _c, _d, cubed_list, list, math, num, number, opposite_day, race, square;
var __slice = Array.prototype.slice;
// Assignment:
number = 42;
opposite_day = true;
@@ -220,7 +223,7 @@ math = {
// Splats:
race = function race(winner) {
var runners;
runners = Array.prototype.slice.call(arguments, 1, arguments.length - 0);
runners = __slice.call(arguments, 1, arguments.length - 0);
return print(winner, runners);
};
// Existence:
@@ -229,13 +232,13 @@ if ((typeof elvis !== "undefined" && elvis !== null)) {
}
// Array comprehensions:
cubed_list = (function() {
_a = []; _b = list;
for (_c = 0, _d = _b.length; _c < _d; _c++) {
num = _b[_c];
_a = []; _c = list;
for (_b = 0, _d = _c.length; _b < _d; _b++) {
num = _c[_b];
_a.push(math.cube(num));
}
return _a;
}).call(this);
})();
;alert(cubed_list);'>run: cubed_list</button><br class='clear' /></div>
<p>
@@ -267,12 +270,12 @@ cubed_list = (function() {
</p>
<p>
To install, first make sure you have a working version of
<a href="http://nodejs.org/">Node.js</a> version 0.1.33 or higher.
To install, first make sure you have a working copy of the latest tagged version of
<a href="http://nodejs.org/">Node.js</a>, currently <b>0.1.90</b> or higher.
Then clone the CoffeeScript
<a href="http://github.com/jashkenas/coffee-script">source repository</a>
from GitHub, or download the latest
release: <a href="http://github.com/jashkenas/coffee-script/tarball/0.5.6">0.5.6</a>.
release: <a href="http://github.com/jashkenas/coffee-script/tarball/0.6.1">0.6.1</a>.
To install the CoffeeScript compiler system-wide
under <tt>/usr/local</tt>, open the directory and run:
</p>
@@ -624,7 +627,7 @@ expensive <span class="Keyword">=</span> expensive <span class="Keyword">||</spa
</pre><br class='clear' /></div>
<p>
You can assign a variable to a half-expression to perform an operation
like Ruby's <tt>||=</tt>, which only assigns a value to a variable
like Ruby's <tt>||=</tt>, which only assigns a value to a variable
if the variable's current value is falsy.
</p>
@@ -717,10 +720,11 @@ alert <span class="String"><span class="String">&quot;</span>Gold: <span class="
alert <span class="String"><span class="String">&quot;</span>Silver: <span class="String">&quot;</span></span> <span class="Keyword">+</span> silver
alert <span class="String"><span class="String">&quot;</span>The Field: <span class="String">&quot;</span></span> <span class="Keyword">+</span> the_field
</pre><pre class="idle"><span class="Storage">var</span> award_medals, contenders, gold, silver, the_field;
<span class="Storage">var</span> __slice <span class="Keyword">=</span> <span class="LibraryClassType">Array</span>.<span class="LibraryConstant">prototype</span>.slice;
gold <span class="Keyword">=</span> (silver <span class="Keyword">=</span> (the_field <span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>unknown<span class="String">&quot;</span></span>));
award_medals <span class="Keyword">=</span> <span class="Storage">function</span> <span class="FunctionName">award_medals</span>(<span class="FunctionArgument">first, second</span>) {
<span class="Storage">var</span> rest;
rest <span class="Keyword">=</span> <span class="LibraryClassType">Array</span>.<span class="LibraryConstant">prototype</span>.slice.<span class="LibraryFunction">call</span>(arguments, <span class="Number">2</span>, arguments.<span class="LibraryConstant">length</span> <span class="Keyword">-</span> <span class="Number">0</span>);
rest <span class="Keyword">=</span> __slice.<span class="LibraryFunction">call</span>(arguments, <span class="Number">2</span>, arguments.<span class="LibraryConstant">length</span> <span class="Keyword">-</span> <span class="Number">0</span>);
gold <span class="Keyword">=</span> first;
silver <span class="Keyword">=</span> second;
the_field <span class="Keyword">=</span> rest;
@@ -732,10 +736,11 @@ award_medals.<span class="LibraryFunction">apply</span>(<span class="Variable">t
<span class="LibraryFunction">alert</span>(<span class="String"><span class="String">&quot;</span>Silver: <span class="String">&quot;</span></span> <span class="Keyword">+</span> silver);
<span class="LibraryFunction">alert</span>(<span class="String"><span class="String">&quot;</span>The Field: <span class="String">&quot;</span></span> <span class="Keyword">+</span> the_field);
</pre><button onclick='javascript: var award_medals, contenders, gold, silver, the_field;
var __slice = Array.prototype.slice;
gold = (silver = (the_field = "unknown"));
award_medals = function award_medals(first, second) {
var rest;
rest = Array.prototype.slice.call(arguments, 2, arguments.length - 0);
rest = __slice.call(arguments, 2, arguments.length - 0);
gold = first;
silver = second;
the_field = rest;
@@ -785,7 +790,7 @@ lyrics <span class="Keyword">=</span> (<span class="Storage">function</span>() {
<span class="String">One fell out and bumped his head.<span class="String">&quot;</span></span>);
}
<span class="Keyword">return</span> _a;
}).<span class="LibraryFunction">call</span>(<span class="Variable">this</span>);
})();
</pre><button onclick='javascript: var _a, lyrics, num;
// Econ 101
if (this.studying_economics) {
@@ -805,7 +810,7 @@ lyrics = (function() {
One fell out and bumped his head.");
}
return _a;
}).call(this);
})();
;alert(lyrics.join("\n"));'>run: lyrics.join("\n")</button><br class='clear' /></div>
<p>
Other JavaScript loops, such as <b>for</b> loops and <b>do-while</b> loops
@@ -834,20 +839,20 @@ lunch<span class="Keyword">:</span> eat food <span class="Keyword">for</span> fo
</pre><pre class="idle"><span class="Storage">var</span> _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, food, lunch, roid, roid2;
<span class="Comment"><span class="Comment">//</span> Eat lunch.</span>
lunch <span class="Keyword">=</span> (<span class="Storage">function</span>() {
_a <span class="Keyword">=</span> []; _b <span class="Keyword">=</span> [<span class="String"><span class="String">'</span>toast<span class="String">'</span></span>, <span class="String"><span class="String">'</span>cheese<span class="String">'</span></span>, <span class="String"><span class="String">'</span>wine<span class="String">'</span></span>];
<span class="Keyword">for</span> (_c <span class="Keyword">=</span> <span class="Number">0</span>, _d <span class="Keyword">=</span> _b.<span class="LibraryConstant">length</span>; _c <span class="Keyword">&lt;</span> _d; _c<span class="Keyword">++</span>) {
food <span class="Keyword">=</span> _b[_c];
_a <span class="Keyword">=</span> []; _c <span class="Keyword">=</span> [<span class="String"><span class="String">'</span>toast<span class="String">'</span></span>, <span class="String"><span class="String">'</span>cheese<span class="String">'</span></span>, <span class="String"><span class="String">'</span>wine<span class="String">'</span></span>];
<span class="Keyword">for</span> (_b <span class="Keyword">=</span> <span class="Number">0</span>, _d <span class="Keyword">=</span> _c.<span class="LibraryConstant">length</span>; _b <span class="Keyword">&lt;</span> _d; _b<span class="Keyword">++</span>) {
food <span class="Keyword">=</span> _c[_b];
_a.<span class="LibraryFunction">push</span>(eat(food));
}
<span class="Keyword">return</span> _a;
}).<span class="LibraryFunction">call</span>(<span class="Variable">this</span>);
})();
<span class="Comment"><span class="Comment">//</span> Naive collision detection.</span>
_e <span class="Keyword">=</span> asteroids;
<span class="Keyword">for</span> (_f <span class="Keyword">=</span> <span class="Number">0</span>, _g <span class="Keyword">=</span> _e.<span class="LibraryConstant">length</span>; _f <span class="Keyword">&lt;</span> _g; _f<span class="Keyword">++</span>) {
roid <span class="Keyword">=</span> _e[_f];
_h <span class="Keyword">=</span> asteroids;
<span class="Keyword">for</span> (_i <span class="Keyword">=</span> <span class="Number">0</span>, _j <span class="Keyword">=</span> _h.<span class="LibraryConstant">length</span>; _i <span class="Keyword">&lt;</span> _j; _i<span class="Keyword">++</span>) {
roid2 <span class="Keyword">=</span> _h[_i];
_f <span class="Keyword">=</span> asteroids;
<span class="Keyword">for</span> (_e <span class="Keyword">=</span> <span class="Number">0</span>, _g <span class="Keyword">=</span> _f.<span class="LibraryConstant">length</span>; _e <span class="Keyword">&lt;</span> _g; _e<span class="Keyword">++</span>) {
roid <span class="Keyword">=</span> _f[_e];
_i <span class="Keyword">=</span> asteroids;
<span class="Keyword">for</span> (_h <span class="Keyword">=</span> <span class="Number">0</span>, _j <span class="Keyword">=</span> _i.<span class="LibraryConstant">length</span>; _h <span class="Keyword">&lt;</span> _j; _h<span class="Keyword">++</span>) {
roid2 <span class="Keyword">=</span> _i[_h];
<span class="Keyword">if</span> (roid <span class="Keyword">!</span><span class="Keyword">==</span> roid2) {
<span class="Keyword">if</span> (roid.overlaps(roid2)) {
roid.explode();
@@ -868,43 +873,43 @@ _e <span class="Keyword">=</span> asteroids;
<span class="Keyword">for</span> i <span class="Keyword">in</span> [<span class="Number">0</span>...eggs.length] <span class="Keyword">by</span> <span class="Number">12</span>
dozen_eggs<span class="Keyword">:</span> eggs[i...i<span class="Keyword">+</span><span class="Number">12</span>]
deliver <span class="Keyword">new</span> <span class="TypeName">egg_carton</span>(dozen)
</pre><pre class="idle"><span class="Storage">var</span> _a, _b, _c, _d, _e, countdown, egg_delivery, num;
</pre><pre class="idle"><span class="Storage">var</span> _a, _b, _c, _d, countdown, egg_delivery, num;
countdown <span class="Keyword">=</span> (<span class="Storage">function</span>() {
_a <span class="Keyword">=</span> []; _d <span class="Keyword">=</span> <span class="Number">10</span>; _e <span class="Keyword">=</span> <span class="Number">1</span>;
<span class="Keyword">for</span> (_c <span class="Keyword">=</span> <span class="Number">0</span>, num <span class="Keyword">=</span> _d; (_d <span class="Keyword">&lt;=</span> _e ? num <span class="Keyword">&lt;=</span> _e : num <span class="Keyword">&gt;=</span> _e); (_d <span class="Keyword">&lt;=</span> _e ? num <span class="Keyword">+</span><span class="Keyword">=</span> <span class="Number">1</span> : num <span class="Keyword">-</span><span class="Keyword">=</span> <span class="Number">1</span>), _c<span class="Keyword">++</span>) {
_a <span class="Keyword">=</span> []; _c <span class="Keyword">=</span> <span class="Number">10</span>; _d <span class="Keyword">=</span> <span class="Number">1</span>;
<span class="Keyword">for</span> (_b <span class="Keyword">=</span> <span class="Number">0</span>, num <span class="Keyword">=</span> _c; (_c <span class="Keyword">&lt;=</span> _d ? num <span class="Keyword">&lt;=</span> _d : num <span class="Keyword">&gt;=</span> _d); (_c <span class="Keyword">&lt;=</span> _d ? num <span class="Keyword">+</span><span class="Keyword">=</span> <span class="Number">1</span> : num <span class="Keyword">-</span><span class="Keyword">=</span> <span class="Number">1</span>), _b<span class="Keyword">++</span>) {
_a.<span class="LibraryFunction">push</span>(num);
}
<span class="Keyword">return</span> _a;
}).<span class="LibraryFunction">call</span>(<span class="Variable">this</span>);
})();
egg_delivery <span class="Keyword">=</span> <span class="Storage">function</span> <span class="FunctionName">egg_delivery</span>() {
<span class="Storage">var</span> _f, _g, _h, _i, _j, dozen_eggs, i;
_f <span class="Keyword">=</span> []; _i <span class="Keyword">=</span> <span class="Number">0</span>; _j <span class="Keyword">=</span> eggs.<span class="LibraryConstant">length</span>;
<span class="Keyword">for</span> (_h <span class="Keyword">=</span> <span class="Number">0</span>, i <span class="Keyword">=</span> _i; (_i <span class="Keyword">&lt;=</span> _j ? i <span class="Keyword">&lt;</span> _j : i <span class="Keyword">&gt;</span> _j); (_i <span class="Keyword">&lt;=</span> _j ? i <span class="Keyword">+</span><span class="Keyword">=</span> <span class="Number">12</span> : i <span class="Keyword">-</span><span class="Keyword">=</span> <span class="Number">12</span>), _h<span class="Keyword">++</span>) {
_f.<span class="LibraryFunction">push</span>((<span class="Storage">function</span>() {
<span class="Storage">var</span> _e, _f, _g, _h, dozen_eggs, i;
_e <span class="Keyword">=</span> []; _g <span class="Keyword">=</span> <span class="Number">0</span>; _h <span class="Keyword">=</span> eggs.<span class="LibraryConstant">length</span>;
<span class="Keyword">for</span> (_f <span class="Keyword">=</span> <span class="Number">0</span>, i <span class="Keyword">=</span> _g; (_g <span class="Keyword">&lt;=</span> _h ? i <span class="Keyword">&lt;</span> _h : i <span class="Keyword">&gt;</span> _h); (_g <span class="Keyword">&lt;=</span> _h ? i <span class="Keyword">+</span><span class="Keyword">=</span> <span class="Number">12</span> : i <span class="Keyword">-</span><span class="Keyword">=</span> <span class="Number">12</span>), _f<span class="Keyword">++</span>) {
_e.<span class="LibraryFunction">push</span>((<span class="Storage">function</span>() {
dozen_eggs <span class="Keyword">=</span> eggs.<span class="LibraryFunction">slice</span>(i, i <span class="Keyword">+</span> <span class="Number">12</span>);
<span class="Keyword">return</span> deliver(<span class="Keyword">new</span> <span class="TypeName">egg_carton</span>(dozen));
}).<span class="LibraryFunction">call</span>(<span class="Variable">this</span>));
})());
}
<span class="Keyword">return</span> _f;
<span class="Keyword">return</span> _e;
};
</pre><button onclick='javascript: var _a, _b, _c, _d, _e, countdown, egg_delivery, num;
</pre><button onclick='javascript: var _a, _b, _c, _d, countdown, egg_delivery, num;
countdown = (function() {
_a = []; _d = 10; _e = 1;
for (_c = 0, num = _d; (_d <= _e ? num <= _e : num >= _e); (_d <= _e ? num += 1 : num -= 1), _c++) {
_a = []; _c = 10; _d = 1;
for (_b = 0, num = _c; (_c <= _d ? num <= _d : num >= _d); (_c <= _d ? num += 1 : num -= 1), _b++) {
_a.push(num);
}
return _a;
}).call(this);
})();
egg_delivery = function egg_delivery() {
var _f, _g, _h, _i, _j, dozen_eggs, i;
_f = []; _i = 0; _j = eggs.length;
for (_h = 0, i = _i; (_i <= _j ? i < _j : i > _j); (_i <= _j ? i += 12 : i -= 12), _h++) {
_f.push((function() {
var _e, _f, _g, _h, dozen_eggs, i;
_e = []; _g = 0; _h = eggs.length;
for (_f = 0, i = _g; (_g <= _h ? i < _h : i > _h); (_g <= _h ? i += 12 : i -= 12), _f++) {
_e.push((function() {
dozen_eggs = eggs.slice(i, i + 12);
return deliver(new egg_carton(dozen));
}).call(this));
})());
}
return _f;
return _e;
};
;alert(countdown);'>run: countdown</button><br class='clear' /></div>
<p>
@@ -930,7 +935,7 @@ ages <span class="Keyword">=</span> (<span class="Storage">function</span>() {
_a.<span class="LibraryFunction">push</span>(child <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span> is <span class="String">&quot;</span></span> <span class="Keyword">+</span> age);
}}
<span class="Keyword">return</span> _a;
}).<span class="LibraryFunction">call</span>(<span class="Variable">this</span>);
})();
</pre><button onclick='javascript: var _a, _b, age, ages, child, years_old;
var __hasProp = Object.prototype.hasOwnProperty;
years_old = {
@@ -945,7 +950,7 @@ ages = (function() {
_a.push(child + " is " + age);
}}
return _a;
}).call(this);
})();
;alert(ages.join(", "));'>run: ages.join(", ")</button><br class='clear' /></div>
<p>
@@ -1073,7 +1078,7 @@ globals <span class="Keyword">=</span> (<span class="Storage">function</span>()
_a.<span class="LibraryFunction">push</span>(name);
}}
<span class="Keyword">return</span> _a;
}).<span class="LibraryFunction">call</span>(<span class="Variable">this</span>).<span class="LibraryFunction">slice</span>(<span class="Number">0</span>, <span class="Number">10</span>);
})().<span class="LibraryFunction">slice</span>(<span class="Number">0</span>, <span class="Number">10</span>);
</pre><button onclick='javascript: var _a, _b, globals, name;
var __hasProp = Object.prototype.hasOwnProperty;
// The first ten global properties.
@@ -1083,7 +1088,7 @@ globals = (function() {
_a.push(name);
}}
return _a;
}).call(this).slice(0, 10);
})().slice(0, 10);
;alert(globals);'>run: globals</button><br class='clear' /></div>
<p>
As well as silly things, like passing a <b>try/catch</b> statement directly
@@ -1101,14 +1106,14 @@ globals = (function() {
} <span class="Keyword">catch</span> (error) {
<span class="Keyword">return</span> <span class="String"><span class="String">&quot;</span>And the error is ... <span class="String">&quot;</span></span> <span class="Keyword">+</span> error;
}
}).<span class="LibraryFunction">call</span>(<span class="Variable">this</span>));
})());
</pre><button onclick='javascript: alert((function() {
try {
return nonexistent / undefined;
} catch (error) {
return "And the error is ... " + error;
}
}).call(this));
})());
;'>run</button><br class='clear' /></div>
<p>
There are a handful of statements in JavaScript that can't be meaningfully
@@ -1303,6 +1308,10 @@ tom.move();
return this.replace(/_/g, "-");
};
;alert("one_two".dasherize());'>run: "one_two".dasherize()</button><br class='clear' /></div>
<p>
Finally, you may assign Class-level (static) properties within a class
definition by using<br /><tt>@property: value</tt>
</p>
<p>
<span id="pattern_matching" class="bookmark"></span>
@@ -1419,16 +1428,18 @@ city = _c[1];
</pre><pre class="idle"><span class="Storage">var</span> _a, close, contents, open, tag;
<span class="Storage">var</span> __slice <span class="Keyword">=</span> <span class="LibraryClassType">Array</span>.<span class="LibraryConstant">prototype</span>.slice;
tag <span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>&lt;impossible&gt;<span class="String">&quot;</span></span>;
_a <span class="Keyword">=</span> tag.<span class="LibraryFunction">split</span>(<span class="String"><span class="String">&quot;</span><span class="String">&quot;</span></span>);
open <span class="Keyword">=</span> _a[<span class="Number">0</span>];
contents <span class="Keyword">=</span> <span class="LibraryClassType">Array</span>.<span class="LibraryConstant">prototype</span>.slice.<span class="LibraryFunction">call</span>(_a, <span class="Number">1</span>, _a.<span class="LibraryConstant">length</span> <span class="Keyword">-</span> <span class="Number">1</span>);
contents <span class="Keyword">=</span> __slice.<span class="LibraryFunction">call</span>(_a, <span class="Number">1</span>, _a.<span class="LibraryConstant">length</span> <span class="Keyword">-</span> <span class="Number">1</span>);
close <span class="Keyword">=</span> _a[_a.<span class="LibraryConstant">length</span> <span class="Keyword">-</span> <span class="Number">1</span>];
</pre><button onclick='javascript: var _a, close, contents, open, tag;
var __slice = Array.prototype.slice;
tag = "<impossible>";
_a = tag.split("");
open = _a[0];
contents = Array.prototype.slice.call(_a, 1, _a.length - 1);
contents = __slice.call(_a, 1, _a.length - 1);
close = _a[_a.length - 1];
;alert(contents.join(""));'>run: contents.join("")</button><br class='clear' /></div>
@@ -1457,17 +1468,17 @@ close = _a[_a.length - 1];
$(<span class="String"><span class="String">'</span>.shopping_cart<span class="String">'</span></span>).bind <span class="String"><span class="String">'</span>click<span class="String">'</span></span>, <span class="FunctionArgument">(</span><span class="FunctionArgument">event</span><span class="FunctionArgument">)</span> <span class="Storage">=&gt;</span>
<span class="Variable">@customer</span>.purchase <span class="Variable">@cart</span>
</pre><pre class="idle"><span class="Storage">var</span> Account;
<span class="Storage">var</span> __slice <span class="Keyword">=</span> <span class="LibraryClassType">Array</span>.<span class="LibraryConstant">prototype</span>.slice, <span class="FunctionName">__bind</span> = <span class="Storage">function</span>(<span class="FunctionArgument">func, obj, args</span>) {
<span class="Keyword">return</span> <span class="Storage">function</span>() {
<span class="Keyword">return</span> func.<span class="LibraryFunction">apply</span>(obj <span class="Keyword">||</span> {}, args ? args.<span class="LibraryFunction">concat</span>(__slice.<span class="LibraryFunction">call</span>(arguments, <span class="Number">0</span>)) : arguments);
};
};
Account <span class="Keyword">=</span> <span class="Storage">function</span> <span class="FunctionName">Account</span>(<span class="FunctionArgument">customer, cart</span>) {
<span class="Variable">this</span>.customer <span class="Keyword">=</span> customer;
<span class="Variable">this</span>.cart <span class="Keyword">=</span> cart;
<span class="Keyword">return</span> <span class="Keyword">$</span>(<span class="String"><span class="String">'</span>.shopping_cart<span class="String">'</span></span>).bind(<span class="String"><span class="String">'</span>click<span class="String">'</span></span>, (<span class="Storage">function</span>(__this) {
<span class="Storage">var</span> <span class="FunctionName">__func</span> = <span class="Storage">function</span>(<span class="FunctionArgument">event</span>) {
<span class="Keyword">return</span> <span class="Keyword">$</span>(<span class="String"><span class="String">'</span>.shopping_cart<span class="String">'</span></span>).bind(<span class="String"><span class="String">'</span>click<span class="String">'</span></span>, __bind(<span class="Storage">function</span>(<span class="LibraryClassType">event</span>) {
<span class="Keyword">return</span> <span class="Variable">this</span>.customer.purchase(<span class="Variable">this</span>.cart);
};
<span class="Keyword">return</span> (<span class="Storage">function</span>() {
<span class="Keyword">return</span> __func.<span class="LibraryFunction">apply</span>(__this, arguments);
});
})(<span class="Variable">this</span>));
}, <span class="Variable">this</span>));
};
</pre><br class='clear' /></div>
<p>
@@ -1489,22 +1500,24 @@ get_source<span class="Keyword">:</span> jQuery.get <span class="Keyword">&lt;</
get_source <span class="FunctionArgument">(</span><span class="FunctionArgument">response</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> alert response
</pre><pre class="idle"><span class="Storage">var</span> get_source, url;
url <span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>documentation/coffee/binding.coffee<span class="String">&quot;</span></span>;
get_source <span class="Keyword">=</span> (<span class="Storage">function</span>(func, obj, args) {
<span class="Storage">var</span> __slice <span class="Keyword">=</span> <span class="LibraryClassType">Array</span>.<span class="LibraryConstant">prototype</span>.slice, <span class="FunctionName">__bind</span> = <span class="Storage">function</span>(<span class="FunctionArgument">func, obj, args</span>) {
<span class="Keyword">return</span> <span class="Storage">function</span>() {
<span class="Keyword">return</span> func.<span class="LibraryFunction">apply</span>(obj, args.<span class="LibraryFunction">concat</span>(<span class="LibraryClassType">Array</span>.<span class="LibraryConstant">prototype</span>.slice.<span class="LibraryFunction">call</span>(arguments, <span class="Number">0</span>)));
<span class="Keyword">return</span> func.<span class="LibraryFunction">apply</span>(obj <span class="Keyword">||</span> {}, args ? args.<span class="LibraryFunction">concat</span>(__slice.<span class="LibraryFunction">call</span>(arguments, <span class="Number">0</span>)) : arguments);
};
}(jQuery.get, jQuery, [url]));
};
url <span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>documentation/coffee/binding.coffee<span class="String">&quot;</span></span>;
get_source <span class="Keyword">=</span> __bind(jQuery.get, jQuery, [url]);
get_source(<span class="Storage">function</span>(response) {
<span class="Keyword">return</span> <span class="LibraryFunction">alert</span>(response);
});
</pre><button onclick='javascript: var get_source, url;
url = "documentation/coffee/binding.coffee";
get_source = (function(func, obj, args) {
var __slice = Array.prototype.slice, __bind = function(func, obj, args) {
return function() {
return func.apply(obj, args.concat(Array.prototype.slice.call(arguments, 0)));
return func.apply(obj || {}, args ? args.concat(__slice.call(arguments, 0)) : arguments);
};
}(jQuery.get, jQuery, [url]));
};
url = "documentation/coffee/binding.coffee";
get_source = __bind(jQuery.get, jQuery, [url]);
get_source(function(response) {
return alert(response);
});
@@ -1631,10 +1644,10 @@ healthy = (200 > cholesterol) && (cholesterol > 60);
quote<span class="Keyword">:</span> <span class="String"><span class="String">&quot;</span>A picture is a fact. -- <span class="String"><span class="String">$</span>author</span><span class="String">&quot;</span></span>
</pre><pre class="idle"><span class="Storage">var</span> author, quote;
author <span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>Wittgenstein<span class="String">&quot;</span></span>;
quote <span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>A picture is a fact. -- <span class="String">&quot;</span></span> <span class="Keyword">+</span> author;
quote <span class="Keyword">=</span> (<span class="String"><span class="String">&quot;</span>A picture is a fact. -- <span class="String">&quot;</span></span> <span class="Keyword">+</span> author);
</pre><button onclick='javascript: var author, quote;
author = "Wittgenstein";
quote = "A picture is a fact. -- " + author;
quote = ("A picture is a fact. -- " + author);
;alert(quote);'>run: quote</button><br class='clear' /></div>
<p>
And arbitrary expressions can be interpolated by using brackets <tt>${ ... }</tt><br />
@@ -1647,13 +1660,13 @@ dates<span class="Keyword">:</span><span class="String"> <span class="String">/<
</pre><pre class="idle"><span class="Storage">var</span> dates, sentence, sep;
sentence <span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span><span class="String">&quot;</span></span> <span class="Keyword">+</span> (<span class="Number">22</span> / <span class="Number">7</span>) <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span> is a decent approximation of π<span class="String">&quot;</span></span>;
sentence <span class="Keyword">=</span> (<span class="String"><span class="String">&quot;</span><span class="String">&quot;</span></span> <span class="Keyword">+</span> (<span class="Number">22</span> / <span class="Number">7</span>) <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span> is a decent approximation of π<span class="String">&quot;</span></span>);
sep <span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>[.<span class="UserDefinedConstant">\\</span>/<span class="UserDefinedConstant">\\</span>- ]<span class="String">&quot;</span></span>;
dates <span class="Keyword">=</span> (<span class="Keyword">new</span> <span class="TypeName">RegExp</span>(<span class="String"><span class="String">&quot;</span><span class="UserDefinedConstant">\\</span>d+<span class="String">&quot;</span></span> <span class="Keyword">+</span> sep <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span><span class="UserDefinedConstant">\\</span>d+<span class="String">&quot;</span></span> <span class="Keyword">+</span> sep <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span><span class="UserDefinedConstant">\\</span>d+<span class="String">&quot;</span></span>, <span class="String"><span class="String">&quot;</span>g<span class="String">&quot;</span></span>));
dates <span class="Keyword">=</span> (<span class="Keyword">new</span> <span class="TypeName">RegExp</span>((<span class="String"><span class="String">&quot;</span><span class="UserDefinedConstant">\\</span>d+<span class="String">&quot;</span></span> <span class="Keyword">+</span> sep <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span><span class="UserDefinedConstant">\\</span>d+<span class="String">&quot;</span></span> <span class="Keyword">+</span> sep <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span><span class="UserDefinedConstant">\\</span>d+<span class="String">&quot;</span></span>), <span class="String"><span class="String">&quot;</span>g<span class="String">&quot;</span></span>));
</pre><button onclick='javascript: var dates, sentence, sep;
sentence = "" + (22 / 7) + " is a decent approximation of π";
sentence = ("" + (22 / 7) + " is a decent approximation of π");
sep = "[.\\/\\- ]";
dates = (new RegExp("\\d+" + sep + "\\d+" + sep + "\\d+", "g"));
dates = (new RegExp(("\\d+" + sep + "\\d+" + sep + "\\d+"), "g"));
;alert(sentence);'>run: sentence</button><br class='clear' /></div>
<p>
@@ -1726,9 +1739,9 @@ html <span class="Keyword">=</span> <span class="String"><span class="String">'<
fs.readFile test, <span class="FunctionArgument">(</span><span class="FunctionArgument">err, code</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span> eval coffee.compile code
</pre><pre class="idle">task(<span class="String"><span class="String">'</span>test<span class="String">'</span></span>, <span class="String"><span class="String">'</span>run each of the unit tests<span class="String">'</span></span>, <span class="Storage">function</span>() {
<span class="Storage">var</span> _a, _b, _c, _d, test;
_a <span class="Keyword">=</span> []; _b <span class="Keyword">=</span> test_files;
<span class="Keyword">for</span> (_c <span class="Keyword">=</span> <span class="Number">0</span>, _d <span class="Keyword">=</span> _b.<span class="LibraryConstant">length</span>; _c <span class="Keyword">&lt;</span> _d; _c<span class="Keyword">++</span>) {
test <span class="Keyword">=</span> _b[_c];
_a <span class="Keyword">=</span> []; _c <span class="Keyword">=</span> test_files;
<span class="Keyword">for</span> (_b <span class="Keyword">=</span> <span class="Number">0</span>, _d <span class="Keyword">=</span> _c.<span class="LibraryConstant">length</span>; _b <span class="Keyword">&lt;</span> _d; _b<span class="Keyword">++</span>) {
test <span class="Keyword">=</span> _c[_b];
_a.<span class="LibraryFunction">push</span>(fs.readFile(test, <span class="Storage">function</span>(err, code) {
<span class="Keyword">return</span> <span class="LibraryFunction">eval</span>(coffee.<span class="LibraryFunction">compile</span>(code));
}));
@@ -1778,7 +1791,7 @@ html <span class="Keyword">=</span> <span class="String"><span class="String">'<
<tt>bin/cake build</tt> to rebuild the CoffeeScript compiler, and <br />
<tt>bin/cake build:parser</tt> to regenerate the Jison parser if you're
working on the grammar. <br /><br />
<tt>bin/cake build:full</tt> is a good command to run when you're working
<tt>git checkout lib &amp;&amp; bin/cake build:full</tt> is a good command to run when you're working
on the core language. It'll refresh the lib directory
(in case you broke something), build your altered compiler, use that to
rebuild itself (a good sanity test) and then run all of the tests. If
@@ -1796,20 +1809,66 @@ html <span class="Keyword">=</span> <span class="String"><span class="String">'<
<li>
<b>defunkt</b>'s <a href="http://github.com/defunkt/coffee-mode">CoffeeScript Major Mode</a>
&mdash; a Emacs major mode that provides syntax highlighting, indentation
support, and some bonus commands. (For Vim and TextMate highlighters,
see the <tt>extras</tt> directory of the main repository.)
support, and some bonus commands.
</li>
<li>
<b>jashkenas</b>'s <a href="http://github.com/jashkenas/coffee-script-tmbundle">CoffeeScript TextMate Bundle</a>
&mdash; which provides syntax highlighting, snippet expansion, and the
ability to run bits of CoffeeScript from within TextMate itself.
</li>
<li>
<b>kchmck</b>'s <a href="http://github.com/kchmck/vim-coffee-script">Vim CoffeeScript</a>
&mdash; which adds Vim syntax highlighting and indentation support.
</li>
<li>
<b>mattly</b>'s <a href="http://github.com/mattly/rack-coffee">rack-coffee</a>
&mdash; a small Rack middleware for serving CoffeeScript files as
compiled JavaScript on the fly.
</li>
<li>
<b>jnicklas</b>'s <a href="http://github.com/jnicklas/bistro_car">BistroCar</a>
&mdash; a plugin that serves and bundles CoffeeScript from within your
Rails application.
</li>
<li>
<b>inem</b> and <b>gerad</b>'s <a href="http://github.com/gerad/coffee-haml-filter">coffee-haml-filter</a>
&mdash; a custom filter for rendering CoffeeScript inline within
<a href="http://haml-lang.com/">HAML</a> templates.
</li>
</ul>
<h2>
<span id="webchat" class="bookmark"></span>
Web Chat (IRC)
</h2>
<p>
Quick help and advice can usually be found in the CoffeeScript IRC room.
Join <tt>#coffeescript</tt> on <tt>irc.freenode.net</tt>, or click the
button below to open a webchat session on this page.
</p>
<p>
<button id="open_webchat">click to open #coffeescript</button>
</p>
<h2>
<span id="change_log" class="bookmark"></span>
Change Log
</h2>
<p>
<b class="header" style="margin-top: 20px;">0.6.1</b>
Upgraded CoffeeScript for compatibility with the new Node.js <b>v0.1.90</b>
series.
</p>
<p>
<b class="header" style="margin-top: 20px;">0.6.0</b>
Trailing commas are now allowed, a-la Python. Static
properties may be assigned directly within class definitions,
using <tt>@property</tt> notation.
</p>
<p>
<b class="header" style="margin-top: 20px;">0.5.6</b>
@@ -2075,6 +2134,9 @@ html <span class="Keyword">=</span> <span class="String"><span class="String">'<
$('.navigation .minimize').click ->
document.body.className: 'minimized'
$('#open_webchat').click ->
$(this).replaceWith $('<iframe src="http://webchat.freenode.net/?channels=coffeescript" width="625" height="400"></iframe>')
compile_source()
</script>

View File

@@ -20,9 +20,15 @@
oparse = null;
// Mixin the top-level Cake functions for Cakefiles to use directly.
helpers.extend(global, {
// Define a Cake task with a short name, a sentence description,
// Define a Cake task with a short name, an optional sentence description,
// and the function to run as the action itself.
task: function task(name, description, action) {
var _a;
if (!(action)) {
_a = [description, action];
action = _a[0];
description = _a[1];
}
tasks[name] = {
name: name,
description: description,
@@ -51,7 +57,7 @@
return path.exists('Cakefile', function(exists) {
var _a, _b, _c, _d, arg, args;
if (!(exists)) {
throw new Error("Cakefile not found in " + (process.cwd()));
throw new Error(("Cakefile not found in " + (process.cwd())));
}
args = process.argv.slice(2, process.argv.length);
CoffeeScript.run(fs.readFileSync('Cakefile'), {
@@ -62,9 +68,9 @@
return print_tasks();
}
options = oparse.parse(args);
_a = []; _b = options.arguments;
for (_c = 0, _d = _b.length; _c < _d; _c++) {
arg = _b[_c];
_a = []; _c = options.arguments;
for (_b = 0, _d = _c.length; _b < _d; _b++) {
arg = _c[_b];
_a.push(invoke(arg));
}
return _a;
@@ -72,20 +78,21 @@
};
// Display the list of Cake tasks in a format similar to `rake -T`
print_tasks = function print_tasks() {
var _a, _b, _c, _d, _e, _f, i, name, spaces, task;
var _a, _b, _c, _d, _e, desc, i, name, spaces, task;
puts('');
_a = tasks;
for (name in _a) { if (__hasProp.call(_a, name)) {
task = _a[name];
spaces = 20 - name.length;
spaces = spaces > 0 ? (function() {
_b = []; _e = 0; _f = spaces;
for (_d = 0, i = _e; (_e <= _f ? i <= _f : i >= _f); (_e <= _f ? i += 1 : i -= 1), _d++) {
_b = []; _d = 0; _e = spaces;
for (_c = 0, i = _d; (_d <= _e ? i <= _e : i >= _e); (_d <= _e ? i += 1 : i -= 1), _c++) {
_b.push(' ');
}
return _b;
}).call(this).join('') : '';
puts("cake " + name + spaces + " # " + (task.description));
})().join('') : '';
desc = task.description ? ("# " + task.description) : '';
puts(("cake " + name + spaces + " " + desc));
}}
if (switches.length) {
return puts(oparse.help());
@@ -93,7 +100,7 @@
};
// Print an error and exit when attempting to all an undefined task.
no_such_task = function no_such_task(task) {
process.stdio.writeError("No such task: \"" + task + "\"\n");
puts(("No such task: \"" + task + "\"\n"));
return process.exit(1);
};
})();

View File

@@ -23,7 +23,7 @@
helpers = this.helpers;
}
// The current CoffeeScript version number.
exports.VERSION = '0.5.6';
exports.VERSION = '0.6.1';
// Instantiate a Lexer for our use here.
lexer = new Lexer();
// Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
@@ -34,7 +34,7 @@
return (parser.parse(lexer.tokenize(code))).compile(options);
} catch (err) {
if (options.source) {
err.message = "In " + (options.source) + ", " + (err.message);
err.message = ("In " + options.source + ", " + err.message);
}
throw err;
}
@@ -95,9 +95,9 @@
if ((typeof document !== "undefined" && document !== null) && document.getElementsByTagName) {
process_scripts = function process_scripts() {
var _a, _b, _c, _d, tag;
_a = []; _b = document.getElementsByTagName('script');
for (_c = 0, _d = _b.length; _c < _d; _c++) {
tag = _b[_c];
_a = []; _c = document.getElementsByTagName('script');
for (_b = 0, _d = _c.length; _b < _d; _b++) {
tag = _c[_b];
tag.type === 'text/coffeescript' ? _a.push(eval(exports.compile(tag.innerHTML))) : null;
}
return _a;

View File

@@ -1,5 +1,5 @@
(function(){
var BANNER, CoffeeScript, SWITCHES, compile_options, compile_script, compile_scripts, compile_stdio, fs, lint, option_parser, options, optparse, parse_options, path, print_tokens, sources, usage, version, watch_scripts, write_js;
var BANNER, CoffeeScript, SWITCHES, _a, compile_options, compile_script, compile_scripts, compile_stdio, exec, fs, lint, option_parser, options, optparse, parse_options, path, print_tokens, sources, spawn, usage, version, watch_scripts, write_js;
// The `coffee` utility. Handles command-line compilation of CoffeeScript
// into various forms: saved into `.js` files or printed to stdout, piped to
// [JSLint](http://javascriptlint.com/) or recompiled every time the source is
@@ -10,6 +10,9 @@
path = require('path');
optparse = require('./optparse');
CoffeeScript = require('./coffee-script');
_a = require('child_process');
spawn = _a.spawn;
exec = _a.exec;
// The help banner that is printed when `coffee` is called without arguments.
BANNER = 'coffee compiles CoffeeScript source files into JavaScript.\n\nUsage:\n coffee path/to/script.coffee';
// The list of all the valid option flags that `coffee` knows how to handle.
@@ -57,23 +60,30 @@
// Asynchronously read in each CoffeeScript in a list of source files and
// compile them.
compile_scripts = function compile_scripts() {
var _a, _b, _c, _d, compile, source;
var compile, run;
compile = function compile(source) {
return path.exists(source, function(exists) {
if (!(exists)) {
throw new Error("File not found: " + source);
throw new Error(("File not found: " + source));
}
return fs.readFile(source, function(err, code) {
return compile_script(source, code);
});
});
};
_a = []; _b = sources;
for (_c = 0, _d = _b.length; _c < _d; _c++) {
source = _b[_c];
_a.push(compile(source));
run = function run() {
var _b, _c, _d, _e, source;
_b = []; _d = sources;
for (_c = 0, _e = _d.length; _c < _e; _c++) {
source = _d[_c];
_b.push(compile(source));
}
return _b;
};
if (!(options.output && options.compile)) {
return run();
}
return _a;
return exec(("mkdir -p " + options.output), run);
};
// Compile a single source script, containing the given code, according to the
// requested options. Both compile_scripts and watch_scripts share this method
@@ -93,7 +103,7 @@
} else {
js = CoffeeScript.compile(code, code_opts);
if (o.print) {
return process.stdio.write(js);
return print(js);
} else if (o.compile) {
return write_js(source, js);
} else if (o.lint) {
@@ -111,15 +121,15 @@
// Attach the appropriate listeners to compile scripts incoming over **stdin**,
// and write them back to **stdout**.
compile_stdio = function compile_stdio() {
var code;
var code, stdin;
code = '';
process.stdio.open();
process.stdio.addListener('data', function(string) {
if (string) {
return code += string;
stdin = process.openStdin();
stdin.addListener('data', function(buffer) {
if (buffer) {
return code += buffer.toString();
}
});
return process.stdio.addListener('close', function() {
return stdin.addListener('end', function() {
return compile_script('stdio', code);
});
};
@@ -127,7 +137,7 @@
// them every time the files are updated. May be used in combination with other
// options, such as `--lint` or `--print`.
watch_scripts = function watch_scripts() {
var _a, _b, _c, _d, source, watch;
var _b, _c, _d, _e, source, watch;
watch = function watch(source) {
return fs.watchFile(source, {
persistent: true,
@@ -141,12 +151,12 @@
});
});
};
_a = []; _b = sources;
for (_c = 0, _d = _b.length; _c < _d; _c++) {
source = _b[_c];
_a.push(watch(source));
_b = []; _d = sources;
for (_c = 0, _e = _d.length; _c < _e; _c++) {
source = _d[_c];
_b.push(watch(source));
}
return _a;
return _b;
};
// Write out a JavaScript source file with the compiled code. By default, files
// are written out in `cwd` as `.js` files with the same name, but the output
@@ -161,37 +171,32 @@
// Pipe compiled JS through JSLint (requires a working `jsl` command), printing
// any errors or warnings that arise.
lint = function lint(js) {
var jsl;
jsl = process.createChildProcess('jsl', ['-nologo', '-stdin']);
jsl.addListener('output', function(result) {
if (result) {
return puts(result.replace(/\n/g, ''));
}
});
jsl.addListener('error', function(result) {
if (result) {
return puts(result);
}
});
jsl.write(js);
return jsl.close();
var jsl, print_it;
print_it = function print_it(buffer) {
return puts(buffer.toString());
};
jsl = spawn('jsl', ['-nologo', '-stdin']);
jsl.stdout.addListener('data', print_it);
jsl.stderr.addListener('data', print_it);
jsl.stdin.write(js);
return jsl.stdin.end();
};
// Pretty-print a stream of tokens.
print_tokens = function print_tokens(tokens) {
var _a, _b, _c, _d, _e, strings, tag, token, value;
var _b, _c, _d, _e, _f, strings, tag, token, value;
strings = (function() {
_a = []; _b = tokens;
for (_c = 0, _d = _b.length; _c < _d; _c++) {
token = _b[_c];
_a.push((function() {
_e = [token[0], token[1].toString().replace(/\n/, '\\n')];
tag = _e[0];
value = _e[1];
_b = []; _d = tokens;
for (_c = 0, _e = _d.length; _c < _e; _c++) {
token = _d[_c];
_b.push((function() {
_f = [token[0], token[1].toString().replace(/\n/, '\\n')];
tag = _f[0];
value = _f[1];
return "[" + tag + " " + value + "]";
}).call(this));
})());
}
return _a;
}).call(this);
return _b;
})();
return puts(strings.join(' '));
};
// Use the [OptionParser module](optparse.html) to extract all options from
@@ -221,7 +226,7 @@
};
// Print the `--version` message and exit.
version = function version() {
puts("CoffeeScript version " + (CoffeeScript.VERSION));
puts(("CoffeeScript version " + CoffeeScript.VERSION));
return process.exit(0);
};
})();

View File

@@ -33,8 +33,8 @@
if (!(action)) {
return [pattern_string, '$$ = $1;', options];
}
action = (match = (action + '').match(unwrap)) ? match[1] : "(" + action + "())";
return [pattern_string, "$$ = " + action + ";", options];
action = (match = (action + '').match(unwrap)) ? match[1] : ("(" + action + "())");
return [pattern_string, ("$$ = " + action + ";"), options];
};
// Grammatical Rules
// -----------------
@@ -53,25 +53,33 @@
return new Expressions();
}), o("TERMINATOR", function() {
return new Expressions();
}), o("Expressions"), o("Block TERMINATOR")
}), o("Body"), o("Block TERMINATOR")
],
// Any list of expressions or method body, seperated by line breaks or
// semicolons.
Expressions: [o("Expression", function() {
// Any list of statements and expressions, seperated by line breaks or semicolons.
Body: [o("Line", function() {
return Expressions.wrap([$1]);
}), o("Expressions TERMINATOR Expression", function() {
}), o("Body TERMINATOR Line", function() {
return $1.push($3);
}), o("Expressions TERMINATOR")
}), o("Body TERMINATOR")
],
// Expressions and statements, which make up a line in a body.
Line: [o("Expression"), o("Statement")],
// Pure statements which cannot be expressions.
Statement: [o("Return"), o("Throw"), o("BREAK", function() {
return new LiteralNode(yytext);
}), o("CONTINUE", function() {
return new LiteralNode(yytext);
})
],
// All the different types of expressions in our language. The basic unit of
// CoffeeScript is the **Expression** -- you'll notice that there is no
// "statement" nonterminal. Expressions serve as the building blocks
// of many other rules, making them somewhat circular.
Expression: [o("Value"), o("Call"), o("Curry"), o("Code"), o("Operation"), o("Assign"), o("If"), o("Try"), o("Throw"), o("Return"), o("While"), o("For"), o("Switch"), o("Extends"), o("Class"), o("Splat"), o("Existence"), o("Comment"), o("Extension")],
// CoffeeScript is the **Expression** -- everything that can be an expression
// is one. Expressions serve as the building blocks of many other rules, making
// them somewhat circular.
Expression: [o("Value"), o("Call"), o("Curry"), 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"), o("Extension")],
// A an indented block of expressions. Note that the [Rewriter](rewriter.html)
// will convert some postfix forms into blocks for us, by adjusting the
// token stream.
Block: [o("INDENT Expressions OUTDENT", function() {
Block: [o("INDENT Body OUTDENT", function() {
return $2;
}), o("INDENT OUTDENT", function() {
return new Expressions();
@@ -98,10 +106,6 @@
return new LiteralNode(yytext);
}), o("REGEX", function() {
return new LiteralNode(yytext);
}), o("BREAK", function() {
return new LiteralNode(yytext);
}), o("CONTINUE", function() {
return new LiteralNode(yytext);
}), o("TRUE", function() {
return new LiteralNode(true);
}), o("FALSE", function() {
@@ -117,7 +121,7 @@
})
],
// Assignment of a variable, property, or index to a value.
Assign: [o("Value ASSIGN Expression", function() {
Assign: [o("Assignable ASSIGN Expression", function() {
return new AssignNode($1, $3);
})
],
@@ -187,24 +191,32 @@
return new SplatNode($1);
})
],
// The types of things that can be treated as values -- assigned to, invoked
// as functions, indexed into, named as a class, etc.
Value: [o("Identifier", function() {
// Variables and properties that can be assigned to.
SimpleAssignable: [o("Identifier", function() {
return new ValueNode($1);
}), o("Literal", function() {
return new ValueNode($1);
}), o("Array", function() {
}), o("Value Accessor", function() {
return $1.push($2);
}), o("Invocation Accessor", function() {
return new ValueNode($1, [$2]);
}), o("ThisProperty")
],
// Everything that can be assigned to.
Assignable: [o("SimpleAssignable"), o("Array", function() {
return new ValueNode($1);
}), o("Object", function() {
return new ValueNode($1);
})
],
// The types of things that can be treated as values -- assigned to, invoked
// as functions, indexed into, named as a class, etc.
Value: [o("Assignable"), o("Literal", function() {
return new ValueNode($1);
}), o("Parenthetical", function() {
return new ValueNode($1);
}), o("Range", function() {
return new ValueNode($1);
}), o("This"), o("Value Accessor", function() {
return $1.push($2);
}), o("Invocation Accessor", function() {
return new ValueNode($1, [$2]);
}), o("This"), o("NULL", function() {
return new ValueNode(new LiteralNode('null'));
})
],
// The general group of accessors into an object, by property, by prototype
@@ -233,18 +245,10 @@
return new ObjectNode($2);
}), o("{ IndentedAssignList }", function() {
return new ObjectNode($2);
})
],
// Class definitions have optional bodies of prototype property assignments,
// and optional references to the superclass.
Class: [o("CLASS Value", function() {
return new ClassNode($2);
}), o("CLASS Value EXTENDS Value", function() {
return new ClassNode($2, $4);
}), o("CLASS Value IndentedAssignList", function() {
return new ClassNode($2, null, $3);
}), o("CLASS Value EXTENDS Value IndentedAssignList", function() {
return new ClassNode($2, $4, $5);
}), o("{ AssignList , }", function() {
return new ObjectNode($2);
}), o("{ IndentedAssignList , }", function() {
return new ObjectNode($2);
})
],
// Assignment of properties within an object literal can be separated by
@@ -264,6 +268,36 @@
// An **AssignList** within a block indentation.
IndentedAssignList: [o("INDENT AssignList OUTDENT", function() {
return $2;
}), o("INDENT AssignList , OUTDENT", function() {
return $2;
})
],
// Class definitions have optional bodies of prototype property assignments,
// and optional references to the superclass.
Class: [o("CLASS SimpleAssignable", function() {
return new ClassNode($2);
}), o("CLASS SimpleAssignable EXTENDS Value", function() {
return new ClassNode($2, $4);
}), o("CLASS SimpleAssignable INDENT ClassBody OUTDENT", function() {
return new ClassNode($2, null, $4);
}), o("CLASS SimpleAssignable EXTENDS Value INDENT ClassBody OUTDENT", function() {
return new ClassNode($2, $4, $6);
})
],
// Assignments that can happen directly inside a class declaration.
ClassAssign: [o("AssignObj", function() {
return $1;
}), o("ThisProperty ASSIGN Expression", function() {
return new AssignNode(new ValueNode($1), $3, 'this');
})
],
// A list of assignments to a class.
ClassBody: [o("", function() {
return [];
}), o("ClassAssign", function() {
return [$1];
}), o("ClassBody TERMINATOR ClassAssign", function() {
return $1.concat($3);
})
],
// The three flavors of function call: normal, object instantiation with `new`,
@@ -272,13 +306,14 @@
return $2.new_instance();
}), o("Super")
],
// Binds a function call to a context and/or arguments.
Curry: [o("Value <- Arguments", function() {
return new CurryNode($1, $3);
})
],
// Extending an object by setting its prototype chain to reference a parent
// object.
Extends: [o("Value EXTENDS Value", function() {
Extends: [o("SimpleAssignable EXTENDS Value", function() {
return new ExtendsNode($1, $3);
})
],
@@ -292,17 +327,26 @@
// The list of arguments to a function call.
Arguments: [o("CALL_START ArgList CALL_END", function() {
return $2;
}), o("CALL_START ArgList , CALL_END", function() {
return $2;
})
],
// Calling super.
Super: [o("SUPER CALL_START ArgList CALL_END", function() {
return new CallNode('super', $3);
}), o("SUPER CALL_START ArgList , CALL_END", function() {
return new CallNode('super', $3);
})
],
// A reference to the *this* current object, either naked or to a property.
This: [o("@", function() {
// A reference to the *this* current object.
This: [o("THIS", function() {
return new ValueNode(new LiteralNode('this'));
}), o("@ Identifier", function() {
}), o("@", function() {
return new ValueNode(new LiteralNode('this'));
})
],
// A reference to a property on *this*.
ThisProperty: [o("@ Identifier", function() {
return new ValueNode(new LiteralNode('this'), [new AccessorNode($2)]);
})
],
@@ -323,6 +367,8 @@
// The array literal.
Array: [o("[ ArgList ]", function() {
return new ArrayNode($2);
}), o("[ ArgList , ]", function() {
return new ArrayNode($2);
})
],
// The **ArgList** is both the list of objects passed into a function call,
@@ -342,7 +388,7 @@
return $1.concat([$4]);
}), o("ArgList , INDENT Expression", function() {
return $1.concat([$4]);
}), o("ArgList OUTDENT")
}), o("ArgList OUTDENT"), o("ArgList , OUTDENT")
],
// Just simple, comma-separated, required arguments (no fancy syntax). We need
// this to be separate from the **ArgList** for use in **Switch** blocks, where
@@ -378,7 +424,7 @@
// not an **Expression**, so if you need to use an expression in a place
// where only values are accepted, wrapping it in parentheses will always do
// the trick.
Parenthetical: [o("( Expression )", function() {
Parenthetical: [o("( Line )", function() {
return new ParentheticalNode($2);
})
],
@@ -401,6 +447,8 @@
// or postfix, with a single expression. There is no do..while.
While: [o("WhileSource Block", function() {
return $1.add_body($2);
}), o("Statement WhileSource", function() {
return $2.add_body(Expressions.wrap([$1]));
}), o("Expression WhileSource", function() {
return $2.add_body(Expressions.wrap([$1]));
})
@@ -408,7 +456,9 @@
// Array, object, and range comprehensions, at the most generic level.
// Comprehensions can either be normal, with a block of expressions to execute,
// or postfix, with a single expression.
For: [o("Expression FOR ForVariables ForSource", function() {
For: [o("Statement FOR ForVariables ForSource", function() {
return new ForNode($1, $4, $3[0], $3[1]);
}), o("Expression FOR ForVariables ForSource", function() {
return new ForNode($1, $4, $3[0], $3[1]);
}), o("FOR ForVariables ForSource Block", function() {
return new ForNode($4, $3, $2[0], $2[1]);
@@ -424,7 +474,7 @@
})
],
// The source of a comprehension is an array or object with an optional filter
// clause. If it's an array comprehension, you can also choose to step throug
// clause. If it's an array comprehension, you can also choose to step through
// in fixed-size increments.
ForSource: [o("IN Expression", function() {
return {
@@ -435,12 +485,34 @@
source: $2,
object: true
};
}), o("ForSource WHEN Expression", function() {
$1.filter = $3;
return $1;
}), o("ForSource BY Expression", function() {
$1.step = $3;
return $1;
}), o("IN Expression WHEN Expression", function() {
return {
source: $2,
filter: $4
};
}), o("OF Expression WHEN Expression", function() {
return {
source: $2,
filter: $4,
object: true
};
}), o("IN Expression BY Expression", function() {
return {
source: $2,
step: $4
};
}), o("IN Expression WHEN Expression BY Expression", function() {
return {
source: $2,
filter: $4,
step: $6
};
}), o("IN Expression BY Expression WHEN Expression", function() {
return {
source: $2,
step: $4,
filter: $6
};
})
],
// The CoffeeScript switch/when/else block replaces the JavaScript
@@ -492,10 +564,19 @@
],
// The full complement of *if* expressions, including postfix one-liner
// *if* and *unless*.
If: [o("IfBlock"), o("Expression IF Expression", function() {
If: [o("IfBlock"), o("Statement IF Expression", function() {
return new IfNode($3, Expressions.wrap([$1]), null, {
statement: true
});
}), o("Expression IF Expression", function() {
return new IfNode($3, Expressions.wrap([$1]), null, {
statement: true
});
}), o("Statement UNLESS Expression", function() {
return new IfNode($3, Expressions.wrap([$1]), null, {
statement: true,
invert: true
});
}), o("Expression UNLESS Expression", function() {
return new IfNode($3, Expressions.wrap([$1]), null, {
statement: true,
@@ -617,25 +698,25 @@
for (name in _a) { if (__hasProp.call(_a, name)) {
alternatives = _a[name];
grammar[name] = (function() {
_b = []; _c = alternatives;
for (_d = 0, _e = _c.length; _d < _e; _d++) {
alt = _c[_d];
_b = []; _d = alternatives;
for (_c = 0, _e = _d.length; _c < _e; _c++) {
alt = _d[_c];
_b.push((function() {
_f = alt[0].split(' ');
for (_g = 0, _h = _f.length; _g < _h; _g++) {
token = _f[_g];
_g = alt[0].split(' ');
for (_f = 0, _h = _g.length; _f < _h; _f++) {
token = _g[_f];
if (!(grammar[token])) {
tokens.push(token);
}
}
if (name === 'Root') {
alt[1] = "return " + (alt[1]);
alt[1] = ("return " + (alt[1]));
}
return alt;
}).call(this));
})());
}
return _b;
}).call(this);
})();
}}
// Initialize the **Parser** with our list of terminal **tokens**, our **grammar**
// rules, and the name of the root. Reverse the operators because Jison orders

View File

@@ -20,9 +20,9 @@
// Trim out all falsy values from an array.
helpers.compact = (compact = function compact(array) {
var _a, _b, _c, _d, item;
_a = []; _b = array;
for (_c = 0, _d = _b.length; _c < _d; _c++) {
item = _b[_c];
_a = []; _c = array;
for (_b = 0, _d = _c.length; _b < _d; _b++) {
item = _c[_b];
item ? _a.push(item) : null;
}
return _a;
@@ -74,9 +74,9 @@
helpers.flatten = (flatten = function flatten(array) {
var _a, _b, _c, item, memo;
memo = [];
_a = array;
for (_b = 0, _c = _a.length; _b < _c; _b++) {
item = _a[_b];
_b = array;
for (_a = 0, _c = _b.length; _a < _c; _a++) {
item = _b[_a];
item instanceof Array ? (memo = memo.concat(item)) : memo.push(item);
}
return memo;
@@ -103,9 +103,9 @@
if (levels.length && starts(str, '\\', i)) {
i += 1;
} else {
_a = delimited;
for (_b = 0, _c = _a.length; _b < _c; _b++) {
pair = _a[_b];
_b = delimited;
for (_a = 0, _c = _b.length; _a < _c; _a++) {
pair = _b[_a];
_d = pair;
open = _d[0];
close = _d[1];
@@ -132,7 +132,7 @@
if (slash) {
return false;
}
throw new Error("SyntaxError: Unterminated " + (levels.pop()[0]) + " starting on line " + (this.line + 1));
throw new Error(("SyntaxError: Unterminated " + (levels.pop()[0]) + " starting on line " + (this.line + 1)));
}
if (!i) {
return false;

View File

@@ -1,5 +1,6 @@
(function(){
var ACCESSORS, ASSIGNMENT, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_KEYWORDS, COMMENT, COMMENT_CLEANER, CONVERSIONS, HALF_ASSIGNMENTS, HEREDOC, HEREDOC_INDENT, IDENTIFIER, INTERPOLATION, JS_CLEANER, JS_FORBIDDEN, JS_KEYWORDS, KEYWORDS, LAST_DENT, LAST_DENTS, LINE_BREAK, Lexer, MULTILINER, MULTI_DENT, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX_ESCAPE, REGEX_FLAGS, REGEX_INTERPOLATION, REGEX_START, RESERVED, Rewriter, STRING_NEWLINES, WHITESPACE, balanced_string, compact, count, helpers, include, starts;
var __slice = Array.prototype.slice;
// The CoffeeScript Lexer. Uses a series of token-matching regexes to attempt
// matches against the beginning of the source code. When a match is found,
// a token is produced, we consume the match, and start again. Tokens are in the
@@ -106,9 +107,9 @@
// as something else.
Lexer.prototype.extension_token = function extension_token() {
var _a, _b, _c, extension;
_a = Lexer.extensions;
for (_b = 0, _c = _a.length; _b < _c; _b++) {
extension = _a[_b];
_b = Lexer.extensions;
for (_a = 0, _c = _b.length; _a < _c; _a++) {
extension = _b[_a];
if (extension.call(this)) {
return true;
}
@@ -184,7 +185,7 @@
}
quote = match[1].substr(0, 1);
doc = this.sanitize_heredoc(match[2] || match[4], quote);
this.interpolate_string("" + quote + doc + quote);
this.interpolate_string(("" + quote + doc + quote));
this.line += count(match[1], "\n");
this.i += match[1].length;
return true;
@@ -224,8 +225,8 @@
return '\\' + escaped;
});
this.tokens = this.tokens.concat([['(', '('], ['NEW', 'new'], ['IDENTIFIER', 'RegExp'], ['CALL_START', '(']]);
this.interpolate_string("\"" + str + "\"", true);
this.tokens = this.tokens.concat([[',', ','], ['STRING', "\"" + flags + "\""], [')', ')'], [')', ')']]);
this.interpolate_string(("\"" + str + "\""), true);
this.tokens = this.tokens.concat([[',', ','], ['STRING', ("\"" + flags + "\"")], [')', ')'], [')', ')']]);
} else {
this.token('REGEX', regex);
}
@@ -236,7 +237,7 @@
// balanced (ie. strings, JS literals).
Lexer.prototype.balanced_token = function balanced_token() {
var delimited;
delimited = Array.prototype.slice.call(arguments, 0, arguments.length - 0);
delimited = __slice.call(arguments, 0, arguments.length - 0);
return balanced_string(this.chunk, delimited);
};
// Matches and conumes comments. We pass through comments into JavaScript,
@@ -411,7 +412,7 @@
Lexer.prototype.tag_half_assignment = function tag_half_assignment(tag) {
var last;
last = this.tokens.pop();
this.tokens.push(["" + tag + "=", "" + tag + "=", last[2]]);
this.tokens.push([("" + tag + "="), ("" + tag + "="), last[2]]);
return true;
};
// A source of ambiguity in our grammar used to be parameter lists in function
@@ -434,7 +435,8 @@
} else if (_a === ')') {
tok[0] = 'PARAM_END';
} else if (_a === '(') {
return (tok[0] = 'PARAM_START');
tok[0] = 'PARAM_START';
return tok[0];
}
}
return true;
@@ -446,12 +448,12 @@
// The error for when you try to use a forbidden word in JavaScript as
// an identifier.
Lexer.prototype.identifier_error = function identifier_error(word) {
throw new Error("SyntaxError: Reserved word \"" + word + "\" on line " + (this.line + 1));
throw new Error(("SyntaxError: Reserved word \"" + word + "\" on line " + (this.line + 1)));
};
// The error for when you try to assign to a reserved word in JavaScript,
// like "function" or "default".
Lexer.prototype.assignment_error = function assignment_error() {
throw new Error("SyntaxError: Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned");
throw new Error(("SyntaxError: Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned"));
};
// Expand variables and expressions inside double-quoted strings using
// [ECMA Harmony's interpolation syntax](http://wiki.ecmascript.org/doku.php?id=strawman:string_interpolation)
@@ -462,7 +464,7 @@
// new Lexer, tokenize the interpolated contents, and merge them into the
// token stream.
Lexer.prototype.interpolate_string = function interpolate_string(str, escape_quotes) {
var _a, _b, _c, _d, _e, escaped, expr, group, i, inner, interp, lexer, match, nested, pi, quote, tag, token, tokens, value;
var _a, _b, _c, _d, _e, _f, _g, escaped, expr, group, i, idx, inner, interp, interpolated, lexer, match, nested, pi, quote, tag, tok, token, tokens, value;
if (str.length < 3 || !starts(str, '"')) {
return this.token('STRING', str);
} else {
@@ -480,28 +482,32 @@
group = _b[0];
interp = _b[1];
if (starts(interp, '@')) {
interp = "this." + (interp.substring(1));
interp = ("this." + (interp.substring(1)));
}
if (pi < i) {
tokens.push(['STRING', "" + quote + (str.substring(pi, i)) + quote]);
tokens.push(['STRING', ("" + quote + (str.substring(pi, i)) + quote)]);
}
tokens.push(['IDENTIFIER', interp]);
i += group.length - 1;
pi = i + 1;
} else if ((expr = balanced_string(str.substring(i), [['${', '}']]))) {
if (pi < i) {
tokens.push(['STRING', "" + quote + (str.substring(pi, i)) + quote]);
tokens.push(['STRING', ("" + quote + (str.substring(pi, i)) + quote)]);
}
inner = expr.substring(2, expr.length - 1);
if (inner.length) {
nested = lexer.tokenize("(" + inner + ")", {
rewrite: false,
nested = lexer.tokenize(("(" + inner + ")"), {
line: this.line
});
_c = nested;
for (idx = 0, _d = _c.length; idx < _d; idx++) {
tok = _c[idx];
tok[0] === 'CALL_END' ? (tok[0] = ')') : null;
}
nested.pop();
tokens.push(['TOKENS', nested]);
} else {
tokens.push(['STRING', "" + quote + quote]);
tokens.push(['STRING', ("" + quote + quote)]);
}
i += expr.length - 1;
pi = i + 1;
@@ -509,22 +515,26 @@
i += 1;
}
if (pi < i && pi < str.length - 1) {
tokens.push(['STRING', "" + quote + (str.substring(pi, i)) + quote]);
tokens.push(['STRING', ("" + quote + (str.substring(pi, i)) + quote)]);
}
if (!(tokens[0][0] === 'STRING')) {
tokens.unshift(['STRING', '""']);
}
_c = tokens;
for (i = 0, _d = _c.length; i < _d; i++) {
token = _c[i];
_e = token;
tag = _e[0];
value = _e[1];
interpolated = tokens.length > 1;
if (interpolated) {
this.token('(', '(');
}
_e = tokens;
for (i = 0, _f = _e.length; i < _f; i++) {
token = _e[i];
_g = token;
tag = _g[0];
value = _g[1];
if (tag === 'TOKENS') {
this.tokens = this.tokens.concat(value);
} else if (tag === 'STRING' && escape_quotes) {
escaped = value.substring(1, value.length - 1).replace(/"/g, '\\"');
this.token(tag, "\"" + escaped + "\"");
this.token(tag, ("\"" + escaped + "\""));
} else {
this.token(tag, value);
}
@@ -532,6 +542,9 @@
this.token('+', '+');
}
}
if (interpolated) {
this.token(')', ')');
}
return tokens;
}
};
@@ -542,13 +555,14 @@
return this.tokens.push([tag, value, this.line]);
};
// Peek at a tag in the current token stream.
Lexer.prototype.tag = function tag(index, tag) {
Lexer.prototype.tag = function tag(index, new_tag) {
var tok;
if (!(tok = this.prev(index))) {
return null;
}
if ((typeof tag !== "undefined" && tag !== null)) {
return (tok[0] = tag);
if ((typeof new_tag !== "undefined" && new_tag !== null)) {
tok[0] = new_tag;
return tok[0];
}
return tok[0];
};
@@ -559,7 +573,8 @@
return null;
}
if ((typeof val !== "undefined" && val !== null)) {
return (tok[1] = val);
tok[1] = val;
return tok[1];
}
return tok[1];
};
@@ -586,14 +601,16 @@
prev = this.prev(2);
return this.value() && this.value().match && this.value().match(NO_NEWLINE) && prev && (prev[0] !== '.') && !this.value().match(CODE);
};
// Lexer Properties
// ----------------
// There are no exensions to the core lexer by default.
Lexer.extensions = [];
return Lexer;
}).call(this);
// There are no exensions to the core lexer by default.
Lexer.extensions = [];
// Constants
// ---------
// Keywords that CoffeeScript shares in common with JavaScript.
JS_KEYWORDS = ["if", "else", "true", "false", "new", "return", "try", "catch", "finally", "throw", "break", "continue", "for", "in", "while", "delete", "instanceof", "typeof", "switch", "super", "extends", "class"];
JS_KEYWORDS = ["if", "else", "true", "false", "new", "return", "try", "catch", "finally", "throw", "break", "continue", "for", "in", "while", "delete", "instanceof", "typeof", "switch", "super", "extends", "class", "this", "null"];
// CoffeeScript-only keywords, which we're more relaxed about allowing. They can't
// be used standalone, but you can reference them as an attached property.
COFFEE_ALIASES = ["and", "or", "is", "isnt", "not"];
@@ -604,7 +621,7 @@
// The list of keywords that are reserved by JavaScript, but not used, or are
// used by CoffeeScript internally. We throw an error when these are encountered,
// to avoid having a JavaScript error at runtime.
RESERVED = ["case", "default", "do", "function", "var", "void", "with", "const", "let", "debugger", "enum", "export", "import", "native", "__extends", "__hasProp"];
RESERVED = ["case", "default", "do", "function", "var", "void", "with", "const", "let", "debugger", "enum", "export", "import", "native"];
// The superset of both JavaScript keywords and reserved words, none of which may
// be used as identifiers or properties.
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED);
@@ -641,7 +658,7 @@
// Tokens which could legitimately be invoked or indexed. A opening
// parentheses or bracket following these tokens will be recorded as the start
// of a function invocation or indexing operation.
CALLABLE = ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING', '@'];
CALLABLE = ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING', '@', 'THIS'];
// Tokens that indicate an access -- keywords immediately following will be
// treated as identifiers.
ACCESSORS = ['PROPERTY_ACCESS', 'PROTOTYPE_ACCESS', 'SOAK_ACCESS', '@'];

File diff suppressed because it is too large Load Diff

View File

@@ -24,12 +24,12 @@
arguments: []
};
args = normalize_arguments(args);
while (arg = args.shift()) {
while ((arg = args.shift())) {
is_option = !!(arg.match(LONG_FLAG) || arg.match(SHORT_FLAG));
matched_rule = false;
_a = this.rules;
for (_b = 0, _c = _a.length; _b < _c; _b++) {
rule = _a[_b];
_b = this.rules;
for (_a = 0, _c = _b.length; _a < _c; _a++) {
rule = _b[_a];
if (rule.short_flag === arg || rule.long_flag === arg) {
options[rule.name] = rule.has_argument ? args.shift() : true;
matched_rule = true;
@@ -37,7 +37,7 @@
}
}
if (is_option && !matched_rule) {
throw new Error("unrecognized option: " + arg);
throw new Error(("unrecognized option: " + arg));
}
if (!(is_option)) {
options.arguments.push(arg);
@@ -48,29 +48,29 @@
// Return the help text for this **OptionParser**, listing and describing all
// of the valid options, for `--help` and such.
OptionParser.prototype.help = function help() {
var _a, _b, _c, _d, _e, _f, _g, _h, i, let_part, lines, rule, spaces;
var _a, _b, _c, _d, _e, _f, _g, i, let_part, lines, rule, spaces;
lines = ['Available options:'];
if (this.banner) {
lines.unshift("" + this.banner + "\n");
lines.unshift(("" + this.banner + "\n"));
}
_a = this.rules;
for (_b = 0, _c = _a.length; _b < _c; _b++) {
rule = _a[_b];
_b = this.rules;
for (_a = 0, _c = _b.length; _a < _c; _a++) {
rule = _b[_a];
spaces = 15 - rule.long_flag.length;
spaces = spaces > 0 ? (function() {
_d = []; _g = 0; _h = spaces;
for (_f = 0, i = _g; (_g <= _h ? i <= _h : i >= _h); (_g <= _h ? i += 1 : i -= 1), _f++) {
_d = []; _f = 0; _g = spaces;
for (_e = 0, i = _f; (_f <= _g ? i <= _g : i >= _g); (_f <= _g ? i += 1 : i -= 1), _e++) {
_d.push(' ');
}
return _d;
}).call(this).join('') : '';
})().join('') : '';
let_part = rule.short_flag ? rule.short_flag + ', ' : ' ';
lines.push(" " + let_part + (rule.long_flag) + spaces + (rule.description));
lines.push((" " + let_part + rule.long_flag + spaces + rule.description));
}
return "\n" + (lines.join('\n')) + "\n";
};
return OptionParser;
}).call(this);
})();
// Helpers
// -------
// Regex matchers for option flags.
@@ -82,15 +82,15 @@
// unspecified, leave it out by padding with `null`.
build_rules = function build_rules(rules) {
var _a, _b, _c, _d, tuple;
_a = []; _b = rules;
for (_c = 0, _d = _b.length; _c < _d; _c++) {
tuple = _b[_c];
_a = []; _c = rules;
for (_b = 0, _d = _c.length; _b < _d; _b++) {
tuple = _c[_b];
_a.push((function() {
if (tuple.length < 3) {
tuple.unshift(null);
}
return build_rule.apply(this, tuple);
}).call(this));
})());
}
return _a;
};
@@ -114,13 +114,13 @@
var _a, _b, _c, _d, _e, _f, arg, l, match, result;
args = args.slice(0);
result = [];
_a = args;
for (_b = 0, _c = _a.length; _b < _c; _b++) {
arg = _a[_b];
_b = args;
for (_a = 0, _c = _b.length; _a < _c; _a++) {
arg = _b[_a];
if ((match = arg.match(MULTI_FLAG))) {
_d = match[1].split('');
for (_e = 0, _f = _d.length; _e < _f; _e++) {
l = _d[_e];
_e = match[1].split('');
for (_d = 0, _f = _e.length; _d < _f; _d++) {
l = _e[_d];
result.push('-' + l);
}
} else {

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
(function(){
var CoffeeScript, helpers, prompt, run;
var CoffeeScript, helpers, prompt, run, stdin;
// A very simple Read-Eval-Print-Loop. Compiles one line at a time to JavaScript
// and evaluates it. Good for simple tests, or poking around the **Node.js** API.
// Using it looks like this:
@@ -18,10 +18,10 @@
// The main REPL function. **run** is called every time a line of code is entered.
// Attempt to evaluate the command. If there's an exception, print it out instead
// of exiting.
run = function run(code) {
run = function run(buffer) {
var val;
try {
val = CoffeeScript.run(code, {
val = CoffeeScript.run(buffer.toString(), {
no_wrap: true,
globals: true,
source: 'repl'
@@ -34,8 +34,8 @@
}
return print(prompt);
};
// Start up the REPL by opening **stdio** and listening for input.
process.stdio.addListener('data', run);
process.stdio.open();
// Start up the REPL by opening **stdin** and listening for input.
stdin = process.openStdin();
stdin.addListener('data', run);
print(prompt);
})();

View File

@@ -1,6 +1,10 @@
(function(){
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, INVERSES, Rewriter, SINGLE_CLOSERS, SINGLE_LINERS, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, helpers, include, pair;
var __hasProp = Object.prototype.hasOwnProperty;
var __slice = Array.prototype.slice, __bind = function(func, obj, args) {
return function() {
return func.apply(obj || {}, args ? args.concat(__slice.call(arguments, 0)) : arguments);
};
}, __hasProp = Object.prototype.hasOwnProperty;
// The CoffeeScript language has a good deal of optional syntax, implicit syntax,
// and shorthand syntax. This can greatly complicate a grammar and bloat
// the resulting parse table. Instead of making the parser handle it all, we take
@@ -57,8 +61,7 @@
// Massage newlines and indentations so that comments don't have to be
// correctly indented, or appear on a line of their own.
Rewriter.prototype.adjust_comments = function adjust_comments() {
return this.scan_tokens((function(__this) {
var __func = function(prev, token, post, i) {
return this.scan_tokens(__bind(function(prev, token, post, i) {
var after;
if (!(token[0] === 'COMMENT')) {
return 1;
@@ -74,11 +77,7 @@
} else {
return 1;
}
};
return (function() {
return __func.apply(__this, arguments);
});
})(this));
}, this));
};
// Leading newlines would introduce an ambiguity in the grammar, so we
// dispatch them here.
@@ -93,18 +92,13 @@
// Some blocks occur in the middle of expressions -- when we're expecting
// this, remove their trailing newlines.
Rewriter.prototype.remove_mid_expression_newlines = function remove_mid_expression_newlines() {
return this.scan_tokens((function(__this) {
var __func = function(prev, token, post, i) {
return this.scan_tokens(__bind(function(prev, token, post, i) {
if (!(post && include(EXPRESSION_CLOSE, post[0]) && token[0] === 'TERMINATOR')) {
return 1;
}
this.tokens.splice(i, 1);
return 0;
};
return (function() {
return __func.apply(__this, arguments);
});
})(this));
}, this));
};
// The lexer has tagged the opening parenthesis of a method call, and the
// opening bracket of an indexing operation. Match them with their paired
@@ -113,8 +107,7 @@
var brackets, parens;
parens = [0];
brackets = [0];
return this.scan_tokens((function(__this) {
var __func = function(prev, token, post, i) {
return this.scan_tokens(__bind(function(prev, token, post, i) {
var _a;
if ((_a = token[0]) === 'CALL_START') {
parens.push(0);
@@ -140,27 +133,28 @@
}
}
return 1;
};
return (function() {
return __func.apply(__this, arguments);
});
})(this));
}, this));
};
// Methods may be optionally called without parentheses, for simple cases.
// Insert the implicit parentheses here, so that the parser doesn't have to
// deal with them.
Rewriter.prototype.add_implicit_parentheses = function add_implicit_parentheses() {
var calls, stack;
var calls, parens, stack, start_parens;
stack = [0];
calls = 0;
return this.scan_tokens((function(__this) {
var __func = function(prev, token, post, i) {
var _a, _b, _c, _d, idx, last, open, size, stack_pointer, tag, tmp;
parens = 0;
start_parens = 0;
return this.scan_tokens(__bind(function(prev, token, post, i) {
var _a, _b, _c, idx, last, open, size, stack_pointer, tag, tmp;
tag = token[0];
if (tag === 'CALL_START') {
calls += 1;
} else if (tag === 'CALL_END') {
calls -= 1;
} else if (tag === '(') {
parens += 1;
} else if (tag === ')') {
parens -= 1;
} else if (tag === 'INDENT') {
stack.push(0);
} else if (tag === 'OUTDENT') {
@@ -168,20 +162,18 @@
stack[stack.length - 1] += last;
}
open = stack[stack.length - 1] > 0;
if (tag === 'CALL_END' && calls < 0 && open) {
stack[stack.length - 1] -= 1;
this.tokens.splice(i, 0, ['CALL_END', ')', token[2]]);
return 2;
}
if (!(typeof post !== "undefined" && post !== null) || include(IMPLICIT_END, tag)) {
if (!(typeof post !== "undefined" && post !== null) || (start_parens > parens) || (start_parens === parens && include(IMPLICIT_END, tag))) {
if (tag === 'INDENT' && prev && include(IMPLICIT_BLOCK, prev[0])) {
return 1;
}
if (tag === 'OUTDENT' && token.generated) {
return 1;
}
if (open || tag === 'INDENT') {
idx = tag === 'OUTDENT' ? i + 1 : i;
stack_pointer = tag === 'INDENT' ? 2 : 1;
_c = 0; _d = stack[stack.length - stack_pointer];
for (_b = 0, tmp = _c; (_c <= _d ? tmp < _d : tmp > _d); (_c <= _d ? tmp += 1 : tmp -= 1), _b++) {
_b = 0; _c = stack[stack.length - stack_pointer];
for (_a = 0, tmp = _b; (_b <= _c ? tmp < _c : tmp > _c); (_b <= _c ? tmp += 1 : tmp -= 1), _a++) {
this.tokens.splice(idx, 0, ['CALL_END', ')', token[2]]);
}
size = stack[stack.length - stack_pointer] + 1;
@@ -193,23 +185,19 @@
return 1;
}
calls = 0;
start_parens = tag === '(' ? parens - 1 : parens;
this.tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
stack[stack.length - 1] += 1;
return 2;
};
return (function() {
return __func.apply(__this, arguments);
});
})(this));
}, this));
};
// Because our grammar is LALR(1), it can't handle some single-line
// expressions that lack ending delimiters. The **Rewriter** adds the implicit
// blocks, so it doesn't need to. ')' can close a single-line block,
// but we need to make sure it's balanced.
Rewriter.prototype.add_implicit_indentation = function add_implicit_indentation() {
return this.scan_tokens((function(__this) {
var __func = function(prev, token, post, i) {
var idx, insertion, parens, pre, starter, tok;
return this.scan_tokens(__bind(function(prev, token, post, i) {
var idx, insertion, outdent, parens, pre, starter, tok;
if (!(include(SINGLE_LINERS, token[0]) && post[0] !== 'INDENT' && !(token[0] === 'ELSE' && post[0] === 'IF'))) {
return 1;
}
@@ -223,7 +211,9 @@
pre = this.tokens[idx - 1];
if ((!tok || (include(SINGLE_CLOSERS, tok[0]) && tok[1] !== ';') || (tok[0] === ')' && parens === 0)) && !(starter === 'ELSE' && tok[0] === 'ELSE')) {
insertion = pre[0] === "," ? idx - 1 : idx;
this.tokens.splice(insertion, 0, ['OUTDENT', 2, token[2]]);
outdent = ['OUTDENT', 2, token[2]];
outdent.generated = true;
this.tokens.splice(insertion, 0, outdent);
break;
}
if (tok[0] === '(') {
@@ -238,11 +228,7 @@
}
this.tokens.splice(i, 1);
return 0;
};
return (function() {
return __func.apply(__this, arguments);
});
})(this));
}, this));
};
// Ensure that all listed pairs of tokens are correctly balanced throughout
// the course of the token stream.
@@ -250,12 +236,11 @@
var _a, _b, key, levels, line, open, open_line, unclosed, value;
levels = {};
open_line = {};
this.scan_tokens((function(__this) {
var __func = function(prev, token, post, i) {
this.scan_tokens(__bind(function(prev, token, post, i) {
var _a, _b, _c, _d, close, open, pair;
_a = pairs;
for (_b = 0, _c = _a.length; _b < _c; _b++) {
pair = _a[_b];
_b = pairs;
for (_a = 0, _c = _b.length; _a < _c; _a++) {
pair = _b[_a];
_d = pair;
open = _d[0];
close = _d[1];
@@ -270,15 +255,11 @@
levels[open] -= 1;
}
if (levels[open] < 0) {
throw new Error("too many " + (token[1]) + " on line " + (token[2] + 1));
throw new Error(("too many " + (token[1]) + " on line " + (token[2] + 1)));
}
}
return 1;
};
return (function() {
return __func.apply(__this, arguments);
});
})(this));
}, this));
unclosed = (function() {
_a = []; _b = levels;
for (key in _b) { if (__hasProp.call(_b, key)) {
@@ -286,11 +267,11 @@
value > 0 ? _a.push(key) : null;
}}
return _a;
}).call(this);
})();
if (unclosed.length) {
open = unclosed[0];
line = open_line[open] + 1;
throw new Error("unclosed " + open + " on line " + line);
throw new Error(("unclosed " + open + " on line " + line));
}
};
// We'd like to support syntax like this:
@@ -299,10 +280,10 @@
// In order to accomplish this, move outdents that follow closing parens
// inwards, safely. The steps to accomplish this are:
// 1. Check that all paired tokens are balanced and in order.
// 2. Rewrite the stream with a stack: if you see an '(' or INDENT, add it
// to the stack. If you see an ')' or OUTDENT, pop the stack and replace
// 2. Rewrite the stream with a stack: if you see an `EXPRESSION_START`, add it
// to the stack. If you see an `EXPRESSION_END`, pop the stack and replace
// it with the inverse of what we've just popped.
// 3. Keep track of "debt" for tokens that we fake, to make sure we end
// 3. Keep track of "debt" for tokens that we manufacture, to make sure we end
// up balanced in the end.
Rewriter.prototype.rewrite_closing_parens = function rewrite_closing_parens() {
var _a, debt, key, stack, val;
@@ -313,8 +294,7 @@
val = _a[key];
(debt[key] = 0);
}}
return this.scan_tokens((function(__this) {
var __func = function(prev, token, post, i) {
return this.scan_tokens(__bind(function(prev, token, post, i) {
var inv, match, mtag, tag;
tag = token[0];
inv = INVERSES[token[0]];
@@ -340,14 +320,10 @@
} else {
return 1;
}
};
return (function() {
return __func.apply(__this, arguments);
});
})(this));
}, this));
};
return Rewriter;
}).call(this);
})();
// Constants
// ---------
// List of the token pairs that must be balanced.
@@ -355,36 +331,36 @@
// The inverse mappings of `BALANCED_PAIRS` we're trying to fix up, so we can
// look things up from either end.
INVERSES = {};
_a = BALANCED_PAIRS;
for (_b = 0, _c = _a.length; _b < _c; _b++) {
pair = _a[_b];
_b = BALANCED_PAIRS;
for (_a = 0, _c = _b.length; _a < _c; _a++) {
pair = _b[_a];
INVERSES[pair[0]] = pair[1];
INVERSES[pair[1]] = pair[0];
}
// The tokens that signal the start of a balanced pair.
EXPRESSION_START = (function() {
_d = []; _e = BALANCED_PAIRS;
for (_f = 0, _g = _e.length; _f < _g; _f++) {
pair = _e[_f];
_d = []; _f = BALANCED_PAIRS;
for (_e = 0, _g = _f.length; _e < _g; _e++) {
pair = _f[_e];
_d.push(pair[0]);
}
return _d;
}).call(this);
})();
// The tokens that signal the end of a balanced pair.
EXPRESSION_END = (function() {
_h = []; _i = BALANCED_PAIRS;
for (_j = 0, _k = _i.length; _j < _k; _j++) {
pair = _i[_j];
_h = []; _j = BALANCED_PAIRS;
for (_i = 0, _k = _j.length; _i < _k; _i++) {
pair = _j[_i];
_h.push(pair[1]);
}
return _h;
}).call(this);
})();
// Tokens that indicate the close of a clause of an expression.
EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
// Tokens that, if followed by an `IMPLICIT_CALL`, indicate a function invocation.
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '<-'];
// If preceded by an `IMPLICIT_FUNC`, indicates a function invocation.
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'TRY', 'DELETE', 'TYPEOF', 'SWITCH', 'EXTENSION', 'TRUE', 'FALSE', 'YES', 'NO', 'ON', 'OFF', '!', '!!', 'NOT', '@', '->', '=>', '[', '(', '{'];
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'TRY', 'DELETE', 'TYPEOF', 'SWITCH', 'EXTENSION', 'TRUE', 'FALSE', 'YES', 'NO', 'ON', 'OFF', '!', '!!', 'NOT', 'THIS', 'NULL', '@', '->', '=>', '[', '(', '{'];
// Tokens indicating that the implicit call must enclose a block of expressions.
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ','];
// Tokens that always mark the end of an implicit call for single-liners.

View File

@@ -19,9 +19,16 @@
this.expressions = _a[1];
this.method = _a[2];
this.variables = {};
this.temp_var = this.parent ? this.parent.temp_var : '_a';
if (this.parent) {
this.temp_var = this.parent.temp_var;
} else {
Scope.root = this;
this.temp_var = '_a';
}
return this;
};
// The top-level **Scope** object.
Scope.root = null;
// Initialize a scope with its parent, for lookups up the chain,
// as well as a reference to the **Expressions** node is belongs to, which is
// where it should declare its variables, and a reference to the function that
@@ -35,6 +42,18 @@
this.variables[name] = 'var';
return false;
};
// Test variables and return true the first time fn(v, k) returns true
Scope.prototype.any = function any(fn) {
var _a, k, v;
_a = this.variables;
for (v in _a) { if (__hasProp.call(_a, v)) {
k = _a[v];
if (fn(v, k)) {
return true;
}
}}
return false;
};
// Reserve a variable name as originating from a function parameter for this
// scope. No `var` required for internal references.
Scope.prototype.parameter = function parameter(name) {
@@ -61,10 +80,7 @@
};
// Ensure that an assignment is made at the top of this scope
// (or at the top-level scope, if requested).
Scope.prototype.assign = function assign(name, value, top_level) {
if (top_level && this.parent) {
return this.parent.assign(name, value, top_level);
}
Scope.prototype.assign = function assign(name, value) {
this.variables[name] = {
value: value,
assigned: true
@@ -74,12 +90,16 @@
// Does this scope reference any variables that need to be declared in the
// given function body?
Scope.prototype.has_declarations = function has_declarations(body) {
return body === this.expressions && this.declared_variables().length;
return body === this.expressions && this.any(function(k, val) {
return val === 'var';
});
};
// Does this scope reference any assignments that need to be declared at the
// top of the given function body?
Scope.prototype.has_assignments = function has_assignments(body) {
return body === this.expressions && this.assigned_variables().length;
return body === this.expressions && this.any(function(k, val) {
return val.assigned;
});
};
// Return the list of variables first declared in this scope.
Scope.prototype.declared_variables = function declared_variables() {
@@ -100,7 +120,7 @@
_a = []; _b = this.variables;
for (key in _b) { if (__hasProp.call(_b, key)) {
val = _b[key];
val.assigned ? _a.push("" + key + " = " + (val.value)) : null;
val.assigned ? _a.push(("" + key + " = " + val.value)) : null;
}}
return _a;
};

12
lib/utilities.js Normal file
View File

@@ -0,0 +1,12 @@
(function(){
if (!((typeof process !== "undefined" && process !== null))) {
this.exports = this;
}
exports.utilities = {
extend: "function(child, parent) {\n var ctor = function(){ };\n ctor.prototype = parent.prototype;\n child.__superClass__ = parent.prototype;\n child.prototype = new ctor();\n child.prototype.constructor = child;\n }",
bind: "function(func, obj, args) {\n return function() {\n return func.apply(obj || {}, args ? args.concat(__slice.call(arguments, 0)) : arguments);\n };\n }",
range: "function(array, from, to, exclusive) {\n return [\n (from < 0 ? from + array.length : from || 0),\n (to < 0 ? to + array.length : to || array.length) + (exclusive ? 0 : 1)\n ];\n }",
hasProp: 'Object.prototype.hasOwnProperty',
slice: 'Array.prototype.slice'
};
})();

View File

@@ -3,5 +3,5 @@
"description": "Unfancy JavaScript",
"keywords": ["javascript", "language"],
"author": "Jeremy Ashkenas",
"version": "0.5.6"
"version": "0.6.1"
}

View File

@@ -22,9 +22,10 @@ oparse: null
# Mixin the top-level Cake functions for Cakefiles to use directly.
helpers.extend global, {
# Define a Cake task with a short name, a sentence description,
# Define a Cake task with a short name, an optional sentence description,
# and the function to run as the action itself.
task: (name, description, action) ->
[action, description]: [description, action] unless action
tasks[name]: {name: name, description: description, action: action}
# Define an option that the Cakefile accepts. The parsed options hash,
@@ -59,10 +60,11 @@ print_tasks: ->
for name, task of tasks
spaces: 20 - name.length
spaces: if spaces > 0 then (' ' for i in [0..spaces]).join('') else ''
puts "cake $name$spaces # ${task.description}"
desc: if task.description then "# $task.description" else ''
puts "cake $name$spaces $desc"
puts oparse.help() if switches.length
# Print an error and exit when attempting to all an undefined task.
no_such_task: (task) ->
process.stdio.writeError "No such task: \"$task\"\n"
puts "No such task: \"$task\"\n"
process.exit 1

View File

@@ -22,7 +22,7 @@ else
helpers: this.helpers
# The current CoffeeScript version number.
exports.VERSION: '0.5.6'
exports.VERSION: '0.6.1'
# Instantiate a Lexer for our use here.
lexer: new Lexer()
@@ -34,7 +34,7 @@ exports.compile: compile: (code, options) ->
try
(parser.parse lexer.tokenize code).compile options
catch err
err.message: "In ${options.source}, ${err.message}" if options.source
err.message: "In $options.source, $err.message" if options.source
throw err
# Tokenize a string of CoffeeScript code, and return the array of tokens.
@@ -51,7 +51,7 @@ exports.nodes: (code) ->
# setting `__filename`, `__dirname`, and relative `require()`.
exports.run: ((code, options) ->
module.filename: __filename: options.source
__dirname: path.dirname __filename
__dirname: path.dirname(__filename)
eval exports.compile code, options
)

View File

@@ -9,6 +9,7 @@ fs: require 'fs'
path: require 'path'
optparse: require './optparse'
CoffeeScript: require './coffee-script'
{spawn: spawn, exec: exec}: require('child_process')
# The help banner that is printed when `coffee` is called without arguments.
BANNER: '''
@@ -67,7 +68,9 @@ compile_scripts: ->
path.exists source, (exists) ->
throw new Error "File not found: $source" unless exists
fs.readFile source, (err, code) -> compile_script(source, code)
compile(source) for source in sources
run: -> compile(source) for source in sources
return run() unless options.output and options.compile
exec "mkdir -p $options.output", run
# Compile a single source script, containing the given code, according to the
# requested options. Both compile_scripts and watch_scripts share this method
@@ -82,7 +85,7 @@ compile_script: (source, code) ->
else if o.run then CoffeeScript.run code, code_opts
else
js: CoffeeScript.compile code, code_opts
if o.print then process.stdio.write js
if o.print then print js
else if o.compile then write_js source, js
else if o.lint then lint js
catch err
@@ -92,10 +95,10 @@ compile_script: (source, code) ->
# and write them back to **stdout**.
compile_stdio: ->
code: ''
process.stdio.open()
process.stdio.addListener 'data', (string) ->
code: + string if string
process.stdio.addListener 'close', ->
stdin: process.openStdin()
stdin.addListener 'data', (buffer) ->
code: + buffer.toString() if buffer
stdin.addListener 'end', ->
compile_script 'stdio', code
# Watch a list of source CoffeeScript files using `fs.watchFile`, recompiling
@@ -120,13 +123,12 @@ write_js: (source, js) ->
# Pipe compiled JS through JSLint (requires a working `jsl` command), printing
# any errors or warnings that arise.
lint: (js) ->
jsl: process.createChildProcess('jsl', ['-nologo', '-stdin'])
jsl.addListener 'output', (result) ->
puts result.replace(/\n/g, '') if result
jsl.addListener 'error', (result) ->
puts result if result
jsl.write js
jsl.close()
print_it: (buffer) -> puts buffer.toString()
jsl: spawn 'jsl', ['-nologo', '-stdin']
jsl.stdout.addListener 'data', print_it
jsl.stderr.addListener 'data', print_it
jsl.stdin.write js
jsl.stdin.end()
# Pretty-print a stream of tokens.
print_tokens: (tokens) ->
@@ -157,5 +159,5 @@ usage: ->
# Print the `--version` message and exit.
version: ->
puts "CoffeeScript version ${CoffeeScript.VERSION}"
puts "CoffeeScript version $CoffeeScript.VERSION"
process.exit 0

View File

@@ -53,24 +53,37 @@ grammar: {
# The **Root** is the top-level node in the syntax tree. Since we parse bottom-up,
# all parsing must end here.
Root: [
o "", -> new Expressions()
o "TERMINATOR", -> new Expressions()
o "Expressions"
o "", -> new Expressions()
o "TERMINATOR", -> new Expressions()
o "Body"
o "Block TERMINATOR"
]
# Any list of expressions or method body, seperated by line breaks or
# semicolons.
Expressions: [
o "Expression", -> Expressions.wrap [$1]
o "Expressions TERMINATOR Expression", -> $1.push $3
o "Expressions TERMINATOR"
# Any list of statements and expressions, seperated by line breaks or semicolons.
Body: [
o "Line", -> Expressions.wrap [$1]
o "Body TERMINATOR Line", -> $1.push $3
o "Body TERMINATOR"
]
# Expressions and statements, which make up a line in a body.
Line: [
o "Expression"
o "Statement"
]
# Pure statements which cannot be expressions.
Statement: [
o "Return"
o "Throw"
o "BREAK", -> new LiteralNode yytext
o "CONTINUE", -> new LiteralNode yytext
]
# All the different types of expressions in our language. The basic unit of
# CoffeeScript is the **Expression** -- you'll notice that there is no
# "statement" nonterminal. Expressions serve as the building blocks
# of many other rules, making them somewhat circular.
# CoffeeScript is the **Expression** -- everything that can be an expression
# is one. Expressions serve as the building blocks of many other rules, making
# them somewhat circular.
Expression: [
o "Value"
o "Call"
@@ -80,8 +93,6 @@ grammar: {
o "Assign"
o "If"
o "Try"
o "Throw"
o "Return"
o "While"
o "For"
o "Switch"
@@ -97,7 +108,7 @@ grammar: {
# will convert some postfix forms into blocks for us, by adjusting the
# token stream.
Block: [
o "INDENT Expressions OUTDENT", -> $2
o "INDENT Body OUTDENT", -> $2
o "INDENT OUTDENT", -> new Expressions()
o "TERMINATOR Comment", -> Expressions.wrap [$2]
]
@@ -120,8 +131,6 @@ grammar: {
o "AlphaNumeric"
o "JS", -> new LiteralNode yytext
o "REGEX", -> new LiteralNode yytext
o "BREAK", -> new LiteralNode yytext
o "CONTINUE", -> new LiteralNode yytext
o "TRUE", -> new LiteralNode true
o "FALSE", -> new LiteralNode false
o "YES", -> new LiteralNode true
@@ -132,7 +141,7 @@ grammar: {
# Assignment of a variable, property, or index to a value.
Assign: [
o "Value ASSIGN Expression", -> new AssignNode $1, $3
o "Assignable ASSIGN Expression", -> new AssignNode $1, $3
]
# Assignment when it happens within an object literal. The difference from
@@ -195,18 +204,30 @@ grammar: {
o "Expression . . .", -> new SplatNode $1
]
# Variables and properties that can be assigned to.
SimpleAssignable: [
o "Identifier", -> new ValueNode $1
o "Value Accessor", -> $1.push $2
o "Invocation Accessor", -> new ValueNode $1, [$2]
o "ThisProperty"
]
# Everything that can be assigned to.
Assignable: [
o "SimpleAssignable"
o "Array", -> new ValueNode $1
o "Object", -> new ValueNode $1
]
# The types of things that can be treated as values -- assigned to, invoked
# as functions, indexed into, named as a class, etc.
Value: [
o "Identifier", -> new ValueNode $1
o "Assignable"
o "Literal", -> new ValueNode $1
o "Array", -> new ValueNode $1
o "Object", -> new ValueNode $1
o "Parenthetical", -> new ValueNode $1
o "Range", -> new ValueNode $1
o "This"
o "Value Accessor", -> $1.push $2
o "Invocation Accessor", -> new ValueNode $1, [$2]
o "NULL", -> new ValueNode new LiteralNode 'null'
]
# The general group of accessors into an object, by property, by prototype
@@ -230,15 +251,8 @@ grammar: {
Object: [
o "{ AssignList }", -> new ObjectNode $2
o "{ IndentedAssignList }", -> new ObjectNode $2
]
# Class definitions have optional bodies of prototype property assignments,
# and optional references to the superclass.
Class: [
o "CLASS Value", -> new ClassNode $2
o "CLASS Value EXTENDS Value", -> new ClassNode $2, $4
o "CLASS Value IndentedAssignList", -> new ClassNode $2, null, $3
o "CLASS Value EXTENDS Value IndentedAssignList", -> new ClassNode $2, $4, $5
o "{ AssignList , }", -> new ObjectNode $2
o "{ IndentedAssignList , }", -> new ObjectNode $2
]
# Assignment of properties within an object literal can be separated by
@@ -254,6 +268,29 @@ grammar: {
# An **AssignList** within a block indentation.
IndentedAssignList: [
o "INDENT AssignList OUTDENT", -> $2
o "INDENT AssignList , OUTDENT", -> $2
]
# Class definitions have optional bodies of prototype property assignments,
# and optional references to the superclass.
Class: [
o "CLASS SimpleAssignable", -> new ClassNode $2
o "CLASS SimpleAssignable EXTENDS Value", -> new ClassNode $2, $4
o "CLASS SimpleAssignable INDENT ClassBody OUTDENT", -> new ClassNode $2, null, $4
o "CLASS SimpleAssignable EXTENDS Value INDENT ClassBody OUTDENT", -> new ClassNode $2, $4, $6
]
# Assignments that can happen directly inside a class declaration.
ClassAssign: [
o "AssignObj", -> $1
o "ThisProperty ASSIGN Expression", -> new AssignNode new ValueNode($1), $3, 'this'
]
# A list of assignments to a class.
ClassBody: [
o "", -> []
o "ClassAssign", -> [$1]
o "ClassBody TERMINATOR ClassAssign", -> $1.concat $3
]
# The three flavors of function call: normal, object instantiation with `new`,
@@ -264,6 +301,7 @@ grammar: {
o "Super"
]
# Binds a function call to a context and/or arguments.
Curry: [
o "Value <- Arguments", -> new CurryNode $1, $3
]
@@ -271,7 +309,7 @@ grammar: {
# Extending an object by setting its prototype chain to reference a parent
# object.
Extends: [
o "Value EXTENDS Value", -> new ExtendsNode $1, $3
o "SimpleAssignable EXTENDS Value", -> new ExtendsNode $1, $3
]
# Ordinary function invocation, or a chained series of calls.
@@ -283,16 +321,23 @@ grammar: {
# The list of arguments to a function call.
Arguments: [
o "CALL_START ArgList CALL_END", -> $2
o "CALL_START ArgList , CALL_END", -> $2
]
# Calling super.
Super: [
o "SUPER CALL_START ArgList CALL_END", -> new CallNode 'super', $3
o "SUPER CALL_START ArgList , CALL_END", -> new CallNode 'super', $3
]
# A reference to the *this* current object, either naked or to a property.
# A reference to the *this* current object.
This: [
o "THIS", -> new ValueNode new LiteralNode 'this'
o "@", -> new ValueNode new LiteralNode 'this'
]
# A reference to a property on *this*.
ThisProperty: [
o "@ Identifier", -> new ValueNode new LiteralNode('this'), [new AccessorNode($2)]
]
@@ -311,6 +356,7 @@ grammar: {
# The array literal.
Array: [
o "[ ArgList ]", -> new ArrayNode $2
o "[ ArgList , ]", -> new ArrayNode $2
]
# The **ArgList** is both the list of objects passed into a function call,
@@ -325,6 +371,7 @@ grammar: {
o "ArgList , TERMINATOR Expression", -> $1.concat [$4]
o "ArgList , INDENT Expression", -> $1.concat [$4]
o "ArgList OUTDENT"
o "ArgList , OUTDENT"
]
# Just simple, comma-separated, required arguments (no fancy syntax). We need
@@ -358,7 +405,7 @@ grammar: {
# where only values are accepted, wrapping it in parentheses will always do
# the trick.
Parenthetical: [
o "( Expression )", -> new ParentheticalNode $2
o "( Line )", -> new ParentheticalNode $2
]
# A language extension to CoffeeScript from the outside. We simply pass
@@ -377,6 +424,7 @@ grammar: {
# or postfix, with a single expression. There is no do..while.
While: [
o "WhileSource Block", -> $1.add_body $2
o "Statement WhileSource", -> $2.add_body Expressions.wrap [$1]
o "Expression WhileSource", -> $2.add_body Expressions.wrap [$1]
]
@@ -384,6 +432,7 @@ grammar: {
# Comprehensions can either be normal, with a block of expressions to execute,
# or postfix, with a single expression.
For: [
o "Statement FOR ForVariables ForSource", -> new ForNode $1, $4, $3[0], $3[1]
o "Expression FOR ForVariables ForSource", -> new ForNode $1, $4, $3[0], $3[1]
o "FOR ForVariables ForSource Block", -> new ForNode $4, $3, $2[0], $2[1]
]
@@ -397,13 +446,16 @@ grammar: {
]
# The source of a comprehension is an array or object with an optional filter
# clause. If it's an array comprehension, you can also choose to step throug
# clause. If it's an array comprehension, you can also choose to step through
# in fixed-size increments.
ForSource: [
o "IN Expression", -> {source: $2}
o "OF Expression", -> {source: $2, object: true}
o "ForSource WHEN Expression", -> $1.filter: $3; $1
o "ForSource BY Expression", -> $1.step: $3; $1
o "IN Expression", -> {source: $2}
o "OF Expression", -> {source: $2, object: true}
o "IN Expression WHEN Expression", -> {source: $2, filter: $4}
o "OF Expression WHEN Expression", -> {source: $2, filter: $4, object: true}
o "IN Expression BY Expression", -> {source: $2, step: $4}
o "IN Expression WHEN Expression BY Expression", -> {source: $2, filter: $4; step: $6}
o "IN Expression BY Expression WHEN Expression", -> {source: $2, step: $4, filter: $6}
]
# The CoffeeScript switch/when/else block replaces the JavaScript
@@ -422,9 +474,9 @@ grammar: {
# An individual **When** clause, with action.
When: [
o "LEADING_WHEN SimpleArgs Block", -> new IfNode $2, $3, null, {statement: true}
o "LEADING_WHEN SimpleArgs Block", -> new IfNode $2, $3, null, {statement: true}
o "LEADING_WHEN SimpleArgs Block TERMINATOR", -> new IfNode $2, $3, null, {statement: true}
o "Comment TERMINATOR When", -> $3.comment: $1; $3
o "Comment TERMINATOR When", -> $3.comment: $1; $3
]
# The most basic form of *if* is a condition and an action. The following
@@ -450,7 +502,9 @@ grammar: {
# *if* and *unless*.
If: [
o "IfBlock"
o "Statement IF Expression", -> new IfNode $3, Expressions.wrap([$1]), null, {statement: true}
o "Expression IF Expression", -> new IfNode $3, Expressions.wrap([$1]), null, {statement: true}
o "Statement UNLESS Expression", -> new IfNode $3, Expressions.wrap([$1]), null, {statement: true, invert: true}
o "Expression UNLESS Expression", -> new IfNode $3, Expressions.wrap([$1]), null, {statement: true, invert: true}
]

View File

@@ -44,7 +44,7 @@ exports.Lexer: class Lexer
# Before returning the token stream, run it through the [Rewriter](rewriter.html)
# unless explicitly asked not to.
tokenize: (code, options) ->
code : code.replace(/(\r|\s+$)/g, '')
code : code.replace /(\r|\s+$)/g, ''
o : options or {}
@code : code # The remainder of the source code.
@i : 0 # Current character position we're parsing.
@@ -53,7 +53,7 @@ exports.Lexer: class Lexer
@indents : [] # The stack of all current indentation levels.
@tokens : [] # Stream of parsed tokens in the form ['TYPE', value, line]
while @i < @code.length
@chunk: @code.slice(@i)
@chunk: @code.slice @i
@extract_next_token()
@close_indentation()
return @tokens if o.rewrite is off
@@ -94,7 +94,7 @@ exports.Lexer: class Lexer
identifier_token: ->
return false unless id: @match IDENTIFIER, 1
@name_access_type()
accessed: include ACCESSORS, @tag(0)
accessed: include ACCESSORS, @tag 0
tag: 'IDENTIFIER'
tag: id.toUpperCase() if not accessed and include(KEYWORDS, id)
@identifier_error id if include RESERVED, id
@@ -102,8 +102,8 @@ exports.Lexer: class Lexer
@i: + id.length
if not accessed
tag: id: CONVERSIONS[id] if include COFFEE_ALIASES, id
return @tag_half_assignment(tag) if @prev() and @prev()[0] is 'ASSIGN' and include HALF_ASSIGNMENTS, tag
@token(tag, id)
return @tag_half_assignment tag if @prev() and @prev()[0] is 'ASSIGN' and include HALF_ASSIGNMENTS, tag
@token tag, id
true
# Matches numbers, including decimals, hex, and exponential notation.
@@ -120,7 +120,7 @@ exports.Lexer: class Lexer
return false unless string:
@balanced_token(['"', '"'], ['${', '}']) or
@balanced_token ["'", "'"]
@interpolate_string string.replace(STRING_NEWLINES, " \\\n")
@interpolate_string string.replace STRING_NEWLINES, " \\\n"
@line: + count string, "\n"
@i: + string.length
true
@@ -129,7 +129,7 @@ exports.Lexer: class Lexer
# preserve whitespace, but ignore indentation to the left.
heredoc_token: ->
return false unless match: @chunk.match(HEREDOC)
quote: match[1].substr(0, 1)
quote: match[1].substr 0, 1
doc: @sanitize_heredoc match[2] or match[4], quote
@interpolate_string "$quote$doc$quote"
@line: + count match[1], "\n"
@@ -140,7 +140,7 @@ exports.Lexer: class Lexer
js_token: ->
return false unless starts @chunk, '`'
return false unless script: @balanced_token ['`', '`']
@token 'JS', script.replace(JS_CLEANER, '')
@token 'JS', script.replace JS_CLEANER, ''
@i: + script.length
true
@@ -152,7 +152,7 @@ exports.Lexer: class Lexer
return false unless @chunk.match REGEX_START
return false if include NOT_REGEX, @tag()
return false unless regex: @balanced_token ['/', '/']
regex: + (flags: @chunk.substr(regex.length).match(REGEX_FLAGS))
regex: + (flags: @chunk.substr(regex.length).match REGEX_FLAGS)
if regex.match REGEX_INTERPOLATION
str: regex.substring(1).split('/')[0]
str: str.replace REGEX_ESCAPE, (escaped) -> '\\' + escaped
@@ -174,7 +174,7 @@ exports.Lexer: class Lexer
comment_token: ->
return false unless comment: @match COMMENT, 1
@line: + (comment.match(MULTILINER) or []).length
lines: compact comment.replace(COMMENT_CLEANER, '').split(MULTILINER)
lines: compact comment.replace(COMMENT_CLEANER, '').split MULTILINER
i: @tokens.length - 1
if @unfinished()
i: - 1 while @tokens[i] and not include LINE_BREAK, @tokens[i][0]
@@ -202,7 +202,7 @@ exports.Lexer: class Lexer
no_newlines: next_character is '.' or @unfinished()
if size is @indent
return @suppress_newlines() if no_newlines
return @newline_token(indent)
return @newline_token indent
else if size > @indent
return @suppress_newlines() if no_newlines
diff: size - @indent
@@ -249,14 +249,14 @@ exports.Lexer: class Lexer
# here. `;` and newlines are both treated as a `TERMINATOR`, we distinguish
# parentheses that indicate a method call from regular parentheses, and so on.
literal_token: ->
match: @chunk.match(OPERATOR)
match: @chunk.match OPERATOR
value: match and match[1]
space: match and match[2]
@tag_parameters() if value and value.match(CODE)
value: or @chunk.substr(0, 1)
@tag_parameters() if value and value.match CODE
value: or @chunk.substr 0, 1
prev_spaced: @prev() and @prev().spaced
tag: value
if value.match(ASSIGNMENT)
if value.match ASSIGNMENT
tag: 'ASSIGN'
@assignment_error() if include JS_FORBIDDEN, @value
else if value is ';'
@@ -272,7 +272,7 @@ exports.Lexer: class Lexer
tag: 'CALL_START' if value is '('
tag: 'INDEX_START' if value is '['
@i: + value.length
return @tag_half_assignment(tag) if space and prev_spaced and @prev()[0] is 'ASSIGN' and include HALF_ASSIGNMENTS, tag
return @tag_half_assignment tag if space and prev_spaced and @prev()[0] is 'ASSIGN' and include HALF_ASSIGNMENTS, tag
@token tag, value
true
@@ -312,7 +312,7 @@ exports.Lexer: class Lexer
i: 0
while true
i: + 1
tok: @prev(i)
tok: @prev i
return if not tok
switch tok[0]
when 'IDENTIFIER' then tok[0]: 'PARAM'
@@ -322,7 +322,7 @@ exports.Lexer: class Lexer
# Close up all remaining open blocks at the end of the file.
close_indentation: ->
@outdent_token(@indent)
@outdent_token @indent
# The error for when you try to use a forbidden word in JavaScript as
# an identifier.
@@ -350,7 +350,7 @@ exports.Lexer: class Lexer
else
lexer: new Lexer()
tokens: []
quote: str.substring(0, 1)
quote: str.substring 0, 1
[i, pi]: [1, 1]
while i < str.length - 1
if starts str, '\\', i
@@ -366,7 +366,8 @@ exports.Lexer: class Lexer
tokens.push ['STRING', "$quote${ str.substring(pi, i) }$quote"] if pi < i
inner: expr.substring(2, expr.length - 1)
if inner.length
nested: lexer.tokenize "($inner)", {rewrite: no, line: @line}
nested: lexer.tokenize "($inner)", {line: @line}
(tok[0]: ')') for tok, idx in nested when tok[0] is 'CALL_END'
nested.pop()
tokens.push ['TOKENS', nested]
else
@@ -376,6 +377,8 @@ exports.Lexer: class Lexer
i: + 1
tokens.push ['STRING', "$quote${ str.substring(pi, i) }$quote"] if pi < i and pi < str.length - 1
tokens.unshift ['STRING', '""'] unless tokens[0][0] is 'STRING'
interpolated: tokens.length > 1
@token '(', '(' if interpolated
for token, i in tokens
[tag, value]: token
if tag is 'TOKENS'
@@ -386,6 +389,7 @@ exports.Lexer: class Lexer
else
@token tag, value
@token '+', '+' if i < tokens.length - 1
@token ')', ')' if interpolated
tokens
# Helpers
@@ -393,17 +397,17 @@ exports.Lexer: class Lexer
# Add a token to the results, taking note of the line number.
token: (tag, value) ->
@tokens.push([tag, value, @line])
@tokens.push [tag, value, @line]
# Peek at a tag in the current token stream.
tag: (index, tag) ->
return unless tok: @prev(index)
return tok[0]: tag if tag?
tag: (index, new_tag) ->
return unless tok: @prev index
return tok[0]: new_tag if new_tag?
tok[0]
# Peek at a value in the current token stream.
value: (index, val) ->
return unless tok: @prev(index)
return unless tok: @prev index
return tok[1]: val if val?
tok[1]
@@ -414,7 +418,7 @@ exports.Lexer: class Lexer
# Attempt to match a string against the current chunk, returning the indexed
# match if successful, and `false` otherwise.
match: (regex, index) ->
return false unless m: @chunk.match(regex)
return false unless m: @chunk.match regex
if m then m[index] else false
# Are we in the midst of an unfinished expression?
@@ -423,8 +427,11 @@ exports.Lexer: class Lexer
@value() and @value().match and @value().match(NO_NEWLINE) and
prev and (prev[0] isnt '.') and not @value().match(CODE)
# There are no exensions to the core lexer by default.
Lexer.extensions: []
# Lexer Properties
# ----------------
# There are no exensions to the core lexer by default.
@extensions: []
# Constants
# ---------
@@ -438,7 +445,8 @@ JS_KEYWORDS: [
"break", "continue",
"for", "in", "while",
"delete", "instanceof", "typeof",
"switch", "super", "extends", "class"
"switch", "super", "extends", "class",
"this", "null"
]
# CoffeeScript-only keywords, which we're more relaxed about allowing. They can't
@@ -459,8 +467,7 @@ KEYWORDS: JS_KEYWORDS.concat COFFEE_KEYWORDS
# to avoid having a JavaScript error at runtime.
RESERVED: [
"case", "default", "do", "function", "var", "void", "with"
"const", "let", "debugger", "enum", "export", "import", "native",
"__extends", "__hasProp"
"const", "let", "debugger", "enum", "export", "import", "native"
]
# The superset of both JavaScript keywords and reserved words, none of which may
@@ -508,7 +515,7 @@ NOT_REGEX: [
# Tokens which could legitimately be invoked or indexed. A opening
# parentheses or bracket following these tokens will be recorded as the start
# of a function invocation or indexing operation.
CALLABLE: ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING', '@']
CALLABLE: ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING', '@', 'THIS']
# Tokens that indicate an access -- keywords immediately following will be
# treated as identifiers.

View File

@@ -4,7 +4,7 @@
# the syntax tree into a string of JavaScript code, call `compile()` on the root.
# Set up for both **Node.js** and the browser, by
# including the [Scope](scope.html) class.
# including the [Scope](scope.html) class and the [helper](helpers.html) functions.
if process?
Scope: require('./scope').Scope
helpers: require('./helpers').helpers
@@ -13,7 +13,7 @@ else
helpers: this.helpers
Scope: this.Scope
# Import the helpers we need.
# Import the helpers we plan to use.
compact: helpers.compact
flatten: helpers.flatten
merge: helpers.merge
@@ -98,6 +98,10 @@ exports.BaseNode: class BaseNode
return true if node.contains and node.contains block
false
# Is this node of a certain type, or does it contain the type?
contains_type: (type) ->
this instanceof type or @contains (n) -> n instanceof type
# Convenience for the most common use of contains. Does the node contain
# a pure statement?
contains_pure_statement: ->
@@ -113,7 +117,7 @@ exports.BaseNode: class BaseNode
# This is what `coffee --nodes` prints out.
toString: (idt) ->
idt: or ''
'\n' + idt + @type + (child.toString(idt + TAB) for child in @children).join('')
'\n' + idt + @constructor.name + (child.toString(idt + TAB) for child in @children).join('')
# Default implementations of the common node identification methods. Nodes
# will override these with custom logic, if needed.
@@ -129,7 +133,6 @@ exports.BaseNode: class BaseNode
# indented block of code -- the implementation of a function, a clause in an
# `if`, `switch`, or `try`, and so on...
exports.Expressions: class Expressions extends BaseNode
type: 'Expressions'
constructor: (nodes) ->
@children: @expressions: compact flatten nodes or []
@@ -214,7 +217,6 @@ statement Expressions
# JavaScript without translation, such as: strings, numbers,
# `true`, `false`, `null`...
exports.LiteralNode: class LiteralNode extends BaseNode
type: 'Literal'
constructor: (value) ->
@value: value
@@ -238,12 +240,17 @@ exports.LiteralNode: class LiteralNode extends BaseNode
# A `return` is a *pure_statement* -- wrapping it in a closure wouldn't
# make sense.
exports.ReturnNode: class ReturnNode extends BaseNode
type: 'Return'
constructor: (expression) ->
@children: [@expression: expression]
top_sensitive: ->
true
compile_node: (o) ->
expr: @expression.make_return()
return expr.compile(o) unless expr instanceof ReturnNode
del o, 'top'
o.as_statement: true if @expression.is_statement()
"${@tab}return ${@expression.compile(o)};"
@@ -254,7 +261,6 @@ statement ReturnNode, true
# A value, variable or literal or parenthesized, indexed or dotted into,
# or vanilla.
exports.ValueNode: class ValueNode extends BaseNode
type: 'Value'
SOAK: " == undefined ? undefined : "
@@ -329,7 +335,6 @@ exports.ValueNode: class ValueNode extends BaseNode
# CoffeeScript passes through comments as JavaScript comments at the
# same position.
exports.CommentNode: class CommentNode extends BaseNode
type: 'Comment'
constructor: (lines) ->
@lines: lines
@@ -348,7 +353,6 @@ statement CommentNode
# Node for a function invocation. Takes care of converting `super()` calls into
# calls against the prototype's function of the same name.
exports.CallNode: class CallNode extends BaseNode
type: 'Call'
constructor: (variable, args) ->
@is_new: false
@@ -394,16 +398,12 @@ exports.CallNode: class CallNode extends BaseNode
meth: "($temp = ${ @variable.source })${ @variable.last }"
"${@prefix()}${meth}.apply($obj, ${ @compile_splat_arguments(o) })"
#### CurryNode
# Binds a context object and a list of arguments to a function,
# returning the bound function. After ECMAScript 5, Prototype.js, and
# Underscore's `bind` functions.
exports.CurryNode: class CurryNode extends CallNode
type: 'Curry'
body: 'func.apply(obj, args.concat(Array.prototype.slice.call(arguments, 0)))'
constructor: (meth, args) ->
@children: flatten [@meth: meth, @context: args[0], @args: (args.slice(1) or [])]
@@ -415,11 +415,9 @@ exports.CurryNode: class CurryNode extends CallNode
(new ArrayNode(@args)).compile o
compile_node: (o) ->
body: Expressions.wrap([literal @body])
curried: new CodeNode([], body)
curry: new CodeNode([literal('func'), literal('obj'), literal('args')], Expressions.wrap([curried]))
(new ParentheticalNode(new CallNode(curry, [@meth, @context, literal(@arguments(o))]))).compile o
utility 'slice'
ref: new ValueNode literal utility 'bind'
(new CallNode(ref, [@meth, @context, literal(@arguments(o))])).compile o
#### ExtendsNode
@@ -428,38 +426,24 @@ exports.CurryNode: class CurryNode extends CallNode
# After `goog.inherits` from the
# [Closure Library](http://closure-library.googlecode.com/svn/docs/closure_goog_base.js.html).
exports.ExtendsNode: class ExtendsNode extends BaseNode
type: 'Extends'
code: '''
function(child, parent) {
var ctor = function(){ };
ctor.prototype = parent.prototype;
child.__superClass__ = parent.prototype;
child.prototype = new ctor();
child.prototype.constructor = child;
}
'''
constructor: (child, parent) ->
@children: [@child: child, @parent: parent]
# Hooks one constructor into another's prototype chain.
compile_node: (o) ->
o.scope.assign('__extends', @code, true)
ref: new ValueNode literal('__extends')
call: new CallNode ref, [@child, @parent]
call.compile(o)
ref: new ValueNode literal utility 'extends'
(new CallNode ref, [@child, @parent]).compile o
#### AccessorNode
# A `.` accessor into a property of a value, or the `::` shorthand for
# an accessor into the object's prototype.
exports.AccessorNode: class AccessorNode extends BaseNode
type: 'Accessor'
constructor: (name, tag) ->
@children: [@name: name]
@prototype: tag is 'prototype'
@prototype:tag is 'prototype'
@soak_node: tag is 'soak'
this
@@ -471,7 +455,6 @@ exports.AccessorNode: class AccessorNode extends BaseNode
# A `[ ... ]` indexed accessor into an array or object.
exports.IndexNode: class IndexNode extends BaseNode
type: 'Index'
constructor: (index, tag) ->
@children: [@index: index]
@@ -487,7 +470,6 @@ exports.IndexNode: class IndexNode extends BaseNode
# to specify a range for comprehensions, or as a value, to be expanded into the
# corresponding array of integers at runtime.
exports.RangeNode: class RangeNode extends BaseNode
type: 'Range'
constructor: (from, to, exclusive) ->
@children: [@from: from, @to: to]
@@ -529,7 +511,6 @@ exports.RangeNode: class RangeNode extends BaseNode
# specifies the index of the end of the slice, just as the first parameter
# is the index of the beginning.
exports.SliceNode: class SliceNode extends BaseNode
type: 'Slice'
constructor: (range) ->
@children: [@range: range]
@@ -545,7 +526,6 @@ exports.SliceNode: class SliceNode extends BaseNode
# An object literal, nothing fancy.
exports.ObjectNode: class ObjectNode extends BaseNode
type: 'Object'
constructor: (props) ->
@children: @objects: @properties: props or []
@@ -553,17 +533,15 @@ exports.ObjectNode: class ObjectNode extends BaseNode
# All the mucking about with commas is to make sure that CommentNodes and
# AssignNodes get interleaved correctly, with no trailing commas or
# commas affixed to comments.
#
# *TODO: Extract this and add it to ArrayNode*.
compile_node: (o) ->
o.indent: @idt(1)
o.indent: @idt 1
non_comments: prop for prop in @properties when not (prop instanceof CommentNode)
last_noncom: non_comments[non_comments.length - 1]
props: for prop, i in @properties
join: ",\n"
join: "\n" if (prop is last_noncom) or (prop instanceof CommentNode)
join: '' if i is @properties.length - 1
indent: if prop instanceof CommentNode then '' else @idt(1)
indent: if prop instanceof CommentNode then '' else @idt 1
indent + prop.compile(o) + join
props: props.join('')
inner: if props then '\n' + props + '\n' + @idt() else ''
@@ -573,19 +551,18 @@ exports.ObjectNode: class ObjectNode extends BaseNode
# An array literal.
exports.ArrayNode: class ArrayNode extends BaseNode
type: 'Array'
constructor: (objects) ->
@children: @objects: objects or []
@compile_splat_literal: SplatNode.compile_mixed_array <- @, @objects
compile_node: (o) ->
o.indent: @idt(1)
o.indent: @idt 1
objects: []
for obj, i in @objects
code: obj.compile(o)
if obj instanceof SplatNode
return @compile_splat_literal(@objects, o)
return @compile_splat_literal @objects, o
else if obj instanceof CommentNode
objects.push "\n$code\n$o.indent"
else if i is @objects.length - 1
@@ -600,7 +577,6 @@ exports.ArrayNode: class ArrayNode extends BaseNode
# The CoffeeScript class definition.
exports.ClassNode: class ClassNode extends BaseNode
type: 'Class'
# Initialize a **ClassNode** with its name, an optional superclass, and a
# list of prototype property assignments.
@@ -622,14 +598,15 @@ exports.ClassNode: class ClassNode extends BaseNode
o.top: true
for prop in @properties
if prop.variable and prop.variable.base.value is 'constructor'
func: prop.value
[pvar, func]: [prop.variable, prop.value]
if pvar and pvar.base.value is 'constructor' and func instanceof CodeNode
func.body.push(new ReturnNode(literal('this')))
constructor: new AssignNode(@variable, func)
else
if prop.variable
val: new ValueNode(@variable, [new AccessorNode(prop.variable, 'prototype')])
prop: new AssignNode(val, prop.value)
if pvar
access: if prop.context is 'this' then pvar.base.properties[0] else new AccessorNode(pvar, 'prototype')
val: new ValueNode(@variable, [access])
prop: new AssignNode(val, func)
props.push prop
if not constructor
@@ -654,7 +631,6 @@ statement ClassNode
# The **AssignNode** is used to assign a local variable to value, or to set the
# property of an object -- including within object literals.
exports.AssignNode: class AssignNode extends BaseNode
type: 'Assign'
# Matchers for detecting prototype assignments.
PROTO_ASSIGN: /^(\S+)\.prototype/
@@ -729,7 +705,7 @@ exports.AssignNode: class AssignNode extends BaseNode
# Compile the assignment from an array splice literal, using JavaScript's
# `Array#splice` method.
compile_splice: (o) ->
name: @variable.compile(merge(o, {only_first: true}))
name: @variable.compile merge o, {only_first: true}
l: @variable.properties.length
range: @variable.properties[l - 1].range
plus: if range.exclusive then '' else ' + 1'
@@ -744,7 +720,6 @@ exports.AssignNode: class AssignNode extends BaseNode
# When for the purposes of walking the contents of a function body, the CodeNode
# has no *children* -- they're within the inner scope.
exports.CodeNode: class CodeNode extends BaseNode
type: 'Code'
constructor: (params, body, tag) ->
@params: params or []
@@ -786,8 +761,9 @@ exports.CodeNode: class CodeNode extends BaseNode
func: "function${ if @bound then '' else name_part }(${ params.join(', ') }) {$code${@idt(if @bound then 1 else 0)}}"
func: "($func)" if top and not @bound
return func unless @bound
inner: "(function$name_part() {\n${@idt(2)}return __func.apply(__this, arguments);\n${@idt(1)}});"
"(function(__this) {\n${@idt(1)}var __func = $func;\n${@idt(1)}return $inner\n$@tab})(this)"
utility 'slice'
ref: new ValueNode literal utility 'bind'
(new CallNode ref, [literal(func), literal('this')]).compile o
top_sensitive: ->
true
@@ -812,7 +788,6 @@ exports.CodeNode: class CodeNode extends BaseNode
# A splat, either as a parameter to a function, an argument to a call,
# or as part of a destructuring assignment.
exports.SplatNode: class SplatNode extends BaseNode
type: 'Splat'
constructor: (name) ->
name: literal(name) unless name.compile
@@ -830,34 +805,34 @@ exports.SplatNode: class SplatNode extends BaseNode
for trailing in @trailings
o.scope.assign(trailing.compile(o), "arguments[arguments.length - $@trailings.length + $i]")
i: + 1
"$name = Array.prototype.slice.call(arguments, $@index, arguments.length - ${@trailings.length})"
"$name = ${utility('slice')}.call(arguments, $@index, arguments.length - ${@trailings.length})"
# A compiling a splat as a destructuring assignment means slicing arguments
# from the right-hand-side's corresponding array.
compile_value: (o, name, index, trailings) ->
if trailings? then "Array.prototype.slice.call($name, $index, ${name}.length - $trailings)" \
else "Array.prototype.slice.call($name, $index)"
trail: if trailings then ", ${name}.length - $trailings" else ''
"${utility 'slice'}.call($name, $index$trail)"
# Utility function that converts arbitrary number of elements, mixed with
# splats, to a proper array
SplatNode.compile_mixed_array: (list, o) ->
args: []
i: 0
for arg in list
code: arg.compile o
if not (arg instanceof SplatNode)
prev: args[i - 1]
if i is 1 and prev.substr(0, 1) is '[' and prev.substr(prev.length - 1, 1) is ']'
args[i - 1]: "${prev.substr(0, prev.length - 1)}, $code]"
continue
else if i > 1 and prev.substr(0, 9) is '.concat([' and prev.substr(prev.length - 2, 2) is '])'
args[i - 1]: "${prev.substr(0, prev.length - 2)}, $code])"
continue
else
code: "[$code]"
args.push(if i is 0 then code else ".concat($code)")
i: + 1
args.join('')
# Utility function that converts arbitrary number of elements, mixed with
# splats, to a proper array
@compile_mixed_array: (list, o) ->
args: []
i: 0
for arg in list
code: arg.compile o
if not (arg instanceof SplatNode)
prev: args[i - 1]
if i is 1 and prev.substr(0, 1) is '[' and prev.substr(prev.length - 1, 1) is ']'
args[i - 1]: "${prev.substr(0, prev.length - 1)}, $code]"
continue
else if i > 1 and prev.substr(0, 9) is '.concat([' and prev.substr(prev.length - 2, 2) is '])'
args[i - 1]: "${prev.substr(0, prev.length - 2)}, $code])"
continue
else
code: "[$code]"
args.push(if i is 0 then code else ".concat($code)")
i: + 1
args.join('')
#### WhileNode
@@ -865,7 +840,6 @@ SplatNode.compile_mixed_array: (list, o) ->
# it, all other loops can be manufactured. Useful in cases where you need more
# flexibility or more speed than a comprehension can provide.
exports.WhileNode: class WhileNode extends BaseNode
type: 'While'
constructor: (condition, opts) ->
@children:[@condition: condition]
@@ -887,7 +861,7 @@ exports.WhileNode: class WhileNode extends BaseNode
# return an array containing the computed result of each iteration.
compile_node: (o) ->
top: del(o, 'top') and not @returns
o.indent: @idt(1)
o.indent: @idt 1
o.top: true
cond: @condition.compile(o)
set: ''
@@ -911,7 +885,6 @@ statement WhileNode
# Simple Arithmetic and logical operations. Performs some conversion from
# CoffeeScript operations into their JavaScript equivalents.
exports.OpNode: class OpNode extends BaseNode
type: 'Op'
# The map of conversions from CoffeeScript to JavaScript symbols.
CONVERSIONS: {
@@ -930,7 +903,7 @@ exports.OpNode: class OpNode extends BaseNode
PREFIX_OPERATORS: ['typeof', 'delete']
constructor: (operator, first, second, flip) ->
@type: + ' ' + operator
@constructor.name: + ' ' + operator
@children: compact [@first: first, @second: second]
@operator: @CONVERSIONS[operator] or operator
@flip: !!flip
@@ -956,7 +929,7 @@ exports.OpNode: class OpNode extends BaseNode
# true
compile_chain: (o) ->
shared: @first.unwrap().second
[@first.second, shared]: shared.compile_reference(o) if shared instanceof CallNode
[@first.second, shared]: shared.compile_reference(o) if shared.contains_type CallNode
[first, second, shared]: [@first.compile(o), @second.compile(o), shared.compile(o)]
"($first) && ($shared $@operator $second)"
@@ -987,7 +960,6 @@ exports.OpNode: class OpNode extends BaseNode
# A classic *try/catch/finally* block.
exports.TryNode: class TryNode extends BaseNode
type: 'Try'
constructor: (attempt, error, recovery, ensure) ->
@children: compact [@attempt: attempt, @recovery: recovery, @ensure: ensure]
@@ -1002,7 +974,7 @@ exports.TryNode: class TryNode extends BaseNode
# Compilation is more or less as you would expect -- the *finally* clause
# is optional, the *catch* is not.
compile_node: (o) ->
o.indent: @idt(1)
o.indent: @idt 1
o.top: true
attempt_part: @attempt.compile(o)
error_part: if @error then " (${ @error.compile(o) }) " else ' '
@@ -1016,7 +988,6 @@ statement TryNode
# Simple node to throw an exception.
exports.ThrowNode: class ThrowNode extends BaseNode
type: 'Throw'
constructor: (expression) ->
@children: [@expression: expression]
@@ -1036,7 +1007,6 @@ statement ThrowNode
# similar to `.nil?` in Ruby, and avoids having to consult a JavaScript truth
# table.
exports.ExistenceNode: class ExistenceNode extends BaseNode
type: 'Existence'
constructor: (expression) ->
@children: [@expression: expression]
@@ -1044,15 +1014,15 @@ exports.ExistenceNode: class ExistenceNode extends BaseNode
compile_node: (o) ->
ExistenceNode.compile_test(o, @expression)
# The meat of the **ExistenceNode** is in this static `compile_test` method
# because other nodes like to check the existence of their variables as well.
# Be careful not to double-evaluate anything.
ExistenceNode.compile_test: (o, variable) ->
[first, second]: [variable, variable]
if variable instanceof CallNode or (variable instanceof ValueNode and variable.has_properties())
[first, second]: variable.compile_reference(o)
[first, second]: [first.compile(o), second.compile(o)]
"(typeof $first !== \"undefined\" && $second !== null)"
# The meat of the **ExistenceNode** is in this static `compile_test` method
# because other nodes like to check the existence of their variables as well.
# Be careful not to double-evaluate anything.
@compile_test: (o, variable) ->
[first, second]: [variable, variable]
if variable instanceof CallNode or (variable instanceof ValueNode and variable.has_properties())
[first, second]: variable.compile_reference(o)
[first, second]: [first.compile(o), second.compile(o)]
"(typeof $first !== \"undefined\" && $second !== null)"
#### ParentheticalNode
@@ -1062,7 +1032,6 @@ ExistenceNode.compile_test: (o, variable) ->
#
# Parentheses are a good way to force any statement to become an expression.
exports.ParentheticalNode: class ParentheticalNode extends BaseNode
type: 'Paren'
constructor: (expression) ->
@children: [@expression: expression]
@@ -1090,7 +1059,6 @@ exports.ParentheticalNode: class ParentheticalNode extends BaseNode
# the current index of the loop as a second parameter. Unlike Ruby blocks,
# you can map and filter in a single pass.
exports.ForNode: class ForNode extends BaseNode
type: 'For'
constructor: (body, source, name, index) ->
@body: body
@@ -1128,9 +1096,8 @@ exports.ForNode: class ForNode extends BaseNode
index: @index and @index.compile o
scope.find name if name
scope.find index if index
body_dent: @idt(1)
body_dent: @idt 1
rvar: scope.free_variable() unless top_level
svar: scope.free_variable()
ivar: if range then name else index or scope.free_variable()
var_part: ''
body: Expressions.wrap([@body])
@@ -1140,6 +1107,7 @@ exports.ForNode: class ForNode extends BaseNode
for_part: source.compile merge o, {index: ivar, step: @step}
for_part: "$index_var = 0, $for_part, $index_var++"
else
svar: scope.free_variable()
index_var: null
source_part: "$svar = ${ @source.compile(o) };\n$@tab"
var_part: "$body_dent$name = $svar[$ivar];\n" if name
@@ -1155,8 +1123,7 @@ exports.ForNode: class ForNode extends BaseNode
if @filter
body: Expressions.wrap([new IfNode(@filter, body)])
if @object
o.scope.assign('__hasProp', 'Object.prototype.hasOwnProperty', true)
for_part: "$ivar in $svar) { if (__hasProp.call($svar, $ivar)"
for_part: "$ivar in $svar) { if (${utility('hasProp')}.call($svar, $ivar)"
body: body.compile(merge(o, {indent: body_dent, top: true}))
vars: if range then name else "$name, $ivar"
close: if @object then '}}\n' else '}\n'
@@ -1172,7 +1139,6 @@ statement ForNode
# Single-expression **IfNodes** are compiled into ternary operators if possible,
# because ternaries are already proper expressions, and don't need conversion.
exports.IfNode: class IfNode extends BaseNode
type: 'If'
constructor: (condition, body, else_body, tags) ->
@condition: condition
@@ -1251,7 +1217,7 @@ exports.IfNode: class IfNode extends BaseNode
@rewrite_switch(o) if @switcher
child: del o, 'chain_child'
cond_o: merge o
o.indent: @idt(1)
o.indent: @idt 1
o.top: true
if_dent: if child then '' else @idt()
com_dent: if child then @idt() else ''
@@ -1297,15 +1263,58 @@ PushNode: exports.PushNode: {
ClosureNode: exports.ClosureNode: {
# Wrap the expressions body, unless it contains a pure statement,
# in which case, no dice.
# in which case, no dice. If the body mentions `this` or `arguments`,
# then make sure that the closure wrapper preserves the original values.
wrap: (expressions, statement) ->
return expressions if expressions.contains_pure_statement()
func: new ParentheticalNode(new CodeNode([], Expressions.wrap([expressions])))
call: new CallNode(new ValueNode(func, [new AccessorNode(literal('call'))]), [literal('this')])
args: []
mentions_args: expressions.contains (n) -> (n instanceof LiteralNode) and (n.value is 'arguments')
mentions_this: expressions.contains (n) -> (n instanceof LiteralNode) and (n.value is 'this')
if mentions_args or mentions_this
meth: literal(if mentions_args then 'apply' else 'call')
args: [literal('this')]
args.push literal 'arguments' if mentions_args
func: new ValueNode func, [new AccessorNode(meth)]
call: new CallNode(func, args)
if statement then Expressions.wrap([call]) else call
}
# Utility Functions
# -----------------
UTILITIES: {
# Correctly set up a prototype chain for inheritance, including a reference
# to the superclass for `super()` calls. See:
# [goog.inherits](http://closure-library.googlecode.com/svn/docs/closure_goog_base.js.source.html#line1206).
__extends: """
function(child, parent) {
var ctor = function(){ };
ctor.prototype = parent.prototype;
child.__superClass__ = parent.prototype;
child.prototype = new ctor();
child.prototype.constructor = child;
}
"""
# Bind a function to a calling context, optionally including curried arguments.
# See [Underscore's implementation](http://jashkenas.github.com/coffee-script/documentation/docs/underscore.html#section-47).
__bind: """
function(func, obj, args) {
return function() {
return func.apply(obj || {}, args ? args.concat(__slice.call(arguments, 0)) : arguments);
};
}
"""
# Shortcuts to speed up the lookup time for native functions.
__hasProp: 'Object.prototype.hasOwnProperty'
__slice: 'Array.prototype.slice'
}
# Constants
# ---------
@@ -1325,3 +1334,9 @@ IDENTIFIER: /^[a-zA-Z\$_](\w|\$)*$/
# Handy helper for a generating LiteralNode.
literal: (name) ->
new LiteralNode(name)
# Helper for ensuring that utility functions are assigned at the top level.
utility: (name) ->
ref: "__$name"
Scope.root.assign ref, UTILITIES[ref]
ref

View File

@@ -22,7 +22,7 @@ exports.OptionParser: class OptionParser
parse: (args) ->
options: {arguments: []}
args: normalize_arguments args
while arg: args.shift()
while (arg: args.shift())
is_option: !!(arg.match(LONG_FLAG) or arg.match(SHORT_FLAG))
matched_rule: no
for rule in @rules
@@ -43,7 +43,7 @@ exports.OptionParser: class OptionParser
spaces: 15 - rule.long_flag.length
spaces: if spaces > 0 then (' ' for i in [0..spaces]).join('') else ''
let_part: if rule.short_flag then rule.short_flag + ', ' else ' '
lines.push " $let_part${rule.long_flag}$spaces${rule.description}"
lines.push " $let_part$rule.long_flag$spaces$rule.description"
"\n${ lines.join('\n') }\n"
# Helpers

View File

@@ -19,15 +19,15 @@ helpers.extend global, {
# The main REPL function. **run** is called every time a line of code is entered.
# Attempt to evaluate the command. If there's an exception, print it out instead
# of exiting.
run: (code) ->
run: (buffer) ->
try
val: CoffeeScript.run code, {no_wrap: true, globals: true, source: 'repl'}
val: CoffeeScript.run buffer.toString(), {no_wrap: true, globals: true, source: 'repl'}
p val if val isnt undefined
catch err
puts err.stack or err.toString()
print prompt
# Start up the REPL by opening **stdio** and listening for input.
process.stdio.addListener 'data', run
process.stdio.open()
# Start up the REPL by opening **stdin** and listening for input.
stdin: process.openStdin()
stdin.addListener 'data', run
print prompt

View File

@@ -32,7 +32,7 @@ exports.Rewriter: class Rewriter
@close_open_calls_and_indexes()
@add_implicit_indentation()
@add_implicit_parentheses()
@ensure_balance(BALANCED_PAIRS)
@ensure_balance BALANCED_PAIRS
@rewrite_closing_parens()
@tokens
@@ -45,7 +45,7 @@ exports.Rewriter: class Rewriter
i: 0
while true
break unless @tokens[i]
move: block(@tokens[i - 1], @tokens[i], @tokens[i + 1], i)
move: block @tokens[i - 1], @tokens[i], @tokens[i + 1], i
i: + move
true
@@ -75,7 +75,7 @@ exports.Rewriter: class Rewriter
remove_mid_expression_newlines: ->
@scan_tokens (prev, token, post, i) =>
return 1 unless post and include(EXPRESSION_CLOSE, post[0]) and token[0] is 'TERMINATOR'
@tokens.splice(i, 1)
@tokens.splice i, 1
return 0
# The lexer has tagged the opening parenthesis of a method call, and the
@@ -86,8 +86,8 @@ exports.Rewriter: class Rewriter
brackets: [0]
@scan_tokens (prev, token, post, i) =>
switch token[0]
when 'CALL_START' then parens.push(0)
when 'INDEX_START' then brackets.push(0)
when 'CALL_START' then parens.push 0
when 'INDEX_START' then brackets.push 0
when '(' then parens[parens.length - 1]: + 1
when '[' then brackets[brackets.length - 1]: + 1
when ')'
@@ -109,23 +109,24 @@ exports.Rewriter: class Rewriter
# deal with them.
add_implicit_parentheses: ->
stack: [0]
calls: 0
calls: 0
parens: 0
start_parens: 0
@scan_tokens (prev, token, post, i) =>
tag: token[0]
switch tag
when 'CALL_START' then calls: + 1
when 'CALL_END' then calls: - 1
when 'INDENT' then stack.push(0)
when '(' then parens: + 1
when ')' then parens: - 1
when 'INDENT' then stack.push 0
when 'OUTDENT'
last: stack.pop()
stack[stack.length - 1]: + last
open: stack[stack.length - 1] > 0
if tag is 'CALL_END' and calls < 0 and open
stack[stack.length - 1]: - 1
@tokens.splice(i, 0, ['CALL_END', ')', token[2]])
return 2
if !post? or include IMPLICIT_END, tag
if !post? or (start_parens > parens) or (start_parens is parens and include IMPLICIT_END, tag)
return 1 if tag is 'INDENT' and prev and include IMPLICIT_BLOCK, prev[0]
return 1 if tag is 'OUTDENT' and token.generated
if open or tag is 'INDENT'
idx: if tag is 'OUTDENT' then i + 1 else i
stack_pointer: if tag is 'INDENT' then 2 else 1
@@ -134,9 +135,10 @@ exports.Rewriter: class Rewriter
size: stack[stack.length - stack_pointer] + 1
stack[stack.length - stack_pointer]: 0
return size
return 1 unless prev and include(IMPLICIT_FUNC, prev[0]) and include IMPLICIT_CALL, tag
return 1 unless prev and include(IMPLICIT_FUNC, prev[0]) and include(IMPLICIT_CALL, tag)
calls: 0
@tokens.splice(i, 0, ['CALL_START', '(', token[2]])
start_parens: if tag is '(' then parens - 1 else parens
@tokens.splice i, 0, ['CALL_START', '(', token[2]]
stack[stack.length - 1]: + 1
return 2
@@ -150,7 +152,7 @@ exports.Rewriter: class Rewriter
post[0] isnt 'INDENT' and
not (token[0] is 'ELSE' and post[0] is 'IF')
starter: token[0]
@tokens.splice(i + 1, 0, ['INDENT', 2, token[2]])
@tokens.splice i + 1, 0, ['INDENT', 2, token[2]]
idx: i + 1
parens: 0
while true
@@ -159,15 +161,17 @@ exports.Rewriter: class Rewriter
pre: @tokens[idx - 1]
if (not tok or
(include(SINGLE_CLOSERS, tok[0]) and tok[1] isnt ';') or
(tok[0] is ')' && parens is 0)) and
(tok[0] is ')' and parens is 0)) and
not (starter is 'ELSE' and tok[0] is 'ELSE')
insertion: if pre[0] is "," then idx - 1 else idx
@tokens.splice(insertion, 0, ['OUTDENT', 2, token[2]])
outdent: ['OUTDENT', 2, token[2]]
outdent.generated: true
@tokens.splice insertion, 0, outdent
break
parens: + 1 if tok[0] is '('
parens: - 1 if tok[0] is ')'
return 1 unless token[0] is 'THEN'
@tokens.splice(i, 1)
@tokens.splice i, 1
return 0
# Ensure that all listed pairs of tokens are correctly balanced throughout
@@ -200,10 +204,10 @@ exports.Rewriter: class Rewriter
# inwards, safely. The steps to accomplish this are:
#
# 1. Check that all paired tokens are balanced and in order.
# 2. Rewrite the stream with a stack: if you see an '(' or INDENT, add it
# to the stack. If you see an ')' or OUTDENT, pop the stack and replace
# 2. Rewrite the stream with a stack: if you see an `EXPRESSION_START`, add it
# to the stack. If you see an `EXPRESSION_END`, pop the stack and replace
# it with the inverse of what we've just popped.
# 3. Keep track of "debt" for tokens that we fake, to make sure we end
# 3. Keep track of "debt" for tokens that we manufacture, to make sure we end
# up balanced in the end.
#
rewrite_closing_parens: ->
@@ -263,6 +267,7 @@ IMPLICIT_FUNC: ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '<-']
IMPLICIT_CALL: ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START',
'TRY', 'DELETE', 'TYPEOF', 'SWITCH', 'EXTENSION',
'TRUE', 'FALSE', 'YES', 'NO', 'ON', 'OFF', '!', '!!', 'NOT',
'THIS', 'NULL',
'@', '->', '=>', '[', '(', '{']
# Tokens indicating that the implicit call must enclose a block of expressions.

View File

@@ -10,6 +10,9 @@ this.exports: this unless process?
exports.Scope: class Scope
# The top-level **Scope** object.
@root: null
# Initialize a scope with its parent, for lookups up the chain,
# as well as a reference to the **Expressions** node is belongs to, which is
# where it should declare its variables, and a reference to the function that
@@ -17,7 +20,11 @@ exports.Scope: class Scope
constructor: (parent, expressions, method) ->
[@parent, @expressions, @method]: [parent, expressions, method]
@variables: {}
@temp_var: if @parent then @parent.temp_var else '_a'
if @parent
@temp_var: @parent.temp_var
else
Scope.root: this
@temp_var: '_a'
# Look up a variable name in lexical scope, and declare it if it does not
# already exist.
@@ -26,6 +33,12 @@ exports.Scope: class Scope
@variables[name]: 'var'
false
# Test variables and return true the first time fn(v, k) returns true
any: (fn) ->
for v, k of @variables when fn(v, k)
return true
return false
# Reserve a variable name as originating from a function parameter for this
# scope. No `var` required for internal references.
parameter: (name) ->
@@ -47,19 +60,18 @@ exports.Scope: class Scope
# Ensure that an assignment is made at the top of this scope
# (or at the top-level scope, if requested).
assign: (name, value, top_level) ->
return @parent.assign(name, value, top_level) if top_level and @parent
assign: (name, value) ->
@variables[name]: {value: value, assigned: true}
# Does this scope reference any variables that need to be declared in the
# given function body?
has_declarations: (body) ->
body is @expressions and @declared_variables().length
body is @expressions and @any (k, val) -> val is 'var'
# Does this scope reference any assignments that need to be declared at the
# top of the given function body?
has_assignments: (body) ->
body is @expressions and @assigned_variables().length
body is @expressions and @any (k, val) -> val.assigned
# Return the list of variables first declared in this scope.
declared_variables: ->
@@ -68,7 +80,7 @@ exports.Scope: class Scope
# Return the list of assignments that are supposed to be made at the top
# of this scope.
assigned_variables: ->
"$key = ${val.value}" for key, val of @variables when val.assigned
"$key = $val.value" for key, val of @variables when val.assigned
# Compile the JavaScript for all of the variable declarations in this scope.
compiled_declarations: ->

View File

@@ -4,17 +4,17 @@ area: (x, y, x1, y1) ->
x: y: 10
x1: y1: 20
ok area(x, y, x1, y1) is 100, 'basic arguments'
ok area(x, y, x1, y1) is 100
ok(area(x, y,
x1, y1) is 100, 'arguments on split lines')
x1, y1) is 100)
ok(area(
x
y
x1
y1
) is 100, 'newline delimited arguments')
) is 100)
sum_of_args: ->

View File

@@ -1,42 +0,0 @@
nums: n * n for n in [1, 2, 3] when n % 2 isnt 0
results: n * 2 for n in nums
ok results.join(',') is '2,18', 'basic array comprehension'
obj: {one: 1, two: 2, three: 3}
names: prop + '!' for prop of obj
odds: prop + '!' for prop, value of obj when value % 2 isnt 0
ok names.join(' ') is "one! two! three!", 'basic object comprehension'
ok odds.join(' ') is "one! three!", 'object comprehension with a filter'
evens: for num in [1, 2, 3, 4, 5, 6] when num % 2 is 0
num *= -1
num -= 2
num * -1
ok evens.join(', ') is '4, 6, 8', 'multiline array comprehension with filter'
ok 2 in evens, 'the in operator still works, standalone'
# Ensure that the closure wrapper preserves local variables.
obj: {}
methods: ['one', 'two', 'three']
for method in methods
name: method
obj[name]: ->
"I'm " + name
ok obj.one() is "I'm one"
ok obj.two() is "I'm two"
ok obj.three() is "I'm three"
array: [0..10]
ok(num % 2 is 0 for num in array by 2, 'naked ranges are expanded into arrays')

View File

@@ -1,3 +1,4 @@
# Can assign the result of a try/catch block.
result: try
nonexistent * missing
catch error
@@ -5,20 +6,22 @@ catch error
result2: try nonexistent * missing catch error then true
ok result is true and result2 is true, 'can assign the result of a try/catch block'
ok result is true and result2 is true
# Can assign a conditional statement.
get_x: -> 10
if x: get_x() then 100
ok x is 10, 'can assign a conditional statement'
ok x is 10
x: if get_x() then 100
ok x is 100, 'can assign a conditional statement'
ok x is 100
# This-assignment.
tester: ->
@example: -> puts 'example function'
this

View File

@@ -1,7 +1,8 @@
# Basic blocks.
results: [1, 2, 3].map (x) ->
x * x
ok results.join(' ') is '1 4 9', 'basic block syntax'
ok results.join(' ') is '1 4 9'
# Chained blocks, with proper indentation levels:

View File

@@ -1,25 +0,0 @@
identity_wrap: (x) ->
-> x
result: identity_wrap(identity_wrap(true))()()
ok result, 'basic chained function calls'
str: 'god'
result: str.
split('').
reverse().
reverse().
reverse()
ok result.join('') is 'dog', 'chained accesses split on period/newline'
result: str
.split('')
.reverse()
.reverse()
.reverse()
ok result.join('') is 'dog', 'chained accesses split on newline/period'

36
test/test_chaining.coffee Normal file
View File

@@ -0,0 +1,36 @@
# Basic chained function calls.
identity_wrap: (x) ->
-> x
result: identity_wrap(identity_wrap(true))()()
ok result
# Chained accesses split on period/newline, backwards and forwards.
str: 'god'
result: str.
split('').
reverse().
reverse().
reverse()
ok result.join('') is 'dog'
result: str
.split('')
.reverse()
.reverse()
.reverse()
ok result.join('') is 'dog'
# Newline suppression for operators.
six:
1 +
2 +
3
ok six is 6

View File

@@ -1,6 +1,10 @@
# Test classes with a four-level inheritance chain.
class Base
func: (string) ->
'zero/' + string
"zero/$string"
@static: (string) ->
"static/$string"
class FirstChild extends Base
func: (string) ->
@@ -21,6 +25,7 @@ class ThirdChild extends SecondChild
result: (new ThirdChild()).func 'four'
ok result is 'zero/one/two/three/four'
ok Base.static('word') is 'static/word'
class TopClass
@@ -43,4 +48,49 @@ class OneClass
class TwoClass extends OneClass
ok (new TwoClass('three')).name is 'three'
ok (new TwoClass('three')).name is 'three'
# And now the same tests, but written in the manual style:
Base: ->
Base::func: (string) ->
'zero/' + string
FirstChild: ->
FirstChild extends Base
FirstChild::func: (string) ->
super('one/') + string
SecondChild: ->
SecondChild extends FirstChild
SecondChild::func: (string) ->
super('two/') + string
ThirdChild: ->
@array: [1, 2, 3]
this
ThirdChild extends SecondChild
ThirdChild::func: (string) ->
super('three/') + string
result: (new ThirdChild()).func 'four'
ok result is 'zero/one/two/three/four'
TopClass: (arg) ->
@prop: 'top-' + arg
this
SuperClass: (arg) ->
super 'super-' + arg
this
SubClass: ->
super 'sub'
this
SuperClass extends TopClass
SubClass extends SuperClass
ok (new SubClass()).prop is 'top-super-sub'

View File

@@ -54,5 +54,18 @@ js: CoffeeScript.compile 'puts %w{one two three}', {no_wrap: on}
ok js is 'puts(["one", "two", "three"]);'
# Finally, let's try an extension that converts `a << b` into `a.push(b)`.
CoffeeScript.extend ->
return false unless @chunk.match(/^<</)
@i: + 2
@token 'PROPERTY_ACCESS', '.'
@token 'IDENTIFIER', 'push'
js: CoffeeScript.compile 'a << b', {no_wrap: on}
ok js is 'a.push(b);'
Lexer.extensions: []

View File

@@ -0,0 +1,101 @@
# Basic array comprehensions.
nums: n * n for n in [1, 2, 3] when n % 2 isnt 0
results: n * 2 for n in nums
ok results.join(',') is '2,18'
# Basic object comprehensions.
obj: {one: 1, two: 2, three: 3}
names: prop + '!' for prop of obj
odds: prop + '!' for prop, value of obj when value % 2 isnt 0
ok names.join(' ') is "one! two! three!"
ok odds.join(' ') is "one! three!"
# Basic range comprehensions.
nums: i * 3 for i in [1..3]
negs: x for x in [-20..-5*2]
negs: negs[0..2]
result: nums.concat(negs).join(', ')
ok result is '3, 6, 9, -20, -19, -18'
# Ensure that ranges are safe. This used to infinite loop:
j = 5
result: for j in [j..(j+3)]
j
ok result.join(' ') is '5 6 7 8'
# With range comprehensions, you can loop in steps.
results: x for x in [0..25] by 5
ok results.join(' ') is '0 5 10 15 20 25'
# Multiline array comprehension with filter.
evens: for num in [1, 2, 3, 4, 5, 6] when num % 2 is 0
num *= -1
num -= 2
num * -1
ok evens.join(', ') is '4, 6, 8'
# The in operator still works, standalone.
ok 2 in evens
# Ensure that the closure wrapper preserves local variables.
obj: {}
methods: ['one', 'two', 'three']
for method in methods
name: method
obj[name]: ->
"I'm " + name
ok obj.one() is "I'm one"
ok obj.two() is "I'm two"
ok obj.three() is "I'm three"
# Naked ranges are expanded into arrays.
array: [0..10]
ok(num % 2 is 0 for num in array by 2)
# Nested comprehensions.
multi_liner:
for x in [3..5]
for y in [3..5]
[x, y]
single_liner:
[x, y] for y in [3..5] for x in [3..5]
ok multi_liner.length is single_liner.length
ok 5 is multi_liner[2][2][1]
ok 5 is single_liner[2][2][1]
# Comprehensions within parentheses.
result: null
store: (obj) -> result: obj
store (x * 2 for x in [3, 2, 1])
ok result.join(' ') is '6 4 2'
# Closure-wrapped comprehensions that refer to the "arguments" object.
expr: ->
result: item * item for item in arguments
ok expr(2, 4, 8).join(' ') is '4 16 64'

View File

@@ -1,31 +0,0 @@
func: ->
a: 3
b: []
while a >= 0
b.push 'o'
a--
c: {
"text": b
other: null
something_else: (x) -> x + 5
}
c: 'error' unless 42 > 41
c.text: if false
'error'
else
c.text + '---'
d = {
text = c.text
}
c.list: l for l in d.text.split('') when l is '-'
c.single: c.list[1..1][0]
ok func() is '-'

View File

@@ -1,2 +1,19 @@
# Basic exception throwing.
block: -> (throw 'up')
throws block, '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

View File

@@ -6,7 +6,6 @@ ok(if my_special_variable? then true else false)
# Existential assignment.
a: 5
a: null
a ?= 10
@@ -16,7 +15,6 @@ ok a is 10 and b is 10
# The existential operator.
z: null
x: z ? "EX"
@@ -24,7 +22,6 @@ ok z is null and x is "EX"
# Only evaluate once.
counter: 0
get_next_node: ->
throw "up" if counter
@@ -34,7 +31,6 @@ ok(if get_next_node()? then true else false)
# Existence chains, soaking up undefined properties:
obj: {
prop: "hello"
}
@@ -53,7 +49,6 @@ ok obj?['non']?['existent'].property is undefined
# Soaks and caches method calls as well.
arr: ["--", "----"]
ok arr.pop()?.length is 4

View File

@@ -1,5 +1,4 @@
# Ensure that we don't wrap Nodes that are "pure_statement" in a closure.
items: [1, 2, 3, "bacon", 4, 5]
for item in items
@@ -14,7 +13,6 @@ ok findit(items) is "bacon"
# When when a closure wrapper is generated for expression conversion, make sure
# that references to "this" within the wrapper are safely converted as well.
obj: {
num: 5
func: ->

View File

@@ -33,8 +33,6 @@ obj.unbound()
obj.bound()
# The named function should be cleared out before a call occurs:
# Python decorator style wrapper that memoizes any function
memoize: (fn) ->
cache: {}
@@ -74,14 +72,12 @@ ok result is 10
# More fun with optional parens.
fn: (arg) -> arg
ok fn(fn {prop: 101}).prop is 101
# Multi-blocks with optional parens.
result: fn( ->
fn ->
"Wrapped"
@@ -91,7 +87,6 @@ ok result()() is 'Wrapped'
# And even with strange things like this:
funcs: [((x) -> x), ((x) -> x * x)]
result: funcs[1] 5
@@ -103,7 +98,6 @@ ok result is 'lo'
# And with multiple single-line functions on the same line.
func: (x) -> (x) -> (x) -> x
ok func(1)(2)(3) is 3
@@ -111,3 +105,36 @@ ok func(1)(2)(3) is 3
# Ensure that functions with the same name don't clash with helper functions.
del: -> 5
ok del() is 5
# Ensure that functions can have a trailing comma in their argument list
mult: (x, mids..., y) ->
x: * n for n in mids
x: * y
ok mult(1, 2,) is 2
ok mult(1, 2, 3,) is 6
ok mult(10,[1..6]...,) is 7200
# Test for inline functions with parentheses and implicit calls.
combine: (func, num) -> func() * num
result: combine (-> 1 + 2), 3
ok result is 9
# Test for calls/parens/multiline-chains.
f: (x) -> x
result: (f 1).toString()
.length
ok result is 1
# Test implicit calls in functions in parens:
result: ((val) ->
[].push val
val
)(10)
ok result is 10

View File

@@ -27,8 +27,6 @@ ok result
# If statement with a comment-only clause.
result: if false
# comment
else

View File

@@ -1,2 +1,2 @@
# Check if it can import and execute a coffeescript-only module successfully.
# Check if we can import and execute a CoffeeScript-only module successfully.
ok require('./test_module').func() is "from over there"

View File

@@ -1,10 +0,0 @@
num: 1 + 2 + (a: 3)
ok num is 6
result: if true
false
other: "result"
ok result is "result" and other is "result"

View File

@@ -25,6 +25,18 @@ reg: /\\/
ok reg(str) and str is '\\'
trailing_comma: [1, 2, 3,]
ok (trailing_comma[0] is 1) and (trailing_comma[2] is 3) and (trailing_comma.length is 3)
trailing_comma: [
1, 2, 3,
4, 5, 6
7, 8, 9,
]
(sum: (sum or 0) + n) for n in trailing_comma
trailing_comma: {k1: "v1", k2: 4, k3: (-> true),}
ok trailing_comma.k3() and (trailing_comma.k2 is 4) and (trailing_comma.k1 is "v1")
money$: 'dollars'
@@ -41,8 +53,8 @@ ok multiline is 'one two three'
ok {a: (num) -> num is 10 }.a 10
bob: {
name: 'Bob'
moe: {
name: 'Moe'
greet: (salutation) ->
salutation + " " + @name
hello: ->
@@ -50,13 +62,18 @@ bob: {
10: 'number'
}
ok bob.hello() is "Hello Bob"
ok bob[10] is 'number'
ok moe.hello() is "Hello Moe"
ok moe[10] is 'number'
moe.hello: ->
this['greet'] "Hello"
ok moe.hello() is 'Hello Moe'
obj: {
'is': -> yes
'not': -> no
'is': -> yes,
'not': -> no,
}
ok obj.is()

View File

@@ -1,11 +0,0 @@
multi_liner:
for x in [3..5]
for y in [3..5]
[x, y]
single_liner:
[x, y] for y in [3..5] for x in [3..5]
ok multi_liner.length is single_liner.length
ok 5 is multi_liner[2][2][1]
ok 5 is single_liner[2][2][1]

View File

@@ -1,6 +0,0 @@
six:
1 +
2 +
3
ok six is 6

View File

@@ -1,42 +0,0 @@
Base: ->
Base::func: (string) ->
'zero/' + string
FirstChild: ->
FirstChild extends Base
FirstChild::func: (string) ->
super('one/') + string
SecondChild: ->
SecondChild extends FirstChild
SecondChild::func: (string) ->
super('two/') + string
ThirdChild: ->
@array: [1, 2, 3]
this
ThirdChild extends SecondChild
ThirdChild::func: (string) ->
super('three/') + string
result: (new ThirdChild()).func 'four'
ok result is 'zero/one/two/three/four', 'successfully set up and called a four-level inheritance chain'
TopClass: (arg) ->
@prop: 'top-' + arg
this
SuperClass: (arg) ->
super 'super-' + arg
this
SubClass: ->
super 'sub'
this
SuperClass extends TopClass
SubClass extends SuperClass
ok (new SubClass()).prop is 'top-super-sub', 'inheritance'

View File

@@ -1,5 +1,4 @@
# CoffeeScript's operations should be chainable, like Python's.
ok 500 > 50 > 5 > -5
ok true is not false is true is not false
@@ -13,7 +12,6 @@ ok 50 > 10 > 5 is parseInt('5', 10)
# Make sure that each argument is only evaluated once, even if used
# more than once.
i: 0
func: -> i++
@@ -21,10 +19,18 @@ ok 1 > func() < 1
# `:` and `=` should be interchangeable, as should be `==` and `is`.
a: 1
b: 1
ok a is 1 and b is 1
ok a == b
ok a is b
# Ensure that chained operations don't cause functions to be evaluated more
# than once.
val: 0
func: -> val: + 1
ok 2 > (func null) < 2
ok val is 1

View File

@@ -1,3 +1,4 @@
# Simple variable swapping.
a: -1
b: -2
@@ -6,13 +7,11 @@ b: -2
ok a is -2
ok b is -1
func: ->
[a, b]: [b, a]
ok func().join(' ') is '-1 -2'
noop: ->
noop [a,b]: [c,d]: [1,2]
@@ -20,6 +19,7 @@ noop [a,b]: [c,d]: [1,2]
ok a is 1 and b is 2
# Array destructuring, including splats.
arr: [1, 2, 3]
[a, b, c]: arr
@@ -43,6 +43,8 @@ ok last is 40
ok z.length is 3 and z[2] is 4
ok end is 5
# Object destructuring.
obj: {x: 10, y: 20, z: 30}
{x: a, y: b, z: c}: obj
@@ -51,9 +53,8 @@ ok a is 10
ok b is 20
ok c is 30
person: {
name: "Bob"
name: "Moe"
family: {
brother: {
addresses: [
@@ -69,10 +70,9 @@ person: {
{name: a, family: {brother: {addresses: [one, {city: b}]}}}: person
ok a is "Bob"
ok a is "Moe"
ok b is "Moquasset NY, 10021"
test: {
person: {
address: [
@@ -89,6 +89,7 @@ test: {
ok addr.join(', ') is "Street 101, Apt 101, City 101"
# Destructuring against an expression.
[a, b]: if true then [2, 1] else [1, 2]
ok a is 2

View File

@@ -1,20 +0,0 @@
nums: i * 3 for i in [1..3]
negs: x for x in [-20..-5*2]
negs: negs[0..2]
result: nums.concat(negs).join(', ')
ok result is '3, 6, 9, -20, -19, -18'
# Ensure that ranges are safe. This used to infinite loop:
j = 5
result: for j in [j..(j+3)]
j
ok result.join(' ') is '5 6 7 8'
# With range comprehensions, you can loop in steps.
results: x for x in [0..25] by 5
ok results.join(' ') is '0 5 10 15 20 25'

View File

@@ -1,16 +0,0 @@
array: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
a: array[7..9]
b: array[2...4]
result: a.concat(b).join(' ')
ok result is "7 8 9 2 3"
countdown: [10..1].join(' ')
ok countdown is "10 9 8 7 6 5 4 3 2 1"
array: [(1+5)..1+9]
ok array.join(' ') is "6 7 8 9 10"

View File

@@ -0,0 +1,41 @@
# Slice.
array: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
a: array[7..9]
b: array[2...4]
result: a.concat(b).join(' ')
ok result is "7 8 9 2 3"
a: [0, 1, 2, 3, 4, 5, 6, 7]
deepEqual a[2...6], [2, 3, 4, 5]
# Range.
countdown: [10..1].join(' ')
ok countdown is "10 9 8 7 6 5 4 3 2 1"
# Expression-based range.
array: [(1+5)..1+9]
ok array.join(' ') is "6 7 8 9 10"
# String slicing (at least on Node).
hello: "Hello World"
ok hello[1...1] is ""
ok hello[1..1] is "e"
ok hello[1...5] is "ello"
ok hello[0..4] is "Hello"
# Splice literals.
array: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
array[5..10]: [0, 0, 0]
ok array.join(' ') is '0 1 2 3 4 0 0 0'

View File

@@ -1,12 +1,13 @@
name: 'Bob'
# Interpolate regular expressions.
name: 'Moe'
ok not not '"Bob"'.match(/^"${name}"$/i)
ok '"Bobby"'.match(/^"${name}"$/i) is null
ok not not '"Moe"'.match(/^"${name}"$/i)
ok '"Moe!"'.match(/^"${name}"$/i) is null
ok not not 'Bob'.match(/^$name$/)
ok 'Bobby'.match(/^$name/)
ok not not 'Moe'.match(/^$name$/)
ok 'Moe!'.match(/^$name/)
ok 'Bobby'.match(/${"${"${"$name"}"}"}/imgy)
ok 'Moe!'.match(/${"${"${"$name"}"}"}/imgy)
ok '$a$b$c'.match(/\$A\$B\$C/i)

View File

@@ -1,3 +1,4 @@
# Regular expression literals.
ok 'x'.match(/x/g)
ok 'x'.match /x/g
ok 'x'.match(/x/)

13
test/test_returns.coffee Normal file
View File

@@ -0,0 +1,13 @@
# Expression conversion under explicit returns.
first: ->
return 'do' for x in [1,2,3]
second: ->
return ['re' for x in [1,2,3]]
third: ->
return ('mi' for x in [1,2,3])
ok first().join(' ') is 'do do do'
ok second()[0].join(' ') is 're re re'
ok third().join(' ') is 'mi mi mi'

View File

@@ -45,12 +45,12 @@ ok bronze is "Mighty Mouse"
ok last is "Michael Phelps"
ok the_field.length is 8
medalists contenders..., 'Tim', 'Bob', 'Jim'
medalists contenders..., 'Tim', 'Moe', 'Jim'
ok last is 'Jim'
obj: {
name: 'bob'
name: 'moe'
accessor: (args...) ->
[@name].concat(args).join(' ')
getNames: ->
@@ -58,7 +58,7 @@ obj: {
@accessor(args...)
}
ok obj.getNames() is 'bob jane ted'
ok obj.getNames() is 'moe jane ted'
crowd: [

View File

@@ -1,5 +0,0 @@
array: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
array[5..10]: [0, 0, 0]
ok array.join(' ') is '0 1 2 3 4 0 0 0'

View File

@@ -48,8 +48,10 @@ ok "values: ${list.join ' '}" is 'values: 0 1 2 3 4 5 6 7 8 9'
obj: {
name: 'Joe'
hi: -> "Hello $@name."
cya: -> "Hello $@name.".replace('Hello','Goodbye')
}
ok obj.hi() is "Hello Joe."
ok obj.cya() is "Goodbye Joe."
ok "With ${"quotes"}" is 'With quotes'
ok 'With ${"quotes"}' is 'With ${"quotes"}'
@@ -66,3 +68,8 @@ a: 1
b: 2
c: 3
ok "$a$b$c" is '123'
result: null
stash: (str) -> result: str
stash "a ${ ('aa').replace /a/g, 'b' } c"
ok result is 'a bb c'

View File

@@ -1,14 +0,0 @@
result: try
10
finally
15
ok result is 10
result: try
throw 'up'
catch err
err.length
ok result is 2