mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-01-14 01:07:55 -05:00
Compare commits
170 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c50cf23b7b | ||
|
|
25c8b4b34f | ||
|
|
c0a89a7988 | ||
|
|
07d9e9b71e | ||
|
|
269f4e8da8 | ||
|
|
481c3d536b | ||
|
|
7e5db250d3 | ||
|
|
970bfbe151 | ||
|
|
7d98bb216a | ||
|
|
e4b7d06f35 | ||
|
|
b19c004680 | ||
|
|
7bc91bf6c6 | ||
|
|
c49cd02365 | ||
|
|
992f4192bf | ||
|
|
921ab3ce68 | ||
|
|
69942c9a81 | ||
|
|
fb5158630a | ||
|
|
34c29b3406 | ||
|
|
c0796da7b9 | ||
|
|
83651a7d6a | ||
|
|
10d57705a0 | ||
|
|
71998e06cf | ||
|
|
a16594ed7b | ||
|
|
f7fce3cd68 | ||
|
|
ba850790ed | ||
|
|
abc1e83319 | ||
|
|
99a06ce4ea | ||
|
|
31441868e0 | ||
|
|
5d82dddfb1 | ||
|
|
d568b56c5e | ||
|
|
3ab0c12bf1 | ||
|
|
ed74f42323 | ||
|
|
15d84dbb4e | ||
|
|
65fa0411b4 | ||
|
|
408833daef | ||
|
|
bb35b3e3b2 | ||
|
|
4a3e1fb0cb | ||
|
|
fe68261bc2 | ||
|
|
1f2c6c77fd | ||
|
|
08e1101c1f | ||
|
|
72847b9b26 | ||
|
|
4b2d40d3b5 | ||
|
|
72d7fe2f7a | ||
|
|
43f7f6c355 | ||
|
|
a53c104db1 | ||
|
|
2a0bd1adc7 | ||
|
|
a2631759c0 | ||
|
|
2b87cabbb4 | ||
|
|
d8465ce767 | ||
|
|
60f80e2698 | ||
|
|
c782c2ec1c | ||
|
|
f0d778ce49 | ||
|
|
a3c224e57a | ||
|
|
b727245834 | ||
|
|
6b19e61bd0 | ||
|
|
38ce0cfd9a | ||
|
|
61a39e04fc | ||
|
|
ea3aa6803a | ||
|
|
3a20d7dacb | ||
|
|
e5837b4ee9 | ||
|
|
d1f31c5143 | ||
|
|
4af41e9bfb | ||
|
|
121110a485 | ||
|
|
d41a414b5c | ||
|
|
9bd3cca7c4 | ||
|
|
18cbddff6a | ||
|
|
df414dab02 | ||
|
|
904207ba8f | ||
|
|
44618d5765 | ||
|
|
70cfd54ad4 | ||
|
|
62bf0a2bc9 | ||
|
|
c9289155b4 | ||
|
|
cd67ec6e69 | ||
|
|
cd6261d477 | ||
|
|
3b60aad487 | ||
|
|
493780efab | ||
|
|
9290e508c6 | ||
|
|
a1ebb14495 | ||
|
|
eb9a524ea1 | ||
|
|
0caa731291 | ||
|
|
704fbf499b | ||
|
|
04fd24e068 | ||
|
|
dc6a83c030 | ||
|
|
bcecbd051b | ||
|
|
6607224493 | ||
|
|
6224edd6ce | ||
|
|
9598b11c77 | ||
|
|
fa95f743f3 | ||
|
|
e2c46d14f0 | ||
|
|
bd3471b3d1 | ||
|
|
1b88d18d61 | ||
|
|
b4de17d504 | ||
|
|
f90fac0e55 | ||
|
|
9fd92bf884 | ||
|
|
117204a784 | ||
|
|
e7834de929 | ||
|
|
d5d5de55ae | ||
|
|
143c4d5efc | ||
|
|
13adc44867 | ||
|
|
87693d84cb | ||
|
|
6ed33fcc6d | ||
|
|
2e59cc4807 | ||
|
|
4ddd65a4c4 | ||
|
|
bf6bafa3ac | ||
|
|
24f1174b16 | ||
|
|
098caa9979 | ||
|
|
b608d4a5ea | ||
|
|
4d32c47bee | ||
|
|
ec54b50c67 | ||
|
|
387c690530 | ||
|
|
536e24b024 | ||
|
|
1b05cd81f0 | ||
|
|
db181e2a36 | ||
|
|
f41ca2e5e8 | ||
|
|
a8c6a641d7 | ||
|
|
474c372b17 | ||
|
|
5b9b45814f | ||
|
|
01cd5476a0 | ||
|
|
027b9e9dc3 | ||
|
|
197f576cab | ||
|
|
0b8facc66f | ||
|
|
7a0d95c612 | ||
|
|
975b82f09b | ||
|
|
f496cc229b | ||
|
|
9894eeb8e9 | ||
|
|
129e950c59 | ||
|
|
c90a75ebc5 | ||
|
|
1d6eca76f8 | ||
|
|
6555d86328 | ||
|
|
c71f2794eb | ||
|
|
ca18f1fad6 | ||
|
|
ead9b1041c | ||
|
|
1eebbfe2bc | ||
|
|
d30c8b321c | ||
|
|
083500fc0e | ||
|
|
fd6e9a1e66 | ||
|
|
8c45aa480b | ||
|
|
d704afa0e9 | ||
|
|
2ec857ef8d | ||
|
|
ba02ebc3dc | ||
|
|
ac752a46bc | ||
|
|
398ec3be5a | ||
|
|
6c997978bc | ||
|
|
642e7fada5 | ||
|
|
12493779b9 | ||
|
|
7142131f3d | ||
|
|
5bdf78d5ec | ||
|
|
60a4138d50 | ||
|
|
cb52be6475 | ||
|
|
c2ec40e6ce | ||
|
|
87fd05afb0 | ||
|
|
45b5bae7d7 | ||
|
|
d0b918e083 | ||
|
|
0231f8da1b | ||
|
|
3eda5a2e85 | ||
|
|
18d6fd72de | ||
|
|
d286b33601 | ||
|
|
a749d43897 | ||
|
|
08506f160d | ||
|
|
b902377304 | ||
|
|
1c903450c8 | ||
|
|
f950e282a6 | ||
|
|
4da982b253 | ||
|
|
b1b78dca47 | ||
|
|
0ada5a7734 | ||
|
|
cc10641f38 | ||
|
|
9df3e6a538 | ||
|
|
133aa7be4a | ||
|
|
6555659e82 | ||
|
|
b1f7d5e33b |
37
Cakefile
37
Cakefile
@@ -2,6 +2,7 @@ fs = require 'fs'
|
||||
{helpers} = require './lib/helpers'
|
||||
CoffeeScript = require './lib/coffee-script'
|
||||
{spawn, exec} = require 'child_process'
|
||||
path = require 'path'
|
||||
|
||||
# ANSI Terminal Colors.
|
||||
red = '\033[0;31m'
|
||||
@@ -16,25 +17,25 @@ run = (args) ->
|
||||
|
||||
# Log a message with a color.
|
||||
log = (message, color, explanation) ->
|
||||
puts "#color#message#reset #{explanation or ''}"
|
||||
puts color + message + reset + ' ' + (explanation or '')
|
||||
|
||||
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"
|
||||
bin = "#base/bin"
|
||||
lib = "#{base}/lib/coffee-script"
|
||||
bin = "#{base}/bin"
|
||||
node = "~/.node_libraries/coffee-script"
|
||||
puts "Installing CoffeeScript to #lib"
|
||||
puts "Linking to #node"
|
||||
puts "Linking 'coffee' to #bin/coffee"
|
||||
puts "Installing CoffeeScript to #{lib}"
|
||||
puts "Linking to #{node}"
|
||||
puts "Linking 'coffee' to #{bin}/coffee"
|
||||
exec([
|
||||
"mkdir -p #lib #bin"
|
||||
"cp -rf bin lib LICENSE README package.json src #lib"
|
||||
"ln -sf #lib/bin/coffee #bin/coffee"
|
||||
"ln -sf #lib/bin/cake #bin/cake"
|
||||
"mkdir -p #{lib} #{bin}"
|
||||
"cp -rf bin lib LICENSE README package.json src #{lib}"
|
||||
"ln -sf #{lib}/bin/coffee #{bin}/coffee"
|
||||
"ln -sf #{lib}/bin/cake #{bin}/cake"
|
||||
"mkdir -p ~/.node_libraries"
|
||||
"ln -sf #lib/lib #node"
|
||||
"ln -sf #{lib}/lib #{node}"
|
||||
].join(' && '), (err, stdout, stderr) ->
|
||||
if err then print stderr else log 'done', green
|
||||
)
|
||||
@@ -57,8 +58,9 @@ task 'build:parser', 'rebuild the Jison parser (run build first)', ->
|
||||
require 'jison'
|
||||
parser = require('./lib/grammar').parser
|
||||
js = parser.generate()
|
||||
parserPath = 'lib/parser.js'
|
||||
fs.writeFile parserPath, js
|
||||
# TODO: Remove this when the Jison patch is released.
|
||||
js = js.replace 'if (require.main === module)', 'if (typeof module !== "undefined" && require.main === module)'
|
||||
fs.writeFile 'lib/parser.js', js
|
||||
|
||||
|
||||
task 'build:ultraviolet', 'build and install the Ultraviolet syntax highlighter', ->
|
||||
@@ -97,15 +99,14 @@ task 'test', 'run the CoffeeScript language test suite', ->
|
||||
passedTests = failedTests = 0
|
||||
startTime = new Date
|
||||
originalOk = ok
|
||||
helpers.extend global, {
|
||||
helpers.extend global,
|
||||
ok: (args...) -> passedTests += 1; originalOk(args...)
|
||||
CoffeeScript: CoffeeScript
|
||||
}
|
||||
process.on 'exit', ->
|
||||
time = ((new Date - startTime) / 1000).toFixed(2)
|
||||
message = "passed #passedTests tests in #time seconds#reset"
|
||||
message = "passed #{passedTests} tests in #{time} seconds#{reset}"
|
||||
if failedTests
|
||||
log "failed #failedTests and #message", red
|
||||
log "failed #{failedTests} and #{message}", red
|
||||
else
|
||||
log message, green
|
||||
fs.readdir 'test', (err, files) ->
|
||||
@@ -117,4 +118,4 @@ task 'test', 'run the CoffeeScript language test suite', ->
|
||||
CoffeeScript.run code.toString(), {fileName}
|
||||
catch err
|
||||
failedTests += 1
|
||||
log "failed #fileName", red, '\n' + err.stack.toString()
|
||||
log "failed #{fileName}", red, '\n' + err.stack.toString()
|
||||
|
||||
2
README
2
README
@@ -56,10 +56,12 @@
|
||||
Timothy Jones (Tesco)
|
||||
Chris Lloyd (chrislloyd)
|
||||
Matt Lyon (mattly)
|
||||
Satoshi Murakami (satyr)
|
||||
Jeff Olson (olsonjeffery)
|
||||
Nathan Ostgard (noonat)
|
||||
Samuel Reis (grgh)
|
||||
Tom Robinson (tlrobinson)
|
||||
Tim Smart (Tim-Smart)
|
||||
Sam Stephenson (sstephenson)
|
||||
Dr. Nic Williams (drnic)
|
||||
|
||||
26
Rakefile
26
Rakefile
@@ -2,11 +2,11 @@ require 'erb'
|
||||
require 'fileutils'
|
||||
require 'rake/testtask'
|
||||
require 'rubygems'
|
||||
require 'yui/compressor'
|
||||
require 'closure-compiler'
|
||||
|
||||
HEADER = <<-EOS
|
||||
/**
|
||||
* CoffeeScript Compiler v0.9.0
|
||||
* CoffeeScript Compiler v0.9.4
|
||||
* http://coffeescript.org
|
||||
*
|
||||
* Copyright 2010, Jeremy Ashkenas
|
||||
@@ -33,9 +33,21 @@ end
|
||||
|
||||
desc "Build the single concatenated and minified script for the browser"
|
||||
task :browser do
|
||||
sources = %w(helpers.js rewriter.js lexer.js parser.js scope.js nodes.js coffee-script.js)
|
||||
code = sources.map {|s| File.read('lib/' + s) }.join('')
|
||||
code = YUI::JavaScriptCompressor.new.compress(code)
|
||||
File.open('extras/coffee-script.js', 'w+') {|f| f.write(HEADER + code) }
|
||||
sources = %w(helpers rewriter lexer parser scope nodes coffee-script browser)
|
||||
code = sources.inject '' do |js, name|
|
||||
js << <<-"JS"
|
||||
require['./#{name}'] = new function(){
|
||||
var exports = this;
|
||||
#{ File.read "lib/#{name}.js" }
|
||||
}
|
||||
JS
|
||||
end
|
||||
code = Closure::Compiler.new.compress(<<-"JS")
|
||||
this.CoffeeScript = function(){
|
||||
function require(path){ return require[path] }
|
||||
#{ code }
|
||||
return require['./coffee-script']
|
||||
}()
|
||||
JS
|
||||
File.open('extras/coffee-script.js', 'wb+') {|f| f.write(HEADER + code) }
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###
|
||||
CoffeeScript Compiler v0.9.0
|
||||
CoffeeScript Compiler v0.9.4
|
||||
Released under the MIT License
|
||||
###
|
||||
@@ -2,8 +2,8 @@ fs = require 'fs'
|
||||
|
||||
option '-o', '--output [DIR]', 'directory for compiled code'
|
||||
|
||||
task 'build:parser', 'rebuild the Jison parser', ->
|
||||
task 'build:parser', 'rebuild the Jison parser', (options) ->
|
||||
require 'jison'
|
||||
code = require('./lib/grammar').parser.generate()
|
||||
dir = options.output or 'lib'
|
||||
fs.writeFile "#dir/parser.js", code
|
||||
fs.writeFile "#{dir}/parser.js", code
|
||||
@@ -1,2 +1,2 @@
|
||||
author = "Wittgenstein"
|
||||
quote = "A picture is a fact. -- #author"
|
||||
quote = "A picture is a fact. -- #{author}"
|
||||
@@ -1,6 +1,6 @@
|
||||
sentence = "#{ 22 / 7 } is a decent approximation of π"
|
||||
|
||||
sep = "[.\\/\\- ]"
|
||||
dates = /\d+#sep\d+#sep\d+/g
|
||||
dates = /\d+#{sep}\d+#{sep}\d+/g
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
mobyDick = "Call me Ishmael. Some years ago --
|
||||
never mind how long precisely -- having little
|
||||
or no money in my purse, and nothing particular
|
||||
to interest me on shore, I thought I would sail
|
||||
about a little and see the watery part of the
|
||||
world..."
|
||||
never mind how long precisely -- having little
|
||||
or no money in my purse, and nothing particular
|
||||
to interest me on shore, I thought I would sail
|
||||
about a little and see the watery part of the
|
||||
world..."
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
switch day
|
||||
when "Mon" then goToWork()
|
||||
when "Tue" then goToThePark()
|
||||
when "Thu" then goIceFishing()
|
||||
when "Mon" then go work
|
||||
when "Tue" then go relax
|
||||
when "Thu" then go iceFishing
|
||||
when "Fri", "Sat"
|
||||
if day is bingoDay
|
||||
goToBingo()
|
||||
goDancing()
|
||||
when "Sun" then goToChurch()
|
||||
else goToWork()
|
||||
go bingo
|
||||
go dancing
|
||||
when "Sun" then go church
|
||||
else go work
|
||||
@@ -15,7 +15,7 @@ a {
|
||||
color: #000055;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 40px;
|
||||
margin-top: 50px;
|
||||
}
|
||||
br.clear {
|
||||
height: 0;
|
||||
|
||||
24
documentation/docs/browser.html
Normal file
24
documentation/docs/browser.html
Normal file
@@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html> <html> <head> <title>browser.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> browser.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>Override exported methods for non-Node.js engines.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s1">'./coffee-script'</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-2">#</a> </div> <p>Use standard JavaScript <code>eval</code> to eval code.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.eval = </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nb">eval</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">options</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>Running code does not provide access to this scope.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.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">-></span>
|
||||
<span class="p">(</span><span class="nb">Function</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">options</span><span class="p">)()</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>If we're not in a browser environment, we're finished with the public API.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">return</span> <span class="nx">unless</span> <span class="nb">window</span><span class="o">?</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Load a remote script from the current domain via XHR.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.load = </span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">xhr = </span><span class="k">new</span> <span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">ActiveXObject</span> <span class="o">or</span> <span class="nx">XMLHttpRequest</span><span class="p">)(</span><span class="s1">'Microsoft.XMLHTTP'</span><span class="p">)</span>
|
||||
<span class="nx">xhr</span><span class="p">.</span><span class="nx">open</span> <span class="s1">'GET'</span><span class="p">,</span> <span class="nx">url</span><span class="p">,</span> <span class="kc">true</span>
|
||||
<span class="nx">xhr</span><span class="p">.</span><span class="nx">overrideMimeType</span> <span class="s1">'text/plain'</span> <span class="k">if</span> <span class="s1">'overrideMimeType'</span> <span class="k">of</span> <span class="nx">xhr</span>
|
||||
<span class="nv">xhr.onreadystatechange = </span><span class="o">-></span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">responseText</span><span class="p">,</span> <span class="nx">options</span> <span class="k">if</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">readyState</span> <span class="o">is</span> <span class="mi">4</span>
|
||||
<span class="nx">xhr</span><span class="p">.</span><span class="nx">send</span> <span class="kc">null</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</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.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">processScripts = </span><span class="o">-></span>
|
||||
<span class="k">for</span> <span class="nx">script</span> <span class="k">in</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span> <span class="s1">'script'</span>
|
||||
<span class="k">if</span> <span class="nx">script</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s1">'text/coffeescript'</span>
|
||||
<span class="k">if</span> <span class="nx">script</span><span class="p">.</span><span class="nx">src</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">load</span> <span class="nx">script</span><span class="p">.</span><span class="nx">src</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">setTimeout</span> <span class="o">-></span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">script</span><span class="p">.</span><span class="nx">innerHTML</span>
|
||||
<span class="kc">null</span>
|
||||
<span class="k">if</span> <span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span>
|
||||
<span class="nx">addEventListener</span> <span class="s1">'DOMContentLoaded'</span><span class="p">,</span> <span class="nx">processScripts</span><span class="p">,</span> <span class="kc">false</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">attachEvent</span> <span class="s1">'onload'</span><span class="p">,</span> <span class="nx">processScripts</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html> <html> <head> <title>cake.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> cake.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p><code>cake</code> is a simplified version of <a href="http://www.gnu.org/software/make/">Make</a>
|
||||
<!DOCTYPE html> <html> <head> <title>cake.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> cake.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p><code>cake</code> is a simplified version of <a href="http://www.gnu.org/software/make/">Make</a>
|
||||
(<a href="http://rake.rubyforge.org/">Rake</a>, <a href="http://github.com/280north/jake">Jake</a>)
|
||||
for CoffeeScript. You define tasks with names and descriptions in a Cakefile,
|
||||
and can call them from the command line, or invoke them from other tasks.</p>
|
||||
@@ -33,11 +33,11 @@ If no tasks are passed, print the help screen.</p> </td>
|
||||
<span class="nx">puts</span> <span class="s1">''</span>
|
||||
<span class="k">for</span> <span class="nx">all</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">></span> <span class="mi">0</span> <span class="k">then</span> <span class="p">(</span><span class="s1">' '</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">''</span><span class="p">)</span> <span class="k">else</span> <span class="s1">''</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">"# #task.description"</span> <span class="k">else</span> <span class="s1">''</span>
|
||||
<span class="nx">puts</span> <span class="s2">"cake #name#spaces #desc"</span>
|
||||
<span class="nv">spaces = </span><span class="k">if</span> <span class="nx">spaces</span> <span class="o">></span> <span class="mi">0</span> <span class="k">then</span> <span class="nb">Array</span><span class="p">(</span><span class="nx">spaces</span> <span class="o">+</span> <span class="mi">1</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s1">' '</span><span class="p">)</span> <span class="k">else</span> <span class="s1">''</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">"# #{task.description}"</span> <span class="k">else</span> <span class="s1">''</span>
|
||||
<span class="nx">puts</span> <span class="s2">"cake #{name}#{spaces} #{desc}"</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">missingTask = </span><span class="p">(</span><span class="nx">task</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">puts</span> <span class="s2">"No such task: \"#task\""</span>
|
||||
<span class="nx">puts</span> <span class="s2">"No such task: \"#{task}\""</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>
|
||||
@@ -1,38 +1,37 @@
|
||||
<!DOCTYPE html> <html> <head> <title>coffee-script.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> coffee-script.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>CoffeeScript can be used both on the server, as a command-line compiler based
|
||||
<!DOCTYPE html> <html> <head> <title>coffee-script.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> coffee-script.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>CoffeeScript can be used both on the server, as a command-line compiler based
|
||||
on Node.js/V8, or to run CoffeeScripts directly in the browser. This module
|
||||
contains the main entry functions for tokenzing, parsing, and compiling source
|
||||
CoffeeScript into JavaScript.</p>
|
||||
|
||||
<p>If included on a webpage, it will automatically sniff out, compile, and
|
||||
execute all scripts present in <code>text/coffeescript</code> tags.</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 dependencies correctly for both the server and the browser.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nx">process</span><span class="o">?</span>
|
||||
<span class="nv">path = </span><span class="nx">require</span> <span class="s1">'path'</span>
|
||||
<span class="nv">Lexer = </span><span class="nx">require</span><span class="p">(</span><span class="s1">'./lexer'</span><span class="p">).</span><span class="nx">Lexer</span>
|
||||
<span class="nv">parser = </span><span class="nx">require</span><span class="p">(</span><span class="s1">'./parser'</span><span class="p">).</span><span class="nx">parser</span>
|
||||
<span class="nv">helpers = </span><span class="nx">require</span><span class="p">(</span><span class="s1">'./helpers'</span><span class="p">).</span><span class="nx">helpers</span>
|
||||
<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="nx">require</span> <span class="s1">'./nodes'</span>
|
||||
<span class="k">if</span> <span class="nx">require</span><span class="p">.</span><span class="nx">registerExtension</span>
|
||||
<span class="nx">require</span><span class="p">.</span><span class="nx">registerExtension</span> <span class="s1">'.coffee'</span><span class="p">,</span> <span class="p">(</span><span class="nx">content</span><span class="p">)</span> <span class="o">-></span> <span class="nx">compile</span> <span class="nx">content</span>
|
||||
<span class="k">else</span>
|
||||
<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">'0.9.0'</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Instantiate a Lexer for our use here.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lexer = </span><span class="k">new</span> <span class="nx">Lexer</span></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
|
||||
execute all scripts present in <code>text/coffeescript</code> tags.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">path = </span><span class="nx">require</span> <span class="s1">'path'</span>
|
||||
<span class="p">{</span><span class="nx">Lexer</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'./lexer'</span>
|
||||
<span class="p">{</span><span class="nx">parser</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'./parser'</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-2">#</a> </div> <p>TODO: Remove registerExtension when fully deprecated</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span>
|
||||
<span class="nv">fs = </span><span class="nx">require</span> <span class="s1">'fs'</span>
|
||||
<span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span><span class="p">[</span><span class="s1">'.coffee'</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="nx">module</span><span class="p">,</span> <span class="nx">filename</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">content = </span><span class="nx">compile</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span> <span class="nx">filename</span><span class="p">,</span> <span class="s1">'utf8'</span>
|
||||
<span class="nv">module.filename = </span><span class="s2">"#{filename} (compiled)"</span>
|
||||
<span class="nx">module</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">content</span><span class="p">,</span> <span class="nx">module</span><span class="p">.</span><span class="nx">filename</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">require</span><span class="p">.</span><span class="nx">registerExtension</span>
|
||||
<span class="nx">require</span><span class="p">.</span><span class="nx">registerExtension</span> <span class="s1">'.coffee'</span><span class="p">,</span> <span class="p">(</span><span class="nx">content</span><span class="p">)</span> <span class="o">-></span> <span class="nx">compile</span> <span class="nx">content</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>The current CoffeeScript version number.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.VERSION = </span><span class="s1">'0.9.4'</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
|
||||
compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.compile = compile = </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">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">"In #options.fileName, #err.message"</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">fileName</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">-></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
|
||||
<span class="nv">err.message = </span><span class="s2">"In #{options.fileName}, #{err.message}"</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">fileName</span>
|
||||
<span class="k">throw</span> <span class="nx">err</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</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">-></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-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</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
|
||||
<code>.traverse()</code> with a callback.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.nodes = </span><span class="p">(</span><span class="nx">code</span><span class="p">)</span> <span class="o">-></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></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">-></span>
|
||||
<span class="nv">module.filename = __filename = </span><span class="nx">options</span><span class="p">.</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="nx">__filename</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>The real Lexer produces a generic stream of tokens. This object provides a
|
||||
<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-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</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">-></span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>We want the root module.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">root = </span><span class="nx">module</span>
|
||||
<span class="k">while</span> <span class="nx">root</span><span class="p">.</span><span class="nx">parent</span>
|
||||
<span class="nv">root = </span><span class="nx">root</span><span class="p">.</span><span class="nx">parent</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Set the filename</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">root.filename = __filename = </span><span class="s2">"#{options.fileName} (compiled)"</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Clear the module cache</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">root.moduleCache = </span><span class="p">{}</span> <span class="k">if</span> <span class="nx">root</span><span class="p">.</span><span class="nx">moduleCache</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Compile</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">root</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">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="nx">root</span><span class="p">.</span><span class="nx">filename</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>Compile and evaluate a string of CoffeeScript (in a Node.js-like environment).
|
||||
The CoffeeScript REPL uses this to run the input.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.eval = </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">__filename = </span><span class="nx">options</span><span class="p">.</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="nx">__filename</span>
|
||||
<span class="nb">eval</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</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-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>Instantiate a Lexer for our use here.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lexer = </span><span class="k">new</span> <span class="nx">Lexer</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</a> </div> <p>The real Lexer produces a generic stream of tokens. This object provides a
|
||||
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="nx">lex</span><span class="o">:</span> <span class="o">-></span>
|
||||
@@ -44,16 +43,8 @@ directly as a "Jison lexer".</p> </td> <td class="code">
|
||||
<span class="nx">setInput</span><span class="o">:</span> <span class="p">(</span><span class="nx">tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="vi">@tokens = </span><span class="nx">tokens</span>
|
||||
<span class="vi">@pos = </span><span class="mi">0</span>
|
||||
<span class="nx">upcomingInput</span><span class="o">:</span> <span class="o">-></span> <span class="s2">""</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</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
|
||||
accessed from the browser, so only inline script tags will work.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nb">document</span><span class="o">?</span> <span class="o">and</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span>
|
||||
<span class="nv">processScripts = </span><span class="o">-></span>
|
||||
<span class="k">for</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="s1">'script'</span><span class="p">)</span> <span class="k">when</span> <span class="nx">tag</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s1">'text/coffeescript'</span>
|
||||
<span class="nb">eval</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">tag</span><span class="p">.</span><span class="nx">innerHTML</span>
|
||||
<span class="k">if</span> <span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span>
|
||||
<span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span> <span class="s1">'load'</span><span class="p">,</span> <span class="nx">processScripts</span><span class="p">,</span> <span class="kc">false</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nb">window</span><span class="p">.</span><span class="nx">attachEvent</span>
|
||||
<span class="nb">window</span><span class="p">.</span><span class="nx">attachEvent</span> <span class="s1">'onload'</span><span class="p">,</span> <span class="nx">processScripts</span>
|
||||
<span class="nx">upcomingInput</span><span class="o">:</span> <span class="o">-></span> <span class="s2">""</span>
|
||||
|
||||
<span class="nv">parser.yy = </span><span class="nx">require</span> <span class="s1">'./nodes'</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -1,59 +1,63 @@
|
||||
<!DOCTYPE html> <html> <head> <title>command.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> command.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>The <code>coffee</code> utility. Handles command-line compilation of CoffeeScript
|
||||
<!DOCTYPE html> <html> <head> <title>command.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> command.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>The <code>coffee</code> utility. Handles command-line compilation of CoffeeScript
|
||||
into various forms: saved into <code>.js</code> files or printed to stdout, piped to
|
||||
<a href="http://javascriptlint.com/">JSLint</a> or recompiled every time the source is
|
||||
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">'fs'</span>
|
||||
<span class="nv">path = </span><span class="nx">require</span> <span class="s1">'path'</span>
|
||||
<span class="nv">optparse = </span><span class="nx">require</span> <span class="s1">'./optparse'</span>
|
||||
<span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s1">'./coffee-script'</span>
|
||||
<span class="p">{</span><span class="nx">spawn</span><span class="p">,</span> <span class="nx">exec</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'child_process'</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">'''</span>
|
||||
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">'fs'</span>
|
||||
<span class="nv">path = </span><span class="nx">require</span> <span class="s1">'path'</span>
|
||||
<span class="nv">optparse = </span><span class="nx">require</span> <span class="s1">'./optparse'</span>
|
||||
<span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s1">'./coffee-script'</span>
|
||||
<span class="p">{</span><span class="nx">helpers</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'./helpers'</span>
|
||||
<span class="p">{</span><span class="nx">spawn</span><span class="p">,</span> <span class="nx">exec</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'child_process'</span>
|
||||
<span class="p">{</span><span class="nx">EventEmitter</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'events'</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>Allow CoffeeScript to emit Node.js events, and add it to global scope.</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">CoffeeScript</span><span class="p">,</span> <span class="k">new</span> <span class="nx">EventEmitter</span>
|
||||
<span class="nv">global.CoffeeScript = </span><span class="nx">CoffeeScript</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</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">'''</span>
|
||||
<span class="s1"> coffee compiles CoffeeScript source files into JavaScript.</span>
|
||||
|
||||
<span class="s1"> Usage:</span>
|
||||
<span class="s1"> coffee path/to/script.coffee</span>
|
||||
<span class="s1"> '''</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>The list of all the valid option flags that <code>coffee</code> knows how to handle.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">SWITCHES = </span><span class="p">[</span>
|
||||
<span class="p">[</span><span class="s1">'-c'</span><span class="p">,</span> <span class="s1">'--compile'</span><span class="p">,</span> <span class="s1">'compile to JavaScript and save as .js files'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-i'</span><span class="p">,</span> <span class="s1">'--interactive'</span><span class="p">,</span> <span class="s1">'run an interactive CoffeeScript REPL'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-o'</span><span class="p">,</span> <span class="s1">'--output [DIR]'</span><span class="p">,</span> <span class="s1">'set the directory for compiled JavaScript'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-w'</span><span class="p">,</span> <span class="s1">'--watch'</span><span class="p">,</span> <span class="s1">'watch scripts for changes, and recompile'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-p'</span><span class="p">,</span> <span class="s1">'--print'</span><span class="p">,</span> <span class="s1">'print the compiled JavaScript to stdout'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-l'</span><span class="p">,</span> <span class="s1">'--lint'</span><span class="p">,</span> <span class="s1">'pipe the compiled JavaScript through JSLint'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-s'</span><span class="p">,</span> <span class="s1">'--stdio'</span><span class="p">,</span> <span class="s1">'listen for and compile scripts over stdio'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-e'</span><span class="p">,</span> <span class="s1">'--eval'</span><span class="p">,</span> <span class="s1">'compile a string from the command line'</span><span class="p">]</span>
|
||||
<span class="p">[</span> <span class="s1">'--no-wrap'</span><span class="p">,</span> <span class="s1">'compile without the top-level function wrapper'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-t'</span><span class="p">,</span> <span class="s1">'--tokens'</span><span class="p">,</span> <span class="s1">'print the tokens that the lexer produces'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-n'</span><span class="p">,</span> <span class="s1">'--nodes'</span><span class="p">,</span> <span class="s1">'print the parse tree that Jison produces'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-v'</span><span class="p">,</span> <span class="s1">'--version'</span><span class="p">,</span> <span class="s1">'display CoffeeScript version'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-h'</span><span class="p">,</span> <span class="s1">'--help'</span><span class="p">,</span> <span class="s1">'display this help message'</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>Top-level objects shared by all the functions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">options = </span><span class="p">{}</span>
|
||||
<span class="s1"> '''</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 list of all the valid option flags that <code>coffee</code> knows how to handle.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">SWITCHES = </span><span class="p">[</span>
|
||||
<span class="p">[</span><span class="s1">'-c'</span><span class="p">,</span> <span class="s1">'--compile'</span><span class="p">,</span> <span class="s1">'compile to JavaScript and save as .js files'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-i'</span><span class="p">,</span> <span class="s1">'--interactive'</span><span class="p">,</span> <span class="s1">'run an interactive CoffeeScript REPL'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-o'</span><span class="p">,</span> <span class="s1">'--output [DIR]'</span><span class="p">,</span> <span class="s1">'set the directory for compiled JavaScript'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-w'</span><span class="p">,</span> <span class="s1">'--watch'</span><span class="p">,</span> <span class="s1">'watch scripts for changes, and recompile'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-p'</span><span class="p">,</span> <span class="s1">'--print'</span><span class="p">,</span> <span class="s1">'print the compiled JavaScript to stdout'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-l'</span><span class="p">,</span> <span class="s1">'--lint'</span><span class="p">,</span> <span class="s1">'pipe the compiled JavaScript through JSLint'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-s'</span><span class="p">,</span> <span class="s1">'--stdio'</span><span class="p">,</span> <span class="s1">'listen for and compile scripts over stdio'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-e'</span><span class="p">,</span> <span class="s1">'--eval'</span><span class="p">,</span> <span class="s1">'compile a string from the command line'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-r'</span><span class="p">,</span> <span class="s1">'--require [FILE*]'</span><span class="p">,</span> <span class="s1">'require a library before executing your script'</span><span class="p">]</span>
|
||||
<span class="p">[</span> <span class="s1">'--no-wrap'</span><span class="p">,</span> <span class="s1">'compile without the top-level function wrapper'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-t'</span><span class="p">,</span> <span class="s1">'--tokens'</span><span class="p">,</span> <span class="s1">'print the tokens that the lexer produces'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-n'</span><span class="p">,</span> <span class="s1">'--nodes'</span><span class="p">,</span> <span class="s1">'print the parse tree that Jison produces'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-v'</span><span class="p">,</span> <span class="s1">'--version'</span><span class="p">,</span> <span class="s1">'display CoffeeScript version'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-h'</span><span class="p">,</span> <span class="s1">'--help'</span><span class="p">,</span> <span class="s1">'display this help message'</span><span class="p">]</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>Top-level objects shared by all the functions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">opts = </span><span class="p">{}</span>
|
||||
<span class="nv">sources = </span><span class="p">[]</span>
|
||||
<span class="nv">optionParser = </span><span class="kc">null</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Run <code>coffee</code> by parsing passed options and determining what action to take.
|
||||
<span class="nv">optionParser = </span><span class="kc">null</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Run <code>coffee</code> by parsing passed options and determining what action to take.
|
||||
Many flags cause us to divert before compiling anything. Flags passed after
|
||||
<code>--</code> will be passed verbatim to your script as arguments in <code>process.argv</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run = </span><span class="o">-></span>
|
||||
<span class="nx">parseOptions</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="nx">usage</span><span class="p">()</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">help</span>
|
||||
<span class="k">return</span> <span class="nx">version</span><span class="p">()</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">version</span>
|
||||
<span class="k">return</span> <span class="nx">require</span> <span class="s1">'./repl'</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">interactive</span>
|
||||
<span class="k">return</span> <span class="nx">compileStdio</span><span class="p">()</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">stdio</span>
|
||||
<span class="k">return</span> <span class="nx">compileScript</span> <span class="s1">'console'</span><span class="p">,</span> <span class="nx">sources</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nb">eval</span>
|
||||
<span class="k">return</span> <span class="nx">usage</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">help</span>
|
||||
<span class="k">return</span> <span class="nx">version</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">version</span>
|
||||
<span class="k">return</span> <span class="nx">require</span> <span class="s1">'./repl'</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">interactive</span>
|
||||
<span class="k">return</span> <span class="nx">compileStdio</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">stdio</span>
|
||||
<span class="k">return</span> <span class="nx">compileScript</span> <span class="s1">'console'</span><span class="p">,</span> <span class="nx">sources</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nb">eval</span>
|
||||
<span class="k">return</span> <span class="nx">require</span> <span class="s1">'./repl'</span> <span class="nx">unless</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">separator = </span><span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span> <span class="s1">'--'</span>
|
||||
<span class="nv">flags = </span><span class="p">[]</span>
|
||||
<span class="k">if</span> <span class="nx">separator</span> <span class="o">>=</span> <span class="mi">0</span>
|
||||
<span class="nv">flags = </span><span class="nx">sources</span><span class="p">[(</span><span class="nx">separator</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)...</span><span class="nx">sources</span><span class="p">.</span><span class="nx">length</span><span class="p">]</span>
|
||||
<span class="nv">sources = </span><span class="nx">sources</span><span class="p">[</span><span class="mi">0</span><span class="p">...</span><span class="nx">separator</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">run</span>
|
||||
<span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">run</span>
|
||||
<span class="nv">flags = </span><span class="nx">sources</span><span class="p">[</span><span class="mi">1</span><span class="p">..</span><span class="nx">sources</span><span class="p">.</span><span class="nx">length</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">flags</span>
|
||||
<span class="nv">sources = </span><span class="p">[</span><span class="nx">sources</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span>
|
||||
<span class="nv">process.ARGV = process.argv = </span><span class="nx">flags</span>
|
||||
<span class="nx">compileScripts</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Asynchronously read in each CoffeeScript in a list of source files and
|
||||
<span class="nx">compileScripts</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>Asynchronously read in each CoffeeScript in a list of source files and
|
||||
compile them. If a directory is passed, recursively compile all
|
||||
'.coffee' extension source files in it and all subdirectories.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileScripts = </span><span class="o">-></span>
|
||||
<span class="k">for</span> <span class="nx">source</span> <span class="k">in</span> <span class="nx">sources</span>
|
||||
<span class="nv">base = </span><span class="nx">source</span>
|
||||
<span class="nv">compile = </span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">topLevel</span><span class="p">)</span> <span class="o">-></span>
|
||||
<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">-></span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"File not found: #source"</span> <span class="nx">unless</span> <span class="nx">exists</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"File not found: #{source}"</span> <span class="nx">unless</span> <span class="nx">exists</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">stat</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">stats</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">stats</span><span class="p">.</span><span class="nx">isDirectory</span><span class="p">()</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">readdir</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">files</span><span class="p">)</span> <span class="o">-></span>
|
||||
@@ -61,73 +65,84 @@ compile them. If a directory is passed, recursively compile all
|
||||
<span class="nx">compile</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">file</span><span class="p">)</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">topLevel</span> <span class="o">or</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'.coffee'</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">-></span> <span class="nx">compileScript</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">toString</span><span class="p">(),</span> <span class="nx">base</span><span class="p">)</span>
|
||||
<span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">watch</span>
|
||||
<span class="nx">compile</span> <span class="nx">source</span><span class="p">,</span> <span class="kc">true</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="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span>
|
||||
<span class="nx">compile</span> <span class="nx">source</span><span class="p">,</span> <span class="kc">true</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Compile a single source script, containing the given code, according to the
|
||||
requested options. 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">compileScript = </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">base</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">o = </span><span class="nx">options</span>
|
||||
<span class="nv">codeOpts = </span><span class="nx">compileOptions</span> <span class="nx">source</span>
|
||||
<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">compileScript = </span><span class="p">(</span><span class="nx">file</span><span class="p">,</span> <span class="nx">input</span><span class="p">,</span> <span class="nx">base</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">o = </span><span class="nx">opts</span>
|
||||
<span class="nv">options = </span><span class="nx">compileOptions</span> <span class="nx">file</span>
|
||||
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">require</span>
|
||||
<span class="nx">require</span><span class="p">(</span><span class="k">if</span> <span class="nx">helpers</span><span class="p">.</span><span class="nx">starts</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="s1">'.'</span><span class="p">)</span> <span class="k">then</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span><span class="p">(</span><span class="nx">req</span><span class="p">)</span> <span class="k">else</span> <span class="nx">req</span><span class="p">)</span> <span class="k">for</span> <span class="nx">req</span> <span class="k">in</span> <span class="nx">o</span><span class="p">.</span><span class="nx">require</span>
|
||||
<span class="k">try</span>
|
||||
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">tokens</span> <span class="k">then</span> <span class="nx">printTokens</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">tokens</span> <span class="nx">code</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">nodes</span> <span class="k">then</span> <span class="nx">puts</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">nodes</span><span class="p">(</span><span class="nx">code</span><span class="p">).</span><span class="nx">toString</span><span class="p">()</span>
|
||||
<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">codeOpts</span>
|
||||
<span class="nv">t = task = </span><span class="p">{</span><span class="nx">file</span><span class="p">,</span> <span class="nx">input</span><span class="p">,</span> <span class="nx">options</span><span class="p">}</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s1">'compile'</span><span class="p">,</span> <span class="nx">task</span>
|
||||
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">tokens</span> <span class="k">then</span> <span class="nx">printTokens</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">tokens</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">nodes</span> <span class="k">then</span> <span class="nx">puts</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">nodes</span><span class="p">(</span><span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">).</span><span class="nx">toString</span><span class="p">()</span>
|
||||
<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">t</span><span class="p">.</span><span class="nx">input</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">options</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">codeOpts</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">writeJs</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">js</span><span class="p">,</span> <span class="nx">base</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="nx">error</span><span class="p">(</span><span class="nx">err</span><span class="p">.</span><span class="nx">stack</span><span class="p">)</span> <span class="o">and</span> <span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">o</span><span class="p">.</span><span class="nx">watch</span>
|
||||
<span class="nx">puts</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</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>,
|
||||
<span class="nv">t.output = </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">options</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s1">'success'</span><span class="p">,</span> <span class="nx">task</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">t</span><span class="p">.</span><span class="nx">output</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">writeJs</span> <span class="nx">t</span><span class="p">.</span><span class="nx">file</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">output</span><span class="p">,</span> <span class="nx">base</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">t</span><span class="p">.</span><span class="nx">output</span>
|
||||
<span class="k">catch</span> <span class="nx">err</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Avoid using 'error' as it is a special event -- if there is no handler,
|
||||
node will print a stack trace and exit the program.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s1">'failure'</span><span class="p">,</span> <span class="nx">err</span><span class="p">,</span> <span class="nx">task</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">listeners</span><span class="p">(</span><span class="s1">'failure'</span><span class="p">).</span><span class="nx">length</span>
|
||||
<span class="k">return</span> <span class="nx">puts</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">watch</span>
|
||||
<span class="nx">error</span> <span class="nx">err</span><span class="p">.</span><span class="nx">stack</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>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">compileStdio = </span><span class="o">-></span>
|
||||
<span class="nv">code = </span><span class="s1">''</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="kc">on</span> <span class="s1">'data'</span><span class="p">,</span> <span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">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="kc">on</span> <span class="s1">'end'</span><span class="p">,</span> <span class="o">-></span>
|
||||
<span class="nx">compileScript</span> <span class="s1">'stdio'</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 source CoffeeScript file using <code>fs.watchFile</code>, recompiling it every
|
||||
<span class="nx">compileScript</span> <span class="s1">'stdio'</span><span class="p">,</span> <span class="nx">code</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>Watch a source CoffeeScript file using <code>fs.watchFile</code>, recompiling it every
|
||||
time the file is 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 = </span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">base</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">watchFile</span> <span class="nx">source</span><span class="p">,</span> <span class="p">{</span><span class="nx">persistent</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">interval</span><span class="o">:</span> <span class="mi">500</span><span class="p">},</span> <span class="p">(</span><span class="nx">curr</span><span class="p">,</span> <span class="nx">prev</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">curr</span><span class="p">.</span><span class="nx">mtime</span><span class="p">.</span><span class="nx">getTime</span><span class="p">()</span> <span class="o">is</span> <span class="nx">prev</span><span class="p">.</span><span class="nx">mtime</span><span class="p">.</span><span class="nx">getTime</span><span class="p">()</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">-></span> <span class="nx">compileScript</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">toString</span><span class="p">(),</span> <span class="nx">base</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>Write out a JavaScript source file with the compiled code. By default, files
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">curr</span><span class="p">.</span><span class="nx">size</span> <span class="o">is</span> <span class="nx">prev</span><span class="p">.</span><span class="nx">size</span> <span class="o">and</span> <span class="nx">curr</span><span class="p">.</span><span class="nx">mtime</span><span class="p">.</span><span class="nx">getTime</span><span class="p">()</span> <span class="o">is</span> <span class="nx">prev</span><span class="p">.</span><span class="nx">mtime</span><span class="p">.</span><span class="nx">getTime</span><span class="p">()</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">-></span>
|
||||
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
|
||||
<span class="nx">compileScript</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">toString</span><span class="p">(),</span> <span class="nx">base</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>Write out a JavaScript source file with the compiled code. By default, files
|
||||
are written out in <code>cwd</code> as <code>.js</code> files with the same name, but the output
|
||||
directory can be customized with <code>--output</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">writeJs = </span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">js</span><span class="p">,</span> <span class="nx">base</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">filename = </span><span class="nx">path</span><span class="p">.</span><span class="nx">basename</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">source</span><span class="p">))</span> <span class="o">+</span> <span class="s1">'.js'</span>
|
||||
<span class="nv">srcDir = </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">source</span>
|
||||
<span class="nv">baseDir = </span><span class="nx">srcDir</span><span class="p">.</span><span class="nx">substring</span> <span class="nx">base</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">dir = </span><span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">output</span> <span class="k">then</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">options</span><span class="p">.</span><span class="nx">output</span><span class="p">,</span> <span class="nx">baseDir</span> <span class="k">else</span> <span class="nx">srcDir</span>
|
||||
<span class="nv">dir = </span><span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">output</span> <span class="k">then</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">output</span><span class="p">,</span> <span class="nx">baseDir</span> <span class="k">else</span> <span class="nx">srcDir</span>
|
||||
<span class="nv">jsPath = </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="nv">compile = </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="nx">unless</span> <span class="nx">js</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">js = </span><span class="s1">' '</span> <span class="k">if</span> <span class="nx">js</span><span class="p">.</span><span class="nx">length</span> <span class="o"><=</span> <span class="mi">0</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">writeFile</span> <span class="nx">jsPath</span><span class="p">,</span> <span class="nx">js</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">puts</span> <span class="s2">"Compiled #source"</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">compile</span> <span class="o">and</span> <span class="nx">options</span><span class="p">.</span><span class="nx">watch</span>
|
||||
<span class="nx">puts</span> <span class="s2">"Compiled #{source}"</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">compile</span> <span class="o">and</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span>
|
||||
<span class="nx">path</span><span class="p">.</span><span class="nx">exists</span> <span class="nx">dir</span><span class="p">,</span> <span class="p">(</span><span class="nx">exists</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">exists</span> <span class="k">then</span> <span class="nx">compile</span><span class="p">()</span> <span class="k">else</span> <span class="nx">exec</span> <span class="s2">"mkdir -p #dir"</span><span class="p">,</span> <span class="nx">compile</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
|
||||
<span class="k">if</span> <span class="nx">exists</span> <span class="k">then</span> <span class="nx">compile</span><span class="p">()</span> <span class="k">else</span> <span class="nx">exec</span> <span class="s2">"mkdir -p #{dir}"</span><span class="p">,</span> <span class="nx">compile</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</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">-></span>
|
||||
<span class="nv">printIt = </span><span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-></span> <span class="nx">print</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">'jsl'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'-nologo'</span><span class="p">,</span> <span class="s1">'-stdin'</span><span class="p">]</span>
|
||||
<span class="nv">printIt = </span><span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-></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="nx">trim</span><span class="p">()</span>
|
||||
<span class="nv">conf = </span><span class="nx">__dirname</span> <span class="o">+</span> <span class="s1">'/../extras/jsl.conf'</span>
|
||||
<span class="nv">jsl = </span><span class="nx">spawn</span> <span class="s1">'jsl'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'-nologo'</span><span class="p">,</span> <span class="s1">'-stdin'</span><span class="p">,</span> <span class="s1">'-conf'</span><span class="p">,</span> <span class="nx">conf</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="kc">on</span> <span class="s1">'data'</span><span class="p">,</span> <span class="nx">printIt</span>
|
||||
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stderr</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'data'</span><span class="p">,</span> <span class="nx">printIt</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">printTokens = </span><span class="p">(</span><span class="nx">tokens</span><span class="p">)</span> <span class="o">-></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-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>Pretty-print a stream of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">printTokens = </span><span class="p">(</span><span class="nx">tokens</span><span class="p">)</span> <span class="o">-></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">'\\n'</span><span class="p">)]</span>
|
||||
<span class="s2">"[#tag #value]"</span>
|
||||
<span class="nx">puts</span> <span class="nx">strings</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s1">' '</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>Use the <a href="optparse.html">OptionParser module</a> to extract all options from
|
||||
<span class="s2">"[#{tag} #{value}]"</span>
|
||||
<span class="nx">puts</span> <span class="nx">strings</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s1">' '</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>Use the <a href="optparse.html">OptionParser module</a> to extract all options from
|
||||
<code>process.argv</code> that are specified in <code>SWITCHES</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">parseOptions = </span><span class="o">-></span>
|
||||
<span class="nv">optionParser = </span><span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">SWITCHES</span><span class="p">,</span> <span class="nx">BANNER</span>
|
||||
<span class="nv">o = options = </span><span class="nx">optionParser</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">...</span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">.</span><span class="nx">length</span><span class="p">])</span>
|
||||
<span class="nx">options</span><span class="p">.</span><span class="nx">compile</span> <span class="o">or=</span> <span class="o">!!</span><span class="nx">o</span><span class="p">.</span><span class="nx">output</span>
|
||||
<span class="nv">options.run = </span><span class="o">not</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">lint</span><span class="p">)</span>
|
||||
<span class="nv">options.print = </span><span class="o">!!</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nb">eval</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">stdio</span> <span class="o">and</span> <span class="nx">o</span><span class="p">.</span><span class="nx">compile</span><span class="p">))</span>
|
||||
<span class="nv">sources = </span><span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>The compile-time options to pass to the CoffeeScript compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileOptions = </span><span class="p">(</span><span class="nx">fileName</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">optionParser = </span><span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">SWITCHES</span><span class="p">,</span> <span class="nx">BANNER</span>
|
||||
<span class="nv">o = opts = </span><span class="nx">optionParser</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">...</span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">.</span><span class="nx">length</span><span class="p">])</span>
|
||||
<span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="o">or=</span> <span class="o">!!</span><span class="nx">o</span><span class="p">.</span><span class="nx">output</span>
|
||||
<span class="nv">o.run = </span><span class="o">not</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">lint</span><span class="p">)</span>
|
||||
<span class="nv">o.print = </span><span class="o">!!</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nb">eval</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">stdio</span> <span class="o">and</span> <span class="nx">o</span><span class="p">.</span><span class="nx">compile</span><span class="p">))</span>
|
||||
<span class="nv">sources = </span><span class="nx">o</span><span class="p">.</span><span class="nx">arguments</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>The compile-time options to pass to the CoffeeScript compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileOptions = </span><span class="p">(</span><span class="nx">fileName</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">o = </span><span class="p">{</span><span class="nx">fileName</span><span class="p">}</span>
|
||||
<span class="nv">o.noWrap = </span><span class="nx">options</span><span class="p">[</span><span class="s1">'no-wrap'</span><span class="p">]</span>
|
||||
<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">-></span>
|
||||
<span class="nv">o.noWrap = </span><span class="nx">opts</span><span class="p">[</span><span class="s1">'no-wrap'</span><span class="p">]</span>
|
||||
<span class="nx">o</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-18">#</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">-></span>
|
||||
<span class="nx">puts</span> <span class="nx">optionParser</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">-></span>
|
||||
<span class="nx">puts</span> <span class="s2">"CoffeeScript version #CoffeeScript.VERSION"</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-19"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-19">#</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">-></span>
|
||||
<span class="nx">puts</span> <span class="s2">"CoffeeScript version #{CoffeeScript.VERSION}"</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>
|
||||
@@ -26,7 +26,7 @@ h1, h2, h3, h4, h5, h6 {
|
||||
}
|
||||
#background {
|
||||
position: fixed;
|
||||
top: 0; left: 580px; right: 0; bottom: 0;
|
||||
top: 0; left: 575px; right: 0; bottom: 0;
|
||||
background: #f5f5ff;
|
||||
border-left: 1px solid #e5e5ee;
|
||||
z-index: -1;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html> <html> <head> <title>grammar.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> grammar.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>The CoffeeScript parser is generated by <a href="http://github.com/zaach/jison">Jison</a>
|
||||
<!DOCTYPE html> <html> <head> <title>grammar.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> grammar.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>The CoffeeScript parser is generated by <a href="http://github.com/zaach/jison">Jison</a>
|
||||
from this grammar file. Jison is a bottom-up parser generator, similar in
|
||||
style to <a href="http://www.gnu.org/software/bison">Bison</a>, implemented in JavaScript.
|
||||
It can recognize <a href="http://en.wikipedia.org/wiki/LR_grammar">LALR(1), LR(0), SLR(1), and LR(1)</a>
|
||||
@@ -20,8 +20,9 @@ we pass the pattern-defining string, the action to run, and extra options,
|
||||
optionally. If no action is specified, we simply pass the value of the
|
||||
previous nonterminal.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">o = </span><span class="p">(</span><span class="nx">patternString</span><span class="p">,</span> <span class="nx">action</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="p">[</span><span class="nx">patternString</span><span class="p">,</span> <span class="s1">'$$ = $1;'</span><span class="p">,</span> <span class="nx">options</span><span class="p">]</span> <span class="nx">unless</span> <span class="nx">action</span>
|
||||
<span class="nv">action = </span><span class="k">if</span> <span class="nv">match = </span><span class="p">(</span><span class="nx">action</span> <span class="o">+</span> <span class="s1">''</span><span class="p">).</span><span class="nx">match</span><span class="p">(</span><span class="nx">unwrap</span><span class="p">)</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="s2">"(#action())"</span>
|
||||
<span class="p">[</span><span class="nx">patternString</span><span class="p">,</span> <span class="s2">"$$ = #action;"</span><span class="p">,</span> <span class="nx">options</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> <h2>Grammatical Rules</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>In all of the rules that follow, you'll see the name of the nonterminal as
|
||||
<span class="nv">action = </span><span class="k">if</span> <span class="nv">match = </span><span class="p">(</span><span class="nx">action</span> <span class="o">+</span> <span class="s1">''</span><span class="p">).</span><span class="nx">match</span><span class="p">(</span><span class="nx">unwrap</span><span class="p">)</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="s2">"(#{action}())"</span>
|
||||
<span class="nv">action = </span><span class="nx">action</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\b(?:[A-Z][a-z]+Node|Expressions)\b/g</span><span class="p">,</span> <span class="s1">'yy.$&'</span>
|
||||
<span class="p">[</span><span class="nx">patternString</span><span class="p">,</span> <span class="s2">"$$ = #{action};"</span><span class="p">,</span> <span class="nx">options</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> <h2>Grammatical Rules</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>In all of the rules that follow, you'll see the name of the nonterminal as
|
||||
the key to a list of alternative matches. With each match's action, the
|
||||
dollar-sign variables are provided by Jison as references to the value of
|
||||
their numeric position, so in this rule:</p>
|
||||
@@ -49,6 +50,7 @@ all parsing must end here.</p> </td> <td class="code">
|
||||
<span class="nx">o</span> <span class="s2">"Throw"</span>
|
||||
<span class="nx">o</span> <span class="s2">"BREAK"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s2">"CONTINUE"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s2">"DEBUGGER"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">$1</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
|
||||
@@ -65,10 +67,9 @@ them somewhat circular.</p> </td> <td class="code">
|
||||
<span class="nx">o</span> <span class="s2">"Switch"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Extends"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Class"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Splat"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Existence"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Comment"</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>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>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="nx">Block</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"INDENT Body OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span>
|
||||
@@ -182,74 +183,86 @@ and optional references to the superclass.</p> </td> <td
|
||||
<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="nx">ClassAssign</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"AssignObj"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s2">"ThisProperty : Expression"</span><span class="p">,</span> <span class="o">-></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">'this'</span>
|
||||
<span class="nx">o</span> <span class="s2">"ThisProperty : INDENT Expression OUTDENT"</span><span class="p">,</span> <span class="o">-></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">$4</span><span class="p">,</span> <span class="s1">'this'</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="nx">ClassBody</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">""</span><span class="p">,</span> <span class="o">-></span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s2">"ClassAssign"</span><span class="p">,</span> <span class="o">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"ClassBody TERMINATOR ClassAssign"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"{ ClassBody }"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</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="nx">Call</span><span class="o">:</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 two flavors of function call: normal, and object instantiation with <code>new</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Call</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Invocation"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Super"</span>
|
||||
<span class="nx">o</span> <span class="s2">"NEW Invocation"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span><span class="p">.</span><span class="nx">newInstance</span><span class="p">()</span>
|
||||
<span class="nx">o</span> <span class="s2">"NEW Value"</span><span class="p">,</span> <span class="o">-></span> <span class="p">(</span><span class="k">new</span> <span class="nx">CallNode</span><span class="p">(</span><span class="nx">$2</span><span class="p">,</span> <span class="p">[])).</span><span class="nx">newInstance</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>Extending an object by setting its prototype chain to reference a parent
|
||||
object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Extends</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"SimpleAssignable EXTENDS Value"</span><span class="p">,</span> <span class="o">-></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-40"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-40">#</a> </div> <p>Ordinary function invocation, or a chained series of calls.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Invocation</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Value Arguments"</span><span class="p">,</span> <span class="o">-></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">"Invocation Arguments"</span><span class="p">,</span> <span class="o">-></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-41"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-41">#</a> </div> <p>The list of arguments to a function call.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Arguments</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"CALL_START ArgList OptComma CALL_END"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</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>Calling super.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Super</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Value OptFuncExist Arguments"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">CallNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"Invocation OptFuncExist Arguments"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">CallNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"SUPER"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">CallNode</span> <span class="s1">'super'</span><span class="p">,</span> <span class="p">[</span><span class="k">new</span> <span class="nx">SplatNode</span><span class="p">(</span><span class="k">new</span> <span class="nx">LiteralNode</span><span class="p">(</span><span class="s1">'arguments'</span><span class="p">))]</span>
|
||||
<span class="nx">o</span> <span class="s2">"SUPER Arguments"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">CallNode</span> <span class="s1">'super'</span><span class="p">,</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>An optional existence check on a function.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">OptFuncExist</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">""</span><span class="p">,</span> <span class="o">-></span> <span class="kc">no</span>
|
||||
<span class="nx">o</span> <span class="s2">"FUNC_EXIST"</span><span class="p">,</span> <span class="o">-></span> <span class="kc">yes</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="nx">Arguments</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"CALL_START CALL_END"</span><span class="p">,</span> <span class="o">-></span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s2">"CALL_START ArgList OptComma CALL_END"</span><span class="p">,</span> <span class="o">-></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>A reference to the <em>this</em> current object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">This</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"THIS"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="s1">'this'</span>
|
||||
<span class="nx">o</span> <span class="s2">"@"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="s1">'this'</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nx">RangeDots</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">". ."</span><span class="p">,</span> <span class="o">-></span> <span class="s1">'inclusive'</span>
|
||||
<span class="nx">o</span> <span class="s2">". . ."</span><span class="p">,</span> <span class="o">-></span> <span class="s1">'exclusive'</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 a property on <em>this</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ThisProperty</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"@ Identifier"</span><span class="p">,</span> <span class="o">-></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">'this'</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-45"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-45">#</a> </div> <p>The CoffeeScript range literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Range</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"[ Expression . . Expression ]"</span><span class="p">,</span> <span class="o">-></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">"[ Expression . . . Expression ]"</span><span class="p">,</span> <span class="o">-></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="nx">o</span> <span class="s2">"[ Expression RangeDots Expression ]"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">RangeNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$3</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 slice literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Slice</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"INDEX_START Expression . . Expression INDEX_END"</span><span class="p">,</span> <span class="o">-></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">"INDEX_START Expression . . . Expression INDEX_END"</span><span class="p">,</span> <span class="o">-></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="nx">o</span> <span class="s2">"INDEX_START Expression RangeDots Expression INDEX_END"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">RangeNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"INDEX_START Expression RangeDots INDEX_END"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">RangeNode</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">"INDEX_START RangeDots Expression INDEX_END"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">RangeNode</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</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>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">"[ ]"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ArrayNode</span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s2">"[ ArgList OptComma ]"</span><span class="p">,</span> <span class="o">-></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-48"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-48">#</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="nx">ArgList</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">""</span><span class="p">,</span> <span class="o">-></span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"ArgList , Expression"</span><span class="p">,</span> <span class="o">-></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">"ArgList OptComma TERMINATOR Expression"</span><span class="p">,</span> <span class="o">-></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">"Arg"</span><span class="p">,</span> <span class="o">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"ArgList , Arg"</span><span class="p">,</span> <span class="o">-></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">"ArgList OptComma TERMINATOR Arg"</span><span class="p">,</span> <span class="o">-></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">"INDENT ArgList OptComma OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"ArgList OptComma INDENT ArgList OptComma OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</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>Just simple, comma-separated, required arguments (no fancy syntax). We need
|
||||
<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>Valid arguments are Expressions or Splats.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Arg</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Splat"</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="nx">SimpleArgs</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression"</span>
|
||||
<span class="nx">o</span> <span class="s2">"SimpleArgs , Expression"</span><span class="p">,</span> <span class="o">-></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-50"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-50">#</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="nx">Try</span><span class="o">:</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="nx">Try</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"TRY Block Catch"</span><span class="p">,</span> <span class="o">-></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">"TRY Block FINALLY Block"</span><span class="p">,</span> <span class="o">-></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">"TRY Block Catch FINALLY Block"</span><span class="p">,</span> <span class="o">-></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-51"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-51">#</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="nx">Catch</span><span class="o">:</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="nx">Catch</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"CATCH Identifier Block"</span><span class="p">,</span> <span class="o">-></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-52"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-52">#</a> </div> <p>Throw an exception object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Throw</span><span class="o">:</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="nx">Throw</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"THROW Expression"</span><span class="p">,</span> <span class="o">-></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-53"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-53">#</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="nx">Parenthetical</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"( Line )"</span><span class="p">,</span> <span class="o">-></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-54"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-54">#</a> </div> <p>The condition portion of a while loop.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">WhileSource</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"( )"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ParentheticalNode</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="s1">''</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>The condition portion of a while loop.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">WhileSource</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"WHILE Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">WhileNode</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"WHILE Expression WHEN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">WhileNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s2">"UNTIL Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">WhileNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">invert</span><span class="o">:</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s2">"UNTIL Expression WHEN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">WhileNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">invert</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$4</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>The while loop can either be normal, with a block of expressions to execute,
|
||||
<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 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="nx">While</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"WhileSource Block"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">addBody</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"Statement WhileSource"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span><span class="p">.</span><span class="nx">addBody</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>
|
||||
@@ -260,7 +273,7 @@ or postfix, with a single expression. There is no do..while.</p> </t
|
||||
<span class="nx">Loop</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"LOOP Block"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">WhileNode</span><span class="p">(</span><span class="k">new</span> <span class="nx">LiteralNode</span> <span class="s1">'true'</span><span class="p">).</span><span class="nx">addBody</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"LOOP Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">WhileNode</span><span class="p">(</span><span class="k">new</span> <span class="nx">LiteralNode</span> <span class="s1">'true'</span><span class="p">).</span><span class="nx">addBody</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-56"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-56">#</a> </div> <p>Array, object, and range comprehensions, at the most generic level.
|
||||
<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>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="nx">For</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Statement ForBody"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ForNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$2</span><span class="p">.</span><span class="nx">vars</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="nx">vars</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
@@ -276,17 +289,17 @@ or postfix, with a single expression.</p> </td> <td clas
|
||||
<span class="nx">ForStart</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"FOR ForVariables"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"FOR ALL ForVariables"</span><span class="p">,</span> <span class="o">-></span> <span class="nv">$3.raw = </span><span class="kc">true</span><span class="p">;</span> <span class="nx">$3</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 array of all accepted values for a variable inside the loop. This
|
||||
<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 array of all accepted values for a variable inside the loop. This
|
||||
enables support for pattern matching.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ForValue</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Identifier"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Array"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s2">"Object"</span><span class="p">,</span> <span class="o">-></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-58"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-58">#</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="nx">ForVariables</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"ForValue"</span><span class="p">,</span> <span class="o">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"ForValue , ForValue"</span><span class="p">,</span> <span class="o">-></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-59"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-59">#</a> </div> <p>The source of a comprehension is an array or object with an optional guard
|
||||
<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 guard
|
||||
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="nx">ForSource</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"IN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span>
|
||||
@@ -296,92 +309,70 @@ in fixed-size increments.</p> </td> <td class="code">
|
||||
<span class="nx">o</span> <span class="s2">"IN Expression BY Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">step</span><span class="o">:</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s2">"IN Expression WHEN Expression BY Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">step</span><span class="o">:</span> <span class="nx">$6</span>
|
||||
<span class="nx">o</span> <span class="s2">"IN Expression BY Expression WHEN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">step</span><span class="o">:</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$6</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>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="nx">Switch</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"SWITCH Expression INDENT Whens OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$4</span><span class="p">.</span><span class="nx">switchesOver</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"SWITCH Expression INDENT Whens ELSE Block OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$4</span><span class="p">.</span><span class="nx">switchesOver</span><span class="p">(</span><span class="nx">$2</span><span class="p">).</span><span class="nx">addElse</span> <span class="nx">$6</span><span class="p">,</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s2">"SWITCH INDENT Whens OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"SWITCH INDENT Whens ELSE Block OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$3</span><span class="p">.</span><span class="nx">addElse</span> <span class="nx">$5</span><span class="p">,</span> <span class="kc">true</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 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="nx">Whens</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nx">Switch</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"SWITCH Expression INDENT Whens OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">SwitchNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s2">"SWITCH Expression INDENT Whens ELSE Block OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">SwitchNode</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="nx">o</span> <span class="s2">"SWITCH INDENT Whens OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">SwitchNode</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"SWITCH INDENT Whens ELSE Block OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">SwitchNode</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$5</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nx">Whens</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"When"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Whens When"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">addElse</span> <span class="nx">$2</span>
|
||||
<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>An individual <strong>When</strong> clause, with action.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">When</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"LEADING_WHEN SimpleArgs Block"</span><span class="p">,</span> <span class="o">-></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="nx">statement</span><span class="o">:</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s2">"LEADING_WHEN SimpleArgs Block TERMINATOR"</span><span class="p">,</span> <span class="o">-></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="nx">statement</span><span class="o">:</span> <span class="kc">true</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>The most basic form of <em>if</em> is a condition and an action. The following
|
||||
<span class="nx">o</span> <span class="s2">"Whens When"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$2</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>An individual <strong>When</strong> clause, with action.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">When</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"LEADING_WHEN SimpleArgs Block"</span><span class="p">,</span> <span class="o">-></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="nx">o</span> <span class="s2">"LEADING_WHEN SimpleArgs Block TERMINATOR"</span><span class="p">,</span> <span class="o">-></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-62"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-62">#</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="nx">IfBlock</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"IF Expression Block"</span><span class="p">,</span> <span class="o">-></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">"UNLESS Expression Block"</span><span class="p">,</span> <span class="o">-></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="nx">invert</span><span class="o">:</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s2">"IfBlock ELSE IF Expression Block"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">addElse</span> <span class="p">(</span><span class="k">new</span> <span class="nx">IfNode</span><span class="p">(</span><span class="nx">$4</span><span class="p">,</span> <span class="nx">$5</span><span class="p">)).</span><span class="nx">forceStatement</span><span class="p">()</span>
|
||||
<span class="nx">o</span> <span class="s2">"IfBlock ELSE Block"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">addElse</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 full complement of <em>if</em> expressions, including postfix one-liner
|
||||
<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>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="nx">If</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"IfBlock"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Statement IF Expression"</span><span class="p">,</span> <span class="o">-></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="nx">statement</span><span class="o">:</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression IF Expression"</span><span class="p">,</span> <span class="o">-></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="nx">statement</span><span class="o">:</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s2">"Statement UNLESS Expression"</span><span class="p">,</span> <span class="o">-></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="nx">statement</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">invert</span><span class="o">:</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression UNLESS Expression"</span><span class="p">,</span> <span class="o">-></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="nx">statement</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">invert</span><span class="o">:</span> <span class="kc">true</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>Arithmetic and logical operators, working on one or more operands.
|
||||
<span class="nx">o</span> <span class="s2">"Statement POST_IF Expression"</span><span class="p">,</span> <span class="o">-></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="nx">statement</span><span class="o">:</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression POST_IF Expression"</span><span class="p">,</span> <span class="o">-></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="nx">statement</span><span class="o">:</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s2">"Statement POST_UNLESS Expression"</span><span class="p">,</span> <span class="o">-></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="nx">statement</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">invert</span><span class="o">:</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression POST_UNLESS Expression"</span><span class="p">,</span> <span class="o">-></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="nx">statement</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">invert</span><span class="o">:</span> <span class="kc">true</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>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>
|
||||
-type rule, but in order to make the precedence binding possible, separate
|
||||
rules are necessary.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Operation</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"! Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'!'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"!! Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'!!'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span><span class="p">(</span><span class="s2">"- Expression"</span><span class="p">,</span> <span class="p">(</span><span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span><span class="p">(</span><span class="s1">'-'</span><span class="p">,</span> <span class="nx">$2</span><span class="p">)),</span> <span class="p">{</span><span class="nx">prec</span><span class="o">:</span> <span class="s1">'UMINUS'</span><span class="p">})</span>
|
||||
<span class="nx">o</span><span class="p">(</span><span class="s2">"+ Expression"</span><span class="p">,</span> <span class="p">(</span><span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span><span class="p">(</span><span class="s1">'+'</span><span class="p">,</span> <span class="nx">$2</span><span class="p">)),</span> <span class="p">{</span><span class="nx">prec</span><span class="o">:</span> <span class="s1">'UPLUS'</span><span class="p">})</span>
|
||||
<span class="nx">o</span> <span class="s2">"~ Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'~'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"UNARY Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span><span class="p">(</span><span class="s2">"- Expression"</span><span class="p">,</span> <span class="p">(</span><span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span><span class="p">(</span><span class="s1">'-'</span><span class="p">,</span> <span class="nx">$2</span><span class="p">)),</span> <span class="p">{</span><span class="nx">prec</span><span class="o">:</span> <span class="s1">'UNARY'</span><span class="p">})</span>
|
||||
<span class="nx">o</span><span class="p">(</span><span class="s2">"+ Expression"</span><span class="p">,</span> <span class="p">(</span><span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span><span class="p">(</span><span class="s1">'+'</span><span class="p">,</span> <span class="nx">$2</span><span class="p">)),</span> <span class="p">{</span><span class="nx">prec</span><span class="o">:</span> <span class="s1">'UNARY'</span><span class="p">})</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s2">"-- Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'--'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"++ Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'++'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"DELETE Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'delete'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"TYPEOF Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'typeof'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression --"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'--'</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="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression ++"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'++'</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="kc">true</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s2">"Expression * Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'*'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression / Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'/'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression % Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'%'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s2">"Expression ? Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'?'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression + Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'+'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression - Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'-'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s2">"Expression << Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'<<'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression >> Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'>>'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression >>> Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'>>>'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression & Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'&'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression | Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'|'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression ^ Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'^'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s2">"Expression <= Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'<='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression < Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'<'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression > Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'>'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression >= Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'>='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s2">"Expression == Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'=='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression != Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'!='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s2">"Expression && Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'&&'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression || Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'||'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression OP? Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'?'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression MATH Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression SHIFT Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression COMPARE Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression LOGIC Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Value COMPOUND_ASSIGN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Value COMPOUND_ASSIGN INDENT Expression OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s2">"Expression -= Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'-='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression += Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'+='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression /= Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'/='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression *= Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'*='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression %= Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'%='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression ||= Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'||='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression &&= Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'&&='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression ?= Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'?='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s2">"Expression INSTANCEOF Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'instanceof'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression IN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">InNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression OF Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'in'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression ! IN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'!'</span><span class="p">,</span> <span class="k">new</span> <span class="nx">InNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression ! OF Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'!'</span><span class="p">,</span> <span class="k">new</span> <span class="nx">ParentheticalNode</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'in'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</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> <h2>Precedence</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-67"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-67">#</a> </div> <p>Operators at the top of this list have higher precedence than the ones lower
|
||||
<span class="nx">o</span> <span class="s2">"Expression INSTANCEOF Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'instanceof'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression UNARY IN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="k">new</span> <span class="nx">InNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression UNARY OF Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="k">new</span> <span class="nx">ParentheticalNode</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'in'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression UNARY INSTANCEOF Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="k">new</span> <span class="nx">ParentheticalNode</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'instanceof'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</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> <h2>Precedence</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-66"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-66">#</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)
|
||||
@@ -391,26 +382,25 @@ down. Following these rules is what makes <code>2 + 3 * 4</code> parse as:</p>
|
||||
|
||||
<pre><code>(2 + 3) * 4
|
||||
</code></pre> </td> <td class="code"> <div class="highlight"><pre><span class="nv">operators = </span><span class="p">[</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'?'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"nonassoc"</span><span class="p">,</span> <span class="s1">'UMINUS'</span><span class="p">,</span> <span class="s1">'UPLUS'</span><span class="p">,</span> <span class="s1">'!'</span><span class="p">,</span> <span class="s1">'!!'</span><span class="p">,</span> <span class="s1">'~'</span><span class="p">,</span> <span class="s1">'++'</span><span class="p">,</span> <span class="s1">'--'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'*'</span><span class="p">,</span> <span class="s1">'/'</span><span class="p">,</span> <span class="s1">'%'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"right"</span><span class="p">,</span> <span class="s1">'?'</span><span class="p">,</span> <span class="s1">'NEW'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'CALL_START'</span><span class="p">,</span> <span class="s1">'CALL_END'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"nonassoc"</span><span class="p">,</span> <span class="s1">'++'</span><span class="p">,</span> <span class="s1">'--'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"right"</span><span class="p">,</span> <span class="s1">'UNARY'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'MATH'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'+'</span><span class="p">,</span> <span class="s1">'-'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'<<'</span><span class="p">,</span> <span class="s1">'>>'</span><span class="p">,</span> <span class="s1">'>>>'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'&'</span><span class="p">,</span> <span class="s1">'|'</span><span class="p">,</span> <span class="s1">'^'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'<='</span><span class="p">,</span> <span class="s1">'<'</span><span class="p">,</span> <span class="s1">'>'</span><span class="p">,</span> <span class="s1">'>='</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"right"</span><span class="p">,</span> <span class="s1">'DELETE'</span><span class="p">,</span> <span class="s1">'INSTANCEOF'</span><span class="p">,</span> <span class="s1">'TYPEOF'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'SHIFT'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'COMPARE'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'INSTANCEOF'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'=='</span><span class="p">,</span> <span class="s1">'!='</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'&&'</span><span class="p">,</span> <span class="s1">'||'</span><span class="p">,</span> <span class="s1">'OP?'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"right"</span><span class="p">,</span> <span class="s1">'-='</span><span class="p">,</span> <span class="s1">'+='</span><span class="p">,</span> <span class="s1">'/='</span><span class="p">,</span> <span class="s1">'*='</span><span class="p">,</span> <span class="s1">'%='</span><span class="p">,</span> <span class="s1">'||='</span><span class="p">,</span> <span class="s1">'&&='</span><span class="p">,</span> <span class="s1">'?='</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'LOGIC'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"right"</span><span class="p">,</span> <span class="s1">'COMPOUND_ASSIGN'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'.'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"right"</span><span class="p">,</span> <span class="s1">'INDENT'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"nonassoc"</span><span class="p">,</span> <span class="s1">'INDENT'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"right"</span><span class="p">,</span> <span class="s1">'WHEN'</span><span class="p">,</span> <span class="s1">'LEADING_WHEN'</span><span class="p">,</span> <span class="s1">'IN'</span><span class="p">,</span> <span class="s1">'OF'</span><span class="p">,</span> <span class="s1">'BY'</span><span class="p">,</span> <span class="s1">'THROW'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"right"</span><span class="p">,</span> <span class="s1">'FOR'</span><span class="p">,</span> <span class="s1">'WHILE'</span><span class="p">,</span> <span class="s1">'UNTIL'</span><span class="p">,</span> <span class="s1">'LOOP'</span><span class="p">,</span> <span class="s1">'NEW'</span><span class="p">,</span> <span class="s1">'SUPER'</span><span class="p">,</span> <span class="s1">'CLASS'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'EXTENDS'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"right"</span><span class="p">,</span> <span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'UNLESS'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">,</span> <span class="s1">'FOR'</span><span class="p">,</span> <span class="s1">'WHILE'</span><span class="p">,</span> <span class="s1">'UNTIL'</span><span class="p">,</span> <span class="s1">'LOOP'</span><span class="p">,</span> <span class="s1">'SUPER'</span><span class="p">,</span> <span class="s1">'CLASS'</span><span class="p">,</span> <span class="s1">'EXTENDS'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"right"</span><span class="p">,</span> <span class="s1">'='</span><span class="p">,</span> <span class="s1">':'</span><span class="p">,</span> <span class="s1">'RETURN'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"right"</span><span class="p">,</span> <span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">,</span> <span class="s1">'UNLESS'</span><span class="p">,</span> <span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">]</span>
|
||||
<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> <h2>Wrapping Up</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-69"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-69">#</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">"right"</span><span class="p">,</span> <span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">,</span> <span class="s1">'UNLESS'</span><span class="p">,</span> <span class="s1">'POST_IF'</span><span class="p">,</span> <span class="s1">'POST_UNLESS'</span><span class="p">]</span>
|
||||
<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> <h2>Wrapping Up</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-68"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-68">#</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>
|
||||
@@ -419,14 +409,13 @@ as "tokens".</p> </td> <td class="code"> <
|
||||
<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">' '</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">"return #{alt[1]}"</span> <span class="k">if</span> <span class="nx">name</span> <span class="o">is</span> <span class="s1">'Root'</span>
|
||||
<span class="nx">alt</span></pre></div> </td> </tr> <tr id="section-70"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-70">#</a> </div> <p>Initialize the <strong>Parser</strong> with our list of terminal <strong>tokens</strong>, our <strong>grammar</strong>
|
||||
<span class="nx">alt</span></pre></div> </td> </tr> <tr id="section-69"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-69">#</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>
|
||||
(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="nx">tokens</span><span class="o">:</span> <span class="nx">tokens</span><span class="p">.</span><span class="nx">join</span> <span class="s1">' '</span>
|
||||
<span class="nx">bnf</span><span class="o">:</span> <span class="nx">grammar</span>
|
||||
<span class="nx">operators</span><span class="o">:</span> <span class="nx">operators</span><span class="p">.</span><span class="nx">reverse</span><span class="p">()</span>
|
||||
<span class="nx">startSymbol</span><span class="o">:</span> <span class="s1">'Root'</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -1,35 +1,34 @@
|
||||
<!DOCTYPE html> <html> <head> <title>helpers.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> helpers.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>This file contains the common helper functions that we'd like to share among
|
||||
<!DOCTYPE html> <html> <head> <title>helpers.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> helpers.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>This file contains the common helper functions that we'd like to share among
|
||||
the <strong>Lexer</strong>, <strong>Rewriter</strong>, and the <strong>Nodes</strong>. Merge objects, flatten
|
||||
arrays, count characters, that sort of thing.</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">helpers = exports.helpers = </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>Cross-browser indexOf, so that IE can join the party.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.indexOf = indexOf = </span><span class="p">(</span><span class="nx">array</span><span class="p">,</span> <span class="nx">item</span><span class="p">,</span> <span class="nx">from</span><span class="p">)</span> <span class="o">-></span>
|
||||
arrays, count characters, that sort of thing.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers = exports.helpers = </span><span class="p">{}</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-2">#</a> </div> <p>Cross-browser indexOf, so that IE can join the party.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.indexOf = indexOf = </span><span class="p">(</span><span class="nx">array</span><span class="p">,</span> <span class="nx">item</span><span class="p">,</span> <span class="nx">from</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="nx">array</span><span class="p">.</span><span class="nx">indexOf</span> <span class="nx">item</span><span class="p">,</span> <span class="nx">from</span> <span class="k">if</span> <span class="nx">array</span><span class="p">.</span><span class="nx">indexOf</span>
|
||||
<span class="k">for</span> <span class="nx">other</span><span class="p">,</span> <span class="nx">index</span> <span class="k">in</span> <span class="nx">array</span>
|
||||
<span class="k">if</span> <span class="nx">other</span> <span class="o">is</span> <span class="nx">item</span> <span class="o">and</span> <span class="p">(</span><span class="o">not</span> <span class="nx">from</span> <span class="o">or</span> <span class="p">(</span><span class="nx">from</span> <span class="o"><=</span> <span class="nx">index</span><span class="p">))</span>
|
||||
<span class="k">return</span> <span class="nx">index</span>
|
||||
<span class="o">-</span><span class="mi">1</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Does a list include a value?</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.include = include = </span><span class="p">(</span><span class="nx">list</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">indexOf</span><span class="p">(</span><span class="nx">list</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Peek at the beginning of a given string to see if it matches a sequence.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.starts = starts = </span><span class="p">(</span><span class="nx">string</span><span class="p">,</span> <span class="nx">literal</span><span class="p">,</span> <span class="nx">start</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">string</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span> <span class="p">(</span><span class="nx">start</span> <span class="o">or</span> <span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="nx">literal</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="o">is</span> <span class="nx">literal</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Peek at the end of a given string to see if it matches a sequence.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.ends = ends = </span><span class="p">(</span><span class="nx">string</span><span class="p">,</span> <span class="nx">literal</span><span class="p">,</span> <span class="nx">back</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="o">-</span><span class="mi">1</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>Does a list include a value?</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.include = include = </span><span class="p">(</span><span class="nx">list</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">indexOf</span><span class="p">(</span><span class="nx">list</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Peek at the beginning of a given string to see if it matches a sequence.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.starts = starts = </span><span class="p">(</span><span class="nx">string</span><span class="p">,</span> <span class="nx">literal</span><span class="p">,</span> <span class="nx">start</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">string</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span> <span class="p">(</span><span class="nx">start</span> <span class="o">or</span> <span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="nx">literal</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="o">is</span> <span class="nx">literal</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Peek at the end of a given string to see if it matches a sequence.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.ends = ends = </span><span class="p">(</span><span class="nx">string</span><span class="p">,</span> <span class="nx">literal</span><span class="p">,</span> <span class="nx">back</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">start = </span><span class="nx">string</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="nx">literal</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="p">(</span><span class="nx">back</span> <span class="o">?</span> <span class="mi">0</span><span class="p">)</span>
|
||||
<span class="nx">string</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span> <span class="nx">start</span> <span class="o">+</span> <span class="nx">literal</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="o">is</span> <span class="nx">literal</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Trim out all falsy values from an array.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.compact = compact = </span><span class="p">(</span><span class="nx">array</span><span class="p">)</span> <span class="o">-></span> <span class="nx">item</span> <span class="k">for</span> <span class="nx">item</span> <span class="k">in</span> <span class="nx">array</span> <span class="k">when</span> <span class="nx">item</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Count the number of occurences of a character in a string.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.count = count = </span><span class="p">(</span><span class="nx">string</span><span class="p">,</span> <span class="nx">letter</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">string</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span> <span class="nx">start</span> <span class="o">+</span> <span class="nx">literal</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="o">is</span> <span class="nx">literal</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Trim out all falsy values from an array.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.compact = compact = </span><span class="p">(</span><span class="nx">array</span><span class="p">)</span> <span class="o">-></span> <span class="nx">item</span> <span class="k">for</span> <span class="nx">item</span> <span class="k">in</span> <span class="nx">array</span> <span class="k">when</span> <span class="nx">item</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Count the number of occurences of a character in a string.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.count = count = </span><span class="p">(</span><span class="nx">string</span><span class="p">,</span> <span class="nx">letter</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">num = </span><span class="mi">0</span>
|
||||
<span class="nv">pos = </span><span class="nx">indexOf</span> <span class="nx">string</span><span class="p">,</span> <span class="nx">letter</span>
|
||||
<span class="k">while</span> <span class="nx">pos</span> <span class="o">isnt</span> <span class="o">-</span><span class="mi">1</span>
|
||||
<span class="nx">num</span> <span class="o">+=</span> <span class="mi">1</span>
|
||||
<span class="nv">pos = </span><span class="nx">indexOf</span> <span class="nx">string</span><span class="p">,</span> <span class="nx">letter</span><span class="p">,</span> <span class="nx">pos</span> <span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="nx">num</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Merge objects, returning a fresh copy with attributes from both sides.
|
||||
<span class="nx">num</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Merge objects, returning a fresh copy with attributes from both sides.
|
||||
Used every time <code>BaseNode#compile</code> is called, to allow properties in the
|
||||
options hash to propagate down the tree without polluting other branches.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.merge = merge = </span><span class="p">(</span><span class="nx">options</span><span class="p">,</span> <span class="nx">overrides</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">fresh = </span><span class="p">{}</span>
|
||||
<span class="p">(</span><span class="nx">fresh</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">val</span><span class="p">)</span> <span class="k">for</span> <span class="nx">all</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">options</span>
|
||||
<span class="p">(</span><span class="nx">fresh</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">val</span><span class="p">)</span> <span class="k">for</span> <span class="nx">all</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">overrides</span> <span class="k">if</span> <span class="nx">overrides</span>
|
||||
<span class="nx">fresh</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Extend a source object with the properties of another object (shallow copy).
|
||||
<span class="nx">fresh</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 a source object with the properties of another object (shallow copy).
|
||||
We use this to simulate Node's deprecated <code>process.mixin</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.extend = extend = </span><span class="p">(</span><span class="nx">object</span><span class="p">,</span> <span class="nx">properties</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="p">(</span><span class="nx">object</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">val</span><span class="p">)</span> <span class="k">for</span> <span class="nx">all</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">properties</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 a completely flattened version of an array. Handy for getting a
|
||||
<span class="p">(</span><span class="nx">object</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">val</span><span class="p">)</span> <span class="k">for</span> <span class="nx">all</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">properties</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Return a completely flattened version of an array. Handy for getting a
|
||||
list of <code>children</code> from the nodes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.flatten = flatten = </span><span class="p">(</span><span class="nx">array</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">memo = </span><span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="nx">item</span> <span class="k">in</span> <span class="nx">array</span>
|
||||
<span class="k">if</span> <span class="nx">item</span> <span class="k">instanceof</span> <span class="nb">Array</span> <span class="k">then</span> <span class="nv">memo = </span><span class="nx">memo</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">item</span><span class="p">)</span> <span class="k">else</span> <span class="nx">memo</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">item</span><span class="p">)</span>
|
||||
<span class="nx">memo</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>Delete a key from an object, returning the value. Useful when a node is
|
||||
<span class="nx">memo</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Delete a key from an object, returning the value. Useful when a node is
|
||||
looking for a particular method in an options hash.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.del = del = </span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">key</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">val = </span><span class="nx">obj</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span>
|
||||
<span class="k">delete</span> <span class="nx">obj</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<!DOCTYPE html> <html> <head> <title>index.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> index.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>Loader for CoffeeScript as a Node.js library.</p> </td> <td class="code"> <div class="highlight"><pre><span class="p">(</span><span class="nx">exports</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">val</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">require</span> <span class="s1">'./coffee-script'</span>
|
||||
<!DOCTYPE html> <html> <head> <title>index.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> index.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>Loader for CoffeeScript as a Node.js library.</p> </td> <td class="code"> <div class="highlight"><pre><span class="p">(</span><span class="nx">exports</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">val</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">require</span> <span class="s1">'./coffee-script'</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html> <html> <head> <title>optparse.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> optparse.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>A simple <strong>OptionParser</strong> class to parse option flags from the command-line.
|
||||
<!DOCTYPE html> <html> <head> <title>optparse.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> optparse.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>A simple <strong>OptionParser</strong> class to parse option flags from the command-line.
|
||||
Use it like so:</p>
|
||||
|
||||
<pre><code>parser = new OptionParser switches, helpBanner
|
||||
@@ -25,39 +25,42 @@ flag. Instead, you're responsible for interpreting the options object.</p>
|
||||
<span class="nv">matchedRule = </span><span class="kc">no</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">shortFlag</span> <span class="o">is</span> <span class="nx">arg</span> <span class="o">or</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">longFlag</span> <span class="o">is</span> <span class="nx">arg</span>
|
||||
<span class="nx">options</span><span class="p">[</span><span class="nx">rule</span><span class="p">.</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">hasArgument</span> <span class="k">then</span> <span class="nx">args</span><span class="p">[</span><span class="nx">i</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">]</span> <span class="k">else</span> <span class="kc">true</span>
|
||||
<span class="nv">value = </span><span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">hasArgument</span> <span class="k">then</span> <span class="nx">args</span><span class="p">[</span><span class="nx">i</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">]</span> <span class="k">else</span> <span class="kc">true</span>
|
||||
<span class="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">isList</span> <span class="k">then</span> <span class="p">(</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">or</span> <span class="p">[]).</span><span class="nx">concat</span> <span class="nx">value</span> <span class="k">else</span> <span class="nx">value</span>
|
||||
<span class="nv">matchedRule = </span><span class="kc">yes</span>
|
||||
<span class="k">break</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"unrecognized option: #arg"</span> <span class="k">if</span> <span class="nx">isOption</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">matchedRule</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"unrecognized option: #{arg}"</span> <span class="k">if</span> <span class="nx">isOption</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">matchedRule</span>
|
||||
<span class="k">if</span> <span class="o">not</span> <span class="nx">isOption</span>
|
||||
<span class="nv">options.arguments = </span><span class="nx">args</span><span class="p">[</span><span class="nx">i</span><span class="p">...</span><span class="nx">args</span><span class="p">.</span><span class="nx">length</span><span class="p">]</span>
|
||||
<span class="k">break</span>
|
||||
<span class="nx">options</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Return the help text for this <strong>OptionParser</strong>, listing and describing all
|
||||
of the valid options, for <code>--help</code> and such.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">help</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nv">lines = </span><span class="p">[</span><span class="s1">'Available options:'</span><span class="p">]</span>
|
||||
<span class="nx">lines</span><span class="p">.</span><span class="nx">unshift</span> <span class="s2">"#@banner\n"</span> <span class="k">if</span> <span class="nx">@banner</span>
|
||||
<span class="nx">lines</span><span class="p">.</span><span class="nx">unshift</span> <span class="s2">"#{@banner}\n"</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">longFlag</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">></span> <span class="mi">0</span> <span class="k">then</span> <span class="p">(</span><span class="s1">' '</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">''</span><span class="p">)</span> <span class="k">else</span> <span class="s1">''</span>
|
||||
<span class="nv">spaces = </span><span class="k">if</span> <span class="nx">spaces</span> <span class="o">></span> <span class="mi">0</span> <span class="k">then</span> <span class="nb">Array</span><span class="p">(</span><span class="nx">spaces</span> <span class="o">+</span> <span class="mi">1</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s1">' '</span><span class="p">)</span> <span class="k">else</span> <span class="s1">''</span>
|
||||
<span class="nv">letPart = </span><span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">shortFlag</span> <span class="k">then</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">shortFlag</span> <span class="o">+</span> <span class="s1">', '</span> <span class="k">else</span> <span class="s1">' '</span>
|
||||
<span class="nx">lines</span><span class="p">.</span><span class="nx">push</span> <span class="s2">" #letPart#rule.longFlag#spaces#rule.description"</span>
|
||||
<span class="nx">lines</span><span class="p">.</span><span class="nx">push</span> <span class="s1">' '</span> <span class="o">+</span> <span class="nx">letPart</span> <span class="o">+</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">longFlag</span> <span class="o">+</span> <span class="nx">spaces</span> <span class="o">+</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">description</span>
|
||||
<span class="s2">"\n#{ lines.join('\n') }\n"</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>
|
||||
<span class="nv">OPTIONAL = </span><span class="sr">/\[(.+)\]/</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Build and return the list of option rules. If the optional <em>short-flag</em> is
|
||||
<span class="nv">OPTIONAL = </span><span class="sr">/\[(\w+(\*?))\]/</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Build and return the list of option rules. If the optional <em>short-flag</em> is
|
||||
unspecified, leave it out by padding with <code>null</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">buildRules = </span><span class="p">(</span><span class="nx">rules</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">for</span> <span class="nx">tuple</span> <span class="k">in</span> <span class="nx">rules</span>
|
||||
<span class="nx">tuple</span><span class="p">.</span><span class="nx">unshift</span> <span class="kc">null</span> <span class="k">if</span> <span class="nx">tuple</span><span class="p">.</span><span class="nx">length</span> <span class="o"><</span> <span class="mi">3</span>
|
||||
<span class="nx">buildRule</span> <span class="nx">tuple</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>Build a rule from a <code>-o</code> short flag, a <code>--output [DIR]</code> long flag, and the
|
||||
description of what the option does.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">buildRule = </span><span class="p">(</span><span class="nx">shortFlag</span><span class="p">,</span> <span class="nx">longFlag</span><span class="p">,</span> <span class="nx">description</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">match = </span><span class="nx">longFlag</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">OPTIONAL</span><span class="p">)</span>
|
||||
<span class="nv">longFlag = </span><span class="nx">longFlag</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="mi">1</span><span class="p">]</span>
|
||||
description of what the option does.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">buildRule = </span><span class="p">(</span><span class="nx">shortFlag</span><span class="p">,</span> <span class="nx">longFlag</span><span class="p">,</span> <span class="nx">description</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">match = </span><span class="nx">longFlag</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">OPTIONAL</span><span class="p">)</span>
|
||||
<span class="nv">longFlag = </span><span class="nx">longFlag</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="mi">1</span><span class="p">]</span>
|
||||
<span class="nx">options</span> <span class="o">or=</span> <span class="p">{}</span>
|
||||
<span class="p">{</span>
|
||||
<span class="nx">name</span><span class="o">:</span> <span class="nx">longFlag</span><span class="p">.</span><span class="nx">substr</span> <span class="mi">2</span>
|
||||
<span class="nx">shortFlag</span><span class="o">:</span> <span class="nx">shortFlag</span>
|
||||
<span class="nx">longFlag</span><span class="o">:</span> <span class="nx">longFlag</span>
|
||||
<span class="nx">description</span><span class="o">:</span> <span class="nx">description</span>
|
||||
<span class="nx">hasArgument</span><span class="o">:</span> <span class="o">!!</span><span class="p">(</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="nx">isList</span><span class="o">:</span> <span class="o">!!</span><span class="p">(</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="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>Normalize arguments by expanding merged flags into multiple flags. This allows
|
||||
you to have <code>-wl</code> be the same as <code>--watch --lint</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">normalizeArguments = </span><span class="p">(</span><span class="nx">args</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">args = </span><span class="nx">args</span><span class="p">.</span><span class="nx">slice</span> <span class="mi">0</span>
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<!DOCTYPE html> <html> <head> <title>repl.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> repl.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>A very simple Read-Eval-Print-Loop. Compiles one line at a time to JavaScript
|
||||
<!DOCTYPE html> <html> <head> <title>repl.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> repl.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>A 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 <strong>Node.js</strong> API.
|
||||
Using it looks like this:</p>
|
||||
|
||||
<pre><code>coffee> puts "#num bottles of beer" for num in [99..1]
|
||||
<pre><code>coffee> puts "#{num} bottles of beer" for num in [99..1]
|
||||
</code></pre> </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>Require the <strong>coffee-script</strong> module to get access to the compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s1">'./coffee-script'</span>
|
||||
<span class="nv">helpers = </span><span class="nx">require</span><span class="p">(</span><span class="s1">'./helpers'</span><span class="p">).</span><span class="nx">helpers</span>
|
||||
<span class="nv">readline = </span><span class="nx">require</span> <span class="s1">'readline'</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>Start by opening up <strong>stdio</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">stdio = </span><span class="nx">process</span><span class="p">.</span><span class="nx">openStdin</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Quick alias for quitting the REPL.</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="nx">quit</span><span class="o">:</span> <span class="o">-></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></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">buffer</span><span class="p">)</span> <span class="o">-></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">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">(),</span> <span class="nx">noWrap</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">globals</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">fileName</span><span class="o">:</span> <span class="s1">'repl'</span>
|
||||
<span class="nv">val = </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nb">eval</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">(),</span> <span class="nx">noWrap</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">globals</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">fileName</span><span class="o">:</span> <span class="s1">'repl'</span>
|
||||
<span class="nx">puts</span> <span class="nx">inspect</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>
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
<!DOCTYPE html> <html> <head> <title>rewriter.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> rewriter.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>The CoffeeScript language has a good deal of optional syntax, implicit syntax,
|
||||
<!DOCTYPE html> <html> <head> <title>rewriter.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> rewriter.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>The CoffeeScript language has a good deal of optional syntax, implicit syntax,
|
||||
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
|
||||
a series of passes over the token stream, using this <strong>Rewriter</strong> to convert
|
||||
shorthand into the unambiguous long form, add implicit indentation and
|
||||
parentheses, balance incorrect nestings, and generally clean things up.</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 Node.js and the browser.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nx">process</span><span class="o">?</span>
|
||||
<span class="p">{</span><span class="nx">helpers</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'./helpers'</span><span class="p">)</span>
|
||||
<span class="k">else</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nv">exports = </span><span class="k">this</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>Import the helpers we need.</p> </td> <td class="code"> <div class="highlight"><pre><span class="p">{</span><span class="nx">include</span><span class="p">}</span> <span class="o">=</span> <span class="nx">helpers</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>The <strong>Rewriter</strong> class is used by the <a href="lexer.html">Lexer</a>, directly against
|
||||
its internal array of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Rewriter = </span><span class="nx">class</span> <span class="nx">Rewriter</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Helpful snippet for debugging:
|
||||
puts (t[0] + '/' + t[1] for t in @tokens).join ' '</p> </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>Rewrite the token stream in multiple passes, one logical filter at
|
||||
parentheses, balance incorrect nestings, and generally clean things up.</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>Import the helpers we need.</p> </td> <td class="code"> <div class="highlight"><pre><span class="p">{</span><span class="nx">include</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'./helpers'</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 <strong>Rewriter</strong> class is used by the <a href="lexer.html">Lexer</a>, directly against
|
||||
its internal array of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Rewriter = </span><span class="nx">class</span> <span class="nx">Rewriter</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Helpful snippet for debugging:
|
||||
puts (t[0] + '/' + t[1] for t in @tokens).join ' '</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Rewrite the token stream in multiple passes, one logical filter at
|
||||
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
|
||||
@@ -18,13 +14,15 @@ corrected before implicit parentheses can be wrapped around blocks of code.</p>
|
||||
<span class="nx">@adjustComments</span><span class="p">()</span>
|
||||
<span class="nx">@removeLeadingNewlines</span><span class="p">()</span>
|
||||
<span class="nx">@removeMidExpressionNewlines</span><span class="p">()</span>
|
||||
<span class="nx">@closeOpenCallsAndIndexes</span><span class="p">()</span>
|
||||
<span class="nx">@closeOpenCalls</span><span class="p">()</span>
|
||||
<span class="nx">@closeOpenIndexes</span><span class="p">()</span>
|
||||
<span class="nx">@addImplicitIndentation</span><span class="p">()</span>
|
||||
<span class="nx">@tagPostfixConditionals</span><span class="p">()</span>
|
||||
<span class="nx">@addImplicitBraces</span><span class="p">()</span>
|
||||
<span class="nx">@addImplicitParentheses</span><span class="p">()</span>
|
||||
<span class="nx">@ensureBalance</span> <span class="nx">BALANCED_PAIRS</span>
|
||||
<span class="nx">@rewriteClosingParens</span><span class="p">()</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>Rewrite the token stream, looking one token ahead and behind.
|
||||
<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
|
||||
@@ -32,13 +30,24 @@ our feet.</p> </td> <td class="code"> <div
|
||||
<span class="nv">i = </span><span class="mi">0</span>
|
||||
<span class="nx">loop</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">move = </span><span class="nx">block</span><span class="p">.</span><span class="nx">call</span> <span class="k">this</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">i</span>
|
||||
<span class="nx">i</span> <span class="o">+=</span> <span class="nx">move</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Massage newlines and indentations so that comments don't have to be
|
||||
<span class="kc">true</span>
|
||||
|
||||
<span class="nx">detectEnd</span><span class="o">:</span> <span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">levels = </span><span class="mi">0</span>
|
||||
<span class="nx">loop</span>
|
||||
<span class="nv">token = </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>
|
||||
<span class="k">return</span> <span class="nx">action</span><span class="p">.</span><span class="nx">call</span> <span class="k">this</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">i</span> <span class="k">if</span> <span class="nx">levels</span> <span class="o">is</span> <span class="mi">0</span> <span class="o">and</span> <span class="nx">condition</span><span class="p">.</span><span class="nx">call</span> <span class="k">this</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">i</span>
|
||||
<span class="k">return</span> <span class="nx">action</span><span class="p">.</span><span class="nx">call</span> <span class="k">this</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">token</span> <span class="o">or</span> <span class="nx">levels</span> <span class="o"><</span> <span class="mi">0</span>
|
||||
<span class="nx">levels</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">include</span> <span class="nx">EXPRESSION_START</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">levels</span> <span class="o">-=</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">include</span> <span class="nx">EXPRESSION_END</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">i</span> <span class="o">+=</span> <span class="mi">1</span>
|
||||
<span class="nx">i</span> <span class="o">-</span> <span class="mi">1</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="nx">adjustComments</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">post</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=></span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'HERECOMMENT'</span>
|
||||
<span class="p">[</span><span class="nx">before</span><span class="p">,</span> <span class="nx">after</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">],</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="p">[</span><span class="nx">before</span><span class="p">,</span> <span class="nx">prev</span><span class="p">,</span> <span class="nx">post</span><span class="p">,</span> <span class="nx">after</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">],</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</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">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="k">if</span> <span class="nx">after</span> <span class="o">and</span> <span class="nx">after</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'INDENT'</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="k">if</span> <span class="nx">before</span> <span class="o">and</span> <span class="nx">before</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'OUTDENT'</span> <span class="o">and</span> <span class="nx">post</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="nx">post</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span>
|
||||
@@ -53,153 +62,130 @@ correctly indented, or appear on a line of their own.</p> </td>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s2">"\n"</span><span class="p">,</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="k">return</span> <span class="mi">2</span>
|
||||
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Leading newlines would introduce an ambiguity in the grammar, so we
|
||||
<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="nx">removeLeadingNewlines</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">shift</span><span class="p">()</span> <span class="k">while</span> <span class="nx">@tokens</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">and</span> <span class="nx">@tokens</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Some blocks occur in the middle of expressions -- when we're expecting
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">shift</span><span class="p">()</span> <span class="k">while</span> <span class="nx">@tokens</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">and</span> <span class="nx">@tokens</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Some blocks occur in the middle of expressions -- when we're expecting
|
||||
this, remove their trailing newlines.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">removeMidExpressionNewlines</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">post</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=></span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">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">'TERMINATOR'</span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">include</span><span class="p">(</span><span class="nx">EXPRESSION_CLOSE</span><span class="p">,</span> <span class="nx">@tag</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="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">'TERMINATOR'</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-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</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="nx">closeOpenCallsAndIndexes</span><span class="o">:</span> <span class="o">-></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="nx">@scanTokens</span> <span class="p">(</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">post</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=></span>
|
||||
<span class="k">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">'CALL_START'</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">'INDEX_START'</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">'('</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="mi">1</span>
|
||||
<span class="k">when</span> <span class="s1">'['</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="mi">1</span>
|
||||
<span class="k">when</span> <span class="s1">')'</span>
|
||||
<span class="k">if</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">is</span> <span class="mi">0</span>
|
||||
<span class="nx">parens</span><span class="p">.</span><span class="nx">pop</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">=</span> <span class="s1">'CALL_END'</span>
|
||||
<span class="k">else</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="mi">1</span>
|
||||
<span class="k">when</span> <span class="s1">']'</span>
|
||||
<span class="k">if</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="mi">0</span>
|
||||
<span class="nx">brackets</span><span class="p">.</span><span class="nx">pop</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">=</span> <span class="s1">'INDEX_END'</span>
|
||||
<span class="k">else</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="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. Match it with
|
||||
its paired close. We have the mis-nested outdent case included here for
|
||||
calls that close on the same line, just before their outdent.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">closeOpenCalls</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'CALL_START'</span>
|
||||
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</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="k">in</span> <span class="p">[</span><span class="s1">')'</span><span class="p">,</span> <span class="s1">'CALL_END'</span><span class="p">])</span> <span class="o">or</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">'OUTDENT'</span> <span class="o">and</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">')'</span><span class="p">)</span>
|
||||
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">idx = </span><span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'OUTDENT'</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="nx">@tokens</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="o">=</span> <span class="s1">'CALL_END'</span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
|
||||
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>The lexer has tagged the opening parenthesis of an indexing operation call.
|
||||
Match it with its paired close.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">closeOpenIndexes</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'INDEX_START'</span>
|
||||
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s1">']'</span><span class="p">,</span> <span class="s1">'INDEX_END'</span><span class="p">]</span>
|
||||
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'INDEX_END'</span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
|
||||
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>Object literals may be written with implicit braces, for simple cases.
|
||||
Insert the missing braces here, so that the parser doesn't have to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">addImplicitBraces</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nv">stack = </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nv">running = </span><span class="kc">no</span>
|
||||
<span class="nv">closeBrackets = </span><span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="o">=></span>
|
||||
<span class="nv">len = </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="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">len</span><span class="p">]]</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">'}'</span><span class="p">,</span> <span class="s1">'}'</span><span class="p">,</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">][</span><span class="mi">2</span><span class="p">]])</span>
|
||||
<span class="nv">size = </span><span class="nx">stack</span><span class="p">[</span><span class="nx">len</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">len</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
|
||||
<span class="nx">size</span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">post</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=></span>
|
||||
<span class="nv">tag = </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nv">len = </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="nv">before = </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="nv">open = </span><span class="nx">stack</span><span class="p">[</span><span class="nx">len</span><span class="p">]</span> <span class="o">></span> <span class="mi">0</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">tag</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span> <span class="o">and</span> <span class="o">not</span> <span class="p">((</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">':'</span><span class="p">)</span> <span class="o">or</span> <span class="p">(</span><span class="nx">post</span> <span class="o">and</span> <span class="nx">post</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'@'</span> <span class="o">and</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">3</span><span class="p">]</span> <span class="o">and</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">3</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">':'</span><span class="p">)))</span> <span class="o">or</span>
|
||||
<span class="p">(</span><span class="nx">running</span> <span class="o">and</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">','</span> <span class="o">and</span> <span class="nx">post</span> <span class="o">and</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">not</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'STRING'</span><span class="p">,</span> <span class="s1">'@'</span><span class="p">]))</span>
|
||||
<span class="nv">running = </span><span class="kc">no</span>
|
||||
<span class="k">return</span> <span class="nx">closeBrackets</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span>
|
||||
<span class="k">else</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>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'{'</span> <span class="k">then</span> <span class="mi">1</span> <span class="k">else</span> <span class="mi">0</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="mi">2</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'{'</span> <span class="o">and</span> <span class="nx">post</span> <span class="o">and</span> <span class="nx">post</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'INDENT'</span>
|
||||
<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">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">'OUTDENT'</span> <span class="o">and</span> <span class="nx">post</span> <span class="o">and</span> <span class="nx">post</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'}'</span>
|
||||
<span class="nv">size = </span><span class="nx">closeBrackets</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'OUTDENT'</span>
|
||||
<span class="nx">stack</span><span class="p">[</span><span class="nx">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">+=</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">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">-=</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'}'</span>
|
||||
<span class="k">return</span> <span class="nx">size</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'OUTDENT'</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">':'</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">open</span>
|
||||
<span class="nv">idx = </span><span class="k">if</span> <span class="nx">before</span> <span class="o">and</span> <span class="nx">before</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'@'</span> <span class="k">then</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span> <span class="k">else</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</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">'{'</span><span class="p">,</span> <span class="s1">'{'</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="mi">1</span>
|
||||
<span class="nv">running = </span><span class="kc">yes</span>
|
||||
<span class="nv">stack = </span><span class="p">[]</span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">include</span> <span class="nx">EXPRESSION_START</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">stack</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="k">if</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">'INDENT'</span> <span class="o">and</span> <span class="p">(</span><span class="nx">@tag</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="o">is</span> <span class="s1">'{'</span><span class="p">))</span> <span class="k">then</span> <span class="s1">'{'</span> <span class="k">else</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_END</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">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="nv">last = </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="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">':'</span> <span class="o">and</span> <span class="p">(</span><span class="o">not</span> <span class="nx">last</span> <span class="o">or</span> <span class="nx">last</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'{'</span><span class="p">)</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="s1">'{'</span>
|
||||
<span class="nv">idx = </span><span class="k">if</span> <span class="nx">@tag</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="o">is</span> <span class="s1">'@'</span> <span class="k">then</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span> <span class="k">else</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nx">idx</span> <span class="o">-=</span> <span class="mi">2</span> <span class="k">if</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">idx</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'HERECOMMENT'</span>
|
||||
<span class="nv">tok = </span><span class="p">[</span><span class="s1">'{'</span><span class="p">,</span> <span class="s1">'{'</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">tok.generated = </span><span class="kc">yes</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">idx</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">tok</span>
|
||||
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="p">[</span><span class="nx">one</span><span class="p">,</span> <span class="nx">two</span><span class="p">,</span> <span class="nx">three</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@tokens</span><span class="p">.</span><span class="nx">slice</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="o">+</span> <span class="mi">4</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="k">if</span> <span class="s1">'HERECOMMENT'</span> <span class="k">in</span> <span class="p">[</span><span class="nx">@tag</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">@tag</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="p">((</span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">])</span> <span class="o">and</span> <span class="o">not</span> <span class="p">((</span><span class="nx">two</span> <span class="o">and</span> <span class="nx">two</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">':'</span><span class="p">)</span> <span class="o">or</span> <span class="p">(</span><span class="nx">one</span> <span class="o">and</span> <span class="nx">one</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'@'</span> <span class="o">and</span> <span class="nx">three</span> <span class="o">and</span> <span class="nx">three</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">':'</span><span class="p">)))</span> <span class="o">or</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">','</span> <span class="o">and</span> <span class="nx">one</span> <span class="o">and</span> <span class="p">(</span><span class="nx">one</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">not</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'STRING'</span><span class="p">,</span> <span class="s1">'@'</span><span class="p">,</span> <span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">]))</span>
|
||||
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">'}'</span><span class="p">,</span> <span class="s1">'}'</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
|
||||
<span class="k">return</span> <span class="mi">2</span>
|
||||
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>Methods may be optionally called without parentheses, for simple cases.
|
||||
Insert the implicit parentheses here, so that the parser doesn't have to
|
||||
deal with them.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">addImplicitParentheses</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nv">stack = </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nv">closeCalls = </span><span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="o">=></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="mi">1</span><span class="p">]]</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">'CALL_END'</span><span class="p">,</span> <span class="s1">')'</span><span class="p">,</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">][</span><span class="mi">2</span><span class="p">]])</span>
|
||||
<span class="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="mi">1</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="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
|
||||
<span class="nx">size</span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">post</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=></span>
|
||||
<span class="nv">tag = </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nv">before = </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="o">and</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="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">2</span><span class="p">]</span> <span class="o">+=</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'OUTDENT'</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">></span> <span class="mi">0</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="nx">spaced</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="o">and</span>
|
||||
<span class="o">not</span> <span class="p">(</span><span class="nx">tag</span> <span class="o">is</span> <span class="s1">'!'</span> <span class="o">and</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="k">in</span> <span class="p">[</span><span class="s1">'IN'</span><span class="p">,</span> <span class="s1">'OF'</span><span class="p">]))</span>
|
||||
<span class="nv">classLine = </span><span class="kc">no</span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">classLine = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'CLASS'</span>
|
||||
<span class="nv">prev = </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="nv">next = </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="nv">idx = </span><span class="mi">1</span>
|
||||
<span class="nv">callObject = </span><span class="o">not</span> <span class="nx">classLine</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">'INDENT'</span> <span class="o">and</span> <span class="nx">next</span> <span class="o">and</span> <span class="nx">next</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'{'</span> <span class="o">and</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="nv">idx = </span><span class="mi">2</span> <span class="k">if</span> <span class="nx">callObject</span>
|
||||
<span class="nv">seenSingle = </span><span class="kc">no</span>
|
||||
<span class="nv">classLine = </span><span class="kc">no</span> <span class="k">if</span> <span class="nx">include</span><span class="p">(</span><span class="nx">LINEBREAKS</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">token.call = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">prev</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">prev</span><span class="p">.</span><span class="nx">spaced</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">'?'</span>
|
||||
<span class="k">if</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="nx">spaced</span> <span class="o">and</span> <span class="p">(</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">or</span> <span class="nx">prev</span><span class="p">.</span><span class="nx">call</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">token</span><span class="p">[</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">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'UNARY'</span> <span class="o">and</span> <span class="p">(</span><span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'IN'</span><span class="p">,</span> <span class="s1">'OF'</span><span class="p">,</span> <span class="s1">'INSTANCEOF'</span><span class="p">])))</span> <span class="o">or</span> <span class="nx">callObject</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">'CALL_START'</span><span class="p">,</span> <span class="s1">'('</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="mi">1</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="mi">0</span> <span class="k">if</span> <span class="nx">include</span><span class="p">(</span><span class="nx">EXPRESSION_START</span><span class="p">,</span> <span class="nx">tag</span><span class="p">)</span>
|
||||
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">yes</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">seenSingle</span> <span class="o">and</span> <span class="nx">token</span><span class="p">.</span><span class="nx">fromThen</span>
|
||||
<span class="nv">seenSingle = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">,</span> <span class="s1">'UNLESS'</span><span class="p">,</span> <span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">]</span>
|
||||
<span class="nv">post = </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="p">(</span><span class="o">not</span> <span class="nx">token</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">','</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_END</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="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">'INDENT'</span> <span class="o">and</span> <span class="p">(</span><span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_BLOCK</span><span class="p">,</span> <span class="nx">@tag</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="o">or</span> <span class="nx">@tag</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="o">is</span> <span class="s1">'CLASS'</span> <span class="o">or</span> <span class="p">(</span><span class="nx">post</span> <span class="o">and</span> <span class="nx">post</span><span class="p">.</span><span class="nx">generated</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">'{'</span><span class="p">))))</span> <span class="o">or</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">'PROPERTY_ACCESS'</span> <span class="o">and</span> <span class="nx">@tag</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="o">is</span> <span class="s1">'OUTDENT'</span>
|
||||
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">idx = </span><span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'OUTDENT'</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="nx">@tokens</span><span class="p">.</span><span class="nx">splice</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">'CALL_END'</span><span class="p">,</span> <span class="s1">')'</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">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="nx">idx</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
|
||||
<span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'FUNC_EXIST'</span> <span class="k">if</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">'?'</span>
|
||||
<span class="k">return</span> <span class="mi">2</span>
|
||||
<span class="k">if</span> <span class="nx">include</span><span class="p">(</span><span class="nx">EXPRESSION_START</span><span class="p">,</span> <span class="nx">tag</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'INDENT'</span> <span class="o">and</span> <span class="o">!</span><span class="nx">token</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">open</span> <span class="o">and</span> <span class="o">not</span>
|
||||
<span class="p">((</span><span class="nx">prev</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</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="o">or</span> <span class="nx">before</span> <span class="o">and</span> <span class="nx">before</span> <span class="o">is</span> <span class="s1">'CLASS'</span><span class="p">)</span>
|
||||
<span class="nv">size = </span><span class="nx">closeCalls</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="mi">0</span>
|
||||
<span class="k">return</span> <span class="nx">size</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="mi">0</span>
|
||||
<span class="k">return</span> <span class="mi">1</span>
|
||||
<span class="k">if</span> <span class="nx">open</span> <span class="o">and</span> <span class="o">!</span><span class="nx">token</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">','</span> <span class="o">and</span> <span class="p">(</span><span class="o">!</span><span class="nx">post</span> <span class="o">or</span> <span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_END</span><span class="p">,</span> <span class="nx">tag</span><span class="p">))</span>
|
||||
<span class="nv">j = </span><span class="mi">1</span><span class="p">;</span> <span class="nx">j</span><span class="o">++</span> <span class="k">while</span> <span class="p">(</span><span class="nv">nx = </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="nx">j</span><span class="p">])</span><span class="o">?</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_END</span><span class="p">,</span> <span class="nx">nx</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
|
||||
<span class="k">if</span> <span class="nx">nx</span><span class="o">?</span> <span class="o">and</span> <span class="nx">nx</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">','</span> <span class="o">and</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="nx">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'OUTDENT'</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">size = </span><span class="nx">closeCalls</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">isnt</span> <span class="s1">'OUTDENT'</span> <span class="o">and</span> <span class="nx">include</span> <span class="nx">EXPRESSION_END</span><span class="p">,</span> <span class="nx">tag</span>
|
||||
<span class="k">return</span> <span class="nx">size</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="o">isnt</span> <span class="s1">'OUTDENT'</span> <span class="o">and</span> <span class="nx">include</span> <span class="nx">EXPRESSION_END</span><span class="p">,</span> <span class="nx">tag</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">2</span><span class="p">]</span> <span class="o">+=</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="mi">1</span>
|
||||
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</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="nx">addImplicitIndentation</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">post</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=></span>
|
||||
<span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'ELSE'</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'OUTDENT'</span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'ELSE'</span> <span class="o">and</span> <span class="nx">@tag</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="o">isnt</span> <span class="s1">'OUTDENT'</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">@indentation</span><span class="p">(</span><span class="nx">token</span><span class="p">)...</span>
|
||||
<span class="k">return</span> <span class="mi">2</span>
|
||||
<span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'CATCH'</span> <span class="o">and</span>
|
||||
<span class="p">(</span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span> <span class="o">or</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'FINALLY'</span><span class="p">)</span>
|
||||
<span class="p">(</span><span class="nx">@tag</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="o">is</span> <span class="s1">'TERMINATOR'</span> <span class="o">or</span> <span class="nx">@tag</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="o">is</span> <span class="s1">'FINALLY'</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">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">@indentation</span><span class="p">(</span><span class="nx">token</span><span class="p">)...</span>
|
||||
<span class="k">return</span> <span class="mi">4</span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">include</span><span class="p">(</span><span class="nx">SINGLE_LINERS</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">and</span>
|
||||
<span class="nx">post</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'INDENT'</span> <span class="o">and</span>
|
||||
<span class="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">'ELSE'</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">'IF'</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="p">[</span><span class="nx">indent</span><span class="p">,</span> <span class="nx">outdent</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@indentation</span> <span class="nx">token</span>
|
||||
<span class="nv">indent.generated = outdent.generated = </span><span class="kc">true</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">indent</span>
|
||||
<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="nx">loop</span>
|
||||
<span class="nx">idx</span> <span class="o">+=</span> <span class="mi">1</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">';'</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">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">')'</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">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'ELSE'</span> <span class="o">and</span> <span class="nx">starter</span> <span class="o">not</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'THEN'</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">","</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="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="nx">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">'('</span>
|
||||
<span class="nx">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">')'</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">'THEN'</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-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>Ensure that all listed pairs of tokens are correctly balanced throughout
|
||||
<span class="k">if</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">@tag</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="o">isnt</span> <span class="s1">'INDENT'</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">'ELSE'</span> <span class="o">and</span> <span class="nx">@tag</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="o">is</span> <span class="s1">'IF'</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="p">[</span><span class="nx">indent</span><span class="p">,</span> <span class="nx">outdent</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@indentation</span> <span class="nx">token</span>
|
||||
<span class="nv">indent.fromThen = </span><span class="kc">true</span> <span class="k">if</span> <span class="nx">starter</span> <span class="o">is</span> <span class="s1">'THEN'</span>
|
||||
<span class="nv">indent.generated = outdent.generated = </span><span class="kc">true</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">indent</span>
|
||||
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></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">token</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">1</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">';'</span><span class="p">)</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">'ELSE'</span> <span class="o">and</span> <span class="nx">starter</span> <span class="o">not</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'THEN'</span><span class="p">])</span>
|
||||
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">idx = </span><span class="k">if</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="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">','</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="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">idx</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">outdent</span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</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">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'THEN'</span>
|
||||
<span class="k">return</span> <span class="mi">2</span>
|
||||
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>Tag postfix conditionals as such, so that we can parse them with a
|
||||
different precedence.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">tagPostfixConditionals</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'UNLESS'</span><span class="p">]</span>
|
||||
<span class="nv">original = </span><span class="nx">token</span>
|
||||
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'INDENT'</span><span class="p">]</span>
|
||||
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">original</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'POST_'</span> <span class="o">+</span> <span class="nx">original</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'INDENT'</span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
|
||||
<span class="k">return</span> <span class="mi">1</span>
|
||||
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</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="nx">ensureBalance</span><span class="o">:</span> <span class="p">(</span><span class="nx">pairs</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">levels = </span><span class="p">{}</span>
|
||||
<span class="nv">openLine = </span><span class="p">{}</span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">post</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=></span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></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">or=</span> <span class="mi">0</span>
|
||||
@@ -213,7 +199,7 @@ the course of the token stream.</p> </td> <td class="cod
|
||||
<span class="k">if</span> <span class="nx">unclosed</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">open = </span><span class="nx">unclosed</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nv">line = </span><span class="nx">openLine</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"unclosed #open on line #line"</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</a> </div> <p>We'd like to support syntax like this:</p>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"unclosed #{open} on line #{line}"</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>We'd like to support syntax like this:</p>
|
||||
|
||||
<pre><code>el.click((event) ->
|
||||
el.hide())
|
||||
@@ -235,7 +221,7 @@ rewriting.</li>
|
||||
<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="nx">@scanTokens</span> <span class="p">(</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">post</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=></span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></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>
|
||||
@@ -260,19 +246,20 @@ rewriting.</li>
|
||||
<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">val</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-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>Generate the indentation tokens, based on another token on the same line.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">indentation</span><span class="o">:</span> <span class="p">(</span><span class="nx">token</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="p">[[</span><span class="s1">'INDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]],</span> <span class="p">[</span><span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]]</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-18">#</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-19">#</a> </div> <p>List of the token pairs that must be balanced.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BALANCED_PAIRS = </span><span class="p">[[</span><span class="s1">'('</span><span class="p">,</span> <span class="s1">')'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'['</span><span class="p">,</span> <span class="s1">']'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'{'</span><span class="p">,</span> <span class="s1">'}'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'INDENT'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">],</span>
|
||||
<span class="p">[</span><span class="s1">'PARAM_START'</span><span class="p">,</span> <span class="s1">'PARAM_END'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'CALL_START'</span><span class="p">,</span> <span class="s1">'CALL_END'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'INDEX_START'</span><span class="p">,</span> <span class="s1">'INDEX_END'</span><span class="p">]]</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-20">#</a> </div> <p>The inverse mappings of <code>BALANCED_PAIRS</code> we're trying to fix up, so we can
|
||||
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-18">#</a> </div> <p>Generate the indentation tokens, based on another token on the same line.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">indentation</span><span class="o">:</span> <span class="p">(</span><span class="nx">token</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="p">[[</span><span class="s1">'INDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]],</span> <span class="p">[</span><span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]]</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-19">#</a> </div> <p>Look up a tag by token index.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">tag</span><span class="o">:</span> <span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">and</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></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-20">#</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-21">#</a> </div> <p>List of the token pairs that must be balanced.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BALANCED_PAIRS = </span><span class="p">[[</span><span class="s1">'('</span><span class="p">,</span> <span class="s1">')'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'['</span><span class="p">,</span> <span class="s1">']'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'{'</span><span class="p">,</span> <span class="s1">'}'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'INDENT'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">],</span>
|
||||
<span class="p">[</span><span class="s1">'PARAM_START'</span><span class="p">,</span> <span class="s1">'PARAM_END'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'CALL_START'</span><span class="p">,</span> <span class="s1">'CALL_END'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'INDEX_START'</span><span class="p">,</span> <span class="s1">'INDEX_END'</span><span class="p">]]</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-22">#</a> </div> <p>The inverse mappings of <code>BALANCED_PAIRS</code> we're trying to fix up, so we can
|
||||
look things up from either end.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">INVERSES = </span><span class="p">{}</span>
|
||||
<span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span>
|
||||
<span class="nx">INVERSES</span><span class="p">[</span><span class="nx">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span> <span class="o">=</span> <span class="nx">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nx">INVERSES</span><span class="p">[</span><span class="nx">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]]</span> <span class="o">=</span> <span class="nx">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-21">#</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-22"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-22">#</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-23"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-23">#</a> </div> <p>Tokens that indicate the close of a clause of an expression.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_CLOSE = </span><span class="p">[</span><span class="s1">'CATCH'</span><span class="p">,</span> <span class="s1">'WHEN'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">,</span> <span class="s1">'FINALLY'</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">EXPRESSION_END</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-24">#</a> </div> <p>Tokens that, if followed by an <code>IMPLICIT_CALL</code>, indicate a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_FUNC = </span><span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'SUPER'</span><span class="p">,</span> <span class="s1">')'</span><span class="p">,</span> <span class="s1">'CALL_END'</span><span class="p">,</span> <span class="s1">']'</span><span class="p">,</span> <span class="s1">'INDEX_END'</span><span class="p">,</span> <span class="s1">'@'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-25">#</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="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-23"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-23">#</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-24"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-24">#</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-25"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-25">#</a> </div> <p>Tokens that indicate the close of a clause of an expression.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_CLOSE = </span><span class="p">[</span><span class="s1">'CATCH'</span><span class="p">,</span> <span class="s1">'WHEN'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">,</span> <span class="s1">'FINALLY'</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">EXPRESSION_END</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-26">#</a> </div> <p>Tokens that, if followed by an <code>IMPLICIT_CALL</code>, indicate a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_FUNC = </span><span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'SUPER'</span><span class="p">,</span> <span class="s1">')'</span><span class="p">,</span> <span class="s1">'CALL_END'</span><span class="p">,</span> <span class="s1">']'</span><span class="p">,</span> <span class="s1">'INDEX_END'</span><span class="p">,</span> <span class="s1">'@'</span><span class="p">,</span> <span class="s1">'THIS'</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>If preceded by an <code>IMPLICIT_FUNC</code>, indicates a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_CALL = </span><span class="p">[</span>
|
||||
<span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'NUMBER'</span><span class="p">,</span> <span class="s1">'STRING'</span><span class="p">,</span> <span class="s1">'JS'</span><span class="p">,</span> <span class="s1">'REGEX'</span><span class="p">,</span> <span class="s1">'NEW'</span><span class="p">,</span> <span class="s1">'PARAM_START'</span><span class="p">,</span> <span class="s1">'CLASS'</span><span class="p">,</span>
|
||||
<span class="s1">'TRY'</span><span class="p">,</span> <span class="s1">'DELETE'</span><span class="p">,</span> <span class="s1">'TYPEOF'</span><span class="p">,</span> <span class="s1">'SWITCH'</span><span class="p">,</span> <span class="s1">'THIS'</span><span class="p">,</span> <span class="s1">'NULL'</span><span class="p">,</span>
|
||||
<span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'UNLESS'</span><span class="p">,</span> <span class="s1">'TRY'</span><span class="p">,</span> <span class="s1">'SWITCH'</span><span class="p">,</span> <span class="s1">'THIS'</span><span class="p">,</span> <span class="s1">'NULL'</span><span class="p">,</span> <span class="s1">'UNARY'</span>
|
||||
<span class="s1">'TRUE'</span><span class="p">,</span> <span class="s1">'FALSE'</span><span class="p">,</span> <span class="s1">'YES'</span><span class="p">,</span> <span class="s1">'NO'</span><span class="p">,</span> <span class="s1">'ON'</span><span class="p">,</span> <span class="s1">'OFF'</span><span class="p">,</span>
|
||||
<span class="s1">'!'</span><span class="p">,</span> <span class="s1">'!!'</span><span class="p">,</span> <span class="s1">'@'</span><span class="p">,</span> <span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">,</span> <span class="s1">'['</span><span class="p">,</span> <span class="s1">'('</span><span class="p">,</span> <span class="s1">'{'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-26">#</a> </div> <p>Tokens indicating that the implicit call must enclose a block of expressions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_BLOCK = </span><span class="p">[</span><span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">,</span> <span class="s1">'{'</span><span class="p">,</span> <span class="s1">'['</span><span class="p">,</span> <span class="s1">','</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-27">#</a> </div> <p>Tokens that always mark the end of an implicit call for single-liners.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_END = </span><span class="p">[</span><span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'UNLESS'</span><span class="p">,</span> <span class="s1">'FOR'</span><span class="p">,</span> <span class="s1">'WHILE'</span><span class="p">,</span> <span class="s1">'UNTIL'</span><span class="p">,</span> <span class="s1">'LOOP'</span><span class="p">,</span> <span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'INDENT'</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">EXPRESSION_END</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-28">#</a> </div> <p>Single-line flavors of block expressions that have unclosed endings.
|
||||
<span class="s1">'@'</span><span class="p">,</span> <span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">,</span> <span class="s1">'['</span><span class="p">,</span> <span class="s1">'('</span><span class="p">,</span> <span class="s1">'{'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-28">#</a> </div> <p>Tokens indicating that the implicit call must enclose a block of expressions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_BLOCK = </span><span class="p">[</span><span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">,</span> <span class="s1">'{'</span><span class="p">,</span> <span class="s1">'['</span><span class="p">,</span> <span class="s1">','</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-29">#</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">'POST_IF'</span><span class="p">,</span> <span class="s1">'POST_UNLESS'</span><span class="p">,</span> <span class="s1">'FOR'</span><span class="p">,</span> <span class="s1">'WHILE'</span><span class="p">,</span> <span class="s1">'UNTIL'</span><span class="p">,</span> <span class="s1">'LOOP'</span><span class="p">,</span> <span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'INDENT'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-30">#</a> </div> <p>Single-line flavors of block expressions that have unclosed endings.
|
||||
The grammar can't disambiguate them, so we insert the implicit indentation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">SINGLE_LINERS = </span><span class="p">[</span><span class="s1">'ELSE'</span><span class="p">,</span> <span class="s2">"->"</span><span class="p">,</span> <span class="s2">"=>"</span><span class="p">,</span> <span class="s1">'TRY'</span><span class="p">,</span> <span class="s1">'FINALLY'</span><span class="p">,</span> <span class="s1">'THEN'</span><span class="p">]</span>
|
||||
<span class="nv">SINGLE_CLOSERS = </span><span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'CATCH'</span><span class="p">,</span> <span class="s1">'FINALLY'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="s1">'LEADING_WHEN'</span><span class="p">]</span>
|
||||
<span class="nv">SINGLE_CLOSERS = </span><span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'CATCH'</span><span class="p">,</span> <span class="s1">'FINALLY'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="s1">'LEADING_WHEN'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-31">#</a> </div> <p>Tokens that end a line.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">LINEBREAKS = </span><span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'INDENT'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">]</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -1,9 +1,9 @@
|
||||
<!DOCTYPE html> <html> <head> <title>scope.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> scope.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>The <strong>Scope</strong> class regulates lexical scoping within CoffeeScript. As you
|
||||
<!DOCTYPE html> <html> <head> <title>scope.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> scope.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>The <strong>Scope</strong> class regulates lexical scoping within CoffeeScript. As you
|
||||
generate code, you create a tree of scopes in the same shape as the nested
|
||||
function bodies. Each scope knows about the variables declared within it,
|
||||
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>
|
||||
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>Import the helpers we plan to use.</p> </td> <td class="code"> <div class="highlight"><pre><span class="p">{</span><span class="nx">extend</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'./helpers'</span><span class="p">).</span><span class="nx">helpers</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>The top-level <strong>Scope</strong> object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">@root</span><span class="o">:</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
|
||||
@@ -12,37 +12,46 @@ it wraps.</p> </td> <td class="code"> <div
|
||||
<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">@tempVar = </span><span class="nx">@parent</span><span class="p">.</span><span class="nx">tempVar</span>
|
||||
<span class="vi">@garbage = </span><span class="nx">@parent</span><span class="p">.</span><span class="nx">garbage</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">Scope.root = </span><span class="k">this</span>
|
||||
<span class="vi">@tempVar = </span><span class="s1">'_a'</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="nx">find</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<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="vi">@garbage = </span><span class="p">[]</span>
|
||||
<span class="nv">Scope.root = </span><span class="k">this</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Create a new garbage level</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">startLevel</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">@garbage</span><span class="p">.</span><span class="nx">push</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>Return to the previous garbage level and erase referenced temporary
|
||||
variables in current level from scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">endLevel</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="p">(</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">'reuse'</span><span class="p">)</span> <span class="k">for</span> <span class="nx">name</span> <span class="k">in</span> <span class="nx">@garbage</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span> <span class="k">when</span> <span class="nx">@variables</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'var'</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</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="nx">find</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<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="p">,</span> <span class="nx">options</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">'var'</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="nx">any</span><span class="o">:</span> <span class="p">(</span><span class="nx">fn</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="kc">false</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</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="nx">any</span><span class="o">:</span> <span class="p">(</span><span class="nx">fn</span><span class="p">)</span> <span class="o">-></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
|
||||
<span class="k">return</span> <span class="kc">false</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</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="nx">parameter</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></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">'param'</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="nx">check</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></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">hasOwnProperty</span> <span class="nx">name</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="nx">freeVariable</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="k">while</span> <span class="nx">@check</span> <span class="nx">@tempVar</span>
|
||||
<span class="nv">ordinal = </span><span class="mi">1</span> <span class="o">+</span> <span class="nb">parseInt</span> <span class="nx">@tempVar</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">@tempVar = </span><span class="s1">'_'</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">'a'</span><span class="p">)</span>
|
||||
<span class="nx">@variables</span><span class="p">[</span><span class="nx">@tempVar</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'var'</span>
|
||||
<span class="nx">@tempVar</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
|
||||
<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">'param'</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Just check to see if a variable has already been declared, without reserving,
|
||||
walks up to the root scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">check</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">immediate = </span><span class="nb">Object</span><span class="o">::</span><span class="nx">hasOwnProperty</span><span class="p">.</span><span class="nx">call</span> <span class="nx">@variables</span><span class="p">,</span> <span class="nx">name</span>
|
||||
<span class="k">return</span> <span class="nx">immediate</span> <span class="k">if</span> <span class="nx">immediate</span> <span class="o">or</span> <span class="p">(</span><span class="nx">options</span> <span class="o">and</span> <span class="nx">options</span><span class="p">.</span><span class="nx">immediate</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-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Generate a temporary variable name at the given index.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">temporary</span><span class="o">:</span> <span class="p">(</span><span class="nx">type</span><span class="p">,</span> <span class="nx">index</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">type</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">1</span>
|
||||
<span class="s1">'_'</span> <span class="o">+</span> <span class="nx">type</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">index</span> <span class="o">></span> <span class="mi">1</span> <span class="k">then</span> <span class="nx">index</span> <span class="k">else</span> <span class="s1">''</span>
|
||||
<span class="k">else</span>
|
||||
<span class="s1">'_'</span> <span class="o">+</span> <span class="p">(</span><span class="nx">index</span> <span class="o">+</span> <span class="nb">parseInt</span> <span class="nx">type</span><span class="p">,</span> <span class="mi">36</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="sr">/\d/g</span><span class="p">,</span> <span class="s1">'a'</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>If we need to store an intermediate result, find an available name for a
|
||||
compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on...</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">freeVariable</span><span class="o">:</span> <span class="p">(</span><span class="nx">type</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">index = </span><span class="mi">0</span>
|
||||
<span class="nx">index</span><span class="o">++</span> <span class="k">while</span> <span class="nx">@check</span><span class="p">(</span><span class="nv">temp = </span><span class="nx">@temporary</span> <span class="nx">type</span><span class="p">,</span> <span class="nx">index</span><span class="p">)</span> <span class="o">and</span> <span class="nx">@variables</span><span class="p">[</span><span class="nx">temp</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'reuse'</span>
|
||||
<span class="nx">@variables</span><span class="p">[</span><span class="nx">temp</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'var'</span>
|
||||
<span class="nx">@garbage</span><span class="p">[</span><span class="nx">@garbage</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">push</span> <span class="nx">temp</span> <span class="k">if</span> <span class="nx">@garbage</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nx">temp</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 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="nx">assign</span><span class="o">:</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">-></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="nx">value</span><span class="o">:</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">assigned</span><span class="o">:</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>Does this scope reference any variables that need to be declared in the
|
||||
<span class="nx">@variables</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="nx">value</span><span class="o">:</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">assigned</span><span class="o">:</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>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="nx">hasDeclarations</span><span class="o">:</span> <span class="p">(</span><span class="nx">body</span><span class="p">)</span> <span class="o">-></span>
|
||||
<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">-></span> <span class="nx">val</span> <span class="o">is</span> <span class="s1">'var'</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
|
||||
<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">-></span> <span class="nx">val</span> <span class="o">is</span> <span class="s1">'var'</span> <span class="o">or</span> <span class="nx">val</span> <span class="o">is</span> <span class="s1">'reuse'</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</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="nx">hasAssignments</span><span class="o">:</span> <span class="p">(</span><span class="nx">body</span><span class="p">)</span> <span class="o">-></span>
|
||||
<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">-></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="nx">declaredVariables</span><span class="o">:</span> <span class="o">-></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">'var'</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
|
||||
<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">-></span> <span class="nx">val</span><span class="p">.</span><span class="nx">assigned</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</a> </div> <p>Return the list of variables first declared in this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">declaredVariables</span><span class="o">:</span> <span class="o">-></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">'var'</span> <span class="o">or</span> <span class="nx">val</span> <span class="o">is</span> <span class="s1">'reuse'</span><span class="p">).</span><span class="nx">sort</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>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="nx">assignedVariables</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="s2">"#key = #val.value"</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="nx">compiledDeclarations</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">@declaredVariables</span><span class="p">().</span><span class="nx">join</span> <span class="s1">', '</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="nx">compiledAssignments</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="s2">"#{key} = #{val.value}"</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-18"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-18">#</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="nx">compiledDeclarations</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">@declaredVariables</span><span class="p">().</span><span class="nx">join</span> <span class="s1">', '</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-19">#</a> </div> <p>Compile the JavaScript forall of the variable assignments in this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compiledAssignments</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">@assignedVariables</span><span class="p">().</span><span class="nx">join</span> <span class="s1">', '</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
File diff suppressed because one or more lines are too long
@@ -53,7 +53,7 @@
|
||||
<a href="#pattern_matching">Pattern Matching</a>
|
||||
<a href="#fat_arrow">Function Binding</a>
|
||||
<a href="#embedded">Embedded JavaScript</a>
|
||||
<a href="#switch">Switch/When/Else</a>
|
||||
<a href="#switch">The Switch Statement</a>
|
||||
<a href="#try">Try/Catch/Finally</a>
|
||||
<a href="#comparisons">Chained Comparisons</a>
|
||||
<a href="#interpolation">String and RegExp Interpolation</a>
|
||||
@@ -71,10 +71,7 @@
|
||||
</div>
|
||||
<div class="contents repl_wrapper">
|
||||
<div class="code">
|
||||
<div id="repl_source_wrap"><textarea id="repl_source">reverse = (string) ->
|
||||
string.split('').reverse().join ''
|
||||
|
||||
alert reverse '.eeffoC yrT'</textarea></div>
|
||||
<div id="repl_source_wrap"><textarea id="repl_source">alert "Hello CoffeeScript!"</textarea></div>
|
||||
<pre id="repl_results"></pre>
|
||||
<button class="full_screen">go full screen</button>
|
||||
<button class="minimize">minimize</button>
|
||||
@@ -127,7 +124,7 @@ alert reverse '.eeffoC yrT'</textarea></div>
|
||||
|
||||
<p>
|
||||
<b>Latest Version:</b>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/0.9.0">0.9.0</a>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/0.9.4">0.9.4</a>
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
@@ -172,7 +169,7 @@ alert reverse '.eeffoC yrT'</textarea></div>
|
||||
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.9.0">0.9.0</a>.
|
||||
release: <a href="http://github.com/jashkenas/coffee-script/tarball/0.9.4">0.9.4</a>.
|
||||
To install the CoffeeScript compiler system-wide
|
||||
under <tt>/usr/local</tt>, open the directory and run:
|
||||
</p>
|
||||
@@ -260,6 +257,13 @@ sudo npm install coffee-script</pre>
|
||||
command line. For example:<br /><tt>coffee -e "puts num for num in [10..1]"</tt>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>-r, --require</code></td>
|
||||
<td>
|
||||
Load a library before compiling or executing your script. Can be used
|
||||
to hook in to the compiler (to add Growl notifications, for example).
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--no-wrap</code></td>
|
||||
<td>
|
||||
@@ -709,12 +713,11 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
<p>
|
||||
<span id="switch" class="bookmark"></span>
|
||||
<b class="header">Switch/When/Else</b>
|
||||
<b>Switch</b> statements in JavaScript are rather broken. You can only
|
||||
do comparisons based on string equality, and need to remember to <b>break</b> at the end of
|
||||
every <b>case</b> statement to avoid accidentally falling through to
|
||||
the default case. CoffeeScript compiles <b>switch</b> statements into JavaScript if-else chains, allowing you to
|
||||
compare any object (via <b>===</b>), preventing fall-through, and resulting
|
||||
in a returnable, assignable expression. The format is: <tt>switch</tt> condition,
|
||||
<b>Switch</b> statements in JavaScript are a bit awkward. You need to
|
||||
remember to <b>break</b> at the end of every <b>case</b> statement to
|
||||
avoid accidentally falling through to the default case.
|
||||
CoffeeScript prevents accidental fall-through, and can convert the <tt>switch</tt>
|
||||
into a returnable, assignable expression. The format is: <tt>switch</tt> condition,
|
||||
<tt>when</tt> clauses, <tt>else</tt> the default case.
|
||||
</p>
|
||||
<p>
|
||||
@@ -745,9 +748,8 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
<p>
|
||||
<span id="interpolation" class="bookmark"></span>
|
||||
<b class="header">String and RegExp Interpolation</b>
|
||||
A version of <a href="http://wiki.ecmascript.org/doku.php?id=strawman:string_interpolation">ECMAScript Harmony's proposed string interpolation</a>
|
||||
is included in CoffeeScript. Simple variables can be included by prefixing
|
||||
them with a hash mark.
|
||||
Ruby-style string interpolation is included in CoffeeScript. Double-quoted
|
||||
strings allow for interpolated values, while single-quoted strings are literal.
|
||||
</p>
|
||||
<%= code_for('interpolation', 'quote') %>
|
||||
<p>
|
||||
@@ -804,6 +806,11 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
the Node.js API to rebuild CoffeeScript's parser:
|
||||
</p>
|
||||
<%= code_for('cake_tasks') %>
|
||||
<p>
|
||||
If you need to invoke one task before another — for example, running
|
||||
<tt>build</tt> before <tt>test</tt>, you can use the <tt>invoke</tt> function:
|
||||
<tt>invoke 'build'</tt>
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<span id="scripts" class="bookmark"></span>
|
||||
@@ -900,7 +907,7 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
</li>
|
||||
<li>
|
||||
<b>dsc</b>'s <a href="http://github.com/dsc/coffeecup">CoffeeCup</a>
|
||||
— A Python WSGI middleware that compiles CoffeeScript to JavaScript
|
||||
— a Python WSGI middleware that compiles CoffeeScript to JavaScript
|
||||
on-demand during development.
|
||||
</li>
|
||||
<li>
|
||||
@@ -913,9 +920,19 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
— a custom filter for rendering CoffeeScript inline within
|
||||
<a href="http://haml-lang.com/">HAML</a> templates.
|
||||
</li>
|
||||
<li>
|
||||
<b>chrislloyd</b>'s <a href="http://github.com/chrislloyd/roast">Roast</a>
|
||||
— a CoffeeScript compiler plug-in that allows you to include external
|
||||
source files.
|
||||
</li>
|
||||
<li>
|
||||
<b>mauricemach</b>'s <a href="http://github.com/mauricemach/coffeekup">CoffeeKup</a>
|
||||
— Markup as CoffeeScript. After _why's
|
||||
<a href="http://markaby.github.com/">Markaby</a>.
|
||||
</li>
|
||||
<li>
|
||||
<b>jashkenas</b>'s <a href="http://jashkenas.github.com/docco/">Docco</a>
|
||||
— A quick-and-dirty literate-programming-style documentation generator
|
||||
— a quick-and-dirty literate-programming-style documentation generator
|
||||
for CoffeeScript. Used to produce the annotated source.
|
||||
</li>
|
||||
</ul>
|
||||
@@ -939,6 +956,47 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
<span id="change_log" class="bookmark"></span>
|
||||
Change Log
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.4</b>
|
||||
CoffeeScript now uses appropriately-named temporary variables, and recycles
|
||||
their references after use. Added <tt>require.extensions</tt> support for
|
||||
<b>Node.js 0.3</b>. Loading CoffeeScript in the browser now adds just a
|
||||
single <tt>CoffeeScript</tt> object to global scope.
|
||||
Fixes for implicit object and block comment edge cases.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.3</b>
|
||||
CoffeeScript <tt>switch</tt> statements now compile into JS <tt>switch</tt>
|
||||
statements — they previously compiled into <tt>if/else</tt> chains
|
||||
for JavaScript 1.3 compatibility.
|
||||
Soaking a function invocation is now supported. Users of the RubyMine
|
||||
editor should now be able to use <tt>--watch</tt> mode.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.2</b>
|
||||
Specifying the start and end of a range literal is now optional, eg. <tt>array[3..]</tt>.
|
||||
You can now say <tt>a not instanceof b</tt>.
|
||||
Fixed important bugs with nested significant and non-significant indentation (Issue #637).
|
||||
Added a <tt>--require</tt> flag that allows you to hook into the <tt>coffee</tt> command.
|
||||
Added a custom <tt>jsl.conf</tt> file for our preferred JavaScriptLint setup.
|
||||
Sped up Jison grammar compilation time by flattening rules for operations.
|
||||
Block comments can now be used with JavaScript-minifier-friendly syntax.
|
||||
Added JavaScript's compound assignment bitwise operators. Bugfixes to
|
||||
implicit object literals with leading number and string keys, as the subject
|
||||
of implicit calls, and as part of compound assignment.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.1</b>
|
||||
Bugfix release for <b>0.9.1</b>. Greatly improves the handling of mixed
|
||||
implicit objects, implicit function calls, and implicit indentation.
|
||||
String and regex interpolation is now strictly <tt>#{ ... }</tt> (Ruby style).
|
||||
The compiler now takes a <tt>--require</tt> flag, which specifies scripts
|
||||
to run before compilation.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.0</b>
|
||||
@@ -948,7 +1006,7 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
literals use <tt>:</tt>, as in JavaScript. This allows us to have implicit
|
||||
object literals, and YAML-style object definitions. Half assignments are
|
||||
removed, in favor of <tt>+=</tt>, <tt>or=</tt>, and friends.
|
||||
Interpolation now uses a hash mark <tt>#</tt> instead of the dollar sign
|
||||
Interpolation now uses a hash mark <tt>#</tt> instead of the dollar sign
|
||||
<tt>$</tt> — because dollar signs may be part of a valid JS identifier.
|
||||
Downwards range comprehensions are now safe again, and are optimized to
|
||||
straight for loops when created with integer endpoints.
|
||||
@@ -963,6 +1021,7 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
on the object — useful in constructors and setter functions.
|
||||
Constructor functions can now take splats.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.7.2</b>
|
||||
Quick bugfix (right after 0.7.1) for a problem that prevented <tt>coffee</tt>
|
||||
@@ -1168,7 +1227,7 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
conversion. Splats. Splice literals. Object comprehensions. Blocks.
|
||||
The existential operator. Many thanks to all the folks who posted issues,
|
||||
with special thanks to
|
||||
<a href="http://github.com/kamatsu">Liam O'Connor-Davis</a> for whitespace
|
||||
<a href="http://github.com/liamoc">Liam O'Connor-Davis</a> for whitespace
|
||||
and expression help.
|
||||
</p>
|
||||
|
||||
|
||||
@@ -5,11 +5,13 @@ if (ignition === true) {
|
||||
if (band !== SpinalTap) {
|
||||
volume = 10;
|
||||
}
|
||||
if (!(answer === false)) {
|
||||
if (answer !== false) {
|
||||
letTheWildRumpusBegin();
|
||||
}
|
||||
car.speed < limit ? accelerate() : null;
|
||||
if (47 === pick || 92 === pick || 13 === pick) {
|
||||
if (car.speed < limit) {
|
||||
accelerate();
|
||||
}
|
||||
if ((47 === pick || 92 === pick || 13 === pick)) {
|
||||
winner = true;
|
||||
}
|
||||
print(inspect("My name is " + this.name));
|
||||
@@ -1,18 +1,18 @@
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, food, lunch, roid, roid2;
|
||||
var _i, _j, _len, _len2, _ref, _ref2, _result, food, lunch, roid, roid2;
|
||||
lunch = (function() {
|
||||
_a = []; _c = ['toast', 'cheese', 'wine'];
|
||||
for (_b = 0, _d = _c.length; _b < _d; _b++) {
|
||||
food = _c[_b];
|
||||
_a.push(eat(food));
|
||||
_result = []; _ref = ['toast', 'cheese', 'wine'];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
food = _ref[_i];
|
||||
_result.push(eat(food));
|
||||
}
|
||||
return _a;
|
||||
return _result;
|
||||
})();
|
||||
_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];
|
||||
_ref = asteroids;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
roid = _ref[_i];
|
||||
_ref2 = asteroids;
|
||||
for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
|
||||
roid2 = _ref2[_j];
|
||||
if (roid !== roid2) {
|
||||
if (roid.overlaps(roid2)) {
|
||||
roid.explode();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
CoffeeScript Compiler v0.9.0
|
||||
CoffeeScript Compiler v0.9.4
|
||||
Released under the MIT License
|
||||
*/
|
||||
@@ -1,10 +1,10 @@
|
||||
var fs;
|
||||
fs = require('fs');
|
||||
option('-o', '--output [DIR]', 'directory for compiled code');
|
||||
task('build:parser', 'rebuild the Jison parser', function() {
|
||||
task('build:parser', 'rebuild the Jison parser', function(options) {
|
||||
var code, dir;
|
||||
require('jison');
|
||||
code = require('./lib/grammar').parser.generate();
|
||||
dir = options.output || 'lib';
|
||||
return fs.writeFile(("" + dir + "/parser.js"), code);
|
||||
return fs.writeFile("" + (dir) + "/parser.js", code);
|
||||
});
|
||||
@@ -5,10 +5,10 @@ var __extends = function(child, parent) {
|
||||
child.prototype = new ctor();
|
||||
child.prototype.constructor = child;
|
||||
if (typeof parent.extended === "function") parent.extended(child);
|
||||
child.__superClass__ = parent.prototype;
|
||||
child.__super__ = parent.prototype;
|
||||
};
|
||||
Animal = function(_a) {
|
||||
this.name = _a;
|
||||
Animal = function(_arg) {
|
||||
this.name = _arg;
|
||||
return this;
|
||||
};
|
||||
Animal.prototype.move = function(meters) {
|
||||
@@ -20,7 +20,7 @@ Snake = function() {
|
||||
__extends(Snake, Animal);
|
||||
Snake.prototype.move = function() {
|
||||
alert("Slithering...");
|
||||
return Snake.__superClass__.move.call(this, 5);
|
||||
return Snake.__super__.move.call(this, 5);
|
||||
};
|
||||
Horse = function() {
|
||||
return Animal.apply(this, arguments);
|
||||
@@ -28,7 +28,7 @@ Horse = function() {
|
||||
__extends(Horse, Animal);
|
||||
Horse.prototype.move = function() {
|
||||
alert("Galloping...");
|
||||
return Horse.__superClass__.move.call(this, 45);
|
||||
return Horse.__super__.move.call(this, 45);
|
||||
};
|
||||
sam = new Snake("Sammy the Python");
|
||||
tom = new Horse("Tommy the Palomino");
|
||||
|
||||
@@ -9,4 +9,4 @@ if (happy && knowsIt) {
|
||||
showIt();
|
||||
}
|
||||
date = friday ? sue : jill;
|
||||
options = options || defaults;
|
||||
options || (options = defaults);
|
||||
@@ -1,11 +1,11 @@
|
||||
var _a, _b, _c, globals, name;
|
||||
var _i, _ref, _result, globals, name;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
globals = (function() {
|
||||
_b = []; _c = window;
|
||||
for (name in _c) {
|
||||
if (!__hasProp.call(_c, name)) continue;
|
||||
_a = _c[name];
|
||||
_b.push(name);
|
||||
_result = []; _ref = window;
|
||||
for (name in _ref) {
|
||||
if (!__hasProp.call(_ref, name)) continue;
|
||||
_i = _ref[name];
|
||||
_result.push(name);
|
||||
}
|
||||
return _b;
|
||||
return _result;
|
||||
})().slice(0, 10);
|
||||
@@ -1,3 +1,3 @@
|
||||
var author, quote;
|
||||
author = "Wittgenstein";
|
||||
quote = ("A picture is a fact. -- " + author);
|
||||
quote = ("A picture is a fact. -- " + (author));
|
||||
@@ -1,4 +1,4 @@
|
||||
var dates, sentence, sep;
|
||||
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"));
|
||||
@@ -1,8 +1,8 @@
|
||||
var _a, city, forecast, temp, weatherReport;
|
||||
var _ref, city, forecast, temp, weatherReport;
|
||||
weatherReport = function(location) {
|
||||
return [location, 72, "Mostly Sunny"];
|
||||
};
|
||||
_a = weatherReport("Berkeley, CA");
|
||||
city = _a[0];
|
||||
temp = _a[1];
|
||||
forecast = _a[2];
|
||||
_ref = weatherReport("Berkeley, CA");
|
||||
city = _ref[0];
|
||||
temp = _ref[1];
|
||||
forecast = _ref[2];
|
||||
@@ -1,4 +1,4 @@
|
||||
var _a, _b, age, ages, child, yearsOld;
|
||||
var _ref, _result, age, ages, child, yearsOld;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
yearsOld = {
|
||||
max: 10,
|
||||
@@ -6,11 +6,11 @@ yearsOld = {
|
||||
tim: 11
|
||||
};
|
||||
ages = (function() {
|
||||
_a = []; _b = yearsOld;
|
||||
for (child in _b) {
|
||||
if (!__hasProp.call(_b, child)) continue;
|
||||
age = _b[child];
|
||||
_a.push(child + " is " + age);
|
||||
_result = []; _ref = yearsOld;
|
||||
for (child in _ref) {
|
||||
if (!__hasProp.call(_ref, child)) continue;
|
||||
age = _ref[child];
|
||||
_result.push(child + " is " + age);
|
||||
}
|
||||
return _a;
|
||||
return _result;
|
||||
})();
|
||||
@@ -1,4 +1,4 @@
|
||||
var _a, _b, _c, city, futurists, name, street;
|
||||
var _ref, _ref2, _ref3, city, futurists, name, street;
|
||||
futurists = {
|
||||
sculptor: "Umberto Boccioni",
|
||||
painter: "Vladimir Burliuk",
|
||||
@@ -7,9 +7,9 @@ futurists = {
|
||||
address: ["Via Roma 42R", "Bellagio, Italy 22021"]
|
||||
}
|
||||
};
|
||||
_a = futurists;
|
||||
_b = _a.poet;
|
||||
name = _b.name;
|
||||
_c = _b.address;
|
||||
street = _c[0];
|
||||
city = _c[1];
|
||||
_ref = futurists;
|
||||
_ref2 = _ref.poet;
|
||||
name = _ref2.name;
|
||||
_ref3 = _ref2.address;
|
||||
street = _ref3[0];
|
||||
city = _ref3[1];
|
||||
@@ -1,4 +1,4 @@
|
||||
var _a, _b, _c, _d, cubes, list, math, num, number, opposite, race, square;
|
||||
var _i, _len, _ref, _result, cubes, list, math, num, number, opposite, race, square;
|
||||
var __slice = Array.prototype.slice;
|
||||
number = 42;
|
||||
opposite = true;
|
||||
@@ -25,10 +25,10 @@ if (typeof elvis !== "undefined" && elvis !== null) {
|
||||
alert("I knew it!");
|
||||
}
|
||||
cubes = (function() {
|
||||
_a = []; _c = list;
|
||||
for (_b = 0, _d = _c.length; _b < _d; _b++) {
|
||||
num = _c[_b];
|
||||
_a.push(math.cube(num));
|
||||
_result = []; _ref = list;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
num = _ref[_i];
|
||||
_result.push(math.cube(num));
|
||||
}
|
||||
return _a;
|
||||
return _result;
|
||||
})();
|
||||
@@ -1,6 +1,6 @@
|
||||
var _a, theBait, theSwitch;
|
||||
var _ref, theBait, theSwitch;
|
||||
theBait = 1000;
|
||||
theSwitch = 0;
|
||||
_a = [theSwitch, theBait];
|
||||
theBait = _a[0];
|
||||
theSwitch = _a[1];
|
||||
_ref = [theSwitch, theBait];
|
||||
theBait = _ref[0];
|
||||
theSwitch = _ref[1];
|
||||
@@ -1,7 +1,7 @@
|
||||
var _a, close, contents, open, tag;
|
||||
var _ref, close, contents, open, tag;
|
||||
var __slice = Array.prototype.slice;
|
||||
tag = "<impossible>";
|
||||
_a = tag.split("");
|
||||
open = _a[0];
|
||||
contents = __slice.call(_a, 1, _a.length - 1);
|
||||
close = _a[_a.length - 1];
|
||||
_ref = tag.split("");
|
||||
open = _ref[0];
|
||||
contents = __slice.call(_ref, 1, _ref.length - 1);
|
||||
close = _ref[_ref.length - 1];
|
||||
@@ -1,19 +1,19 @@
|
||||
var _a, countdown, deliverEggs, num;
|
||||
var _result, countdown, deliverEggs, num;
|
||||
countdown = (function() {
|
||||
_a = [];
|
||||
_result = [];
|
||||
for (num = 10; num >= 1; num--) {
|
||||
_a.push(num);
|
||||
_result.push(num);
|
||||
}
|
||||
return _a;
|
||||
return _result;
|
||||
})();
|
||||
deliverEggs = function() {
|
||||
var _b, _c, dozen, i;
|
||||
_b = []; _c = eggs.length;
|
||||
for (i = 0; (0 <= _c ? i < _c : i > _c); i += 12) {
|
||||
_b.push((function() {
|
||||
var _ref, _result2, dozen, i;
|
||||
_result2 = []; _ref = eggs.length;
|
||||
for (i = 0; (0 <= _ref ? i < _ref : i > _ref); i += 12) {
|
||||
_result2.push((function() {
|
||||
dozen = eggs.slice(i, i + 12);
|
||||
return deliver(new eggCarton(dozen));
|
||||
})());
|
||||
}
|
||||
return _b;
|
||||
return _result2;
|
||||
};
|
||||
@@ -1,2 +1,2 @@
|
||||
var _a, _b;
|
||||
(_b = (typeof (_a = (lottery.drawWinner())) === "undefined" || _a == undefined ? undefined : _a.address)) == undefined ? undefined : _b.zipcode;
|
||||
var _ref, _ref2;
|
||||
(typeof (_ref2 = ((_ref = lottery.drawWinner()))) === "undefined" || _ref2 === null) ? undefined : _ref2.address == null ? undefined : _ref2.address.zipcode;
|
||||
@@ -1,7 +1,7 @@
|
||||
var mobyDick;
|
||||
mobyDick = "Call me Ishmael. Some years ago -- \
|
||||
never mind how long precisely -- having little \
|
||||
or no money in my purse, and nothing particular \
|
||||
to interest me on shore, I thought I would sail \
|
||||
about a little and see the watery part of the \
|
||||
world...";
|
||||
mobyDick = "Call me Ishmael. Some years ago --\
|
||||
never mind how long precisely -- having little\
|
||||
or no money in my purse, and nothing particular\
|
||||
to interest me on shore, I thought I would sail\
|
||||
about a little and see the watery part of the\
|
||||
world...";
|
||||
@@ -1,16 +1,23 @@
|
||||
if (day === "Mon") {
|
||||
goToWork();
|
||||
} else if (day === "Tue") {
|
||||
goToThePark();
|
||||
} else if (day === "Thu") {
|
||||
goIceFishing();
|
||||
} else if (day === "Fri" || day === "Sat") {
|
||||
if (day === bingoDay) {
|
||||
goToBingo();
|
||||
goDancing();
|
||||
}
|
||||
} else if (day === "Sun") {
|
||||
goToChurch();
|
||||
} else {
|
||||
goToWork();
|
||||
switch (day) {
|
||||
case "Mon":
|
||||
go(work);
|
||||
break;
|
||||
case "Tue":
|
||||
go(relax);
|
||||
break;
|
||||
case "Thu":
|
||||
go(iceFishing);
|
||||
break;
|
||||
case "Fri":
|
||||
case "Sat":
|
||||
if (day === bingoDay) {
|
||||
go(bingo);
|
||||
go(dancing);
|
||||
}
|
||||
break;
|
||||
case "Sun":
|
||||
go(church);
|
||||
break;
|
||||
default:
|
||||
go(work);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
var _a, lyrics, num;
|
||||
var _result, lyrics, num;
|
||||
if (this.studyingEconomics) {
|
||||
while (supply > demand) {
|
||||
buy();
|
||||
@@ -9,10 +9,10 @@ if (this.studyingEconomics) {
|
||||
}
|
||||
num = 6;
|
||||
lyrics = (function() {
|
||||
_a = [];
|
||||
_result = [];
|
||||
while (num -= 1) {
|
||||
_a.push(num + " little monkeys, jumping on the bed. \
|
||||
One fell out and bumped his head.");
|
||||
_result.push(num + " little monkeys, jumping on the bed.\
|
||||
One fell out and bumped his head.");
|
||||
}
|
||||
return _a;
|
||||
return _result;
|
||||
})();
|
||||
@@ -71,7 +71,7 @@
|
||||
|
||||
|
||||
# Current version.
|
||||
_.VERSION = '1.0.2'
|
||||
_.VERSION = '1.1.0'
|
||||
|
||||
|
||||
# Collection Functions
|
||||
@@ -104,8 +104,10 @@
|
||||
|
||||
# **Reduce** builds up a single result from a list of values. Also known as
|
||||
# **inject**, or **foldl**. Uses JavaScript 1.8's version of **reduce**, if possible.
|
||||
_.reduce = (obj, memo, iterator, context) ->
|
||||
return obj.reduce(_.bind(iterator, context), memo) if nativeReduce and obj.reduce is nativeReduce
|
||||
_.reduce = (obj, iterator, memo, context) ->
|
||||
if nativeReduce and obj.reduce is nativeReduce
|
||||
iterator = _.bind iterator, context if context
|
||||
return obj.reduce iterator, memo
|
||||
_.each obj, (value, index, list) ->
|
||||
memo = iterator.call context, memo, value, index, list
|
||||
memo
|
||||
@@ -113,11 +115,12 @@
|
||||
|
||||
# The right-associative version of **reduce**, also known as **foldr**. Uses
|
||||
# JavaScript 1.8's version of **reduceRight**, if available.
|
||||
_.reduceRight = (obj, memo, iterator, context) ->
|
||||
return obj.reduceRight(_.bind(iterator, context), memo) if nativeReduceRight and obj.reduceRight is nativeReduceRight
|
||||
_.each _.clone(_.toArray(obj)).reverse(), (value, index) ->
|
||||
memo = iterator.call context, memo, value, index, obj
|
||||
memo
|
||||
_.reduceRight = (obj, iterator, memo, context) ->
|
||||
if nativeReduceRight and obj.reduceRight is nativeReduceRight
|
||||
iterator = _.bind iterator, context if context
|
||||
return obj.reduceRight iterator, memo
|
||||
reversed = _.clone(_.toArray(obj)).reverse()
|
||||
_.reduce reversed, iterator, memo, context
|
||||
|
||||
|
||||
# Return the first value which passes a truth test.
|
||||
@@ -273,10 +276,11 @@
|
||||
|
||||
# Return a completely flattened version of an array.
|
||||
_.flatten = (array) ->
|
||||
_.reduce array, [], (memo, value) ->
|
||||
_.reduce array, (memo, value) ->
|
||||
return memo.concat(_.flatten(value)) if _.isArray value
|
||||
memo.push value
|
||||
memo
|
||||
, []
|
||||
|
||||
|
||||
# Return a version of the array that does not contain the specified value(s).
|
||||
@@ -378,6 +382,16 @@
|
||||
setTimeout((-> func.apply(func, args)), wait)
|
||||
|
||||
|
||||
# Memoize an expensive function by storing its results.
|
||||
_.memoize = (func, hasher) ->
|
||||
memo = {}
|
||||
hasher or= _.identity
|
||||
->
|
||||
key = hasher.apply this, arguments
|
||||
return memo[key] if key of memo
|
||||
memo[key] = func.apply this, arguments
|
||||
|
||||
|
||||
# Defers a function, scheduling it to run after the current call stack has
|
||||
# cleared.
|
||||
_.defer = (func) ->
|
||||
@@ -457,7 +471,7 @@
|
||||
# Check dates' integer values.
|
||||
return a.getTime() is b.getTime() if _.isDate(a) and _.isDate(b)
|
||||
# Both are NaN?
|
||||
return true if _.isNaN(a) and _.isNaN(b)
|
||||
return false if _.isNaN(a) and _.isNaN(b)
|
||||
# Compare regular expressions.
|
||||
if _.isRegExp(a) and _.isRegExp(b)
|
||||
return a.source is b.source and
|
||||
@@ -473,13 +487,13 @@
|
||||
# Different object sizes?
|
||||
return false if aKeys.length isnt bKeys.length
|
||||
# Recursive comparison of contents.
|
||||
(return false) for key, val of a when !(key in b) or !_.isEqual(val, b[key])
|
||||
(return false) for all key, val of a when !(key of b) or !_.isEqual(val, b[key])
|
||||
true
|
||||
|
||||
|
||||
# Is a given array or object empty?
|
||||
_.isEmpty = (obj) ->
|
||||
return obj.length is 0 if _.isArray obj
|
||||
return obj.length is 0 if _.isArray(obj) or _.isString(obj)
|
||||
(return false) for key of obj when hasOwnProperty.call(obj, key)
|
||||
true
|
||||
|
||||
@@ -582,16 +596,19 @@
|
||||
# JavaScript templating a-la **ERB**, pilfered from John Resig's
|
||||
# *Secrets of the JavaScript Ninja*, page 83.
|
||||
# Single-quote fix from Rick Strahl.
|
||||
# With alterations for arbitrary delimiters, and to preserve whitespace.
|
||||
_.template = (str, data) ->
|
||||
c = _.templateSettings
|
||||
endMatch = new RegExp("'(?=[^"+c.end.substr(0, 1)+"]*"+escapeRegExp(c.end)+")","g")
|
||||
fn = new Function 'obj',
|
||||
'var p=[],print=function(){p.push.apply(p,arguments);};' +
|
||||
'with(obj){p.push(\'' +
|
||||
str.replace(/[\r\t\n]/g, " ")
|
||||
.replace(endMatch,"\t")
|
||||
'with(obj||{}){p.push(\'' +
|
||||
str.replace(/\r/g, '\\r')
|
||||
.replace(/\n/g, '\\n')
|
||||
.replace(/\t/g, '\\t')
|
||||
.replace(endMatch,"✄")
|
||||
.split("'").join("\\'")
|
||||
.split("\t").join("'")
|
||||
.split("✄").join("'")
|
||||
.replace(c.interpolate, "',$1,'")
|
||||
.split(c.start).join("');")
|
||||
.split(c.end).join("p.push('") +
|
||||
@@ -602,15 +619,16 @@
|
||||
# Aliases
|
||||
# -------
|
||||
|
||||
_.forEach = _.each
|
||||
_.foldl = _.inject = _.reduce
|
||||
_.foldr = _.reduceRight
|
||||
_.select = _.filter
|
||||
_.all = _.every
|
||||
_.any = _.some
|
||||
_.head = _.first
|
||||
_.tail = _.rest
|
||||
_.methods = _.functions
|
||||
_.forEach = _.each
|
||||
_.foldl = _.inject = _.reduce
|
||||
_.foldr = _.reduceRight
|
||||
_.select = _.filter
|
||||
_.all = _.every
|
||||
_.any = _.some
|
||||
_.contains = _.include
|
||||
_.head = _.first
|
||||
_.tail = _.rest
|
||||
_.methods = _.functions
|
||||
|
||||
|
||||
# Setup the OOP Wrapper
|
||||
|
||||
File diff suppressed because one or more lines are too long
44
extras/jsl.conf
Normal file
44
extras/jsl.conf
Normal file
@@ -0,0 +1,44 @@
|
||||
# JavaScriptLint configuration file for CoffeeScript.
|
||||
|
||||
+no_return_value # function {0} does not always return a value
|
||||
+duplicate_formal # duplicate formal argument {0}
|
||||
-equal_as_assign # test for equality (==) mistyped as assignment (=)?{0}
|
||||
+var_hides_arg # variable {0} hides argument
|
||||
+redeclared_var # redeclaration of {0} {1}
|
||||
+anon_no_return_value # anonymous function does not always return a value
|
||||
+missing_semicolon # missing semicolon
|
||||
+meaningless_block # meaningless block; curly braces have no impact
|
||||
+comma_separated_stmts # multiple statements separated by commas (use semicolons?)
|
||||
+unreachable_code # unreachable code
|
||||
+missing_break # missing break statement
|
||||
+missing_break_for_last_case # missing break statement for last case in switch
|
||||
-comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
|
||||
+inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement
|
||||
+useless_void # use of the void type may be unnecessary (void is always undefined)
|
||||
+multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
|
||||
+use_of_label # use of label
|
||||
-block_without_braces # block statement without curly braces
|
||||
+leading_decimal_point # leading decimal point may indicate a number or an object member
|
||||
+trailing_decimal_point # trailing decimal point may indicate a number or an object member
|
||||
+octal_number # leading zeros make an octal number
|
||||
+nested_comment # nested comment
|
||||
+misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
|
||||
+ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement
|
||||
+empty_statement # empty statement or extra semicolon
|
||||
-missing_option_explicit # the "option explicit" control comment is missing
|
||||
+partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag
|
||||
+dup_option_explicit # duplicate "option explicit" control comment
|
||||
+useless_assign # useless assignment
|
||||
+ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity
|
||||
+ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent)
|
||||
-missing_default_case # missing default case in switch statement
|
||||
+duplicate_case_in_switch # duplicate case in switch statements
|
||||
+default_not_at_end # the default case is not at the end of the switch statement
|
||||
+legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax
|
||||
+jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax
|
||||
+useless_comparison # useless comparison; comparing identical expressions
|
||||
+with_statement # with statement hides undeclared variables; use temporary variable instead
|
||||
+trailing_comma_in_array # extra comma is not recommended in array initializers
|
||||
+assign_to_function_call # assignment to a function call
|
||||
+parseint_missing_radix # parseInt missing radix parameter
|
||||
+lambda_assign_requires_semicolon
|
||||
528
index.html
528
index.html
@@ -40,7 +40,7 @@
|
||||
<a href="#pattern_matching">Pattern Matching</a>
|
||||
<a href="#fat_arrow">Function Binding</a>
|
||||
<a href="#embedded">Embedded JavaScript</a>
|
||||
<a href="#switch">Switch/When/Else</a>
|
||||
<a href="#switch">The Switch Statement</a>
|
||||
<a href="#try">Try/Catch/Finally</a>
|
||||
<a href="#comparisons">Chained Comparisons</a>
|
||||
<a href="#interpolation">String and RegExp Interpolation</a>
|
||||
@@ -58,10 +58,7 @@
|
||||
</div>
|
||||
<div class="contents repl_wrapper">
|
||||
<div class="code">
|
||||
<div id="repl_source_wrap"><textarea id="repl_source">reverse = (string) ->
|
||||
string.split('').reverse().join ''
|
||||
|
||||
alert reverse '.eeffoC yrT'</textarea></div>
|
||||
<div id="repl_source_wrap"><textarea id="repl_source">alert "Hello CoffeeScript!"</textarea></div>
|
||||
<pre id="repl_results"></pre>
|
||||
<button class="full_screen">go full screen</button>
|
||||
<button class="minimize">minimize</button>
|
||||
@@ -114,7 +111,7 @@ alert reverse '.eeffoC yrT'</textarea></div>
|
||||
|
||||
<p>
|
||||
<b>Latest Version:</b>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/0.9.0">0.9.0</a>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/0.9.4">0.9.4</a>
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
@@ -139,8 +136,8 @@ list <span class="Keyword">=</span> [<span class="Number">1</span>, <span class=
|
||||
|
||||
<span class="Comment"><span class="Comment">#</span> Objects:</span>
|
||||
math <span class="Keyword">=</span>
|
||||
root<span class="Keyword">:</span> Math.sqrt
|
||||
square<span class="Keyword">:</span> square
|
||||
root: Math.sqrt
|
||||
square: square
|
||||
<span class="FunctionName">cube</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">x</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> x <span class="Keyword">*</span> square x
|
||||
|
||||
<span class="Comment"><span class="Comment">#</span> Splats:</span>
|
||||
@@ -152,7 +149,7 @@ alert <span class="String"><span class="String">"</span>I knew it!<span cla
|
||||
|
||||
<span class="Comment"><span class="Comment">#</span> Array comprehensions:</span>
|
||||
cubes <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, cubes, list, math, num, number, opposite, race, square;
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _i, _len, _ref, _result, cubes, list, math, num, number, opposite, race, square;
|
||||
<span class="Storage">var</span> __slice <span class="Keyword">=</span> <span class="LibraryClassType">Array</span>.<span class="LibraryConstant">prototype</span>.slice;
|
||||
number <span class="Keyword">=</span> <span class="Number">42</span>;
|
||||
opposite <span class="Keyword">=</span> <span class="BuiltInConstant">true</span>;
|
||||
@@ -179,14 +176,14 @@ math <span class="Keyword">=</span> {
|
||||
<span class="LibraryFunction">alert</span>(<span class="String"><span class="String">"</span>I knew it!<span class="String">"</span></span>);
|
||||
}
|
||||
cubes <span class="Keyword">=</span> (<span class="Storage">function</span>() {
|
||||
_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"><</span> _d; _b<span class="Keyword">++</span>) {
|
||||
num <span class="Keyword">=</span> _c[_b];
|
||||
_a.<span class="LibraryFunction">push</span>(math.cube(num));
|
||||
_result <span class="Keyword">=</span> []; _ref <span class="Keyword">=</span> list;
|
||||
<span class="Keyword">for</span> (_i <span class="Keyword">=</span> <span class="Number">0</span>, _len <span class="Keyword">=</span> _ref.<span class="LibraryConstant">length</span>; _i <span class="Keyword"><</span> _len; _i<span class="Keyword">++</span>) {
|
||||
num <span class="Keyword">=</span> _ref[_i];
|
||||
_result.<span class="LibraryFunction">push</span>(math.cube(num));
|
||||
}
|
||||
<span class="Keyword">return</span> _a;
|
||||
<span class="Keyword">return</span> _result;
|
||||
})();
|
||||
</pre><button onclick='javascript: var _a, _b, _c, _d, cubes, list, math, num, number, opposite, race, square;
|
||||
</pre><button onclick='javascript: var _i, _len, _ref, _result, cubes, list, math, num, number, opposite, race, square;
|
||||
var __slice = Array.prototype.slice;
|
||||
number = 42;
|
||||
opposite = true;
|
||||
@@ -213,12 +210,12 @@ if (typeof elvis !== "undefined" && elvis !== null) {
|
||||
alert("I knew it!");
|
||||
}
|
||||
cubes = (function() {
|
||||
_a = []; _c = list;
|
||||
for (_b = 0, _d = _c.length; _b < _d; _b++) {
|
||||
num = _c[_b];
|
||||
_a.push(math.cube(num));
|
||||
_result = []; _ref = list;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
num = _ref[_i];
|
||||
_result.push(math.cube(num));
|
||||
}
|
||||
return _a;
|
||||
return _result;
|
||||
})();;alert(cubes);'>run: cubes</button><br class='clear' /></div>
|
||||
|
||||
<p>
|
||||
@@ -254,7 +251,7 @@ cubes = (function() {
|
||||
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.9.0">0.9.0</a>.
|
||||
release: <a href="http://github.com/jashkenas/coffee-script/tarball/0.9.4">0.9.4</a>.
|
||||
To install the CoffeeScript compiler system-wide
|
||||
under <tt>/usr/local</tt>, open the directory and run:
|
||||
</p>
|
||||
@@ -342,6 +339,13 @@ sudo npm install coffee-script</pre>
|
||||
command line. For example:<br /><tt>coffee -e "puts num for num in [10..1]"</tt>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>-r, --require</code></td>
|
||||
<td>
|
||||
Load a library before compiling or executing your script. Can be used
|
||||
to hook in to the compiler (to add Growl notifications, for example).
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>--no-wrap</code></td>
|
||||
<td>
|
||||
@@ -463,7 +467,7 @@ cube = function(x) {
|
||||
</p>
|
||||
<div class='code'><pre class="idle">song <span class="Keyword">=</span> [<span class="String"><span class="String">"</span>do<span class="String">"</span></span>, <span class="String"><span class="String">"</span>re<span class="String">"</span></span>, <span class="String"><span class="String">"</span>mi<span class="String">"</span></span>, <span class="String"><span class="String">"</span>fa<span class="String">"</span></span>, <span class="String"><span class="String">"</span>so<span class="String">"</span></span>]
|
||||
|
||||
singers <span class="Keyword">=</span> {Jagger<span class="Keyword">:</span> <span class="String"><span class="String">"</span>Rock<span class="String">"</span></span>, Elvis<span class="Keyword">:</span> <span class="String"><span class="String">"</span>Roll<span class="String">"</span></span>}
|
||||
singers <span class="Keyword">=</span> {Jagger: <span class="String"><span class="String">"</span>Rock<span class="String">"</span></span>, Elvis: <span class="String"><span class="String">"</span>Roll<span class="String">"</span></span>}
|
||||
|
||||
matrix <span class="Keyword">=</span> [
|
||||
<span class="Number">1</span>, <span class="Number">0</span>, <span class="Number">1</span>
|
||||
@@ -472,12 +476,12 @@ matrix <span class="Keyword">=</span> [
|
||||
]
|
||||
|
||||
kids <span class="Keyword">=</span>
|
||||
brother<span class="Keyword">:</span>
|
||||
name<span class="Keyword">:</span> <span class="String"><span class="String">"</span>Max<span class="String">"</span></span>
|
||||
age<span class="Keyword">:</span> <span class="Number">11</span>
|
||||
sister<span class="Keyword">:</span>
|
||||
name<span class="Keyword">:</span> <span class="String"><span class="String">"</span>Ida<span class="String">"</span></span>
|
||||
age<span class="Keyword">:</span> <span class="Number">9</span>
|
||||
brother:
|
||||
name: <span class="String"><span class="String">"</span>Max<span class="String">"</span></span>
|
||||
age: <span class="Number">11</span>
|
||||
sister:
|
||||
name: <span class="String"><span class="String">"</span>Ida<span class="String">"</span></span>
|
||||
age: <span class="Number">9</span>
|
||||
</pre><pre class="idle"><span class="Storage">var</span> kids, matrix, singers, song;
|
||||
song <span class="Keyword">=</span> [<span class="String"><span class="String">"</span>do<span class="String">"</span></span>, <span class="String"><span class="String">"</span>re<span class="String">"</span></span>, <span class="String"><span class="String">"</span>mi<span class="String">"</span></span>, <span class="String"><span class="String">"</span>fa<span class="String">"</span></span>, <span class="String"><span class="String">"</span>so<span class="String">"</span></span>];
|
||||
singers <span class="Keyword">=</span> {
|
||||
@@ -517,7 +521,7 @@ kids = {
|
||||
of an object, without quoting them as strings. CoffeeScript notices and quotes
|
||||
them for you, so you don't have to worry about it (say, when using jQuery).
|
||||
</p>
|
||||
<div class='code'><pre class="idle">$(<span class="String"><span class="String">'</span>.account<span class="String">'</span></span>).css class<span class="Keyword">:</span> <span class="String"><span class="String">'</span>active<span class="String">'</span></span>
|
||||
<div class='code'><pre class="idle">$(<span class="String"><span class="String">'</span>.account<span class="String">'</span></span>).css class: <span class="String"><span class="String">'</span>active<span class="String">'</span></span>
|
||||
</pre><pre class="idle"><span class="Keyword">$</span>(<span class="String"><span class="String">'</span>.account<span class="String">'</span></span>).css({
|
||||
<span class="String"><span class="String">"</span>class<span class="String">"</span></span>: <span class="String"><span class="String">'</span>active<span class="String">'</span></span>
|
||||
});
|
||||
@@ -617,7 +621,7 @@ options or<span class="Keyword">=</span> defaults
|
||||
showIt();
|
||||
}
|
||||
date <span class="Keyword">=</span> friday ? sue : jill;
|
||||
options <span class="Keyword">=</span> options <span class="Keyword">||</span> defaults;
|
||||
options <span class="Keyword">||</span> (options <span class="Keyword">=</span> defaults);
|
||||
</pre><br class='clear' /></div>
|
||||
|
||||
<p>
|
||||
@@ -674,11 +678,13 @@ print inspect <span class="String"><span class="String">"</span>My name is
|
||||
<span class="Keyword">if</span> (band <span class="Keyword">!</span><span class="Keyword">==</span> SpinalTap) {
|
||||
volume <span class="Keyword">=</span> <span class="Number">10</span>;
|
||||
}
|
||||
<span class="Keyword">if</span> (<span class="Keyword">!</span>(answer <span class="Keyword">===</span> <span class="BuiltInConstant">false</span>)) {
|
||||
<span class="Keyword">if</span> (answer <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">false</span>) {
|
||||
letTheWildRumpusBegin();
|
||||
}
|
||||
car.speed <span class="Keyword"><</span> limit ? accelerate() : <span class="BuiltInConstant">null</span>;
|
||||
<span class="Keyword">if</span> (<span class="Number">47</span> <span class="Keyword">===</span> pick <span class="Keyword">||</span> <span class="Number">92</span> <span class="Keyword">===</span> pick <span class="Keyword">||</span> <span class="Number">13</span> <span class="Keyword">===</span> pick) {
|
||||
<span class="Keyword">if</span> (car.speed <span class="Keyword"><</span> limit) {
|
||||
accelerate();
|
||||
}
|
||||
<span class="Keyword">if</span> ((<span class="Number">47</span> <span class="Keyword">===</span> pick <span class="Keyword">||</span> <span class="Number">92</span> <span class="Keyword">===</span> pick <span class="Keyword">||</span> <span class="Number">13</span> <span class="Keyword">===</span> pick)) {
|
||||
winner <span class="Keyword">=</span> <span class="BuiltInConstant">true</span>;
|
||||
}
|
||||
<span class="LibraryFunction">print</span>(inspect(<span class="String"><span class="String">"</span>My name is <span class="String">"</span></span> <span class="Keyword">+</span> <span class="Variable">this</span>.<span class="LibraryConstant">name</span>));
|
||||
@@ -766,7 +772,7 @@ num <span class="Keyword">=</span> <span class="Number">6</span>
|
||||
lyrics <span class="Keyword">=</span> <span class="Keyword">while</span> num <span class="Keyword">-</span><span class="Keyword">=</span> <span class="Number">1</span>
|
||||
num <span class="Keyword">+</span> <span class="String"><span class="String">"</span> little monkeys, jumping on the bed.</span>
|
||||
<span class="String"> One fell out and bumped his head.<span class="String">"</span></span>
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _a, lyrics, num;
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _result, lyrics, num;
|
||||
<span class="Keyword">if</span> (<span class="Variable">this</span>.studyingEconomics) {
|
||||
<span class="Keyword">while</span> (supply <span class="Keyword">></span> demand) {
|
||||
buy();
|
||||
@@ -777,14 +783,14 @@ lyrics <span class="Keyword">=</span> <span class="Keyword">while</span> num <sp
|
||||
}
|
||||
num <span class="Keyword">=</span> <span class="Number">6</span>;
|
||||
lyrics <span class="Keyword">=</span> (<span class="Storage">function</span>() {
|
||||
_a <span class="Keyword">=</span> [];
|
||||
_result <span class="Keyword">=</span> [];
|
||||
<span class="Keyword">while</span> (num <span class="Keyword">-</span><span class="Keyword">=</span> <span class="Number">1</span>) {
|
||||
_a.<span class="LibraryFunction">push</span>(num <span class="Keyword">+</span> <span class="String"><span class="String">"</span> little monkeys, jumping on the bed. \</span>
|
||||
<span class="String">One fell out and bumped his head.<span class="String">"</span></span>);
|
||||
_result.<span class="LibraryFunction">push</span>(num <span class="Keyword">+</span> <span class="String"><span class="String">"</span> little monkeys, jumping on the bed.\</span>
|
||||
<span class="String"> One fell out and bumped his head.<span class="String">"</span></span>);
|
||||
}
|
||||
<span class="Keyword">return</span> _a;
|
||||
<span class="Keyword">return</span> _result;
|
||||
})();
|
||||
</pre><button onclick='javascript: var _a, lyrics, num;
|
||||
</pre><button onclick='javascript: var _result, lyrics, num;
|
||||
if (this.studyingEconomics) {
|
||||
while (supply > demand) {
|
||||
buy();
|
||||
@@ -795,12 +801,12 @@ if (this.studyingEconomics) {
|
||||
}
|
||||
num = 6;
|
||||
lyrics = (function() {
|
||||
_a = [];
|
||||
_result = [];
|
||||
while (num -= 1) {
|
||||
_a.push(num + " little monkeys, jumping on the bed. \
|
||||
One fell out and bumped his head.");
|
||||
_result.push(num + " little monkeys, jumping on the bed.\
|
||||
One fell out and bumped his head.");
|
||||
}
|
||||
return _a;
|
||||
return _result;
|
||||
})();;alert(lyrics.join("\n"));'>run: lyrics.join("\n")</button><br class='clear' /></div>
|
||||
<p>
|
||||
For readability, the <b>until</b> keyword is equivalent to <tt>while not</tt>,
|
||||
@@ -828,21 +834,21 @@ lunch <span class="Keyword">=</span> eat food <span class="Keyword">for</span> f
|
||||
<span class="Keyword">for</span> roid <span class="Keyword">in</span> asteroids
|
||||
<span class="Keyword">for</span> roid2 <span class="Keyword">in</span> asteroids <span class="Keyword">when</span> roid <span class="Keyword">isnt</span> roid2
|
||||
roid.explode() <span class="Keyword">if</span> roid.overlaps roid2
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, food, lunch, roid, roid2;
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _i, _j, _len, _len2, _ref, _ref2, _result, food, lunch, roid, roid2;
|
||||
lunch <span class="Keyword">=</span> (<span class="Storage">function</span>() {
|
||||
_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"><</span> _d; _b<span class="Keyword">++</span>) {
|
||||
food <span class="Keyword">=</span> _c[_b];
|
||||
_a.<span class="LibraryFunction">push</span>(eat(food));
|
||||
_result <span class="Keyword">=</span> []; _ref <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> (_i <span class="Keyword">=</span> <span class="Number">0</span>, _len <span class="Keyword">=</span> _ref.<span class="LibraryConstant">length</span>; _i <span class="Keyword"><</span> _len; _i<span class="Keyword">++</span>) {
|
||||
food <span class="Keyword">=</span> _ref[_i];
|
||||
_result.<span class="LibraryFunction">push</span>(eat(food));
|
||||
}
|
||||
<span class="Keyword">return</span> _a;
|
||||
<span class="Keyword">return</span> _result;
|
||||
})();
|
||||
_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"><</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"><</span> _j; _h<span class="Keyword">++</span>) {
|
||||
roid2 <span class="Keyword">=</span> _i[_h];
|
||||
_ref <span class="Keyword">=</span> asteroids;
|
||||
<span class="Keyword">for</span> (_i <span class="Keyword">=</span> <span class="Number">0</span>, _len <span class="Keyword">=</span> _ref.<span class="LibraryConstant">length</span>; _i <span class="Keyword"><</span> _len; _i<span class="Keyword">++</span>) {
|
||||
roid <span class="Keyword">=</span> _ref[_i];
|
||||
_ref2 <span class="Keyword">=</span> asteroids;
|
||||
<span class="Keyword">for</span> (_j <span class="Keyword">=</span> <span class="Number">0</span>, _len2 <span class="Keyword">=</span> _ref2.<span class="LibraryConstant">length</span>; _j <span class="Keyword"><</span> _len2; _j<span class="Keyword">++</span>) {
|
||||
roid2 <span class="Keyword">=</span> _ref2[_j];
|
||||
<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();
|
||||
@@ -862,54 +868,54 @@ _f <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 <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">eggCarton</span> dozen
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _a, countdown, deliverEggs, num;
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _result, countdown, deliverEggs, num;
|
||||
countdown <span class="Keyword">=</span> (<span class="Storage">function</span>() {
|
||||
_a <span class="Keyword">=</span> [];
|
||||
_result <span class="Keyword">=</span> [];
|
||||
<span class="Keyword">for</span> (num <span class="Keyword">=</span> <span class="Number">10</span>; num <span class="Keyword">>=</span> <span class="Number">1</span>; num<span class="Keyword">--</span>) {
|
||||
_a.<span class="LibraryFunction">push</span>(num);
|
||||
_result.<span class="LibraryFunction">push</span>(num);
|
||||
}
|
||||
<span class="Keyword">return</span> _a;
|
||||
<span class="Keyword">return</span> _result;
|
||||
})();
|
||||
<span class="FunctionName">deliverEggs</span> = <span class="Storage">function</span>() {
|
||||
<span class="Storage">var</span> _b, _c, dozen, i;
|
||||
_b <span class="Keyword">=</span> []; _c <span class="Keyword">=</span> eggs.<span class="LibraryConstant">length</span>;
|
||||
<span class="Keyword">for</span> (i <span class="Keyword">=</span> <span class="Number">0</span>; (<span class="Number">0</span> <span class="Keyword"><=</span> _c ? i <span class="Keyword"><</span> _c : i <span class="Keyword">></span> _c); i <span class="Keyword">+</span><span class="Keyword">=</span> <span class="Number">12</span>) {
|
||||
_b.<span class="LibraryFunction">push</span>((<span class="Storage">function</span>() {
|
||||
<span class="Storage">var</span> _ref, _result2, dozen, i;
|
||||
_result2 <span class="Keyword">=</span> []; _ref <span class="Keyword">=</span> eggs.<span class="LibraryConstant">length</span>;
|
||||
<span class="Keyword">for</span> (i <span class="Keyword">=</span> <span class="Number">0</span>; (<span class="Number">0</span> <span class="Keyword"><=</span> _ref ? i <span class="Keyword"><</span> _ref : i <span class="Keyword">></span> _ref); i <span class="Keyword">+</span><span class="Keyword">=</span> <span class="Number">12</span>) {
|
||||
_result2.<span class="LibraryFunction">push</span>((<span class="Storage">function</span>() {
|
||||
dozen <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">eggCarton</span>(dozen));
|
||||
})());
|
||||
}
|
||||
<span class="Keyword">return</span> _b;
|
||||
<span class="Keyword">return</span> _result2;
|
||||
};
|
||||
</pre><button onclick='javascript: var _a, countdown, deliverEggs, num;
|
||||
</pre><button onclick='javascript: var _result, countdown, deliverEggs, num;
|
||||
countdown = (function() {
|
||||
_a = [];
|
||||
_result = [];
|
||||
for (num = 10; num >= 1; num--) {
|
||||
_a.push(num);
|
||||
_result.push(num);
|
||||
}
|
||||
return _a;
|
||||
return _result;
|
||||
})();
|
||||
deliverEggs = function() {
|
||||
var _b, _c, dozen, i;
|
||||
_b = []; _c = eggs.length;
|
||||
for (i = 0; (0 <= _c ? i < _c : i > _c); i += 12) {
|
||||
_b.push((function() {
|
||||
var _ref, _result2, dozen, i;
|
||||
_result2 = []; _ref = eggs.length;
|
||||
for (i = 0; (0 <= _ref ? i < _ref : i > _ref); i += 12) {
|
||||
_result2.push((function() {
|
||||
dozen = eggs.slice(i, i + 12);
|
||||
return deliver(new eggCarton(dozen));
|
||||
})());
|
||||
}
|
||||
return _b;
|
||||
return _result2;
|
||||
};;alert(countdown);'>run: countdown</button><br class='clear' /></div>
|
||||
<p>
|
||||
Comprehensions can also be used to iterate over the keys and values in
|
||||
an object. Use <tt>of</tt> to signal comprehension over the properties of
|
||||
an object instead of the values in an array.
|
||||
</p>
|
||||
<div class='code'><pre class="idle">yearsOld <span class="Keyword">=</span> max<span class="Keyword">:</span> <span class="Number">10</span>, ida<span class="Keyword">:</span> <span class="Number">9</span>, tim<span class="Keyword">:</span> <span class="Number">11</span>
|
||||
<div class='code'><pre class="idle">yearsOld <span class="Keyword">=</span> max: <span class="Number">10</span>, ida: <span class="Number">9</span>, tim: <span class="Number">11</span>
|
||||
|
||||
ages <span class="Keyword">=</span> <span class="Keyword">for</span> child, age <span class="Keyword">of</span> yearsOld
|
||||
child <span class="Keyword">+</span> <span class="String"><span class="String">"</span> is <span class="String">"</span></span> <span class="Keyword">+</span> age
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _a, _b, age, ages, child, yearsOld;
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _ref, _result, age, ages, child, yearsOld;
|
||||
<span class="Storage">var</span> __hasProp <span class="Keyword">=</span> <span class="LibraryClassType">Object</span>.<span class="LibraryConstant">prototype</span>.hasOwnProperty;
|
||||
yearsOld <span class="Keyword">=</span> {
|
||||
max: <span class="Number">10</span>,
|
||||
@@ -917,15 +923,15 @@ yearsOld <span class="Keyword">=</span> {
|
||||
tim: <span class="Number">11</span>
|
||||
};
|
||||
ages <span class="Keyword">=</span> (<span class="Storage">function</span>() {
|
||||
_a <span class="Keyword">=</span> []; _b <span class="Keyword">=</span> yearsOld;
|
||||
<span class="Keyword">for</span> (child <span class="Keyword">in</span> _b) {
|
||||
<span class="Keyword">if</span> (<span class="Keyword">!</span>__hasProp.<span class="LibraryFunction">call</span>(_b, child)) <span class="Keyword">continue</span>;
|
||||
age <span class="Keyword">=</span> _b[child];
|
||||
_a.<span class="LibraryFunction">push</span>(child <span class="Keyword">+</span> <span class="String"><span class="String">"</span> is <span class="String">"</span></span> <span class="Keyword">+</span> age);
|
||||
_result <span class="Keyword">=</span> []; _ref <span class="Keyword">=</span> yearsOld;
|
||||
<span class="Keyword">for</span> (child <span class="Keyword">in</span> _ref) {
|
||||
<span class="Keyword">if</span> (<span class="Keyword">!</span>__hasProp.<span class="LibraryFunction">call</span>(_ref, child)) <span class="Keyword">continue</span>;
|
||||
age <span class="Keyword">=</span> _ref[child];
|
||||
_result.<span class="LibraryFunction">push</span>(child <span class="Keyword">+</span> <span class="String"><span class="String">"</span> is <span class="String">"</span></span> <span class="Keyword">+</span> age);
|
||||
}
|
||||
<span class="Keyword">return</span> _a;
|
||||
<span class="Keyword">return</span> _result;
|
||||
})();
|
||||
</pre><button onclick='javascript: var _a, _b, age, ages, child, yearsOld;
|
||||
</pre><button onclick='javascript: var _ref, _result, age, ages, child, yearsOld;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
yearsOld = {
|
||||
max: 10,
|
||||
@@ -933,13 +939,13 @@ yearsOld = {
|
||||
tim: 11
|
||||
};
|
||||
ages = (function() {
|
||||
_a = []; _b = yearsOld;
|
||||
for (child in _b) {
|
||||
if (!__hasProp.call(_b, child)) continue;
|
||||
age = _b[child];
|
||||
_a.push(child + " is " + age);
|
||||
_result = []; _ref = yearsOld;
|
||||
for (child in _ref) {
|
||||
if (!__hasProp.call(_ref, child)) continue;
|
||||
age = _ref[child];
|
||||
_result.push(child + " is " + age);
|
||||
}
|
||||
return _a;
|
||||
return _result;
|
||||
})();;alert(ages.join(", "));'>run: ages.join(", ")</button><br class='clear' /></div>
|
||||
<p>
|
||||
By default, object comprehensions are safe, and use a <tt>hasOwnProperty</tt>
|
||||
@@ -1053,27 +1059,27 @@ six = (one = 1) + (two = 2) + (three = 3);;alert(six);'>run: six</button><br cla
|
||||
<div class='code'><pre class="idle"><span class="Comment"><span class="Comment">#</span> The first ten global properties.</span>
|
||||
|
||||
globals <span class="Keyword">=</span> (name <span class="Keyword">for</span> name <span class="Keyword">of</span> window)[<span class="Number">0</span>...<span class="Number">10</span>]
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _a, _b, _c, globals, name;
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _i, _ref, _result, globals, name;
|
||||
<span class="Storage">var</span> __hasProp <span class="Keyword">=</span> <span class="LibraryClassType">Object</span>.<span class="LibraryConstant">prototype</span>.hasOwnProperty;
|
||||
globals <span class="Keyword">=</span> (<span class="Storage">function</span>() {
|
||||
_b <span class="Keyword">=</span> []; _c <span class="Keyword">=</span> <span class="LibraryClassType">window</span>;
|
||||
<span class="Keyword">for</span> (name <span class="Keyword">in</span> _c) {
|
||||
<span class="Keyword">if</span> (<span class="Keyword">!</span>__hasProp.<span class="LibraryFunction">call</span>(_c, name)) <span class="Keyword">continue</span>;
|
||||
_a <span class="Keyword">=</span> _c[name];
|
||||
_b.<span class="LibraryFunction">push</span>(name);
|
||||
_result <span class="Keyword">=</span> []; _ref <span class="Keyword">=</span> <span class="LibraryClassType">window</span>;
|
||||
<span class="Keyword">for</span> (name <span class="Keyword">in</span> _ref) {
|
||||
<span class="Keyword">if</span> (<span class="Keyword">!</span>__hasProp.<span class="LibraryFunction">call</span>(_ref, name)) <span class="Keyword">continue</span>;
|
||||
_i <span class="Keyword">=</span> _ref[name];
|
||||
_result.<span class="LibraryFunction">push</span>(name);
|
||||
}
|
||||
<span class="Keyword">return</span> _b;
|
||||
<span class="Keyword">return</span> _result;
|
||||
})().<span class="LibraryFunction">slice</span>(<span class="Number">0</span>, <span class="Number">10</span>);
|
||||
</pre><button onclick='javascript: var _a, _b, _c, globals, name;
|
||||
</pre><button onclick='javascript: var _i, _ref, _result, globals, name;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
globals = (function() {
|
||||
_b = []; _c = window;
|
||||
for (name in _c) {
|
||||
if (!__hasProp.call(_c, name)) continue;
|
||||
_a = _c[name];
|
||||
_b.push(name);
|
||||
_result = []; _ref = window;
|
||||
for (name in _ref) {
|
||||
if (!__hasProp.call(_ref, name)) continue;
|
||||
_i = _ref[name];
|
||||
_result.push(name);
|
||||
}
|
||||
return _b;
|
||||
return _result;
|
||||
})().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
|
||||
@@ -1146,8 +1152,8 @@ speed = (typeof speed !== "undefined" && speed !== null) ? speed : 140;;alert(sp
|
||||
the <b>TypeError</b> that would be raised otherwise.
|
||||
</p>
|
||||
<div class='code'><pre class="idle">lottery.drawWinner()<span class="Keyword">?</span>.address<span class="Keyword">?</span>.zipcode
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _a, _b;
|
||||
(_b <span class="Keyword">=</span> (<span class="Keyword">typeof</span> (_a <span class="Keyword">=</span> (lottery.drawWinner())) <span class="Keyword">===</span> <span class="String"><span class="String">"</span>undefined<span class="String">"</span></span> <span class="Keyword">||</span> _a <span class="Keyword">==</span> undefined ? undefined : _a.address)) <span class="Keyword">==</span> undefined ? undefined : _b.zipcode;
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _ref, _ref2;
|
||||
(<span class="Keyword">typeof</span> (_ref2 <span class="Keyword">=</span> ((_ref <span class="Keyword">=</span> lottery.drawWinner()))) <span class="Keyword">===</span> <span class="String"><span class="String">"</span>undefined<span class="String">"</span></span> <span class="Keyword">||</span> _ref2 <span class="Keyword">===</span> <span class="BuiltInConstant">null</span>) ? undefined : _ref2.address <span class="Keyword">==</span> <span class="BuiltInConstant">null</span> ? undefined : _ref2.address.zipcode;
|
||||
</pre><br class='clear' /></div>
|
||||
<p>
|
||||
Soaking up nulls is similar to Ruby's
|
||||
@@ -1177,18 +1183,18 @@ speed = (typeof speed !== "undefined" && speed !== null) ? speed : 140;;alert(sp
|
||||
set the superclass, assign prototypal properties, and define the constructor,
|
||||
in a single assignable expression.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="Storage">class</span><span class="TypeName"> Animal</span>
|
||||
<div class='code'><pre class="idle"><span class="Storage">class</span> <span class="TypeName">Animal</span>
|
||||
<span class="FunctionName">constructor</span><span class="Keyword">:</span> (<span class="Variable">@name</span>) <span class="Storage">-></span>
|
||||
|
||||
<span class="FunctionName">move</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">meters</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
alert <span class="Variable">@name</span> <span class="Keyword">+</span> <span class="String"><span class="String">"</span> moved <span class="String">"</span></span> <span class="Keyword">+</span> meters <span class="Keyword">+</span> <span class="String"><span class="String">"</span>m.<span class="String">"</span></span>
|
||||
|
||||
<span class="Storage">class</span><span class="TypeName"> Snake</span><span class="InheritedClass"> <span class="Keyword">extends</span> Animal</span>
|
||||
<span class="Storage">class</span> <span class="TypeName">Snake</span><span class="InheritedClass"> <span class="Keyword">extends</span> Animal</span>
|
||||
<span class="FunctionName">move</span><span class="Keyword">:</span> <span class="Storage">-></span>
|
||||
alert <span class="String"><span class="String">"</span>Slithering...<span class="String">"</span></span>
|
||||
<span class="Variable">super</span> <span class="Number">5</span>
|
||||
|
||||
<span class="Storage">class</span><span class="TypeName"> Horse</span><span class="InheritedClass"> <span class="Keyword">extends</span> Animal</span>
|
||||
<span class="Storage">class</span> <span class="TypeName">Horse</span><span class="InheritedClass"> <span class="Keyword">extends</span> Animal</span>
|
||||
<span class="FunctionName">move</span><span class="Keyword">:</span> <span class="Storage">-></span>
|
||||
alert <span class="String"><span class="String">"</span>Galloping...<span class="String">"</span></span>
|
||||
<span class="Variable">super</span> <span class="Number">45</span>
|
||||
@@ -1209,10 +1215,10 @@ tom.move()
|
||||
<span class="LibraryClassType">child</span>.<span class="LibraryConstant">prototype</span> = <span class="Keyword">new</span> <span class="TypeName">ctor</span>();
|
||||
<span class="LibraryClassType">child</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">constructor</span> = child;
|
||||
<span class="Keyword">if</span> (<span class="Keyword">typeof</span> parent.extended <span class="Keyword">===</span> <span class="String"><span class="String">"</span>function<span class="String">"</span></span>) parent.extended(child);
|
||||
child.__superClass__ <span class="Keyword">=</span> parent.<span class="LibraryConstant">prototype</span>;
|
||||
child.__super__ <span class="Keyword">=</span> parent.<span class="LibraryConstant">prototype</span>;
|
||||
};
|
||||
<span class="FunctionName">Animal</span> = <span class="Storage">function</span>(<span class="FunctionArgument">_a</span>) {
|
||||
<span class="Variable">this</span>.<span class="LibraryConstant">name</span> <span class="Keyword">=</span> _a;
|
||||
<span class="FunctionName">Animal</span> = <span class="Storage">function</span>(<span class="FunctionArgument">_arg</span>) {
|
||||
<span class="Variable">this</span>.<span class="LibraryConstant">name</span> <span class="Keyword">=</span> _arg;
|
||||
<span class="Keyword">return</span> <span class="Variable">this</span>;
|
||||
};
|
||||
<span class="LibraryClassType">Animal</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">move</span> = <span class="Storage">function</span>(<span class="FunctionArgument">meters</span>) {
|
||||
@@ -1224,7 +1230,7 @@ tom.move()
|
||||
__extends(Snake, Animal);
|
||||
<span class="LibraryClassType">Snake</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">move</span> = <span class="Storage">function</span>() {
|
||||
<span class="LibraryFunction">alert</span>(<span class="String"><span class="String">"</span>Slithering...<span class="String">"</span></span>);
|
||||
<span class="Keyword">return</span> Snake.__superClass__.move.<span class="LibraryFunction">call</span>(<span class="Variable">this</span>, <span class="Number">5</span>);
|
||||
<span class="Keyword">return</span> Snake.__super__.move.<span class="LibraryFunction">call</span>(<span class="Variable">this</span>, <span class="Number">5</span>);
|
||||
};
|
||||
<span class="FunctionName">Horse</span> = <span class="Storage">function</span>() {
|
||||
<span class="Keyword">return</span> Animal.<span class="LibraryFunction">apply</span>(<span class="Variable">this</span>, arguments);
|
||||
@@ -1232,7 +1238,7 @@ __extends(Snake, Animal);
|
||||
__extends(Horse, Animal);
|
||||
<span class="LibraryClassType">Horse</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">move</span> = <span class="Storage">function</span>() {
|
||||
<span class="LibraryFunction">alert</span>(<span class="String"><span class="String">"</span>Galloping...<span class="String">"</span></span>);
|
||||
<span class="Keyword">return</span> Horse.__superClass__.move.<span class="LibraryFunction">call</span>(<span class="Variable">this</span>, <span class="Number">45</span>);
|
||||
<span class="Keyword">return</span> Horse.__super__.move.<span class="LibraryFunction">call</span>(<span class="Variable">this</span>, <span class="Number">45</span>);
|
||||
};
|
||||
sam <span class="Keyword">=</span> <span class="Keyword">new</span> <span class="TypeName">Snake</span>(<span class="String"><span class="String">"</span>Sammy the Python<span class="String">"</span></span>);
|
||||
tom <span class="Keyword">=</span> <span class="Keyword">new</span> <span class="TypeName">Horse</span>(<span class="String"><span class="String">"</span>Tommy the Palomino<span class="String">"</span></span>);
|
||||
@@ -1245,10 +1251,10 @@ var __extends = function(child, parent) {
|
||||
child.prototype = new ctor();
|
||||
child.prototype.constructor = child;
|
||||
if (typeof parent.extended === "function") parent.extended(child);
|
||||
child.__superClass__ = parent.prototype;
|
||||
child.__super__ = parent.prototype;
|
||||
};
|
||||
Animal = function(_a) {
|
||||
this.name = _a;
|
||||
Animal = function(_arg) {
|
||||
this.name = _arg;
|
||||
return this;
|
||||
};
|
||||
Animal.prototype.move = function(meters) {
|
||||
@@ -1260,7 +1266,7 @@ Snake = function() {
|
||||
__extends(Snake, Animal);
|
||||
Snake.prototype.move = function() {
|
||||
alert("Slithering...");
|
||||
return Snake.__superClass__.move.call(this, 5);
|
||||
return Snake.__super__.move.call(this, 5);
|
||||
};
|
||||
Horse = function() {
|
||||
return Animal.apply(this, arguments);
|
||||
@@ -1268,7 +1274,7 @@ Horse = function() {
|
||||
__extends(Horse, Animal);
|
||||
Horse.prototype.move = function() {
|
||||
alert("Galloping...");
|
||||
return Horse.__superClass__.move.call(this, 45);
|
||||
return Horse.__super__.move.call(this, 45);
|
||||
};
|
||||
sam = new Snake("Sammy the Python");
|
||||
tom = new Horse("Tommy the Palomino");
|
||||
@@ -1309,18 +1315,18 @@ tom.move();;'>run</button><br class='clear' /></div>
|
||||
theSwitch <span class="Keyword">=</span> <span class="Number">0</span>
|
||||
|
||||
<span class="Keyword">[</span>theBait, theSwitch<span class="Keyword">] =</span> [theSwitch, theBait]
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _a, theBait, theSwitch;
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _ref, theBait, theSwitch;
|
||||
theBait <span class="Keyword">=</span> <span class="Number">1000</span>;
|
||||
theSwitch <span class="Keyword">=</span> <span class="Number">0</span>;
|
||||
_a <span class="Keyword">=</span> [theSwitch, theBait];
|
||||
theBait <span class="Keyword">=</span> _a[<span class="Number">0</span>];
|
||||
theSwitch <span class="Keyword">=</span> _a[<span class="Number">1</span>];
|
||||
</pre><button onclick='javascript: var _a, theBait, theSwitch;
|
||||
_ref <span class="Keyword">=</span> [theSwitch, theBait];
|
||||
theBait <span class="Keyword">=</span> _ref[<span class="Number">0</span>];
|
||||
theSwitch <span class="Keyword">=</span> _ref[<span class="Number">1</span>];
|
||||
</pre><button onclick='javascript: var _ref, theBait, theSwitch;
|
||||
theBait = 1000;
|
||||
theSwitch = 0;
|
||||
_a = [theSwitch, theBait];
|
||||
theBait = _a[0];
|
||||
theSwitch = _a[1];;alert(theBait);'>run: theBait</button><br class='clear' /></div>
|
||||
_ref = [theSwitch, theBait];
|
||||
theBait = _ref[0];
|
||||
theSwitch = _ref[1];;alert(theBait);'>run: theBait</button><br class='clear' /></div>
|
||||
<p>
|
||||
But it's also helpful for dealing with functions that return multiple
|
||||
values.
|
||||
@@ -1330,38 +1336,38 @@ theSwitch = _a[1];;alert(theBait);'>run: theBait</button><br class='clear' /></d
|
||||
[location, <span class="Number">72</span>, <span class="String"><span class="String">"</span>Mostly Sunny<span class="String">"</span></span>]
|
||||
|
||||
<span class="Keyword">[</span>city, temp, forecast<span class="Keyword">] =</span> weatherReport <span class="String"><span class="String">"</span>Berkeley, CA<span class="String">"</span></span>
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _a, city, forecast, temp, weatherReport;
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _ref, city, forecast, temp, weatherReport;
|
||||
<span class="FunctionName">weatherReport</span> = <span class="Storage">function</span>(<span class="FunctionArgument">location</span>) {
|
||||
<span class="Keyword">return</span> [location, <span class="Number">72</span>, <span class="String"><span class="String">"</span>Mostly Sunny<span class="String">"</span></span>];
|
||||
};
|
||||
_a <span class="Keyword">=</span> weatherReport(<span class="String"><span class="String">"</span>Berkeley, CA<span class="String">"</span></span>);
|
||||
city <span class="Keyword">=</span> _a[<span class="Number">0</span>];
|
||||
temp <span class="Keyword">=</span> _a[<span class="Number">1</span>];
|
||||
forecast <span class="Keyword">=</span> _a[<span class="Number">2</span>];
|
||||
</pre><button onclick='javascript: var _a, city, forecast, temp, weatherReport;
|
||||
_ref <span class="Keyword">=</span> weatherReport(<span class="String"><span class="String">"</span>Berkeley, CA<span class="String">"</span></span>);
|
||||
city <span class="Keyword">=</span> _ref[<span class="Number">0</span>];
|
||||
temp <span class="Keyword">=</span> _ref[<span class="Number">1</span>];
|
||||
forecast <span class="Keyword">=</span> _ref[<span class="Number">2</span>];
|
||||
</pre><button onclick='javascript: var _ref, city, forecast, temp, weatherReport;
|
||||
weatherReport = function(location) {
|
||||
return [location, 72, "Mostly Sunny"];
|
||||
};
|
||||
_a = weatherReport("Berkeley, CA");
|
||||
city = _a[0];
|
||||
temp = _a[1];
|
||||
forecast = _a[2];;alert(forecast);'>run: forecast</button><br class='clear' /></div>
|
||||
_ref = weatherReport("Berkeley, CA");
|
||||
city = _ref[0];
|
||||
temp = _ref[1];
|
||||
forecast = _ref[2];;alert(forecast);'>run: forecast</button><br class='clear' /></div>
|
||||
<p>
|
||||
Pattern matching can be used with any depth of array and object nesting,
|
||||
to help pull out deeply nested properties.
|
||||
</p>
|
||||
<div class='code'><pre class="idle">futurists <span class="Keyword">=</span>
|
||||
sculptor<span class="Keyword">:</span> <span class="String"><span class="String">"</span>Umberto Boccioni<span class="String">"</span></span>
|
||||
painter<span class="Keyword">:</span> <span class="String"><span class="String">"</span>Vladimir Burliuk<span class="String">"</span></span>
|
||||
poet<span class="Keyword">:</span>
|
||||
name<span class="Keyword">:</span> <span class="String"><span class="String">"</span>F.T. Marinetti<span class="String">"</span></span>
|
||||
address<span class="Keyword">:</span> [
|
||||
sculptor: <span class="String"><span class="String">"</span>Umberto Boccioni<span class="String">"</span></span>
|
||||
painter: <span class="String"><span class="String">"</span>Vladimir Burliuk<span class="String">"</span></span>
|
||||
poet:
|
||||
name: <span class="String"><span class="String">"</span>F.T. Marinetti<span class="String">"</span></span>
|
||||
address: [
|
||||
<span class="String"><span class="String">"</span>Via Roma 42R<span class="String">"</span></span>
|
||||
<span class="String"><span class="String">"</span>Bellagio, Italy 22021<span class="String">"</span></span>
|
||||
]
|
||||
|
||||
{poet<span class="Keyword">:</span> {name, address<span class="Keyword">:</span> [street, city]}} <span class="Keyword">=</span> futurists
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _a, _b, _c, city, futurists, name, street;
|
||||
{poet: {name, address: [street, city]}} <span class="Keyword">=</span> futurists
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _ref, _ref2, _ref3, city, futurists, name, street;
|
||||
futurists <span class="Keyword">=</span> {
|
||||
sculptor: <span class="String"><span class="String">"</span>Umberto Boccioni<span class="String">"</span></span>,
|
||||
painter: <span class="String"><span class="String">"</span>Vladimir Burliuk<span class="String">"</span></span>,
|
||||
@@ -1370,13 +1376,13 @@ futurists <span class="Keyword">=</span> {
|
||||
address: [<span class="String"><span class="String">"</span>Via Roma 42R<span class="String">"</span></span>, <span class="String"><span class="String">"</span>Bellagio, Italy 22021<span class="String">"</span></span>]
|
||||
}
|
||||
};
|
||||
_a <span class="Keyword">=</span> futurists;
|
||||
_b <span class="Keyword">=</span> _a.poet;
|
||||
name <span class="Keyword">=</span> _b.<span class="LibraryConstant">name</span>;
|
||||
_c <span class="Keyword">=</span> _b.address;
|
||||
street <span class="Keyword">=</span> _c[<span class="Number">0</span>];
|
||||
city <span class="Keyword">=</span> _c[<span class="Number">1</span>];
|
||||
</pre><button onclick='javascript: var _a, _b, _c, city, futurists, name, street;
|
||||
_ref <span class="Keyword">=</span> futurists;
|
||||
_ref2 <span class="Keyword">=</span> _ref.poet;
|
||||
name <span class="Keyword">=</span> _ref2.<span class="LibraryConstant">name</span>;
|
||||
_ref3 <span class="Keyword">=</span> _ref2.address;
|
||||
street <span class="Keyword">=</span> _ref3[<span class="Number">0</span>];
|
||||
city <span class="Keyword">=</span> _ref3[<span class="Number">1</span>];
|
||||
</pre><button onclick='javascript: var _ref, _ref2, _ref3, city, futurists, name, street;
|
||||
futurists = {
|
||||
sculptor: "Umberto Boccioni",
|
||||
painter: "Vladimir Burliuk",
|
||||
@@ -1385,12 +1391,12 @@ futurists = {
|
||||
address: ["Via Roma 42R", "Bellagio, Italy 22021"]
|
||||
}
|
||||
};
|
||||
_a = futurists;
|
||||
_b = _a.poet;
|
||||
name = _b.name;
|
||||
_c = _b.address;
|
||||
street = _c[0];
|
||||
city = _c[1];;alert(name + " — " + street);'>run: name + " — " + street</button><br class='clear' /></div>
|
||||
_ref = futurists;
|
||||
_ref2 = _ref.poet;
|
||||
name = _ref2.name;
|
||||
_ref3 = _ref2.address;
|
||||
street = _ref3[0];
|
||||
city = _ref3[1];;alert(name + " — " + street);'>run: name + " — " + street</button><br class='clear' /></div>
|
||||
<p>
|
||||
Pattern matching can even be combined with splats.
|
||||
</p>
|
||||
@@ -1401,20 +1407,20 @@ city = _c[1];;alert(name + " — " + street);'>run: name + " — " + street</but
|
||||
|
||||
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _a, close, contents, open, tag;
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _ref, 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">"</span><impossible><span class="String">"</span></span>;
|
||||
_a <span class="Keyword">=</span> tag.<span class="LibraryFunction">split</span>(<span class="String"><span class="String">"</span><span class="String">"</span></span>);
|
||||
open <span class="Keyword">=</span> _a[<span class="Number">0</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;
|
||||
_ref <span class="Keyword">=</span> tag.<span class="LibraryFunction">split</span>(<span class="String"><span class="String">"</span><span class="String">"</span></span>);
|
||||
open <span class="Keyword">=</span> _ref[<span class="Number">0</span>];
|
||||
contents <span class="Keyword">=</span> __slice.<span class="LibraryFunction">call</span>(_ref, <span class="Number">1</span>, _ref.<span class="LibraryConstant">length</span> <span class="Keyword">-</span> <span class="Number">1</span>);
|
||||
close <span class="Keyword">=</span> _ref[_ref.<span class="LibraryConstant">length</span> <span class="Keyword">-</span> <span class="Number">1</span>];
|
||||
</pre><button onclick='javascript: var _ref, close, contents, open, tag;
|
||||
var __slice = Array.prototype.slice;
|
||||
tag = "<impossible>";
|
||||
_a = tag.split("");
|
||||
open = _a[0];
|
||||
contents = __slice.call(_a, 1, _a.length - 1);
|
||||
close = _a[_a.length - 1];;alert(contents.join(""));'>run: contents.join("")</button><br class='clear' /></div>
|
||||
_ref = tag.split("");
|
||||
open = _ref[0];
|
||||
contents = __slice.call(_ref, 1, _ref.length - 1);
|
||||
close = _ref[_ref.length - 1];;alert(contents.join(""));'>run: contents.join("")</button><br class='clear' /></div>
|
||||
|
||||
<p>
|
||||
<span id="fat_arrow" class="bookmark"></span>
|
||||
@@ -1482,12 +1488,11 @@ hi = function() {
|
||||
<p>
|
||||
<span id="switch" class="bookmark"></span>
|
||||
<b class="header">Switch/When/Else</b>
|
||||
<b>Switch</b> statements in JavaScript are rather broken. You can only
|
||||
do comparisons based on string equality, and need to remember to <b>break</b> at the end of
|
||||
every <b>case</b> statement to avoid accidentally falling through to
|
||||
the default case. CoffeeScript compiles <b>switch</b> statements into JavaScript if-else chains, allowing you to
|
||||
compare any object (via <b>===</b>), preventing fall-through, and resulting
|
||||
in a returnable, assignable expression. The format is: <tt>switch</tt> condition,
|
||||
<b>Switch</b> statements in JavaScript are a bit awkward. You need to
|
||||
remember to <b>break</b> at the end of every <b>case</b> statement to
|
||||
avoid accidentally falling through to the default case.
|
||||
CoffeeScript prevents accidental fall-through, and can convert the <tt>switch</tt>
|
||||
into a returnable, assignable expression. The format is: <tt>switch</tt> condition,
|
||||
<tt>when</tt> clauses, <tt>else</tt> the default case.
|
||||
</p>
|
||||
<p>
|
||||
@@ -1496,30 +1501,37 @@ hi = function() {
|
||||
runs.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="Keyword">switch</span> day
|
||||
<span class="Keyword">when</span> <span class="String"><span class="String">"</span>Mon<span class="String">"</span></span> <span class="Keyword">then</span> goToWork()
|
||||
<span class="Keyword">when</span> <span class="String"><span class="String">"</span>Tue<span class="String">"</span></span> <span class="Keyword">then</span> goToThePark()
|
||||
<span class="Keyword">when</span> <span class="String"><span class="String">"</span>Thu<span class="String">"</span></span> <span class="Keyword">then</span> goIceFishing()
|
||||
<span class="Keyword">when</span> <span class="String"><span class="String">"</span>Mon<span class="String">"</span></span> <span class="Keyword">then</span> go work
|
||||
<span class="Keyword">when</span> <span class="String"><span class="String">"</span>Tue<span class="String">"</span></span> <span class="Keyword">then</span> go relax
|
||||
<span class="Keyword">when</span> <span class="String"><span class="String">"</span>Thu<span class="String">"</span></span> <span class="Keyword">then</span> go iceFishing
|
||||
<span class="Keyword">when</span> <span class="String"><span class="String">"</span>Fri<span class="String">"</span></span>, <span class="String"><span class="String">"</span>Sat<span class="String">"</span></span>
|
||||
<span class="Keyword">if</span> day <span class="Keyword">is</span> bingoDay
|
||||
goToBingo()
|
||||
goDancing()
|
||||
<span class="Keyword">when</span> <span class="String"><span class="String">"</span>Sun<span class="String">"</span></span> <span class="Keyword">then</span> goToChurch()
|
||||
<span class="Keyword">else</span> goToWork()
|
||||
</pre><pre class="idle"><span class="Keyword">if</span> (day <span class="Keyword">===</span> <span class="String"><span class="String">"</span>Mon<span class="String">"</span></span>) {
|
||||
goToWork();
|
||||
} <span class="Keyword">else</span> <span class="Keyword">if</span> (day <span class="Keyword">===</span> <span class="String"><span class="String">"</span>Tue<span class="String">"</span></span>) {
|
||||
goToThePark();
|
||||
} <span class="Keyword">else</span> <span class="Keyword">if</span> (day <span class="Keyword">===</span> <span class="String"><span class="String">"</span>Thu<span class="String">"</span></span>) {
|
||||
goIceFishing();
|
||||
} <span class="Keyword">else</span> <span class="Keyword">if</span> (day <span class="Keyword">===</span> <span class="String"><span class="String">"</span>Fri<span class="String">"</span></span> <span class="Keyword">||</span> day <span class="Keyword">===</span> <span class="String"><span class="String">"</span>Sat<span class="String">"</span></span>) {
|
||||
<span class="Keyword">if</span> (day <span class="Keyword">===</span> bingoDay) {
|
||||
goToBingo();
|
||||
goDancing();
|
||||
}
|
||||
} <span class="Keyword">else</span> <span class="Keyword">if</span> (day <span class="Keyword">===</span> <span class="String"><span class="String">"</span>Sun<span class="String">"</span></span>) {
|
||||
goToChurch();
|
||||
} <span class="Keyword">else</span> {
|
||||
goToWork();
|
||||
go bingo
|
||||
go dancing
|
||||
<span class="Keyword">when</span> <span class="String"><span class="String">"</span>Sun<span class="String">"</span></span> <span class="Keyword">then</span> go church
|
||||
<span class="Keyword">else</span> go work
|
||||
</pre><pre class="idle"><span class="Keyword">switch</span> (day) {
|
||||
<span class="Keyword">case</span> <span class="String"><span class="String">"</span>Mon<span class="String">"</span></span>:
|
||||
<span class="LibraryFunction">go</span>(work);
|
||||
<span class="Keyword">break</span>;
|
||||
<span class="Keyword">case</span> <span class="String"><span class="String">"</span>Tue<span class="String">"</span></span>:
|
||||
<span class="LibraryFunction">go</span>(relax);
|
||||
<span class="Keyword">break</span>;
|
||||
<span class="Keyword">case</span> <span class="String"><span class="String">"</span>Thu<span class="String">"</span></span>:
|
||||
<span class="LibraryFunction">go</span>(iceFishing);
|
||||
<span class="Keyword">break</span>;
|
||||
<span class="Keyword">case</span> <span class="String"><span class="String">"</span>Fri<span class="String">"</span></span>:
|
||||
<span class="Keyword">case</span> <span class="String"><span class="String">"</span>Sat<span class="String">"</span></span>:
|
||||
<span class="Keyword">if</span> (day <span class="Keyword">===</span> bingoDay) {
|
||||
<span class="LibraryFunction">go</span>(bingo);
|
||||
<span class="LibraryFunction">go</span>(dancing);
|
||||
}
|
||||
<span class="Keyword">break</span>;
|
||||
<span class="Keyword">case</span> <span class="String"><span class="String">"</span>Sun<span class="String">"</span></span>:
|
||||
<span class="LibraryFunction">go</span>(church);
|
||||
<span class="Keyword">break</span>;
|
||||
<span class="Keyword">default</span>:
|
||||
<span class="LibraryFunction">go</span>(work);
|
||||
}
|
||||
</pre><br class='clear' /></div>
|
||||
|
||||
@@ -1569,18 +1581,17 @@ healthy = (200 > cholesterol) && (cholesterol > 60);;alert(healthy);'>run: healt
|
||||
<p>
|
||||
<span id="interpolation" class="bookmark"></span>
|
||||
<b class="header">String and RegExp Interpolation</b>
|
||||
A version of <a href="http://wiki.ecmascript.org/doku.php?id=strawman:string_interpolation">ECMAScript Harmony's proposed string interpolation</a>
|
||||
is included in CoffeeScript. Simple variables can be included by prefixing
|
||||
them with a hash mark.
|
||||
Ruby-style string interpolation is included in CoffeeScript. Double-quoted
|
||||
strings allow for interpolated values, while single-quoted strings are literal.
|
||||
</p>
|
||||
<div class='code'><pre class="idle">author <span class="Keyword">=</span> <span class="String"><span class="String">"</span>Wittgenstein<span class="String">"</span></span>
|
||||
quote <span class="Keyword">=</span> <span class="String"><span class="String">"</span>A picture is a fact. -- <span class="String"><span class="String">#</span>author</span><span class="String">"</span></span>
|
||||
quote <span class="Keyword">=</span> <span class="String"><span class="String">"</span>A picture is a fact. -- <span class="String"><span class="String">#{</span>author<span class="String">}</span></span><span class="String">"</span></span>
|
||||
</pre><pre class="idle"><span class="Storage">var</span> author, quote;
|
||||
author <span class="Keyword">=</span> <span class="String"><span class="String">"</span>Wittgenstein<span class="String">"</span></span>;
|
||||
quote <span class="Keyword">=</span> (<span class="String"><span class="String">"</span>A picture is a fact. -- <span class="String">"</span></span> <span class="Keyword">+</span> author);
|
||||
quote <span class="Keyword">=</span> (<span class="String"><span class="String">"</span>A picture is a fact. -- <span class="String">"</span></span> <span class="Keyword">+</span> (author));
|
||||
</pre><button onclick='javascript: var author, quote;
|
||||
author = "Wittgenstein";
|
||||
quote = ("A picture is a fact. -- " + author);;alert(quote);'>run: quote</button><br class='clear' /></div>
|
||||
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 />
|
||||
Interpolation works the same way within regular expressions.
|
||||
@@ -1588,17 +1599,17 @@ quote = ("A picture is a fact. -- " + author);;alert(quote);'>run: quote</button
|
||||
<div class='code'><pre class="idle">sentence <span class="Keyword">=</span> <span class="String"><span class="String">"</span><span class="String"><span class="String">#{</span> <span class="Number">22</span> <span class="Keyword">/</span> <span class="Number">7</span> <span class="String">}</span></span> is a decent approximation of π<span class="String">"</span></span>
|
||||
|
||||
sep <span class="Keyword">=</span> <span class="String"><span class="String">"</span>[.<span class="UserDefinedConstant">\\</span>/<span class="UserDefinedConstant">\\</span>- ]<span class="String">"</span></span>
|
||||
dates <span class="Keyword">=</span><span class="String"> /\d+#sep\d+#sep\d+/g</span>
|
||||
dates <span class="Keyword">=</span><span class="String"> /\d+#{sep}\d+#{sep}\d+/g</span>
|
||||
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> dates, sentence, sep;
|
||||
sentence <span class="Keyword">=</span> (<span class="String"><span class="String">"</span><span class="String">"</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">"</span> is a decent approximation of π<span class="String">"</span></span>);
|
||||
sep <span class="Keyword">=</span> <span class="String"><span class="String">"</span>[.<span class="UserDefinedConstant">\\</span>/<span class="UserDefinedConstant">\\</span>- ]<span class="String">"</span></span>;
|
||||
dates <span class="Keyword">=</span> (<span class="Keyword">new</span> <span class="TypeName">RegExp</span>((<span class="String"><span class="String">"</span><span class="UserDefinedConstant">\\</span>d+<span class="String">"</span></span> <span class="Keyword">+</span> sep <span class="Keyword">+</span> <span class="String"><span class="String">"</span><span class="UserDefinedConstant">\\</span>d+<span class="String">"</span></span> <span class="Keyword">+</span> sep <span class="Keyword">+</span> <span class="String"><span class="String">"</span><span class="UserDefinedConstant">\\</span>d+<span class="String">"</span></span>), <span class="String"><span class="String">"</span>g<span class="String">"</span></span>));
|
||||
dates <span class="Keyword">=</span> (<span class="Keyword">new</span> <span class="TypeName">RegExp</span>(<span class="String"><span class="String">"</span><span class="UserDefinedConstant">\\</span>d+<span class="String">"</span></span> <span class="Keyword">+</span> (sep) <span class="Keyword">+</span> <span class="String"><span class="String">"</span><span class="UserDefinedConstant">\\</span>d+<span class="String">"</span></span> <span class="Keyword">+</span> (sep) <span class="Keyword">+</span> <span class="String"><span class="String">"</span><span class="UserDefinedConstant">\\</span>d+<span class="String">"</span></span>, <span class="String"><span class="String">"</span>g<span class="String">"</span></span>));
|
||||
</pre><button onclick='javascript: var dates, sentence, sep;
|
||||
sentence = ("" + (22 / 7) + " is a decent approximation of π");
|
||||
sep = "[.\\/\\- ]";
|
||||
dates = (new RegExp(("\\d+" + sep + "\\d+" + sep + "\\d+"), "g"));;alert(sentence);'>run: sentence</button><br class='clear' /></div>
|
||||
dates = (new RegExp("\\d+" + (sep) + "\\d+" + (sep) + "\\d+", "g"));;alert(sentence);'>run: sentence</button><br class='clear' /></div>
|
||||
|
||||
<p>
|
||||
<span id="heredocs" class="bookmark"></span>
|
||||
@@ -1606,27 +1617,27 @@ dates = (new RegExp(("\\d+" + sep + "\\d+" + sep + "\\d+"), "g"));;alert(sentenc
|
||||
Multiline strings are allowed in CoffeeScript.
|
||||
</p>
|
||||
<div class='code'><pre class="idle">mobyDick <span class="Keyword">=</span> <span class="String"><span class="String">"</span>Call me Ishmael. Some years ago --</span>
|
||||
<span class="String">never mind how long precisely -- having little</span>
|
||||
<span class="String">or no money in my purse, and nothing particular</span>
|
||||
<span class="String">to interest me on shore, I thought I would sail</span>
|
||||
<span class="String">about a little and see the watery part of the</span>
|
||||
<span class="String">world...<span class="String">"</span></span>
|
||||
<span class="String"> never mind how long precisely -- having little</span>
|
||||
<span class="String"> or no money in my purse, and nothing particular</span>
|
||||
<span class="String"> to interest me on shore, I thought I would sail</span>
|
||||
<span class="String"> about a little and see the watery part of the</span>
|
||||
<span class="String"> world...<span class="String">"</span></span>
|
||||
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> mobyDick;
|
||||
mobyDick <span class="Keyword">=</span> <span class="String"><span class="String">"</span>Call me Ishmael. Some years ago -- \</span>
|
||||
<span class="String">never mind how long precisely -- having little \</span>
|
||||
<span class="String">or no money in my purse, and nothing particular \</span>
|
||||
<span class="String">to interest me on shore, I thought I would sail \</span>
|
||||
<span class="String">about a little and see the watery part of the \</span>
|
||||
<span class="String">world...<span class="String">"</span></span>;
|
||||
mobyDick <span class="Keyword">=</span> <span class="String"><span class="String">"</span>Call me Ishmael. Some years ago --\</span>
|
||||
<span class="String"> never mind how long precisely -- having little\</span>
|
||||
<span class="String"> or no money in my purse, and nothing particular\</span>
|
||||
<span class="String"> to interest me on shore, I thought I would sail\</span>
|
||||
<span class="String"> about a little and see the watery part of the\</span>
|
||||
<span class="String"> world...<span class="String">"</span></span>;
|
||||
</pre><button onclick='javascript: var mobyDick;
|
||||
mobyDick = "Call me Ishmael. Some years ago -- \
|
||||
never mind how long precisely -- having little \
|
||||
or no money in my purse, and nothing particular \
|
||||
to interest me on shore, I thought I would sail \
|
||||
about a little and see the watery part of the \
|
||||
world...";;alert(mobyDick);'>run: mobyDick</button><br class='clear' /></div>
|
||||
mobyDick = "Call me Ishmael. Some years ago --\
|
||||
never mind how long precisely -- having little\
|
||||
or no money in my purse, and nothing particular\
|
||||
to interest me on shore, I thought I would sail\
|
||||
about a little and see the watery part of the\
|
||||
world...";;alert(mobyDick);'>run: mobyDick</button><br class='clear' /></div>
|
||||
<p>
|
||||
Heredocs can be used to hold formatted or indentation-sensitive text
|
||||
(or, if you just don't feel like escaping quotes and apostrophes). The
|
||||
@@ -1651,11 +1662,11 @@ html <span class="Keyword">=</span> <span class="String"><span class="String">'<
|
||||
are preserved in the generated code.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="Comment"><span class="Comment">###</span></span>
|
||||
<span class="Comment">CoffeeScript Compiler v0.9.0</span>
|
||||
<span class="Comment">CoffeeScript Compiler v0.9.4</span>
|
||||
<span class="Comment">Released under the MIT License</span>
|
||||
<span class="Comment"><span class="Comment">###</span></span>
|
||||
<span class="Comment">###</span>
|
||||
</pre><pre class="idle"><span class="Comment"><span class="Comment">/*</span></span>
|
||||
<span class="Comment">CoffeeScript Compiler v0.9.0</span>
|
||||
<span class="Comment">CoffeeScript Compiler v0.9.4</span>
|
||||
<span class="Comment">Released under the MIT License</span>
|
||||
<span class="Comment"><span class="Comment">*/</span></span>
|
||||
</pre><br class='clear' /></div>
|
||||
@@ -1687,22 +1698,27 @@ html <span class="Keyword">=</span> <span class="String"><span class="String">'<
|
||||
|
||||
option <span class="String"><span class="String">'</span>-o<span class="String">'</span></span>, <span class="String"><span class="String">'</span>--output [DIR]<span class="String">'</span></span>, <span class="String"><span class="String">'</span>directory for compiled code<span class="String">'</span></span>
|
||||
|
||||
task <span class="String"><span class="String">'</span>build:parser<span class="String">'</span></span>, <span class="String"><span class="String">'</span>rebuild the Jison parser<span class="String">'</span></span>, <span class="Storage">-></span>
|
||||
task <span class="String"><span class="String">'</span>build:parser<span class="String">'</span></span>, <span class="String"><span class="String">'</span>rebuild the Jison parser<span class="String">'</span></span>, <span class="FunctionArgument">(</span><span class="FunctionArgument">options</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
require <span class="String"><span class="String">'</span>jison<span class="String">'</span></span>
|
||||
code <span class="Keyword">=</span> require(<span class="String"><span class="String">'</span>./lib/grammar<span class="String">'</span></span>).parser.generate()
|
||||
dir <span class="Keyword">=</span> options.output <span class="Keyword">or</span> <span class="String"><span class="String">'</span>lib<span class="String">'</span></span>
|
||||
fs.writeFile <span class="String"><span class="String">"</span><span class="String"><span class="String">#</span>dir</span>/parser.js<span class="String">"</span></span>, code
|
||||
fs.writeFile <span class="String"><span class="String">"</span><span class="String"><span class="String">#{</span>dir<span class="String">}</span></span>/parser.js<span class="String">"</span></span>, code
|
||||
</pre><pre class="idle"><span class="Storage">var</span> fs;
|
||||
fs <span class="Keyword">=</span> require(<span class="String"><span class="String">'</span>fs<span class="String">'</span></span>);
|
||||
option(<span class="String"><span class="String">'</span>-o<span class="String">'</span></span>, <span class="String"><span class="String">'</span>--output [DIR]<span class="String">'</span></span>, <span class="String"><span class="String">'</span>directory for compiled code<span class="String">'</span></span>);
|
||||
task(<span class="String"><span class="String">'</span>build:parser<span class="String">'</span></span>, <span class="String"><span class="String">'</span>rebuild the Jison parser<span class="String">'</span></span>, <span class="Storage">function</span>() {
|
||||
task(<span class="String"><span class="String">'</span>build:parser<span class="String">'</span></span>, <span class="String"><span class="String">'</span>rebuild the Jison parser<span class="String">'</span></span>, <span class="Storage">function</span>(options) {
|
||||
<span class="Storage">var</span> code, dir;
|
||||
require(<span class="String"><span class="String">'</span>jison<span class="String">'</span></span>);
|
||||
code <span class="Keyword">=</span> require(<span class="String"><span class="String">'</span>./lib/grammar<span class="String">'</span></span>).parser.generate();
|
||||
dir <span class="Keyword">=</span> options.output <span class="Keyword">||</span> <span class="String"><span class="String">'</span>lib<span class="String">'</span></span>;
|
||||
<span class="Keyword">return</span> fs.writeFile((<span class="String"><span class="String">"</span><span class="String">"</span></span> <span class="Keyword">+</span> dir <span class="Keyword">+</span> <span class="String"><span class="String">"</span>/parser.js<span class="String">"</span></span>), code);
|
||||
<span class="Keyword">return</span> fs.writeFile(<span class="String"><span class="String">"</span><span class="String">"</span></span> <span class="Keyword">+</span> (dir) <span class="Keyword">+</span> <span class="String"><span class="String">"</span>/parser.js<span class="String">"</span></span>, code);
|
||||
});
|
||||
</pre><br class='clear' /></div>
|
||||
<p>
|
||||
If you need to invoke one task before another — for example, running
|
||||
<tt>build</tt> before <tt>test</tt>, you can use the <tt>invoke</tt> function:
|
||||
<tt>invoke 'build'</tt>
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<span id="scripts" class="bookmark"></span>
|
||||
@@ -1799,7 +1815,7 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</li>
|
||||
<li>
|
||||
<b>dsc</b>'s <a href="http://github.com/dsc/coffeecup">CoffeeCup</a>
|
||||
— A Python WSGI middleware that compiles CoffeeScript to JavaScript
|
||||
— a Python WSGI middleware that compiles CoffeeScript to JavaScript
|
||||
on-demand during development.
|
||||
</li>
|
||||
<li>
|
||||
@@ -1812,9 +1828,19 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
— a custom filter for rendering CoffeeScript inline within
|
||||
<a href="http://haml-lang.com/">HAML</a> templates.
|
||||
</li>
|
||||
<li>
|
||||
<b>chrislloyd</b>'s <a href="http://github.com/chrislloyd/roast">Roast</a>
|
||||
— a CoffeeScript compiler plug-in that allows you to include external
|
||||
source files.
|
||||
</li>
|
||||
<li>
|
||||
<b>mauricemach</b>'s <a href="http://github.com/mauricemach/coffeekup">CoffeeKup</a>
|
||||
— Markup as CoffeeScript. After _why's
|
||||
<a href="http://markaby.github.com/">Markaby</a>.
|
||||
</li>
|
||||
<li>
|
||||
<b>jashkenas</b>'s <a href="http://jashkenas.github.com/docco/">Docco</a>
|
||||
— A quick-and-dirty literate-programming-style documentation generator
|
||||
— a quick-and-dirty literate-programming-style documentation generator
|
||||
for CoffeeScript. Used to produce the annotated source.
|
||||
</li>
|
||||
</ul>
|
||||
@@ -1838,6 +1864,47 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
<span id="change_log" class="bookmark"></span>
|
||||
Change Log
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.4</b>
|
||||
CoffeeScript now uses appropriately-named temporary variables, and recycles
|
||||
their references after use. Added <tt>require.extensions</tt> support for
|
||||
<b>Node.js 0.3</b>. Loading CoffeeScript in the browser now adds just a
|
||||
single <tt>CoffeeScript</tt> object to global scope.
|
||||
Fixes for implicit object and block comment edge cases.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.3</b>
|
||||
CoffeeScript <tt>switch</tt> statements now compile into JS <tt>switch</tt>
|
||||
statements — they previously compiled into <tt>if/else</tt> chains
|
||||
for JavaScript 1.3 compatibility.
|
||||
Soaking a function invocation is now supported. Users of the RubyMine
|
||||
editor should now be able to use <tt>--watch</tt> mode.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.2</b>
|
||||
Specifying the start and end of a range literal is now optional, eg. <tt>array[3..]</tt>.
|
||||
You can now say <tt>a not instanceof b</tt>.
|
||||
Fixed important bugs with nested significant and non-significant indentation (Issue #637).
|
||||
Added a <tt>--require</tt> flag that allows you to hook into the <tt>coffee</tt> command.
|
||||
Added a custom <tt>jsl.conf</tt> file for our preferred JavaScriptLint setup.
|
||||
Sped up Jison grammar compilation time by flattening rules for operations.
|
||||
Block comments can now be used with JavaScript-minifier-friendly syntax.
|
||||
Added JavaScript's compound assignment bitwise operators. Bugfixes to
|
||||
implicit object literals with leading number and string keys, as the subject
|
||||
of implicit calls, and as part of compound assignment.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.1</b>
|
||||
Bugfix release for <b>0.9.1</b>. Greatly improves the handling of mixed
|
||||
implicit objects, implicit function calls, and implicit indentation.
|
||||
String and regex interpolation is now strictly <tt>#{ ... }</tt> (Ruby style).
|
||||
The compiler now takes a <tt>--require</tt> flag, which specifies scripts
|
||||
to run before compilation.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.0</b>
|
||||
@@ -1847,7 +1914,7 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
literals use <tt>:</tt>, as in JavaScript. This allows us to have implicit
|
||||
object literals, and YAML-style object definitions. Half assignments are
|
||||
removed, in favor of <tt>+=</tt>, <tt>or=</tt>, and friends.
|
||||
Interpolation now uses a hash mark <tt>#</tt> instead of the dollar sign
|
||||
Interpolation now uses a hash mark <tt>#</tt> instead of the dollar sign
|
||||
<tt>$</tt> — because dollar signs may be part of a valid JS identifier.
|
||||
Downwards range comprehensions are now safe again, and are optimized to
|
||||
straight for loops when created with integer endpoints.
|
||||
@@ -1862,6 +1929,7 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
on the object — useful in constructors and setter functions.
|
||||
Constructor functions can now take splats.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.7.2</b>
|
||||
Quick bugfix (right after 0.7.1) for a problem that prevented <tt>coffee</tt>
|
||||
@@ -2067,7 +2135,7 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
conversion. Splats. Splice literals. Object comprehensions. Blocks.
|
||||
The existential operator. Many thanks to all the folks who posted issues,
|
||||
with special thanks to
|
||||
<a href="http://github.com/kamatsu">Liam O'Connor-Davis</a> for whitespace
|
||||
<a href="http://github.com/liamoc">Liam O'Connor-Davis</a> for whitespace
|
||||
and expression help.
|
||||
</p>
|
||||
|
||||
|
||||
45
lib/browser.js
Normal file
45
lib/browser.js
Normal file
@@ -0,0 +1,45 @@
|
||||
(function() {
|
||||
var CoffeeScript, processScripts;
|
||||
CoffeeScript = require('./coffee-script');
|
||||
CoffeeScript.eval = function(code, options) {
|
||||
return eval(CoffeeScript.compile(code, options));
|
||||
};
|
||||
CoffeeScript.run = function(code, options) {
|
||||
return (Function(CoffeeScript.compile(code, options)))();
|
||||
};
|
||||
if (!(typeof window !== "undefined" && window !== null)) {
|
||||
return null;
|
||||
}
|
||||
CoffeeScript.load = function(url, options) {
|
||||
var xhr;
|
||||
xhr = new (window.ActiveXObject || XMLHttpRequest)('Microsoft.XMLHTTP');
|
||||
xhr.open('GET', url, true);
|
||||
if ('overrideMimeType' in xhr) {
|
||||
xhr.overrideMimeType('text/plain');
|
||||
}
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState === 4) {
|
||||
return CoffeeScript.run(xhr.responseText, options);
|
||||
}
|
||||
};
|
||||
return xhr.send(null);
|
||||
};
|
||||
processScripts = function() {
|
||||
var _i, _len, _ref;
|
||||
_ref = document.getElementsByTagName('script');
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
(function() {
|
||||
var script = _ref[_i];
|
||||
return script.type === 'text/coffeescript' ? (script.src ? CoffeeScript.load(script.src) : setTimeout(function() {
|
||||
return CoffeeScript.run(script.innerHTML);
|
||||
})) : null;
|
||||
})();
|
||||
}
|
||||
return null;
|
||||
};
|
||||
if (window.addEventListener) {
|
||||
addEventListener('DOMContentLoaded', processScripts, false);
|
||||
} else {
|
||||
attachEvent('onload', processScripts);
|
||||
}
|
||||
}).call(this);
|
||||
46
lib/cake.js
46
lib/cake.js
@@ -11,11 +11,11 @@
|
||||
oparse = null;
|
||||
helpers.extend(global, {
|
||||
task: function(name, description, action) {
|
||||
var _a;
|
||||
var _ref;
|
||||
if (!(action)) {
|
||||
_a = [description, action];
|
||||
action = _a[0];
|
||||
description = _a[1];
|
||||
_ref = [description, action];
|
||||
action = _ref[0];
|
||||
description = _ref[1];
|
||||
}
|
||||
return (tasks[name] = {
|
||||
name: name,
|
||||
@@ -35,9 +35,9 @@
|
||||
});
|
||||
exports.run = function() {
|
||||
return path.exists('Cakefile', function(exists) {
|
||||
var _a, _b, _c, _d, arg, args;
|
||||
var _i, _len, _ref, _result, 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').toString(), {
|
||||
@@ -48,37 +48,31 @@
|
||||
return printTasks();
|
||||
}
|
||||
options = oparse.parse(args);
|
||||
_a = []; _c = options.arguments;
|
||||
for (_b = 0, _d = _c.length; _b < _d; _b++) {
|
||||
arg = _c[_b];
|
||||
_a.push(invoke(arg));
|
||||
_result = []; _ref = options.arguments;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
arg = _ref[_i];
|
||||
_result.push(invoke(arg));
|
||||
}
|
||||
return _a;
|
||||
return _result;
|
||||
});
|
||||
};
|
||||
printTasks = function() {
|
||||
var _a, _b, desc, i, name, spaces, task;
|
||||
var _ref, desc, name, spaces, task;
|
||||
puts('');
|
||||
_a = tasks;
|
||||
for (name in _a) {
|
||||
task = _a[name];
|
||||
_ref = tasks;
|
||||
for (name in _ref) {
|
||||
task = _ref[name];
|
||||
spaces = 20 - name.length;
|
||||
spaces = spaces > 0 ? (function() {
|
||||
_b = [];
|
||||
for (i = 0; (0 <= spaces ? i <= spaces : i >= spaces); (0 <= spaces ? i += 1 : i -= 1)) {
|
||||
_b.push(' ');
|
||||
}
|
||||
return _b;
|
||||
})().join('') : '';
|
||||
desc = task.description ? ("# " + task.description) : '';
|
||||
puts("cake " + name + spaces + " " + desc);
|
||||
spaces = spaces > 0 ? Array(spaces + 1).join(' ') : '';
|
||||
desc = task.description ? ("# " + (task.description)) : '';
|
||||
puts("cake " + (name) + (spaces) + " " + (desc));
|
||||
}
|
||||
if (switches.length) {
|
||||
return puts(oparse.help());
|
||||
}
|
||||
};
|
||||
missingTask = function(task) {
|
||||
puts("No such task: \"" + task + "\"");
|
||||
puts("No such task: \"" + (task) + "\"");
|
||||
return process.exit(1);
|
||||
};
|
||||
})();
|
||||
}).call(this);
|
||||
|
||||
76
lib/coffee-script.js
Normal file → Executable file
76
lib/coffee-script.js
Normal file → Executable file
@@ -1,29 +1,31 @@
|
||||
(function() {
|
||||
var Lexer, compile, helpers, lexer, parser, path, processScripts;
|
||||
if (typeof process !== "undefined" && process !== null) {
|
||||
path = require('path');
|
||||
Lexer = require('./lexer').Lexer;
|
||||
parser = require('./parser').parser;
|
||||
helpers = require('./helpers').helpers;
|
||||
helpers.extend(global, require('./nodes'));
|
||||
require.registerExtension ? require.registerExtension('.coffee', function(content) {
|
||||
var Lexer, _ref, compile, fs, lexer, parser, path;
|
||||
path = require('path');
|
||||
_ref = require('./lexer');
|
||||
Lexer = _ref.Lexer;
|
||||
_ref = require('./parser');
|
||||
parser = _ref.parser;
|
||||
if (require.extensions) {
|
||||
fs = require('fs');
|
||||
require.extensions['.coffee'] = function(module, filename) {
|
||||
var content;
|
||||
content = compile(fs.readFileSync(filename, 'utf8'));
|
||||
module.filename = ("" + (filename) + " (compiled)");
|
||||
return module._compile(content, module.filename);
|
||||
};
|
||||
} else if (require.registerExtension) {
|
||||
require.registerExtension('.coffee', function(content) {
|
||||
return compile(content);
|
||||
}) : null;
|
||||
} else {
|
||||
this.exports = (this.CoffeeScript = {});
|
||||
Lexer = this.Lexer;
|
||||
parser = this.parser;
|
||||
helpers = this.helpers;
|
||||
});
|
||||
}
|
||||
exports.VERSION = '0.9.0';
|
||||
lexer = new Lexer();
|
||||
exports.VERSION = '0.9.4';
|
||||
exports.compile = (compile = function(code, options) {
|
||||
options = options || {};
|
||||
options || (options = {});
|
||||
try {
|
||||
return (parser.parse(lexer.tokenize(code))).compile(options);
|
||||
} catch (err) {
|
||||
if (options.fileName) {
|
||||
err.message = ("In " + options.fileName + ", " + err.message);
|
||||
err.message = ("In " + (options.fileName) + ", " + (err.message));
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
@@ -34,12 +36,25 @@
|
||||
exports.nodes = function(code) {
|
||||
return parser.parse(lexer.tokenize(code));
|
||||
};
|
||||
exports.run = (function(code, options) {
|
||||
exports.run = function(code, options) {
|
||||
var __filename, root;
|
||||
root = module;
|
||||
while (root.parent) {
|
||||
root = root.parent;
|
||||
}
|
||||
root.filename = (__filename = ("" + (options.fileName) + " (compiled)"));
|
||||
if (root.moduleCache) {
|
||||
root.moduleCache = {};
|
||||
}
|
||||
return root._compile(exports.compile(code, options), root.filename);
|
||||
};
|
||||
exports.eval = function(code, options) {
|
||||
var __dirname, __filename;
|
||||
module.filename = (__filename = options.fileName);
|
||||
__filename = options.fileName;
|
||||
__dirname = path.dirname(__filename);
|
||||
return eval(exports.compile(code, options));
|
||||
});
|
||||
};
|
||||
lexer = new Lexer();
|
||||
parser.lexer = {
|
||||
lex: function() {
|
||||
var token;
|
||||
@@ -57,20 +72,5 @@
|
||||
return "";
|
||||
}
|
||||
};
|
||||
if ((typeof document !== "undefined" && document !== null) && document.getElementsByTagName) {
|
||||
processScripts = function() {
|
||||
var _a, _b, _c, _d, tag;
|
||||
_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;
|
||||
};
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener('load', processScripts, false);
|
||||
} else if (window.attachEvent) {
|
||||
window.attachEvent('onload', processScripts);
|
||||
}
|
||||
}
|
||||
})();
|
||||
parser.yy = require('./nodes');
|
||||
}).call(this);
|
||||
|
||||
165
lib/command.js
165
lib/command.js
@@ -1,33 +1,39 @@
|
||||
(function() {
|
||||
var BANNER, CoffeeScript, SWITCHES, _a, compileOptions, compileScript, compileScripts, compileStdio, exec, fs, lint, optionParser, options, optparse, parseOptions, path, printTokens, sources, spawn, usage, version, watch, writeJs;
|
||||
var BANNER, CoffeeScript, EventEmitter, SWITCHES, _ref, compileOptions, compileScript, compileScripts, compileStdio, exec, fs, helpers, lint, optionParser, optparse, opts, parseOptions, path, printTokens, sources, spawn, usage, version, watch, writeJs;
|
||||
fs = require('fs');
|
||||
path = require('path');
|
||||
optparse = require('./optparse');
|
||||
CoffeeScript = require('./coffee-script');
|
||||
_a = require('child_process');
|
||||
spawn = _a.spawn;
|
||||
exec = _a.exec;
|
||||
_ref = require('./helpers');
|
||||
helpers = _ref.helpers;
|
||||
_ref = require('child_process');
|
||||
spawn = _ref.spawn;
|
||||
exec = _ref.exec;
|
||||
_ref = require('events');
|
||||
EventEmitter = _ref.EventEmitter;
|
||||
helpers.extend(CoffeeScript, new EventEmitter());
|
||||
global.CoffeeScript = CoffeeScript;
|
||||
BANNER = 'coffee compiles CoffeeScript source files into JavaScript.\n\nUsage:\n coffee path/to/script.coffee';
|
||||
SWITCHES = [['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-o', '--output [DIR]', 'set the directory for compiled JavaScript'], ['-w', '--watch', 'watch scripts for changes, and recompile'], ['-p', '--print', 'print the compiled JavaScript to stdout'], ['-l', '--lint', 'pipe the compiled JavaScript through JSLint'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-e', '--eval', 'compile a string from the command line'], ['--no-wrap', 'compile without the top-level function wrapper'], ['-t', '--tokens', 'print the tokens that the lexer produces'], ['-n', '--nodes', 'print the parse tree that Jison produces'], ['-v', '--version', 'display CoffeeScript version'], ['-h', '--help', 'display this help message']];
|
||||
options = {};
|
||||
SWITCHES = [['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-o', '--output [DIR]', 'set the directory for compiled JavaScript'], ['-w', '--watch', 'watch scripts for changes, and recompile'], ['-p', '--print', 'print the compiled JavaScript to stdout'], ['-l', '--lint', 'pipe the compiled JavaScript through JSLint'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-e', '--eval', 'compile a string from the command line'], ['-r', '--require [FILE*]', 'require a library before executing your script'], ['--no-wrap', 'compile without the top-level function wrapper'], ['-t', '--tokens', 'print the tokens that the lexer produces'], ['-n', '--nodes', 'print the parse tree that Jison produces'], ['-v', '--version', 'display CoffeeScript version'], ['-h', '--help', 'display this help message']];
|
||||
opts = {};
|
||||
sources = [];
|
||||
optionParser = null;
|
||||
exports.run = function() {
|
||||
var flags, separator;
|
||||
parseOptions();
|
||||
if (options.help) {
|
||||
if (opts.help) {
|
||||
return usage();
|
||||
}
|
||||
if (options.version) {
|
||||
if (opts.version) {
|
||||
return version();
|
||||
}
|
||||
if (options.interactive) {
|
||||
if (opts.interactive) {
|
||||
return require('./repl');
|
||||
}
|
||||
if (options.stdio) {
|
||||
if (opts.stdio) {
|
||||
return compileStdio();
|
||||
}
|
||||
if (options.eval) {
|
||||
if (opts.eval) {
|
||||
return compileScript('console', sources[0]);
|
||||
}
|
||||
if (!(sources.length)) {
|
||||
@@ -39,7 +45,7 @@
|
||||
flags = sources.slice((separator + 1), sources.length);
|
||||
sources = sources.slice(0, separator);
|
||||
}
|
||||
if (options.run) {
|
||||
if (opts.run) {
|
||||
flags = sources.slice(1, sources.length + 1).concat(flags);
|
||||
sources = [sources[0]];
|
||||
}
|
||||
@@ -47,35 +53,35 @@
|
||||
return compileScripts();
|
||||
};
|
||||
compileScripts = function() {
|
||||
var _b, _c, _d, _e;
|
||||
_b = []; _d = sources;
|
||||
for (_c = 0, _e = _d.length; _c < _e; _c++) {
|
||||
var _i, _len, _ref2, _result;
|
||||
_result = []; _ref2 = sources;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
(function() {
|
||||
var base, compile;
|
||||
var source = _d[_c];
|
||||
return _b.push((function() {
|
||||
var source = _ref2[_i];
|
||||
return _result.push((function() {
|
||||
base = source;
|
||||
compile = function(source, topLevel) {
|
||||
return path.exists(source, function(exists) {
|
||||
if (!(exists)) {
|
||||
throw new Error("File not found: " + source);
|
||||
throw new Error("File not found: " + (source));
|
||||
}
|
||||
return fs.stat(source, function(err, stats) {
|
||||
if (stats.isDirectory()) {
|
||||
return fs.readdir(source, function(err, files) {
|
||||
var _f, _g, _h, _i, file;
|
||||
_f = []; _h = files;
|
||||
for (_g = 0, _i = _h.length; _g < _i; _g++) {
|
||||
file = _h[_g];
|
||||
_f.push(compile(path.join(source, file)));
|
||||
var _j, _len2, _ref3, _result2, file;
|
||||
_result2 = []; _ref3 = files;
|
||||
for (_j = 0, _len2 = _ref3.length; _j < _len2; _j++) {
|
||||
file = _ref3[_j];
|
||||
_result2.push(compile(path.join(source, file)));
|
||||
}
|
||||
return _f;
|
||||
return _result2;
|
||||
});
|
||||
} else if (topLevel || path.extname(source) === '.coffee') {
|
||||
fs.readFile(source, function(err, code) {
|
||||
return compileScript(source, code.toString(), base);
|
||||
});
|
||||
if (options.watch) {
|
||||
if (opts.watch) {
|
||||
return watch(source, base);
|
||||
}
|
||||
}
|
||||
@@ -86,34 +92,53 @@
|
||||
})());
|
||||
})();
|
||||
}
|
||||
return _b;
|
||||
return _result;
|
||||
};
|
||||
compileScript = function(source, code, base) {
|
||||
var codeOpts, js, o;
|
||||
o = options;
|
||||
codeOpts = compileOptions(source);
|
||||
compileScript = function(file, input, base) {
|
||||
var _i, _len, _ref2, o, options, req, t, task;
|
||||
o = opts;
|
||||
options = compileOptions(file);
|
||||
if (o.require) {
|
||||
_ref2 = o.require;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
req = _ref2[_i];
|
||||
require(helpers.starts(req, '.') ? fs.realpathSync(req) : req);
|
||||
}
|
||||
}
|
||||
try {
|
||||
t = (task = {
|
||||
file: file,
|
||||
input: input,
|
||||
options: options
|
||||
});
|
||||
CoffeeScript.emit('compile', task);
|
||||
if (o.tokens) {
|
||||
return printTokens(CoffeeScript.tokens(code));
|
||||
return printTokens(CoffeeScript.tokens(t.input));
|
||||
} else if (o.nodes) {
|
||||
return puts(CoffeeScript.nodes(code).toString());
|
||||
return puts(CoffeeScript.nodes(t.input).toString());
|
||||
} else if (o.run) {
|
||||
return CoffeeScript.run(code, codeOpts);
|
||||
return CoffeeScript.run(t.input, t.options);
|
||||
} else {
|
||||
js = CoffeeScript.compile(code, codeOpts);
|
||||
t.output = CoffeeScript.compile(t.input, t.options);
|
||||
CoffeeScript.emit('success', task);
|
||||
if (o.print) {
|
||||
return print(js);
|
||||
return print(t.output);
|
||||
} else if (o.compile) {
|
||||
return writeJs(source, js, base);
|
||||
return writeJs(t.file, t.output, base);
|
||||
} else if (o.lint) {
|
||||
return lint(js);
|
||||
return lint(t.output);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
if (!(o.watch)) {
|
||||
error(err.stack) && process.exit(1);
|
||||
CoffeeScript.emit('failure', err, task);
|
||||
if (CoffeeScript.listeners('failure').length) {
|
||||
return null;
|
||||
}
|
||||
return puts(err.message);
|
||||
if (o.watch) {
|
||||
return puts(err.message);
|
||||
}
|
||||
error(err.stack);
|
||||
return process.exit(1);
|
||||
}
|
||||
};
|
||||
compileStdio = function() {
|
||||
@@ -134,10 +159,13 @@
|
||||
persistent: true,
|
||||
interval: 500
|
||||
}, function(curr, prev) {
|
||||
if (curr.mtime.getTime() === prev.mtime.getTime()) {
|
||||
if (curr.size === prev.size && curr.mtime.getTime() === prev.mtime.getTime()) {
|
||||
return null;
|
||||
}
|
||||
return fs.readFile(source, function(err, code) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
return compileScript(source, code.toString(), base);
|
||||
});
|
||||
});
|
||||
@@ -147,65 +175,66 @@
|
||||
filename = path.basename(source, path.extname(source)) + '.js';
|
||||
srcDir = path.dirname(source);
|
||||
baseDir = srcDir.substring(base.length);
|
||||
dir = options.output ? path.join(options.output, baseDir) : srcDir;
|
||||
dir = opts.output ? path.join(opts.output, baseDir) : srcDir;
|
||||
jsPath = path.join(dir, filename);
|
||||
compile = function() {
|
||||
if (!(js.length)) {
|
||||
return null;
|
||||
if (js.length <= 0) {
|
||||
js = ' ';
|
||||
}
|
||||
return fs.writeFile(jsPath, js, function(err) {
|
||||
if (options.compile && options.watch) {
|
||||
return puts("Compiled " + source);
|
||||
if (opts.compile && opts.watch) {
|
||||
return puts("Compiled " + (source));
|
||||
}
|
||||
});
|
||||
};
|
||||
return path.exists(dir, function(exists) {
|
||||
return exists ? compile() : exec(("mkdir -p " + dir), compile);
|
||||
return exists ? compile() : exec("mkdir -p " + (dir), compile);
|
||||
});
|
||||
};
|
||||
lint = function(js) {
|
||||
var jsl, printIt;
|
||||
var conf, jsl, printIt;
|
||||
printIt = function(buffer) {
|
||||
return print(buffer.toString());
|
||||
return puts(buffer.toString().trim());
|
||||
};
|
||||
jsl = spawn('jsl', ['-nologo', '-stdin']);
|
||||
conf = __dirname + '/../extras/jsl.conf';
|
||||
jsl = spawn('jsl', ['-nologo', '-stdin', '-conf', conf]);
|
||||
jsl.stdout.on('data', printIt);
|
||||
jsl.stderr.on('data', printIt);
|
||||
jsl.stdin.write(js);
|
||||
return jsl.stdin.end();
|
||||
};
|
||||
printTokens = function(tokens) {
|
||||
var _b, _c, _d, _e, _f, strings, tag, token, value;
|
||||
var _i, _len, _ref2, _ref3, _result, strings, tag, token, value;
|
||||
strings = (function() {
|
||||
_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 + "]";
|
||||
_result = []; _ref2 = tokens;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
token = _ref2[_i];
|
||||
_result.push((function() {
|
||||
_ref3 = [token[0], token[1].toString().replace(/\n/, '\\n')];
|
||||
tag = _ref3[0];
|
||||
value = _ref3[1];
|
||||
return "[" + (tag) + " " + (value) + "]";
|
||||
})());
|
||||
}
|
||||
return _b;
|
||||
return _result;
|
||||
})();
|
||||
return puts(strings.join(' '));
|
||||
};
|
||||
parseOptions = function() {
|
||||
var o;
|
||||
optionParser = new optparse.OptionParser(SWITCHES, BANNER);
|
||||
o = (options = optionParser.parse(process.argv.slice(2, process.argv.length)));
|
||||
options.compile = options.compile || !!o.output;
|
||||
options.run = !(o.compile || o.print || o.lint);
|
||||
options.print = !!(o.print || (o.eval || o.stdio && o.compile));
|
||||
return (sources = options.arguments);
|
||||
o = (opts = optionParser.parse(process.argv.slice(2, process.argv.length)));
|
||||
o.compile || (o.compile = (!!o.output));
|
||||
o.run = !(o.compile || o.print || o.lint);
|
||||
o.print = !!(o.print || (o.eval || o.stdio && o.compile));
|
||||
return (sources = o.arguments);
|
||||
};
|
||||
compileOptions = function(fileName) {
|
||||
var o;
|
||||
o = {
|
||||
fileName: fileName
|
||||
};
|
||||
o.noWrap = options['no-wrap'];
|
||||
o.noWrap = opts['no-wrap'];
|
||||
return o;
|
||||
};
|
||||
usage = function() {
|
||||
@@ -213,7 +242,7 @@
|
||||
return process.exit(0);
|
||||
};
|
||||
version = function() {
|
||||
puts("CoffeeScript version " + CoffeeScript.VERSION);
|
||||
puts("CoffeeScript version " + (CoffeeScript.VERSION));
|
||||
return process.exit(0);
|
||||
};
|
||||
})();
|
||||
}).call(this);
|
||||
|
||||
241
lib/grammar.js
241
lib/grammar.js
@@ -1,5 +1,5 @@
|
||||
(function() {
|
||||
var Parser, _a, _b, _c, _d, _e, _f, _g, _h, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;
|
||||
var Parser, _i, _j, _len, _len2, _ref, _ref2, _ref3, _result, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
Parser = require('jison').Parser;
|
||||
unwrap = /function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/;
|
||||
@@ -8,8 +8,9 @@
|
||||
if (!(action)) {
|
||||
return [patternString, '$$ = $1;', options];
|
||||
}
|
||||
action = (match = (action + '').match(unwrap)) ? match[1] : ("(" + action + "())");
|
||||
return [patternString, ("$$ = " + action + ";"), options];
|
||||
action = (match = (action + '').match(unwrap)) ? match[1] : ("(" + (action) + "())");
|
||||
action = action.replace(/\b(?:[A-Z][a-z]+Node|Expressions)\b/g, 'yy.$&');
|
||||
return [patternString, ("$$ = " + (action) + ";"), options];
|
||||
};
|
||||
grammar = {
|
||||
Root: [
|
||||
@@ -32,9 +33,11 @@
|
||||
return new LiteralNode($1);
|
||||
}), o("CONTINUE", function() {
|
||||
return new LiteralNode($1);
|
||||
}), o("DEBUGGER", function() {
|
||||
return new LiteralNode($1);
|
||||
})
|
||||
],
|
||||
Expression: [o("Value"), o("Call"), o("Code"), o("Operation"), o("Assign"), o("If"), o("Try"), o("While"), o("For"), o("Switch"), o("Extends"), o("Class"), o("Splat"), o("Existence"), o("Comment")],
|
||||
Expression: [o("Value"), o("Call"), o("Code"), o("Operation"), o("Assign"), o("If"), o("Try"), o("While"), o("For"), o("Switch"), o("Extends"), o("Class"), o("Existence"), o("Comment")],
|
||||
Block: [
|
||||
o("INDENT Body OUTDENT", function() {
|
||||
return $2;
|
||||
@@ -239,6 +242,8 @@
|
||||
return $1;
|
||||
}), o("ThisProperty : Expression", function() {
|
||||
return new AssignNode(new ValueNode($1), $3, 'this');
|
||||
}), o("ThisProperty : INDENT Expression OUTDENT", function() {
|
||||
return new AssignNode(new ValueNode($1), $4, 'this');
|
||||
})
|
||||
],
|
||||
ClassBody: [
|
||||
@@ -253,7 +258,7 @@
|
||||
})
|
||||
],
|
||||
Call: [
|
||||
o("Invocation"), o("Super"), o("NEW Invocation", function() {
|
||||
o("Invocation"), o("NEW Invocation", function() {
|
||||
return $2.newInstance();
|
||||
}), o("NEW Value", function() {
|
||||
return (new CallNode($2, [])).newInstance();
|
||||
@@ -265,24 +270,30 @@
|
||||
})
|
||||
],
|
||||
Invocation: [
|
||||
o("Value Arguments", function() {
|
||||
return new CallNode($1, $2);
|
||||
}), o("Invocation Arguments", function() {
|
||||
return new CallNode($1, $2);
|
||||
})
|
||||
],
|
||||
Arguments: [
|
||||
o("CALL_START ArgList OptComma CALL_END", function() {
|
||||
return $2;
|
||||
})
|
||||
],
|
||||
Super: [
|
||||
o("SUPER", function() {
|
||||
o("Value OptFuncExist Arguments", function() {
|
||||
return new CallNode($1, $3, $2);
|
||||
}), o("Invocation OptFuncExist Arguments", function() {
|
||||
return new CallNode($1, $3, $2);
|
||||
}), o("SUPER", function() {
|
||||
return new CallNode('super', [new SplatNode(new LiteralNode('arguments'))]);
|
||||
}), o("SUPER Arguments", function() {
|
||||
return new CallNode('super', $2);
|
||||
})
|
||||
],
|
||||
OptFuncExist: [
|
||||
o("", function() {
|
||||
return false;
|
||||
}), o("FUNC_EXIST", function() {
|
||||
return true;
|
||||
})
|
||||
],
|
||||
Arguments: [
|
||||
o("CALL_START CALL_END", function() {
|
||||
return [];
|
||||
}), o("CALL_START ArgList OptComma CALL_END", function() {
|
||||
return $2;
|
||||
})
|
||||
],
|
||||
This: [
|
||||
o("THIS", function() {
|
||||
return new ValueNode(new LiteralNode('this'));
|
||||
@@ -290,43 +301,53 @@
|
||||
return new ValueNode(new LiteralNode('this'));
|
||||
})
|
||||
],
|
||||
RangeDots: [
|
||||
o(". .", function() {
|
||||
return 'inclusive';
|
||||
}), o(". . .", function() {
|
||||
return 'exclusive';
|
||||
})
|
||||
],
|
||||
ThisProperty: [
|
||||
o("@ Identifier", function() {
|
||||
return new ValueNode(new LiteralNode('this'), [new AccessorNode($2)]);
|
||||
})
|
||||
],
|
||||
Range: [
|
||||
o("[ Expression . . Expression ]", function() {
|
||||
return new RangeNode($2, $5);
|
||||
}), o("[ Expression . . . Expression ]", function() {
|
||||
return new RangeNode($2, $6, true);
|
||||
o("[ Expression RangeDots Expression ]", function() {
|
||||
return new RangeNode($2, $4, $3);
|
||||
})
|
||||
],
|
||||
Slice: [
|
||||
o("INDEX_START Expression . . Expression INDEX_END", function() {
|
||||
return new RangeNode($2, $5);
|
||||
}), o("INDEX_START Expression . . . Expression INDEX_END", function() {
|
||||
return new RangeNode($2, $6, true);
|
||||
o("INDEX_START Expression RangeDots Expression INDEX_END", function() {
|
||||
return new RangeNode($2, $4, $3);
|
||||
}), o("INDEX_START Expression RangeDots INDEX_END", function() {
|
||||
return new RangeNode($2, null, $3);
|
||||
}), o("INDEX_START RangeDots Expression INDEX_END", function() {
|
||||
return new RangeNode(null, $3, $2);
|
||||
})
|
||||
],
|
||||
Array: [
|
||||
o("[ ArgList OptComma ]", function() {
|
||||
o("[ ]", function() {
|
||||
return new ArrayNode([]);
|
||||
}), o("[ ArgList OptComma ]", function() {
|
||||
return new ArrayNode($2);
|
||||
})
|
||||
],
|
||||
ArgList: [
|
||||
o("", function() {
|
||||
return [];
|
||||
}), o("Expression", function() {
|
||||
o("Arg", function() {
|
||||
return [$1];
|
||||
}), o("ArgList , Expression", function() {
|
||||
}), o("ArgList , Arg", function() {
|
||||
return $1.concat([$3]);
|
||||
}), o("ArgList OptComma TERMINATOR Expression", function() {
|
||||
}), o("ArgList OptComma TERMINATOR Arg", function() {
|
||||
return $1.concat([$4]);
|
||||
}), o("INDENT ArgList OptComma OUTDENT", function() {
|
||||
return $2;
|
||||
}), o("ArgList OptComma INDENT ArgList OptComma OUTDENT", function() {
|
||||
return $1.concat($4);
|
||||
})
|
||||
],
|
||||
Arg: [o("Expression"), o("Splat")],
|
||||
SimpleArgs: [
|
||||
o("Expression"), o("SimpleArgs , Expression", function() {
|
||||
return $1 instanceof Array ? $1.concat([$3]) : [$1].concat([$3]);
|
||||
@@ -354,6 +375,8 @@
|
||||
Parenthetical: [
|
||||
o("( Line )", function() {
|
||||
return new ParentheticalNode($2);
|
||||
}), o("( )", function() {
|
||||
return new ParentheticalNode(new LiteralNode(''));
|
||||
})
|
||||
],
|
||||
WhileSource: [
|
||||
@@ -477,29 +500,25 @@
|
||||
],
|
||||
Switch: [
|
||||
o("SWITCH Expression INDENT Whens OUTDENT", function() {
|
||||
return $4.switchesOver($2);
|
||||
return new SwitchNode($2, $4);
|
||||
}), o("SWITCH Expression INDENT Whens ELSE Block OUTDENT", function() {
|
||||
return $4.switchesOver($2).addElse($6, true);
|
||||
return new SwitchNode($2, $4, $6);
|
||||
}), o("SWITCH INDENT Whens OUTDENT", function() {
|
||||
return $3;
|
||||
return new SwitchNode(null, $3);
|
||||
}), o("SWITCH INDENT Whens ELSE Block OUTDENT", function() {
|
||||
return $3.addElse($5, true);
|
||||
return new SwitchNode(null, $3, $5);
|
||||
})
|
||||
],
|
||||
Whens: [
|
||||
o("When"), o("Whens When", function() {
|
||||
return $1.addElse($2);
|
||||
return $1.concat($2);
|
||||
})
|
||||
],
|
||||
When: [
|
||||
o("LEADING_WHEN SimpleArgs Block", function() {
|
||||
return new IfNode($2, $3, {
|
||||
statement: true
|
||||
});
|
||||
return [[$2, $3]];
|
||||
}), o("LEADING_WHEN SimpleArgs Block TERMINATOR", function() {
|
||||
return new IfNode($2, $3, {
|
||||
statement: true
|
||||
});
|
||||
return [[$2, $3]];
|
||||
})
|
||||
],
|
||||
IfBlock: [
|
||||
@@ -516,20 +535,20 @@
|
||||
})
|
||||
],
|
||||
If: [
|
||||
o("IfBlock"), o("Statement IF Expression", function() {
|
||||
o("IfBlock"), o("Statement POST_IF Expression", function() {
|
||||
return new IfNode($3, Expressions.wrap([$1]), {
|
||||
statement: true
|
||||
});
|
||||
}), o("Expression IF Expression", function() {
|
||||
}), o("Expression POST_IF Expression", function() {
|
||||
return new IfNode($3, Expressions.wrap([$1]), {
|
||||
statement: true
|
||||
});
|
||||
}), o("Statement UNLESS Expression", function() {
|
||||
}), o("Statement POST_UNLESS Expression", function() {
|
||||
return new IfNode($3, Expressions.wrap([$1]), {
|
||||
statement: true,
|
||||
invert: true
|
||||
});
|
||||
}), o("Expression UNLESS Expression", function() {
|
||||
}), o("Expression POST_UNLESS Expression", function() {
|
||||
return new IfNode($3, Expressions.wrap([$1]), {
|
||||
statement: true,
|
||||
invert: true
|
||||
@@ -537,115 +556,75 @@
|
||||
})
|
||||
],
|
||||
Operation: [
|
||||
o("! Expression", function() {
|
||||
return new OpNode('!', $2);
|
||||
}), o("!! Expression", function() {
|
||||
return new OpNode('!!', $2);
|
||||
}), o("- Expression", (function() {
|
||||
o("UNARY Expression", function() {
|
||||
return new OpNode($1, $2);
|
||||
}), o("- Expression", function() {
|
||||
return new OpNode('-', $2);
|
||||
}), {
|
||||
prec: 'UMINUS'
|
||||
}), o("+ Expression", (function() {
|
||||
}, {
|
||||
prec: 'UNARY'
|
||||
}), o("+ Expression", function() {
|
||||
return new OpNode('+', $2);
|
||||
}), {
|
||||
prec: 'UPLUS'
|
||||
}), o("~ Expression", function() {
|
||||
return new OpNode('~', $2);
|
||||
}, {
|
||||
prec: 'UNARY'
|
||||
}), o("-- Expression", function() {
|
||||
return new OpNode('--', $2);
|
||||
}), o("++ Expression", function() {
|
||||
return new OpNode('++', $2);
|
||||
}), o("DELETE Expression", function() {
|
||||
return new OpNode('delete', $2);
|
||||
}), o("TYPEOF Expression", function() {
|
||||
return new OpNode('typeof', $2);
|
||||
}), o("Expression --", function() {
|
||||
return new OpNode('--', $1, null, true);
|
||||
}), o("Expression ++", function() {
|
||||
return new OpNode('++', $1, null, true);
|
||||
}), o("Expression * Expression", function() {
|
||||
return new OpNode('*', $1, $3);
|
||||
}), o("Expression / Expression", function() {
|
||||
return new OpNode('/', $1, $3);
|
||||
}), o("Expression % Expression", function() {
|
||||
return new OpNode('%', $1, $3);
|
||||
}), o("Expression ? Expression", function() {
|
||||
return new OpNode('?', $1, $3);
|
||||
}), o("Expression + Expression", function() {
|
||||
return new OpNode('+', $1, $3);
|
||||
}), o("Expression - Expression", function() {
|
||||
return new OpNode('-', $1, $3);
|
||||
}), o("Expression << Expression", function() {
|
||||
return new OpNode('<<', $1, $3);
|
||||
}), o("Expression >> Expression", function() {
|
||||
return new OpNode('>>', $1, $3);
|
||||
}), o("Expression >>> Expression", function() {
|
||||
return new OpNode('>>>', $1, $3);
|
||||
}), o("Expression & Expression", function() {
|
||||
return new OpNode('&', $1, $3);
|
||||
}), o("Expression | Expression", function() {
|
||||
return new OpNode('|', $1, $3);
|
||||
}), o("Expression ^ Expression", function() {
|
||||
return new OpNode('^', $1, $3);
|
||||
}), o("Expression <= Expression", function() {
|
||||
return new OpNode('<=', $1, $3);
|
||||
}), o("Expression < Expression", function() {
|
||||
return new OpNode('<', $1, $3);
|
||||
}), o("Expression > Expression", function() {
|
||||
return new OpNode('>', $1, $3);
|
||||
}), o("Expression >= Expression", function() {
|
||||
return new OpNode('>=', $1, $3);
|
||||
}), o("Expression == Expression", function() {
|
||||
return new OpNode('==', $1, $3);
|
||||
}), o("Expression != Expression", function() {
|
||||
return new OpNode('!=', $1, $3);
|
||||
}), o("Expression && Expression", function() {
|
||||
return new OpNode('&&', $1, $3);
|
||||
}), o("Expression || Expression", function() {
|
||||
return new OpNode('||', $1, $3);
|
||||
}), o("Expression OP? Expression", function() {
|
||||
return new OpNode('?', $1, $3);
|
||||
}), o("Expression -= Expression", function() {
|
||||
return new OpNode('-=', $1, $3);
|
||||
}), o("Expression += Expression", function() {
|
||||
return new OpNode('+=', $1, $3);
|
||||
}), o("Expression /= Expression", function() {
|
||||
return new OpNode('/=', $1, $3);
|
||||
}), o("Expression *= Expression", function() {
|
||||
return new OpNode('*=', $1, $3);
|
||||
}), o("Expression %= Expression", function() {
|
||||
return new OpNode('%=', $1, $3);
|
||||
}), o("Expression ||= Expression", function() {
|
||||
return new OpNode('||=', $1, $3);
|
||||
}), o("Expression &&= Expression", function() {
|
||||
return new OpNode('&&=', $1, $3);
|
||||
}), o("Expression ?= Expression", function() {
|
||||
return new OpNode('?=', $1, $3);
|
||||
}), o("Expression INSTANCEOF Expression", function() {
|
||||
return new OpNode('instanceof', $1, $3);
|
||||
}), o("Expression MATH Expression", function() {
|
||||
return new OpNode($2, $1, $3);
|
||||
}), o("Expression SHIFT Expression", function() {
|
||||
return new OpNode($2, $1, $3);
|
||||
}), o("Expression COMPARE Expression", function() {
|
||||
return new OpNode($2, $1, $3);
|
||||
}), o("Expression LOGIC Expression", function() {
|
||||
return new OpNode($2, $1, $3);
|
||||
}), o("Value COMPOUND_ASSIGN Expression", function() {
|
||||
return new OpNode($2, $1, $3);
|
||||
}), o("Value COMPOUND_ASSIGN INDENT Expression OUTDENT", function() {
|
||||
return new OpNode($2, $1, $4);
|
||||
}), o("Expression IN Expression", function() {
|
||||
return new InNode($1, $3);
|
||||
}), o("Expression OF Expression", function() {
|
||||
return new OpNode('in', $1, $3);
|
||||
}), o("Expression ! IN Expression", function() {
|
||||
return new OpNode('!', new InNode($1, $4));
|
||||
}), o("Expression ! OF Expression", function() {
|
||||
return new OpNode('!', new ParentheticalNode(new OpNode('in', $1, $4)));
|
||||
}), o("Expression INSTANCEOF Expression", function() {
|
||||
return new OpNode('instanceof', $1, $3);
|
||||
}), o("Expression UNARY IN Expression", function() {
|
||||
return new OpNode($2, new InNode($1, $4));
|
||||
}), o("Expression UNARY OF Expression", function() {
|
||||
return new OpNode($2, new ParentheticalNode(new OpNode('in', $1, $4)));
|
||||
}), o("Expression UNARY INSTANCEOF Expression", function() {
|
||||
return new OpNode($2, new ParentheticalNode(new OpNode('instanceof', $1, $4)));
|
||||
})
|
||||
]
|
||||
};
|
||||
operators = [["left", '?'], ["nonassoc", 'UMINUS', 'UPLUS', '!', '!!', '~', '++', '--'], ["left", '*', '/', '%'], ["left", '+', '-'], ["left", '<<', '>>', '>>>'], ["left", '&', '|', '^'], ["left", '<=', '<', '>', '>='], ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'], ["left", '==', '!='], ["left", '&&', '||', 'OP?'], ["right", '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?='], ["left", '.'], ["right", 'INDENT'], ["left", 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY', 'THROW'], ["right", 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'NEW', 'SUPER', 'CLASS'], ["left", 'EXTENDS'], ["right", '=', ':', 'RETURN'], ["right", '->', '=>', 'UNLESS', 'IF', 'ELSE']];
|
||||
operators = [["right", '?', 'NEW'], ["left", 'CALL_START', 'CALL_END'], ["nonassoc", '++', '--'], ["right", 'UNARY'], ["left", 'MATH'], ["left", '+', '-'], ["left", 'SHIFT'], ["left", 'COMPARE'], ["left", 'INSTANCEOF'], ["left", '==', '!='], ["left", 'LOGIC'], ["right", 'COMPOUND_ASSIGN'], ["left", '.'], ["nonassoc", 'INDENT', 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY', 'THROW'], ["right", 'IF', 'UNLESS', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS', 'EXTENDS'], ["right", '=', ':', 'RETURN'], ["right", '->', '=>', 'UNLESS', 'POST_IF', 'POST_UNLESS']];
|
||||
tokens = [];
|
||||
_a = grammar;
|
||||
for (name in _a) {
|
||||
if (!__hasProp.call(_a, name)) continue;
|
||||
alternatives = _a[name];
|
||||
_ref = grammar;
|
||||
for (name in _ref) {
|
||||
if (!__hasProp.call(_ref, name)) continue;
|
||||
alternatives = _ref[name];
|
||||
grammar[name] = (function() {
|
||||
_b = []; _d = alternatives;
|
||||
for (_c = 0, _e = _d.length; _c < _e; _c++) {
|
||||
alt = _d[_c];
|
||||
_b.push((function() {
|
||||
_g = alt[0].split(' ');
|
||||
for (_f = 0, _h = _g.length; _f < _h; _f++) {
|
||||
token = _g[_f];
|
||||
_result = []; _ref2 = alternatives;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
alt = _ref2[_i];
|
||||
_result.push((function() {
|
||||
_ref3 = alt[0].split(' ');
|
||||
for (_j = 0, _len2 = _ref3.length; _j < _len2; _j++) {
|
||||
token = _ref3[_j];
|
||||
if (!(grammar[token])) {
|
||||
tokens.push(token);
|
||||
}
|
||||
@@ -656,7 +635,7 @@
|
||||
return alt;
|
||||
})());
|
||||
}
|
||||
return _b;
|
||||
return _result;
|
||||
})();
|
||||
}
|
||||
exports.parser = new Parser({
|
||||
@@ -665,4 +644,4 @@
|
||||
operators: operators.reverse(),
|
||||
startSymbol: 'Root'
|
||||
});
|
||||
})();
|
||||
}).call(this);
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
(function() {
|
||||
var compact, count, del, ends, extend, flatten, helpers, include, indexOf, merge, starts;
|
||||
if (!(typeof process !== "undefined" && process !== null)) {
|
||||
this.exports = this;
|
||||
}
|
||||
helpers = (exports.helpers = {});
|
||||
helpers.indexOf = (indexOf = function(array, item, from) {
|
||||
var _a, _b, index, other;
|
||||
var _len, _ref, index, other;
|
||||
if (array.indexOf) {
|
||||
return array.indexOf(item, from);
|
||||
}
|
||||
_a = array;
|
||||
for (index = 0, _b = _a.length; index < _b; index++) {
|
||||
other = _a[index];
|
||||
_ref = array;
|
||||
for (index = 0, _len = _ref.length; index < _len; index++) {
|
||||
other = _ref[index];
|
||||
if (other === item && (!from || (from <= index))) {
|
||||
return index;
|
||||
}
|
||||
@@ -30,13 +27,15 @@
|
||||
return string.substring(start, start + literal.length) === literal;
|
||||
});
|
||||
helpers.compact = (compact = function(array) {
|
||||
var _a, _b, _c, _d, item;
|
||||
_a = []; _c = array;
|
||||
for (_b = 0, _d = _c.length; _b < _d; _b++) {
|
||||
item = _c[_b];
|
||||
item ? _a.push(item) : null;
|
||||
var _i, _len, _ref, _result, item;
|
||||
_result = []; _ref = array;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
item = _ref[_i];
|
||||
if (item) {
|
||||
_result.push(item);
|
||||
}
|
||||
}
|
||||
return _a;
|
||||
return _result;
|
||||
});
|
||||
helpers.count = (count = function(string, letter) {
|
||||
var num, pos;
|
||||
@@ -49,38 +48,42 @@
|
||||
return num;
|
||||
});
|
||||
helpers.merge = (merge = function(options, overrides) {
|
||||
var _a, _b, fresh, key, val;
|
||||
var _ref, fresh, key, val;
|
||||
fresh = {};
|
||||
_a = options;
|
||||
for (key in _a) {
|
||||
val = _a[key];
|
||||
_ref = options;
|
||||
for (key in _ref) {
|
||||
val = _ref[key];
|
||||
(fresh[key] = val);
|
||||
}
|
||||
if (overrides) {
|
||||
_b = overrides;
|
||||
for (key in _b) {
|
||||
val = _b[key];
|
||||
_ref = overrides;
|
||||
for (key in _ref) {
|
||||
val = _ref[key];
|
||||
(fresh[key] = val);
|
||||
}
|
||||
}
|
||||
return fresh;
|
||||
});
|
||||
helpers.extend = (extend = function(object, properties) {
|
||||
var _a, _b, key, val;
|
||||
_a = []; _b = properties;
|
||||
for (key in _b) {
|
||||
val = _b[key];
|
||||
_a.push(object[key] = val);
|
||||
var _ref, _result, key, val;
|
||||
_result = []; _ref = properties;
|
||||
for (key in _ref) {
|
||||
val = _ref[key];
|
||||
_result.push(object[key] = val);
|
||||
}
|
||||
return _a;
|
||||
return _result;
|
||||
});
|
||||
helpers.flatten = (flatten = function(array) {
|
||||
var _a, _b, _c, item, memo;
|
||||
var _i, _len, _ref, item, memo;
|
||||
memo = [];
|
||||
_b = array;
|
||||
for (_a = 0, _c = _b.length; _a < _c; _a++) {
|
||||
item = _b[_a];
|
||||
item instanceof Array ? (memo = memo.concat(item)) : memo.push(item);
|
||||
_ref = array;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
item = _ref[_i];
|
||||
if (item instanceof Array) {
|
||||
memo = memo.concat(item);
|
||||
} else {
|
||||
memo.push(item);
|
||||
}
|
||||
}
|
||||
return memo;
|
||||
});
|
||||
@@ -90,4 +93,4 @@
|
||||
delete obj[key];
|
||||
return val;
|
||||
});
|
||||
})();
|
||||
}).call(this);
|
||||
|
||||
12
lib/index.js
12
lib/index.js
@@ -1,10 +1,10 @@
|
||||
(function() {
|
||||
var _a, key, val;
|
||||
var _ref, key, val;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
_a = require('./coffee-script');
|
||||
for (key in _a) {
|
||||
if (!__hasProp.call(_a, key)) continue;
|
||||
val = _a[key];
|
||||
_ref = require('./coffee-script');
|
||||
for (key in _ref) {
|
||||
if (!__hasProp.call(_ref, key)) continue;
|
||||
val = _ref[key];
|
||||
(exports[key] = val);
|
||||
}
|
||||
})();
|
||||
}).call(this);
|
||||
|
||||
246
lib/lexer.js
246
lib/lexer.js
@@ -1,21 +1,13 @@
|
||||
(function() {
|
||||
var ASSIGNED, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_KEYWORDS, COMMENT, CONVERSIONS, HEREDOC, HEREDOC_INDENT, IDENTIFIER, INTERPOLATION, JS_CLEANER, JS_FORBIDDEN, JS_KEYWORDS, LAST_DENT, LAST_DENTS, LINE_BREAK, Lexer, MULTILINER, MULTI_DENT, NEXT_CHARACTER, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX_END, REGEX_ESCAPE, REGEX_INTERPOLATION, REGEX_START, RESERVED, Rewriter, STRING_NEWLINES, WHITESPACE, _a, _b, _c, compact, count, helpers, include, starts;
|
||||
var ASSIGNED, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, CONVERSIONS, HEREDOC, HEREDOC_INDENT, IDENTIFIER, JS_CLEANER, JS_FORBIDDEN, JS_KEYWORDS, LAST_DENT, LAST_DENTS, LINE_BREAK, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NEXT_CHARACTER, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX_END, REGEX_ESCAPE, REGEX_INTERPOLATION, REGEX_START, RESERVED, Rewriter, SHIFT, UNARY, WHITESPACE, _ref, compact, count, include, starts;
|
||||
var __slice = Array.prototype.slice;
|
||||
if (typeof process !== "undefined" && process !== null) {
|
||||
_a = require('./rewriter');
|
||||
Rewriter = _a.Rewriter;
|
||||
_b = require('./helpers');
|
||||
helpers = _b.helpers;
|
||||
} else {
|
||||
this.exports = this;
|
||||
Rewriter = this.Rewriter;
|
||||
helpers = this.helpers;
|
||||
}
|
||||
_c = helpers;
|
||||
include = _c.include;
|
||||
count = _c.count;
|
||||
starts = _c.starts;
|
||||
compact = _c.compact;
|
||||
_ref = require('./rewriter');
|
||||
Rewriter = _ref.Rewriter;
|
||||
_ref = require('./helpers').helpers;
|
||||
include = _ref.include;
|
||||
count = _ref.count;
|
||||
starts = _ref.starts;
|
||||
compact = _ref.compact;
|
||||
exports.Lexer = (function() {
|
||||
Lexer = function() {};
|
||||
Lexer.prototype.tokenize = function(code, options) {
|
||||
@@ -26,6 +18,7 @@
|
||||
this.i = 0;
|
||||
this.line = o.line || 0;
|
||||
this.indent = 0;
|
||||
this.indebt = 0;
|
||||
this.outdebt = 0;
|
||||
this.indents = [];
|
||||
this.tokens = [];
|
||||
@@ -86,10 +79,13 @@
|
||||
if (id === 'all' && this.tag() === 'FOR') {
|
||||
tag = 'ALL';
|
||||
}
|
||||
if (include(UNARY, tag)) {
|
||||
tag = 'UNARY';
|
||||
}
|
||||
if (include(JS_FORBIDDEN, id)) {
|
||||
if (forcedIdentifier) {
|
||||
tag = 'STRING';
|
||||
id = ("\"" + id + "\"");
|
||||
id = ("\"" + (id) + "\"");
|
||||
if (forcedIdentifier === 'accessor') {
|
||||
close_index = true;
|
||||
if (this.tag() !== '@') {
|
||||
@@ -105,6 +101,12 @@
|
||||
if (include(COFFEE_ALIASES, id)) {
|
||||
tag = (id = CONVERSIONS[id]);
|
||||
}
|
||||
if (include(LOGIC, id)) {
|
||||
tag = 'LOGIC';
|
||||
}
|
||||
if (id === '!') {
|
||||
tag = 'UNARY';
|
||||
}
|
||||
}
|
||||
this.token(tag, id);
|
||||
if (close_index) {
|
||||
@@ -132,7 +134,7 @@
|
||||
if (!(string = this.balancedToken(['"', '"'], ['#{', '}']) || this.balancedToken(["'", "'"]))) {
|
||||
return false;
|
||||
}
|
||||
this.interpolateString(string.replace(STRING_NEWLINES, " \\\n"));
|
||||
this.interpolateString(string.replace(/\n/g, '\\\n'));
|
||||
this.line += count(string, "\n");
|
||||
this.i += string.length;
|
||||
return true;
|
||||
@@ -143,10 +145,10 @@
|
||||
return false;
|
||||
}
|
||||
quote = match[1].substr(0, 1);
|
||||
doc = this.sanitizeHeredoc(match[2] || match[4], {
|
||||
doc = this.sanitizeHeredoc(match[2] || match[4] || '', {
|
||||
quote: quote
|
||||
});
|
||||
this.interpolateString(("" + quote + doc + quote), {
|
||||
this.interpolateString(quote + doc + quote, {
|
||||
heredoc: true
|
||||
});
|
||||
this.line += count(match[1], "\n");
|
||||
@@ -154,17 +156,17 @@
|
||||
return true;
|
||||
};
|
||||
Lexer.prototype.commentToken = function() {
|
||||
var comment, match;
|
||||
var match;
|
||||
if (!(match = this.chunk.match(COMMENT))) {
|
||||
return false;
|
||||
}
|
||||
this.line += count(match[1], "\n");
|
||||
this.i += match[1].length;
|
||||
if (match[2]) {
|
||||
comment = this.sanitizeHeredoc(match[2], {
|
||||
herecomment: true
|
||||
});
|
||||
this.token('HERECOMMENT', comment.split(MULTILINER));
|
||||
this.token('HERECOMMENT', this.sanitizeHeredoc(match[2], {
|
||||
herecomment: true,
|
||||
indent: Array(this.indent + 1).join(' ')
|
||||
}));
|
||||
this.token('TERMINATOR', '\n');
|
||||
}
|
||||
return true;
|
||||
@@ -182,8 +184,11 @@
|
||||
return true;
|
||||
};
|
||||
Lexer.prototype.regexToken = function() {
|
||||
var end, flags, regex, str;
|
||||
if (!(this.chunk.match(REGEX_START))) {
|
||||
var _ref2, end, first, flags, regex, str;
|
||||
if (!(first = this.chunk.match(REGEX_START))) {
|
||||
return false;
|
||||
}
|
||||
if (first[1] === ' ' && !('CALL_START' === (_ref2 = this.tag()) || '=' === _ref2)) {
|
||||
return false;
|
||||
}
|
||||
if (include(NOT_REGEX, this.tag())) {
|
||||
@@ -204,11 +209,11 @@
|
||||
return '\\' + escaped;
|
||||
});
|
||||
this.tokens = this.tokens.concat([['(', '('], ['NEW', 'new'], ['IDENTIFIER', 'RegExp'], ['CALL_START', '(']]);
|
||||
this.interpolateString(("\"" + str + "\""), {
|
||||
this.interpolateString("\"" + (str) + "\"", {
|
||||
escapeQuotes: true
|
||||
});
|
||||
if (flags) {
|
||||
this.tokens.splice(this.tokens.length, 0, [',', ','], ['STRING', ("\"" + flags + "\"")]);
|
||||
this.tokens.splice(this.tokens.length, 0, [',', ','], ['STRING', ("\"" + (flags) + "\"")]);
|
||||
}
|
||||
this.tokens.splice(this.tokens.length, 0, [')', ')'], [')', ')']);
|
||||
} else {
|
||||
@@ -233,20 +238,22 @@
|
||||
size = indent.match(LAST_DENTS).reverse()[0].match(LAST_DENT)[1].length;
|
||||
nextCharacter = this.match(NEXT_CHARACTER, 1);
|
||||
noNewlines = nextCharacter === '.' || nextCharacter === ',' || this.unfinished();
|
||||
if (size === this.indent) {
|
||||
if (size - this.indebt === this.indent) {
|
||||
if (noNewlines) {
|
||||
return this.suppressNewlines();
|
||||
}
|
||||
return this.newlineToken(indent);
|
||||
} else if (size > this.indent) {
|
||||
if (noNewlines) {
|
||||
this.indebt = size - this.indent;
|
||||
return this.suppressNewlines();
|
||||
}
|
||||
this.outdebt = 0;
|
||||
diff = size - this.indent;
|
||||
diff = size - this.indent + this.outdebt;
|
||||
this.token('INDENT', diff);
|
||||
this.indents.push(diff);
|
||||
this.outdebt = (this.indebt = 0);
|
||||
} else {
|
||||
this.indebt = 0;
|
||||
this.outdentToken(this.indent - size, noNewlines);
|
||||
}
|
||||
this.indent = size;
|
||||
@@ -293,7 +300,7 @@
|
||||
return true;
|
||||
};
|
||||
Lexer.prototype.newlineToken = function(newlines) {
|
||||
if (!(this.tag() === 'TERMINATOR')) {
|
||||
if (this.tag() !== 'TERMINATOR') {
|
||||
this.token('TERMINATOR', "\n");
|
||||
}
|
||||
return true;
|
||||
@@ -305,31 +312,45 @@
|
||||
return true;
|
||||
};
|
||||
Lexer.prototype.literalToken = function() {
|
||||
var _d, match, prevSpaced, space, tag, value;
|
||||
var _ref2, match, prev, space, spaced, tag, value;
|
||||
match = this.chunk.match(OPERATOR);
|
||||
value = match && match[1];
|
||||
space = match && match[2];
|
||||
if (value && value.match(CODE)) {
|
||||
this.tagParameters();
|
||||
}
|
||||
value = value || this.chunk.substr(0, 1);
|
||||
value || (value = this.chunk.substr(0, 1));
|
||||
this.i += value.length;
|
||||
prevSpaced = this.prev() && this.prev().spaced;
|
||||
spaced = (prev = this.prev()) && prev.spaced;
|
||||
tag = value;
|
||||
if (value === '=') {
|
||||
if (include(JS_FORBIDDEN, this.value())) {
|
||||
this.assignmentError();
|
||||
}
|
||||
if (('or' === (_d = this.value()) || 'and' === _d)) {
|
||||
return this.tag(1, CONVERSIONS[this.value()] + '=');
|
||||
if (('or' === (_ref2 = this.value()) || 'and' === _ref2)) {
|
||||
this.tokens.splice(this.tokens.length - 1, 1, ['COMPOUND_ASSIGN', CONVERSIONS[this.value()] + '=', prev[2]]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (value === ';') {
|
||||
tag = 'TERMINATOR';
|
||||
} else if (value === '?' && prevSpaced) {
|
||||
tag = 'OP?';
|
||||
} else if (include(CALLABLE, this.tag()) && !prevSpaced) {
|
||||
} else if (include(LOGIC, value)) {
|
||||
tag = 'LOGIC';
|
||||
} else if (include(MATH, value)) {
|
||||
tag = 'MATH';
|
||||
} else if (include(COMPARE, value)) {
|
||||
tag = 'COMPARE';
|
||||
} else if (include(COMPOUND_ASSIGN, value)) {
|
||||
tag = 'COMPOUND_ASSIGN';
|
||||
} else if (include(UNARY, value)) {
|
||||
tag = 'UNARY';
|
||||
} else if (include(SHIFT, value)) {
|
||||
tag = 'SHIFT';
|
||||
} else if (include(CALLABLE, this.tag()) && !spaced) {
|
||||
if (value === '(') {
|
||||
if (prev[0] === '?') {
|
||||
prev[0] = 'FUNC_EXIST';
|
||||
}
|
||||
tag = 'CALL_START';
|
||||
} else if (value === '[') {
|
||||
tag = 'INDEX_START';
|
||||
@@ -366,21 +387,29 @@
|
||||
return accessor ? 'accessor' : false;
|
||||
};
|
||||
Lexer.prototype.sanitizeHeredoc = function(doc, options) {
|
||||
var _d, attempt, indent, match;
|
||||
while ((match = HEREDOC_INDENT.exec(doc))) {
|
||||
attempt = (typeof (_d = match[2]) !== "undefined" && _d !== null) ? match[2] : match[3];
|
||||
if (!indent || attempt.length < indent.length) {
|
||||
indent = attempt;
|
||||
var _ref2, attempt, indent, match;
|
||||
indent = options.indent;
|
||||
if (options.herecomment && !include(doc, '\n')) {
|
||||
return doc;
|
||||
}
|
||||
if (!(options.herecomment)) {
|
||||
while ((match = HEREDOC_INDENT.exec(doc)) !== null) {
|
||||
attempt = (typeof (_ref2 = match[2]) !== "undefined" && _ref2 !== null) ? match[2] : match[3];
|
||||
if (!(typeof indent !== "undefined" && indent !== null) || attempt.length < indent.length) {
|
||||
indent = attempt;
|
||||
}
|
||||
}
|
||||
}
|
||||
indent || (indent = '');
|
||||
doc = doc.replace(new RegExp("^" + indent, 'gm'), '');
|
||||
if (options.herecomment) {
|
||||
return doc;
|
||||
}
|
||||
return doc.replace(MULTILINER, "\\n").replace(new RegExp(options.quote, 'g'), ("\\" + options.quote));
|
||||
doc = doc.replace(/^\n/, '');
|
||||
return doc.replace(MULTILINER, "\\n").replace(new RegExp(options.quote, 'g'), "\\" + (options.quote));
|
||||
};
|
||||
Lexer.prototype.tagParameters = function() {
|
||||
var _d, i, tok;
|
||||
var i, tok;
|
||||
if (this.tag() !== ')') {
|
||||
return null;
|
||||
}
|
||||
@@ -391,12 +420,16 @@
|
||||
if (!tok) {
|
||||
return null;
|
||||
}
|
||||
if ((_d = tok[0]) === 'IDENTIFIER') {
|
||||
tok[0] = 'PARAM';
|
||||
} else if (_d === ')') {
|
||||
tok[0] = 'PARAM_END';
|
||||
} else if (_d === '(' || _d === 'CALL_START') {
|
||||
return (tok[0] = 'PARAM_START');
|
||||
switch (tok[0]) {
|
||||
case 'IDENTIFIER':
|
||||
tok[0] = 'PARAM';
|
||||
break;
|
||||
case ')':
|
||||
tok[0] = 'PARAM_END';
|
||||
break;
|
||||
case '(':
|
||||
case 'CALL_START':
|
||||
return (tok[0] = 'PARAM_START');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -405,14 +438,14 @@
|
||||
return this.outdentToken(this.indent);
|
||||
};
|
||||
Lexer.prototype.identifierError = function(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));
|
||||
};
|
||||
Lexer.prototype.assignmentError = function() {
|
||||
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");
|
||||
};
|
||||
Lexer.prototype.balancedString = function(str, delimited, options) {
|
||||
var _d, _e, _f, _g, close, i, levels, open, pair, slash;
|
||||
options = options || {};
|
||||
var _i, _len, _ref2, _ref3, close, i, levels, open, pair, slash;
|
||||
options || (options = {});
|
||||
slash = delimited[0][0] === '/';
|
||||
levels = [];
|
||||
i = 0;
|
||||
@@ -420,12 +453,12 @@
|
||||
if (levels.length && starts(str, '\\', i)) {
|
||||
i += 1;
|
||||
} else {
|
||||
_e = delimited;
|
||||
for (_d = 0, _f = _e.length; _d < _f; _d++) {
|
||||
pair = _e[_d];
|
||||
_g = pair;
|
||||
open = _g[0];
|
||||
close = _g[1];
|
||||
_ref2 = delimited;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
pair = _ref2[_i];
|
||||
_ref3 = pair;
|
||||
open = _ref3[0];
|
||||
close = _ref3[1];
|
||||
if (levels.length && starts(str, close, i) && levels[levels.length - 1] === pair) {
|
||||
levels.pop();
|
||||
i += close.length - 1;
|
||||
@@ -449,59 +482,48 @@
|
||||
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));
|
||||
}
|
||||
return !i ? false : str.substring(0, i);
|
||||
};
|
||||
Lexer.prototype.interpolateString = function(str, options) {
|
||||
var _d, _e, _f, _g, _h, _i, _j, escaped, expr, group, i, idx, inner, interp, interpolated, lexer, match, nested, pi, quote, tag, tok, token, tokens, value;
|
||||
options = options || {};
|
||||
var _len, _ref2, _ref3, escaped, expr, i, idx, inner, interpolated, lexer, nested, pi, quote, tag, tok, token, tokens, value;
|
||||
options || (options = {});
|
||||
if (str.length < 3 || !starts(str, '"')) {
|
||||
return this.token('STRING', str);
|
||||
} else {
|
||||
lexer = new Lexer();
|
||||
tokens = [];
|
||||
quote = str.substring(0, 1);
|
||||
_d = [1, 1];
|
||||
i = _d[0];
|
||||
pi = _d[1];
|
||||
_ref2 = [1, 1];
|
||||
i = _ref2[0];
|
||||
pi = _ref2[1];
|
||||
while (i < str.length - 1) {
|
||||
if (starts(str, '\\', i)) {
|
||||
i += 1;
|
||||
} else if ((match = str.substring(i).match(INTERPOLATION))) {
|
||||
_e = match;
|
||||
group = _e[0];
|
||||
interp = _e[1];
|
||||
if (starts(interp, '@')) {
|
||||
interp = ("this." + (interp.substring(1)));
|
||||
}
|
||||
} else if (expr = this.balancedString(str.substring(i), [['#{', '}']])) {
|
||||
if (pi < i) {
|
||||
tokens.push(['STRING', ("" + quote + (str.substring(pi, i)) + quote)]);
|
||||
}
|
||||
tokens.push(['IDENTIFIER', interp]);
|
||||
i += group.length - 1;
|
||||
pi = i + 1;
|
||||
} else if ((expr = this.balancedString(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) {
|
||||
if (options.heredoc) {
|
||||
inner = inner.replace(new RegExp('\\\\' + quote, 'g'), quote);
|
||||
}
|
||||
nested = lexer.tokenize(("(" + inner + ")"), {
|
||||
nested = lexer.tokenize("(" + (inner) + ")", {
|
||||
line: this.line
|
||||
});
|
||||
_f = nested;
|
||||
for (idx = 0, _g = _f.length; idx < _g; idx++) {
|
||||
tok = _f[idx];
|
||||
tok[0] === 'CALL_END' ? (tok[0] = ')') : null;
|
||||
_ref2 = nested;
|
||||
for (idx = 0, _len = _ref2.length; idx < _len; idx++) {
|
||||
tok = _ref2[idx];
|
||||
if (tok[0] === 'CALL_END') {
|
||||
(tok[0] = ')');
|
||||
}
|
||||
}
|
||||
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,26 +531,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')) {
|
||||
if (tokens[0][0] !== 'STRING') {
|
||||
tokens.unshift(['STRING', '""']);
|
||||
}
|
||||
interpolated = tokens.length > 1;
|
||||
if (interpolated) {
|
||||
this.token('(', '(');
|
||||
}
|
||||
_h = tokens;
|
||||
for (i = 0, _i = _h.length; i < _i; i++) {
|
||||
token = _h[i];
|
||||
_j = token;
|
||||
tag = _j[0];
|
||||
value = _j[1];
|
||||
_ref2 = tokens;
|
||||
for (i = 0, _len = _ref2.length; i < _len; i++) {
|
||||
token = _ref2[i];
|
||||
_ref3 = token;
|
||||
tag = _ref3[0];
|
||||
value = _ref3[1];
|
||||
if (tag === 'TOKENS') {
|
||||
this.tokens = this.tokens.concat(value);
|
||||
} else if (tag === 'STRING' && options.escapeQuotes) {
|
||||
escaped = value.substring(1, value.length - 1).replace(/"/g, '\\"');
|
||||
this.token(tag, ("\"" + escaped + "\""));
|
||||
this.token(tag, "\"" + (escaped) + "\"");
|
||||
} else {
|
||||
this.token(tag, value);
|
||||
}
|
||||
@@ -582,33 +604,37 @@
|
||||
};
|
||||
return Lexer;
|
||||
})();
|
||||
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"];
|
||||
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", "debugger"];
|
||||
COFFEE_ALIASES = ["and", "or", "is", "isnt", "not"];
|
||||
COFFEE_KEYWORDS = COFFEE_ALIASES.concat(["then", "unless", "until", "loop", "yes", "no", "on", "off", "of", "by", "where", "when"]);
|
||||
RESERVED = ["case", "default", "do", "function", "var", "void", "with", "const", "let", "enum", "export", "import", "native", "__hasProp", "__extends", "__slice"];
|
||||
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED);
|
||||
IDENTIFIER = /^([a-zA-Z\$_](\w|\$)*)/;
|
||||
NUMBER = /^(((\b0(x|X)[0-9a-fA-F]+)|((\b[0-9]+(\.[0-9]+)?|\.[0-9]+)(e[+\-]?[0-9]+)?)))\b/i;
|
||||
HEREDOC = /^("{6}|'{6}|"{3}\n?([\s\S]*?)\n?([ \t]*)"{3}|'{3}\n?([\s\S]*?)\n?([ \t]*)'{3})/;
|
||||
INTERPOLATION = /^#([a-zA-Z_@]\w*(\.\w+)*)/;
|
||||
OPERATOR = /^(-[\-=>]?|\+[+=]?|[*&|\/%=<>:!?]+)([ \t]*)/;
|
||||
HEREDOC = /^("{6}|'{6}|"{3}([\s\S]*?)\n?([ \t]*)"{3}|'{3}([\s\S]*?)\n?([ \t]*)'{3})/;
|
||||
OPERATOR = /^(-[\-=>]?|\+[+=]?|[*&|\/%=<>^:!?]+)([ \t]*)/;
|
||||
WHITESPACE = /^([ \t]+)/;
|
||||
COMMENT = /^(\s*\#{3}(?!#)[ \t]*\n+([\s\S]*?)[ \t]*\n+[ \t]*\#{3}|(\s*#(?!##[^#])[^\n]*)+)/;
|
||||
COMMENT = /^(###([^#][\s\S]*?)(###[ \t]*\n|(###)?$)|(\s*#(?!##[^#])[^\n]*)+)/;
|
||||
CODE = /^((-|=)>)/;
|
||||
MULTI_DENT = /^((\n([ \t]*))+)(\.)?/;
|
||||
LAST_DENTS = /\n([ \t]*)/g;
|
||||
LAST_DENT = /\n([ \t]*)/;
|
||||
REGEX_START = /^\/[^\/ ]/;
|
||||
REGEX_INTERPOLATION = /([^\\]#[a-zA-Z_@]|[^\\]#\{.*[^\\]\})/;
|
||||
REGEX_START = /^\/([^\/])/;
|
||||
REGEX_INTERPOLATION = /([^\\]#\{.*[^\\]\})/;
|
||||
REGEX_END = /^(([imgy]{1,4})\b|\W|$)/;
|
||||
REGEX_ESCAPE = /\\[^\$]/g;
|
||||
JS_CLEANER = /(^`|`$)/g;
|
||||
MULTILINER = /\n/g;
|
||||
STRING_NEWLINES = /\n[ \t]*/g;
|
||||
NO_NEWLINE = /^([+\*&|\/\-%=<>!.\\][<>=&|]*|and|or|is|isnt|not|delete|typeof|instanceof)$/;
|
||||
HEREDOC_INDENT = /(\n+([ \t]*)|^([ \t]+))/g;
|
||||
ASSIGNED = /^\s*([a-zA-Z\$_@]\w*[ \t]*?[:=][^=])/;
|
||||
ASSIGNED = /^\s*(([a-zA-Z\$_@]\w*|["'][^\r\n]+?["']|\d+)[ \t]*?[:=][^:=])/;
|
||||
NEXT_CHARACTER = /^\s*(\S)/;
|
||||
COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|='];
|
||||
UNARY = ['UMINUS', 'UPLUS', '!', '!!', '~', 'TYPEOF', 'DELETE'];
|
||||
LOGIC = ['&', '|', '^', '&&', '||'];
|
||||
SHIFT = ['<<', '>>', '>>>'];
|
||||
COMPARE = ['<=', '<', '>', '>='];
|
||||
MATH = ['*', '/', '%'];
|
||||
NOT_REGEX = ['NUMBER', 'REGEX', '++', '--', 'FALSE', 'NULL', 'TRUE', ']'];
|
||||
CALLABLE = ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING', '@', 'THIS', '?', '::'];
|
||||
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];
|
||||
@@ -620,4 +646,4 @@
|
||||
'not': '!',
|
||||
'===': '=='
|
||||
};
|
||||
})();
|
||||
}).call(this);
|
||||
|
||||
1249
lib/nodes.js
1249
lib/nodes.js
File diff suppressed because it is too large
Load Diff
@@ -7,27 +7,28 @@
|
||||
return this;
|
||||
};
|
||||
OptionParser.prototype.parse = function(args) {
|
||||
var _a, _b, _c, _d, _e, arg, i, isOption, matchedRule, options, rule;
|
||||
var _i, _len, _len2, _ref, _ref2, arg, i, isOption, matchedRule, options, rule, value;
|
||||
options = {
|
||||
arguments: []
|
||||
};
|
||||
args = normalizeArguments(args);
|
||||
_a = args;
|
||||
for (i = 0, _b = _a.length; i < _b; i++) {
|
||||
arg = _a[i];
|
||||
_ref = args;
|
||||
for (i = 0, _len = _ref.length; i < _len; i++) {
|
||||
arg = _ref[i];
|
||||
isOption = !!(arg.match(LONG_FLAG) || arg.match(SHORT_FLAG));
|
||||
matchedRule = false;
|
||||
_d = this.rules;
|
||||
for (_c = 0, _e = _d.length; _c < _e; _c++) {
|
||||
rule = _d[_c];
|
||||
_ref2 = this.rules;
|
||||
for (_i = 0, _len2 = _ref2.length; _i < _len2; _i++) {
|
||||
rule = _ref2[_i];
|
||||
if (rule.shortFlag === arg || rule.longFlag === arg) {
|
||||
options[rule.name] = rule.hasArgument ? args[i += 1] : true;
|
||||
value = rule.hasArgument ? args[i += 1] : true;
|
||||
options[rule.name] = rule.isList ? (options[rule.name] || []).concat(value) : value;
|
||||
matchedRule = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isOption && !matchedRule) {
|
||||
throw new Error("unrecognized option: " + arg);
|
||||
throw new Error("unrecognized option: " + (arg));
|
||||
}
|
||||
if (!isOption) {
|
||||
options.arguments = args.slice(i, args.length);
|
||||
@@ -37,24 +38,18 @@
|
||||
return options;
|
||||
};
|
||||
OptionParser.prototype.help = function() {
|
||||
var _a, _b, _c, _d, i, letPart, lines, rule, spaces;
|
||||
var _i, _len, _ref, letPart, lines, rule, spaces;
|
||||
lines = ['Available options:'];
|
||||
if (this.banner) {
|
||||
lines.unshift("" + this.banner + "\n");
|
||||
lines.unshift("" + (this.banner) + "\n");
|
||||
}
|
||||
_b = this.rules;
|
||||
for (_a = 0, _c = _b.length; _a < _c; _a++) {
|
||||
rule = _b[_a];
|
||||
_ref = this.rules;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
rule = _ref[_i];
|
||||
spaces = 15 - rule.longFlag.length;
|
||||
spaces = spaces > 0 ? (function() {
|
||||
_d = [];
|
||||
for (i = 0; (0 <= spaces ? i <= spaces : i >= spaces); (0 <= spaces ? i += 1 : i -= 1)) {
|
||||
_d.push(' ');
|
||||
}
|
||||
return _d;
|
||||
})().join('') : '';
|
||||
spaces = spaces > 0 ? Array(spaces + 1).join(' ') : '';
|
||||
letPart = rule.shortFlag ? rule.shortFlag + ', ' : ' ';
|
||||
lines.push(" " + letPart + rule.longFlag + spaces + rule.description);
|
||||
lines.push(' ' + letPart + rule.longFlag + spaces + rule.description);
|
||||
}
|
||||
return "\n" + (lines.join('\n')) + "\n";
|
||||
};
|
||||
@@ -63,44 +58,46 @@
|
||||
LONG_FLAG = /^(--\w[\w\-]+)/;
|
||||
SHORT_FLAG = /^(-\w)/;
|
||||
MULTI_FLAG = /^-(\w{2,})/;
|
||||
OPTIONAL = /\[(.+)\]/;
|
||||
OPTIONAL = /\[(\w+(\*?))\]/;
|
||||
buildRules = function(rules) {
|
||||
var _a, _b, _c, _d, tuple;
|
||||
_a = []; _c = rules;
|
||||
for (_b = 0, _d = _c.length; _b < _d; _b++) {
|
||||
tuple = _c[_b];
|
||||
_a.push((function() {
|
||||
var _i, _len, _ref, _result, tuple;
|
||||
_result = []; _ref = rules;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
tuple = _ref[_i];
|
||||
_result.push((function() {
|
||||
if (tuple.length < 3) {
|
||||
tuple.unshift(null);
|
||||
}
|
||||
return buildRule.apply(this, tuple);
|
||||
})());
|
||||
}
|
||||
return _a;
|
||||
return _result;
|
||||
};
|
||||
buildRule = function(shortFlag, longFlag, description) {
|
||||
buildRule = function(shortFlag, longFlag, description, options) {
|
||||
var match;
|
||||
match = longFlag.match(OPTIONAL);
|
||||
longFlag = longFlag.match(LONG_FLAG)[1];
|
||||
options || (options = {});
|
||||
return {
|
||||
name: longFlag.substr(2),
|
||||
shortFlag: shortFlag,
|
||||
longFlag: longFlag,
|
||||
description: description,
|
||||
hasArgument: !!(match && match[1])
|
||||
hasArgument: !!(match && match[1]),
|
||||
isList: !!(match && match[2])
|
||||
};
|
||||
};
|
||||
normalizeArguments = function(args) {
|
||||
var _a, _b, _c, _d, _e, _f, arg, l, match, result;
|
||||
var _i, _j, _len, _len2, _ref, _ref2, arg, l, match, result;
|
||||
args = args.slice(0);
|
||||
result = [];
|
||||
_b = args;
|
||||
for (_a = 0, _c = _b.length; _a < _c; _a++) {
|
||||
arg = _b[_a];
|
||||
if ((match = arg.match(MULTI_FLAG))) {
|
||||
_e = match[1].split('');
|
||||
for (_d = 0, _f = _e.length; _d < _f; _d++) {
|
||||
l = _e[_d];
|
||||
_ref = args;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
arg = _ref[_i];
|
||||
if (match = arg.match(MULTI_FLAG)) {
|
||||
_ref2 = match[1].split('');
|
||||
for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
|
||||
l = _ref2[_j];
|
||||
result.push('-' + l);
|
||||
}
|
||||
} else {
|
||||
@@ -109,4 +106,4 @@
|
||||
}
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
}).call(this);
|
||||
|
||||
398
lib/parser.js
398
lib/parser.js
File diff suppressed because one or more lines are too long
@@ -12,7 +12,7 @@
|
||||
run = function(buffer) {
|
||||
var val;
|
||||
try {
|
||||
val = CoffeeScript.run(buffer.toString(), {
|
||||
val = CoffeeScript.eval(buffer.toString(), {
|
||||
noWrap: true,
|
||||
globals: true,
|
||||
fileName: 'repl'
|
||||
@@ -35,4 +35,4 @@
|
||||
});
|
||||
repl.on('line', run);
|
||||
repl.prompt();
|
||||
})();
|
||||
}).call(this);
|
||||
|
||||
496
lib/rewriter.js
496
lib/rewriter.js
@@ -1,17 +1,8 @@
|
||||
(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, _l, _m, helpers, include, pair;
|
||||
var __bind = function(func, context) {
|
||||
return function(){ return func.apply(context, arguments); };
|
||||
}, __hasProp = Object.prototype.hasOwnProperty;
|
||||
if (typeof process !== "undefined" && process !== null) {
|
||||
_a = require('./helpers');
|
||||
helpers = _a.helpers;
|
||||
} else {
|
||||
this.exports = this;
|
||||
helpers = this.helpers;
|
||||
}
|
||||
_b = helpers;
|
||||
include = _b.include;
|
||||
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, INVERSES, LINEBREAKS, Rewriter, SINGLE_CLOSERS, SINGLE_LINERS, _i, _len, _ref, _result, include, pair;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
_ref = require('./helpers').helpers;
|
||||
include = _ref.include;
|
||||
exports.Rewriter = (function() {
|
||||
Rewriter = function() {};
|
||||
Rewriter.prototype.rewrite = function(tokens) {
|
||||
@@ -19,8 +10,10 @@
|
||||
this.adjustComments();
|
||||
this.removeLeadingNewlines();
|
||||
this.removeMidExpressionNewlines();
|
||||
this.closeOpenCallsAndIndexes();
|
||||
this.closeOpenCalls();
|
||||
this.closeOpenIndexes();
|
||||
this.addImplicitIndentation();
|
||||
this.tagPostfixConditionals();
|
||||
this.addImplicitBraces();
|
||||
this.addImplicitParentheses();
|
||||
this.ensureBalance(BALANCED_PAIRS);
|
||||
@@ -34,258 +27,275 @@
|
||||
if (!(this.tokens[i])) {
|
||||
break;
|
||||
}
|
||||
move = block(this.tokens[i - 1], this.tokens[i], this.tokens[i + 1], i);
|
||||
move = block.call(this, this.tokens[i], i);
|
||||
i += move;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
Rewriter.prototype.detectEnd = function(i, condition, action) {
|
||||
var levels, token;
|
||||
levels = 0;
|
||||
while (true) {
|
||||
token = this.tokens[i];
|
||||
if (levels === 0 && condition.call(this, token, i)) {
|
||||
return action.call(this, token, i);
|
||||
}
|
||||
if (!token || levels < 0) {
|
||||
return action.call(this, token, i - 1);
|
||||
}
|
||||
if (include(EXPRESSION_START, token[0])) {
|
||||
levels += 1;
|
||||
}
|
||||
if (include(EXPRESSION_END, token[0])) {
|
||||
levels -= 1;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return i - 1;
|
||||
};
|
||||
Rewriter.prototype.adjustComments = function() {
|
||||
return this.scanTokens(__bind(function(prev, token, post, i) {
|
||||
var _c, _d, after, before;
|
||||
if (!(token[0] === 'HERECOMMENT')) {
|
||||
return this.scanTokens(function(token, i) {
|
||||
var _ref2, after, before, post, prev;
|
||||
if (token[0] !== 'HERECOMMENT') {
|
||||
return 1;
|
||||
}
|
||||
_c = [this.tokens[i - 2], this.tokens[i + 2]];
|
||||
before = _c[0];
|
||||
after = _c[1];
|
||||
_ref2 = [this.tokens[i - 2], this.tokens[i - 1], this.tokens[i + 1], this.tokens[i + 2]];
|
||||
before = _ref2[0];
|
||||
prev = _ref2[1];
|
||||
post = _ref2[2];
|
||||
after = _ref2[3];
|
||||
if (after && after[0] === 'INDENT') {
|
||||
this.tokens.splice(i + 2, 1);
|
||||
before && before[0] === 'OUTDENT' && post && (prev[0] === post[0]) && (post[0] === 'TERMINATOR') ? this.tokens.splice(i - 2, 1) : this.tokens.splice(i, 0, after);
|
||||
} else if (prev && !('TERMINATOR' === (_d = prev[0]) || 'INDENT' === _d || 'OUTDENT' === _d)) {
|
||||
if (before && before[0] === 'OUTDENT' && post && (prev[0] === post[0]) && (post[0] === 'TERMINATOR')) {
|
||||
this.tokens.splice(i - 2, 1);
|
||||
} else {
|
||||
this.tokens.splice(i, 0, after);
|
||||
}
|
||||
} else if (prev && !('TERMINATOR' === (_ref2 = prev[0]) || 'INDENT' === _ref2 || 'OUTDENT' === _ref2)) {
|
||||
if (post && post[0] === 'TERMINATOR' && after && after[0] === 'OUTDENT') {
|
||||
this.tokens.splice.apply(this.tokens, [i + 2, 0].concat(this.tokens.splice(i, 2)));
|
||||
this.tokens[i + 2][0] !== 'TERMINATOR' ? this.tokens.splice(i + 2, 0, ['TERMINATOR', "\n", prev[2]]) : null;
|
||||
if (this.tokens[i + 2][0] !== 'TERMINATOR') {
|
||||
this.tokens.splice(i + 2, 0, ['TERMINATOR', "\n", prev[2]]);
|
||||
}
|
||||
} else {
|
||||
this.tokens.splice(i, 0, ['TERMINATOR', "\n", prev[2]]);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}, this));
|
||||
});
|
||||
};
|
||||
Rewriter.prototype.removeLeadingNewlines = function() {
|
||||
var _c;
|
||||
_c = [];
|
||||
var _result;
|
||||
_result = [];
|
||||
while (this.tokens[0] && this.tokens[0][0] === 'TERMINATOR') {
|
||||
_c.push(this.tokens.shift());
|
||||
_result.push(this.tokens.shift());
|
||||
}
|
||||
return _c;
|
||||
return _result;
|
||||
};
|
||||
Rewriter.prototype.removeMidExpressionNewlines = function() {
|
||||
return this.scanTokens(__bind(function(prev, token, post, i) {
|
||||
if (!(post && include(EXPRESSION_CLOSE, post[0]) && token[0] === 'TERMINATOR')) {
|
||||
return this.scanTokens(function(token, i) {
|
||||
if (!(include(EXPRESSION_CLOSE, this.tag(i + 1)) && token[0] === 'TERMINATOR')) {
|
||||
return 1;
|
||||
}
|
||||
this.tokens.splice(i, 1);
|
||||
return 0;
|
||||
}, this));
|
||||
});
|
||||
};
|
||||
Rewriter.prototype.closeOpenCallsAndIndexes = function() {
|
||||
var brackets, parens;
|
||||
parens = [0];
|
||||
brackets = [0];
|
||||
return this.scanTokens(__bind(function(prev, token, post, i) {
|
||||
var _c;
|
||||
if ((_c = token[0]) === 'CALL_START') {
|
||||
parens.push(0);
|
||||
} else if (_c === 'INDEX_START') {
|
||||
brackets.push(0);
|
||||
} else if (_c === '(') {
|
||||
parens[parens.length - 1] += 1;
|
||||
} else if (_c === '[') {
|
||||
brackets[brackets.length - 1] += 1;
|
||||
} else if (_c === ')') {
|
||||
if (parens[parens.length - 1] === 0) {
|
||||
parens.pop();
|
||||
token[0] = 'CALL_END';
|
||||
} else {
|
||||
parens[parens.length - 1] -= 1;
|
||||
}
|
||||
} else if (_c === ']') {
|
||||
if (brackets[brackets.length - 1] === 0) {
|
||||
brackets.pop();
|
||||
token[0] = 'INDEX_END';
|
||||
} else {
|
||||
brackets[brackets.length - 1] -= 1;
|
||||
}
|
||||
Rewriter.prototype.closeOpenCalls = function() {
|
||||
return this.scanTokens(function(token, i) {
|
||||
var action, condition;
|
||||
if (token[0] === 'CALL_START') {
|
||||
condition = function(token, i) {
|
||||
var _ref2;
|
||||
return ((')' === (_ref2 = token[0]) || 'CALL_END' === _ref2)) || (token[0] === 'OUTDENT' && this.tokens[i - 1][0] === ')');
|
||||
};
|
||||
action = function(token, i) {
|
||||
var idx;
|
||||
idx = token[0] === 'OUTDENT' ? i - 1 : i;
|
||||
return (this.tokens[idx][0] = 'CALL_END');
|
||||
};
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
}
|
||||
return 1;
|
||||
}, this));
|
||||
});
|
||||
};
|
||||
Rewriter.prototype.closeOpenIndexes = function() {
|
||||
return this.scanTokens(function(token, i) {
|
||||
var action, condition;
|
||||
if (token[0] === 'INDEX_START') {
|
||||
condition = function(token, i) {
|
||||
var _ref2;
|
||||
return (']' === (_ref2 = token[0]) || 'INDEX_END' === _ref2);
|
||||
};
|
||||
action = function(token, i) {
|
||||
return (token[0] = 'INDEX_END');
|
||||
};
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
Rewriter.prototype.addImplicitBraces = function() {
|
||||
var closeBrackets, running, stack;
|
||||
stack = [0];
|
||||
running = false;
|
||||
closeBrackets = __bind(function(i) {
|
||||
var _c, len, size, tmp;
|
||||
len = stack.length - 1;
|
||||
_c = stack[len];
|
||||
for (tmp = 0; (0 <= _c ? tmp < _c : tmp > _c); (0 <= _c ? tmp += 1 : tmp -= 1)) {
|
||||
this.tokens.splice(i, 0, ['}', '}', this.tokens[i][2]]);
|
||||
var stack;
|
||||
stack = [];
|
||||
return this.scanTokens(function(token, i) {
|
||||
var action, condition, idx, last, tok;
|
||||
if (include(EXPRESSION_START, token[0])) {
|
||||
stack.push((token[0] === 'INDENT' && (this.tag(i - 1) === '{')) ? '{' : token[0]);
|
||||
}
|
||||
size = stack[len] + 1;
|
||||
stack[len] = 0;
|
||||
return size;
|
||||
}, this);
|
||||
return this.scanTokens(__bind(function(prev, token, post, i) {
|
||||
var _c, after, before, idx, len, open, size, tag;
|
||||
tag = token[0];
|
||||
len = stack.length - 1;
|
||||
before = this.tokens[i - 2];
|
||||
after = this.tokens[i + 2];
|
||||
open = stack[len] > 0;
|
||||
if ((tag === 'TERMINATOR' && !((after && after[0] === ':') || (post && post[0] === '@' && this.tokens[i + 3] && this.tokens[i + 3][0] === ':'))) || (running && tag === ',' && post && (!('IDENTIFIER' === (_c = post[0]) || 'STRING' === _c || '@' === _c || 'TERMINATOR' === _c)))) {
|
||||
running = false;
|
||||
return closeBrackets(post && post[0] === 'OUTDENT' ? i + 1 : i);
|
||||
} else if (include(EXPRESSION_START, tag)) {
|
||||
stack.push(tag === '{' ? 1 : 0);
|
||||
if (tag === '{' && post && post[0] === 'INDENT') {
|
||||
return 2;
|
||||
if (include(EXPRESSION_END, token[0])) {
|
||||
stack.pop();
|
||||
}
|
||||
last = stack[stack.length - 1];
|
||||
if (token[0] === ':' && (!last || last[0] !== '{')) {
|
||||
stack.push('{');
|
||||
idx = this.tag(i - 2) === '@' ? i - 2 : i - 1;
|
||||
if (this.tag(idx - 2) === 'HERECOMMENT') {
|
||||
idx -= 2;
|
||||
}
|
||||
} else if (include(EXPRESSION_END, tag)) {
|
||||
if (tag === 'OUTDENT' && post && post[0] === '}') {
|
||||
return 1;
|
||||
}
|
||||
if (tag === 'OUTDENT') {
|
||||
size = closeBrackets(i);
|
||||
}
|
||||
stack[len - 1] += stack.pop();
|
||||
if (tag === '}') {
|
||||
stack[len - 1] -= 1;
|
||||
}
|
||||
if (tag === 'OUTDENT') {
|
||||
return size;
|
||||
}
|
||||
} else if (tag === ':' && !open) {
|
||||
idx = before && before[0] === '@' ? i - 2 : i - 1;
|
||||
this.tokens.splice(idx, 0, ['{', '{', token[2]]);
|
||||
stack[stack.length - 1] += 1;
|
||||
running = true;
|
||||
tok = ['{', '{', token[2]];
|
||||
tok.generated = true;
|
||||
this.tokens.splice(idx, 0, tok);
|
||||
condition = function(token, i) {
|
||||
var _ref2, one, three, two;
|
||||
_ref2 = this.tokens.slice(i + 1, i + 4);
|
||||
one = _ref2[0];
|
||||
two = _ref2[1];
|
||||
three = _ref2[2];
|
||||
if ((this.tag(i + 1) === 'HERECOMMENT' || this.tag(i - 1) === 'HERECOMMENT')) {
|
||||
return false;
|
||||
}
|
||||
return ((('TERMINATOR' === (_ref2 = token[0]) || 'OUTDENT' === _ref2)) && !((two && two[0] === ':') || (one && one[0] === '@' && three && three[0] === ':'))) || (token[0] === ',' && one && (!('IDENTIFIER' === (_ref2 = one[0]) || 'STRING' === _ref2 || '@' === _ref2 || 'TERMINATOR' === _ref2 || 'OUTDENT' === _ref2)));
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens.splice(i, 0, ['}', '}', token[2]]);
|
||||
};
|
||||
this.detectEnd(i + 2, condition, action);
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}, this));
|
||||
});
|
||||
};
|
||||
Rewriter.prototype.addImplicitParentheses = function() {
|
||||
var closeCalls, stack;
|
||||
stack = [0];
|
||||
closeCalls = __bind(function(i) {
|
||||
var _c, size, tmp;
|
||||
_c = stack[stack.length - 1];
|
||||
for (tmp = 0; (0 <= _c ? tmp < _c : tmp > _c); (0 <= _c ? tmp += 1 : tmp -= 1)) {
|
||||
this.tokens.splice(i, 0, ['CALL_END', ')', this.tokens[i][2]]);
|
||||
var classLine;
|
||||
classLine = false;
|
||||
return this.scanTokens(function(token, i) {
|
||||
var _ref2, action, callObject, condition, idx, next, prev, seenSingle;
|
||||
if (token[0] === 'CLASS') {
|
||||
classLine = true;
|
||||
}
|
||||
size = stack[stack.length - 1] + 1;
|
||||
stack[stack.length - 1] = 0;
|
||||
return size;
|
||||
}, this);
|
||||
return this.scanTokens(__bind(function(prev, token, post, i) {
|
||||
var _c, _d, before, j, nx, open, size, tag;
|
||||
tag = token[0];
|
||||
before = this.tokens[i - 2] && this.tokens[i - 2][0];
|
||||
if (tag === 'OUTDENT') {
|
||||
stack[stack.length - 2] += stack.pop();
|
||||
prev = this.tokens[i - 1];
|
||||
next = this.tokens[i + 1];
|
||||
idx = 1;
|
||||
callObject = !classLine && token[0] === 'INDENT' && next && next.generated && next[0] === '{' && prev && include(IMPLICIT_FUNC, prev[0]);
|
||||
if (callObject) {
|
||||
idx = 2;
|
||||
}
|
||||
open = stack[stack.length - 1] > 0;
|
||||
if (prev && prev.spaced && include(IMPLICIT_FUNC, prev[0]) && include(IMPLICIT_CALL, tag) && !(tag === '!' && (('IN' === (_c = post[0]) || 'OF' === _c)))) {
|
||||
seenSingle = false;
|
||||
if (include(LINEBREAKS, token[0])) {
|
||||
classLine = false;
|
||||
}
|
||||
if (prev && !prev.spaced && token[0] === '?') {
|
||||
token.call = true;
|
||||
}
|
||||
if (prev && (prev.spaced && (include(IMPLICIT_FUNC, prev[0]) || prev.call) && include(IMPLICIT_CALL, token[0]) && !(token[0] === 'UNARY' && (('IN' === (_ref2 = this.tag(i + 1)) || 'OF' === _ref2 || 'INSTANCEOF' === _ref2)))) || callObject) {
|
||||
this.tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
|
||||
stack[stack.length - 1] += 1;
|
||||
if (include(EXPRESSION_START, tag)) {
|
||||
stack.push(0);
|
||||
condition = function(token, i) {
|
||||
var _ref2, post;
|
||||
if (!seenSingle && token.fromThen) {
|
||||
return true;
|
||||
}
|
||||
if (('IF' === (_ref2 = token[0]) || 'ELSE' === _ref2 || 'UNLESS' === _ref2 || '->' === _ref2 || '=>' === _ref2)) {
|
||||
seenSingle = true;
|
||||
}
|
||||
post = this.tokens[i + 1];
|
||||
return (!token.generated && this.tokens[i - 1][0] !== ',' && include(IMPLICIT_END, token[0]) && !(token[0] === 'INDENT' && (include(IMPLICIT_BLOCK, this.tag(i - 1)) || this.tag(i - 2) === 'CLASS' || (post && post.generated && post[0] === '{')))) || token[0] === 'PROPERTY_ACCESS' && this.tag(i - 1) === 'OUTDENT';
|
||||
};
|
||||
action = function(token, i) {
|
||||
idx = token[0] === 'OUTDENT' ? i + 1 : i;
|
||||
return this.tokens.splice(idx, 0, ['CALL_END', ')', token[2]]);
|
||||
};
|
||||
this.detectEnd(i + idx, condition, action);
|
||||
if (prev[0] === '?') {
|
||||
prev[0] = 'FUNC_EXIST';
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
if (include(EXPRESSION_START, tag)) {
|
||||
if (tag === 'INDENT' && !token.generated && open && !((prev && include(IMPLICIT_BLOCK, prev[0])) || before && before === 'CLASS')) {
|
||||
size = closeCalls(i);
|
||||
stack.push(0);
|
||||
return size;
|
||||
}
|
||||
stack.push(0);
|
||||
return 1;
|
||||
}
|
||||
if (open && !token.generated && prev[0] !== ',' && (!post || include(IMPLICIT_END, tag))) {
|
||||
j = 1;
|
||||
while ((typeof (_d = (nx = this.tokens[i + j])) !== "undefined" && _d !== null) && include(IMPLICIT_END, nx[0])) {
|
||||
j++;
|
||||
}
|
||||
if ((typeof nx !== "undefined" && nx !== null) && nx[0] === ',' && this.tokens[i + j - 1][0] === 'OUTDENT') {
|
||||
if (tag === 'TERMINATOR') {
|
||||
this.tokens.splice(i, 1);
|
||||
}
|
||||
} else {
|
||||
size = closeCalls(i);
|
||||
if (tag !== 'OUTDENT' && include(EXPRESSION_END, tag)) {
|
||||
stack.pop();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
}
|
||||
if (tag !== 'OUTDENT' && include(EXPRESSION_END, tag)) {
|
||||
stack[stack.length - 2] += stack.pop();
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}, this));
|
||||
});
|
||||
};
|
||||
Rewriter.prototype.addImplicitIndentation = function() {
|
||||
return this.scanTokens(__bind(function(prev, token, post, i) {
|
||||
var _c, idx, indent, insertion, outdent, parens, pre, starter, tok;
|
||||
if (token[0] === 'ELSE' && prev[0] !== 'OUTDENT') {
|
||||
return this.scanTokens(function(token, i) {
|
||||
var _ref2, action, condition, indent, outdent, starter;
|
||||
if (token[0] === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {
|
||||
this.tokens.splice.apply(this.tokens, [i, 0].concat(this.indentation(token)));
|
||||
return 2;
|
||||
}
|
||||
if (token[0] === 'CATCH' && (this.tokens[i + 2][0] === 'TERMINATOR' || this.tokens[i + 2][0] === 'FINALLY')) {
|
||||
if (token[0] === 'CATCH' && (this.tag(i + 2) === 'TERMINATOR' || this.tag(i + 2) === 'FINALLY')) {
|
||||
this.tokens.splice.apply(this.tokens, [i + 2, 0].concat(this.indentation(token)));
|
||||
return 4;
|
||||
}
|
||||
if (!(include(SINGLE_LINERS, token[0]) && post[0] !== 'INDENT' && !(token[0] === 'ELSE' && post[0] === 'IF'))) {
|
||||
if (include(SINGLE_LINERS, token[0]) && this.tag(i + 1) !== 'INDENT' && !(token[0] === 'ELSE' && this.tag(i + 1) === 'IF')) {
|
||||
starter = token[0];
|
||||
_ref2 = this.indentation(token);
|
||||
indent = _ref2[0];
|
||||
outdent = _ref2[1];
|
||||
if (starter === 'THEN') {
|
||||
indent.fromThen = true;
|
||||
}
|
||||
indent.generated = (outdent.generated = true);
|
||||
this.tokens.splice(i + 1, 0, indent);
|
||||
condition = function(token, i) {
|
||||
return (include(SINGLE_CLOSERS, token[0]) && token[1] !== ';') && !(token[0] === 'ELSE' && !('IF' === starter || 'THEN' === starter));
|
||||
};
|
||||
action = function(token, i) {
|
||||
var idx;
|
||||
idx = this.tokens[i - 1][0] === ',' ? i - 1 : i;
|
||||
return this.tokens.splice(idx, 0, outdent);
|
||||
};
|
||||
this.detectEnd(i + 2, condition, action);
|
||||
if (token[0] === 'THEN') {
|
||||
this.tokens.splice(i, 1);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
Rewriter.prototype.tagPostfixConditionals = function() {
|
||||
return this.scanTokens(function(token, i) {
|
||||
var _ref2, action, condition, original;
|
||||
if (('IF' === (_ref2 = token[0]) || 'UNLESS' === _ref2)) {
|
||||
original = token;
|
||||
condition = function(token, i) {
|
||||
var _ref2;
|
||||
return ('TERMINATOR' === (_ref2 = token[0]) || 'INDENT' === _ref2);
|
||||
};
|
||||
action = function(token, i) {
|
||||
if (token[0] !== 'INDENT') {
|
||||
return (original[0] = 'POST_' + original[0]);
|
||||
}
|
||||
};
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
return 1;
|
||||
}
|
||||
starter = token[0];
|
||||
_c = this.indentation(token);
|
||||
indent = _c[0];
|
||||
outdent = _c[1];
|
||||
indent.generated = (outdent.generated = true);
|
||||
this.tokens.splice(i + 1, 0, indent);
|
||||
idx = i + 1;
|
||||
parens = 0;
|
||||
while (true) {
|
||||
idx += 1;
|
||||
tok = this.tokens[idx];
|
||||
pre = this.tokens[idx - 1];
|
||||
if ((!tok || (include(SINGLE_CLOSERS, tok[0]) && tok[1] !== ';' && parens === 0) || (tok[0] === ')' && parens === 0)) && !(tok[0] === 'ELSE' && !('IF' === starter || 'THEN' === starter))) {
|
||||
insertion = pre[0] === "," ? idx - 1 : idx;
|
||||
this.tokens.splice(insertion, 0, outdent);
|
||||
break;
|
||||
}
|
||||
if (tok[0] === '(') {
|
||||
parens += 1;
|
||||
}
|
||||
if (tok[0] === ')') {
|
||||
parens -= 1;
|
||||
}
|
||||
}
|
||||
if (!(token[0] === 'THEN')) {
|
||||
return 1;
|
||||
}
|
||||
this.tokens.splice(i, 1);
|
||||
return 0;
|
||||
}, this));
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
Rewriter.prototype.ensureBalance = function(pairs) {
|
||||
var _c, _d, key, levels, line, open, openLine, unclosed, value;
|
||||
var _ref2, _result, key, levels, line, open, openLine, unclosed, value;
|
||||
levels = {};
|
||||
openLine = {};
|
||||
this.scanTokens(__bind(function(prev, token, post, i) {
|
||||
var _c, _d, _e, _f, close, open, pair;
|
||||
_d = pairs;
|
||||
for (_c = 0, _e = _d.length; _c < _e; _c++) {
|
||||
pair = _d[_c];
|
||||
_f = pair;
|
||||
open = _f[0];
|
||||
close = _f[1];
|
||||
levels[open] = levels[open] || 0;
|
||||
this.scanTokens(function(token, i) {
|
||||
var _i, _len, _ref2, _ref3, close, open, pair;
|
||||
_ref2 = pairs;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
pair = _ref2[_i];
|
||||
_ref3 = pair;
|
||||
open = _ref3[0];
|
||||
close = _ref3[1];
|
||||
levels[open] || (levels[open] = 0);
|
||||
if (token[0] === open) {
|
||||
if (levels[open] === 0) {
|
||||
openLine[open] = token[2];
|
||||
@@ -296,37 +306,39 @@
|
||||
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;
|
||||
}, this));
|
||||
});
|
||||
unclosed = (function() {
|
||||
_c = []; _d = levels;
|
||||
for (key in _d) {
|
||||
if (!__hasProp.call(_d, key)) continue;
|
||||
value = _d[key];
|
||||
value > 0 ? _c.push(key) : null;
|
||||
_result = []; _ref2 = levels;
|
||||
for (key in _ref2) {
|
||||
if (!__hasProp.call(_ref2, key)) continue;
|
||||
value = _ref2[key];
|
||||
if (value > 0) {
|
||||
_result.push(key);
|
||||
}
|
||||
}
|
||||
return _c;
|
||||
return _result;
|
||||
})();
|
||||
if (unclosed.length) {
|
||||
open = unclosed[0];
|
||||
line = openLine[open] + 1;
|
||||
throw new Error("unclosed " + open + " on line " + line);
|
||||
throw new Error("unclosed " + (open) + " on line " + (line));
|
||||
}
|
||||
};
|
||||
Rewriter.prototype.rewriteClosingParens = function() {
|
||||
var _c, debt, key, stack, val;
|
||||
var _ref2, debt, key, stack, val;
|
||||
stack = [];
|
||||
debt = {};
|
||||
_c = INVERSES;
|
||||
for (key in _c) {
|
||||
if (!__hasProp.call(_c, key)) continue;
|
||||
val = _c[key];
|
||||
_ref2 = INVERSES;
|
||||
for (key in _ref2) {
|
||||
if (!__hasProp.call(_ref2, key)) continue;
|
||||
val = _ref2[key];
|
||||
(debt[key] = 0);
|
||||
}
|
||||
return this.scanTokens(__bind(function(prev, token, post, i) {
|
||||
return this.scanTokens(function(token, i) {
|
||||
var inv, match, mtag, oppos, tag;
|
||||
tag = token[0];
|
||||
inv = INVERSES[token[0]];
|
||||
@@ -347,7 +359,7 @@
|
||||
}
|
||||
debt[mtag] += 1;
|
||||
val = [oppos, mtag === 'INDENT' ? match[1] : oppos];
|
||||
if ((this.tokens[i + 2] == undefined ? undefined : this.tokens[i + 2][0]) === mtag) {
|
||||
if ((this.tokens[i + 2] == null ? undefined : this.tokens[i + 2][0]) === mtag) {
|
||||
this.tokens.splice(i + 3, 0, val);
|
||||
stack.push(match);
|
||||
} else {
|
||||
@@ -358,42 +370,46 @@
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}, this));
|
||||
});
|
||||
};
|
||||
Rewriter.prototype.indentation = function(token) {
|
||||
return [['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]]];
|
||||
};
|
||||
Rewriter.prototype.tag = function(i) {
|
||||
return this.tokens[i] && this.tokens[i][0];
|
||||
};
|
||||
return Rewriter;
|
||||
})();
|
||||
BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['PARAM_START', 'PARAM_END'], ['CALL_START', 'CALL_END'], ['INDEX_START', 'INDEX_END']];
|
||||
INVERSES = {};
|
||||
_d = BALANCED_PAIRS;
|
||||
for (_c = 0, _e = _d.length; _c < _e; _c++) {
|
||||
pair = _d[_c];
|
||||
_ref = BALANCED_PAIRS;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
pair = _ref[_i];
|
||||
INVERSES[pair[0]] = pair[1];
|
||||
INVERSES[pair[1]] = pair[0];
|
||||
}
|
||||
EXPRESSION_START = (function() {
|
||||
_f = []; _h = BALANCED_PAIRS;
|
||||
for (_g = 0, _i = _h.length; _g < _i; _g++) {
|
||||
pair = _h[_g];
|
||||
_f.push(pair[0]);
|
||||
_result = []; _ref = BALANCED_PAIRS;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
pair = _ref[_i];
|
||||
_result.push(pair[0]);
|
||||
}
|
||||
return _f;
|
||||
return _result;
|
||||
})();
|
||||
EXPRESSION_END = (function() {
|
||||
_j = []; _l = BALANCED_PAIRS;
|
||||
for (_k = 0, _m = _l.length; _k < _m; _k++) {
|
||||
pair = _l[_k];
|
||||
_j.push(pair[1]);
|
||||
_result = []; _ref = BALANCED_PAIRS;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
pair = _ref[_i];
|
||||
_result.push(pair[1]);
|
||||
}
|
||||
return _j;
|
||||
return _result;
|
||||
})();
|
||||
EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@'];
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'TRY', 'DELETE', 'TYPEOF', 'SWITCH', 'THIS', 'NULL', 'TRUE', 'FALSE', 'YES', 'NO', 'ON', 'OFF', '!', '!!', '@', '->', '=>', '[', '(', '{'];
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'UNLESS', 'TRY', 'SWITCH', 'THIS', 'NULL', 'UNARY', 'TRUE', 'FALSE', 'YES', 'NO', 'ON', 'OFF', '@', '->', '=>', '[', '(', '{'];
|
||||
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ','];
|
||||
IMPLICIT_END = ['IF', 'UNLESS', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'TERMINATOR', 'INDENT'].concat(EXPRESSION_END);
|
||||
IMPLICIT_END = ['POST_IF', 'POST_UNLESS', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'TERMINATOR', 'INDENT'];
|
||||
SINGLE_LINERS = ['ELSE', "->", "=>", 'TRY', 'FINALLY', 'THEN'];
|
||||
SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN'];
|
||||
})();
|
||||
LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT'];
|
||||
}).call(this);
|
||||
|
||||
113
lib/scope.js
113
lib/scope.js
@@ -1,39 +1,52 @@
|
||||
(function() {
|
||||
var Scope;
|
||||
var Scope, _ref, extend;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
if (!(typeof process !== "undefined" && process !== null)) {
|
||||
this.exports = this;
|
||||
}
|
||||
_ref = require('./helpers').helpers;
|
||||
extend = _ref.extend;
|
||||
exports.Scope = (function() {
|
||||
Scope = function(parent, expressions, method) {
|
||||
var _a;
|
||||
_a = [parent, expressions, method];
|
||||
this.parent = _a[0];
|
||||
this.expressions = _a[1];
|
||||
this.method = _a[2];
|
||||
var _ref2;
|
||||
_ref2 = [parent, expressions, method];
|
||||
this.parent = _ref2[0];
|
||||
this.expressions = _ref2[1];
|
||||
this.method = _ref2[2];
|
||||
this.variables = {};
|
||||
if (this.parent) {
|
||||
this.tempVar = this.parent.tempVar;
|
||||
this.garbage = this.parent.garbage;
|
||||
} else {
|
||||
this.garbage = [];
|
||||
Scope.root = this;
|
||||
this.tempVar = '_a';
|
||||
}
|
||||
return this;
|
||||
};
|
||||
Scope.root = null;
|
||||
Scope.prototype.find = function(name) {
|
||||
if (this.check(name)) {
|
||||
Scope.prototype.startLevel = function() {
|
||||
return this.garbage.push([]);
|
||||
};
|
||||
Scope.prototype.endLevel = function() {
|
||||
var _i, _len, _ref2, _result, name;
|
||||
_result = []; _ref2 = this.garbage.pop();
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
name = _ref2[_i];
|
||||
if (this.variables[name] === 'var') {
|
||||
_result.push(this.variables[name] = 'reuse');
|
||||
}
|
||||
}
|
||||
return _result;
|
||||
};
|
||||
Scope.prototype.find = function(name, options) {
|
||||
if (this.check(name, options)) {
|
||||
return true;
|
||||
}
|
||||
this.variables[name] = 'var';
|
||||
return false;
|
||||
};
|
||||
Scope.prototype.any = function(fn) {
|
||||
var _a, k, v;
|
||||
_a = this.variables;
|
||||
for (v in _a) {
|
||||
if (!__hasProp.call(_a, v)) continue;
|
||||
k = _a[v];
|
||||
var _ref2, k, v;
|
||||
_ref2 = this.variables;
|
||||
for (v in _ref2) {
|
||||
if (!__hasProp.call(_ref2, v)) continue;
|
||||
k = _ref2[v];
|
||||
if (fn(v, k)) {
|
||||
return true;
|
||||
}
|
||||
@@ -43,20 +56,28 @@
|
||||
Scope.prototype.parameter = function(name) {
|
||||
return (this.variables[name] = 'param');
|
||||
};
|
||||
Scope.prototype.check = function(name) {
|
||||
if (this.variables.hasOwnProperty(name)) {
|
||||
return true;
|
||||
Scope.prototype.check = function(name, options) {
|
||||
var immediate;
|
||||
immediate = Object.prototype.hasOwnProperty.call(this.variables, name);
|
||||
if (immediate || (options && options.immediate)) {
|
||||
return immediate;
|
||||
}
|
||||
return !!(this.parent && this.parent.check(name));
|
||||
};
|
||||
Scope.prototype.freeVariable = function() {
|
||||
var ordinal;
|
||||
while (this.check(this.tempVar)) {
|
||||
ordinal = 1 + parseInt(this.tempVar.substr(1), 36);
|
||||
this.tempVar = '_' + ordinal.toString(36).replace(/\d/g, 'a');
|
||||
Scope.prototype.temporary = function(type, index) {
|
||||
return type.length > 1 ? '_' + type + (index > 1 ? index : '') : '_' + (index + parseInt(type, 36)).toString(36).replace(/\d/g, 'a');
|
||||
};
|
||||
Scope.prototype.freeVariable = function(type) {
|
||||
var index, temp;
|
||||
index = 0;
|
||||
while (this.check(temp = this.temporary(type, index)) && this.variables[temp] !== 'reuse') {
|
||||
index++;
|
||||
}
|
||||
this.variables[this.tempVar] = 'var';
|
||||
return this.tempVar;
|
||||
this.variables[temp] = 'var';
|
||||
if (this.garbage.length) {
|
||||
this.garbage[this.garbage.length - 1].push(temp);
|
||||
}
|
||||
return temp;
|
||||
};
|
||||
Scope.prototype.assign = function(name, value) {
|
||||
return (this.variables[name] = {
|
||||
@@ -66,7 +87,7 @@
|
||||
};
|
||||
Scope.prototype.hasDeclarations = function(body) {
|
||||
return body === this.expressions && this.any(function(k, val) {
|
||||
return val === 'var';
|
||||
return val === 'var' || val === 'reuse';
|
||||
});
|
||||
};
|
||||
Scope.prototype.hasAssignments = function(body) {
|
||||
@@ -75,26 +96,30 @@
|
||||
});
|
||||
};
|
||||
Scope.prototype.declaredVariables = function() {
|
||||
var _a, _b, key, val;
|
||||
var _ref2, _result, key, val;
|
||||
return (function() {
|
||||
_a = []; _b = this.variables;
|
||||
for (key in _b) {
|
||||
if (!__hasProp.call(_b, key)) continue;
|
||||
val = _b[key];
|
||||
val === 'var' ? _a.push(key) : null;
|
||||
_result = []; _ref2 = this.variables;
|
||||
for (key in _ref2) {
|
||||
if (!__hasProp.call(_ref2, key)) continue;
|
||||
val = _ref2[key];
|
||||
if (val === 'var' || val === 'reuse') {
|
||||
_result.push(key);
|
||||
}
|
||||
}
|
||||
return _a;
|
||||
return _result;
|
||||
}).call(this).sort();
|
||||
};
|
||||
Scope.prototype.assignedVariables = function() {
|
||||
var _a, _b, key, val;
|
||||
_a = []; _b = this.variables;
|
||||
for (key in _b) {
|
||||
if (!__hasProp.call(_b, key)) continue;
|
||||
val = _b[key];
|
||||
val.assigned ? _a.push("" + key + " = " + val.value) : null;
|
||||
var _ref2, _result, key, val;
|
||||
_result = []; _ref2 = this.variables;
|
||||
for (key in _ref2) {
|
||||
if (!__hasProp.call(_ref2, key)) continue;
|
||||
val = _ref2[key];
|
||||
if (val.assigned) {
|
||||
_result.push("" + (key) + " = " + (val.value));
|
||||
}
|
||||
}
|
||||
return _a;
|
||||
return _result;
|
||||
};
|
||||
Scope.prototype.compiledDeclarations = function() {
|
||||
return this.declaredVariables().join(', ');
|
||||
@@ -104,4 +129,4 @@
|
||||
};
|
||||
return Scope;
|
||||
}).call(this);
|
||||
})();
|
||||
}).call(this);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "Unfancy JavaScript",
|
||||
"keywords": ["javascript", "language", "coffeescript", "compiler"],
|
||||
"author": "Jeremy Ashkenas",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.4",
|
||||
"licenses": [{
|
||||
"type": "MIT",
|
||||
"url": "http://github.com/jashkenas/coffee-script/raw/master/LICENSE"
|
||||
@@ -11,6 +11,10 @@
|
||||
"engines": {
|
||||
"node": ">=0.1.99"
|
||||
},
|
||||
"directories" : {
|
||||
"lib" : "./lib"
|
||||
},
|
||||
"main" : "./lib/coffee-script",
|
||||
"bin": {
|
||||
"coffee": "./bin/coffee",
|
||||
"cake": "./bin/cake"
|
||||
|
||||
39
src/browser.coffee
Normal file
39
src/browser.coffee
Normal file
@@ -0,0 +1,39 @@
|
||||
# Override exported methods for non-Node.js engines.
|
||||
|
||||
CoffeeScript = require './coffee-script'
|
||||
|
||||
# Use standard JavaScript `eval` to eval code.
|
||||
CoffeeScript.eval = (code, options) ->
|
||||
eval CoffeeScript.compile code, options
|
||||
|
||||
# Running code does not provide access to this scope.
|
||||
CoffeeScript.run = (code, options) ->
|
||||
(Function CoffeeScript.compile code, options)()
|
||||
|
||||
# If we're not in a browser environment, we're finished with the public API.
|
||||
return unless window?
|
||||
|
||||
# Load a remote script from the current domain via XHR.
|
||||
CoffeeScript.load = (url, options) ->
|
||||
xhr = new (window.ActiveXObject or XMLHttpRequest)('Microsoft.XMLHTTP')
|
||||
xhr.open 'GET', url, true
|
||||
xhr.overrideMimeType 'text/plain' if 'overrideMimeType' of xhr
|
||||
xhr.onreadystatechange = ->
|
||||
CoffeeScript.run xhr.responseText, options if xhr.readyState is 4
|
||||
xhr.send null
|
||||
|
||||
# Activate CoffeeScript in the browser by having it compile and evaluate
|
||||
# all script tags with a content-type of `text/coffeescript`.
|
||||
# This happens on page load.
|
||||
processScripts = ->
|
||||
for script in document.getElementsByTagName 'script'
|
||||
if script.type is 'text/coffeescript'
|
||||
if script.src
|
||||
CoffeeScript.load script.src
|
||||
else
|
||||
setTimeout -> CoffeeScript.run script.innerHTML
|
||||
null
|
||||
if window.addEventListener
|
||||
addEventListener 'DOMContentLoaded', processScripts, false
|
||||
else
|
||||
attachEvent 'onload', processScripts
|
||||
@@ -58,12 +58,12 @@ printTasks = ->
|
||||
puts ''
|
||||
for all name, task of tasks
|
||||
spaces = 20 - name.length
|
||||
spaces = if spaces > 0 then (' ' for i in [0..spaces]).join('') else ''
|
||||
desc = if task.description then "# #task.description" else ''
|
||||
puts "cake #name#spaces #desc"
|
||||
spaces = if spaces > 0 then Array(spaces + 1).join(' ') else ''
|
||||
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.
|
||||
missingTask = (task) ->
|
||||
puts "No such task: \"#task\""
|
||||
puts "No such task: \"#{task}\""
|
||||
process.exit 1
|
||||
|
||||
73
src/coffee-script.coffee
Normal file → Executable file
73
src/coffee-script.coffee
Normal file → Executable file
@@ -6,26 +6,22 @@
|
||||
# If included on a webpage, it will automatically sniff out, compile, and
|
||||
# execute all scripts present in `text/coffeescript` tags.
|
||||
|
||||
# Set up dependencies correctly for both the server and the browser.
|
||||
if process?
|
||||
path = require 'path'
|
||||
Lexer = require('./lexer').Lexer
|
||||
parser = require('./parser').parser
|
||||
helpers = require('./helpers').helpers
|
||||
helpers.extend global, require './nodes'
|
||||
if require.registerExtension
|
||||
require.registerExtension '.coffee', (content) -> compile content
|
||||
else
|
||||
this.exports = this.CoffeeScript = {}
|
||||
Lexer = this.Lexer
|
||||
parser = this.parser
|
||||
helpers = this.helpers
|
||||
path = require 'path'
|
||||
{Lexer} = require './lexer'
|
||||
{parser} = require './parser'
|
||||
|
||||
# TODO: Remove registerExtension when fully deprecated
|
||||
if require.extensions
|
||||
fs = require 'fs'
|
||||
require.extensions['.coffee'] = (module, filename) ->
|
||||
content = compile fs.readFileSync filename, 'utf8'
|
||||
module.filename = "#{filename} (compiled)"
|
||||
module._compile content, module.filename
|
||||
else if require.registerExtension
|
||||
require.registerExtension '.coffee', (content) -> compile content
|
||||
|
||||
# The current CoffeeScript version number.
|
||||
exports.VERSION = '0.9.0'
|
||||
|
||||
# Instantiate a Lexer for our use here.
|
||||
lexer = new Lexer
|
||||
exports.VERSION = '0.9.4'
|
||||
|
||||
# Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
|
||||
# compiler.
|
||||
@@ -34,7 +30,7 @@ exports.compile = compile = (code, options) ->
|
||||
try
|
||||
(parser.parse lexer.tokenize code).compile options
|
||||
catch err
|
||||
err.message = "In #options.fileName, #err.message" if options.fileName
|
||||
err.message = "In #{options.fileName}, #{err.message}" if options.fileName
|
||||
throw err
|
||||
|
||||
# Tokenize a string of CoffeeScript code, and return the array of tokens.
|
||||
@@ -49,11 +45,27 @@ exports.nodes = (code) ->
|
||||
|
||||
# Compile and execute a string of CoffeeScript (on the server), correctly
|
||||
# setting `__filename`, `__dirname`, and relative `require()`.
|
||||
exports.run = ((code, options) ->
|
||||
module.filename = __filename = options.fileName
|
||||
__dirname = path.dirname __filename
|
||||
eval exports.compile code, options
|
||||
)
|
||||
exports.run = (code, options) ->
|
||||
# We want the root module.
|
||||
root = module
|
||||
while root.parent
|
||||
root = root.parent
|
||||
# Set the filename
|
||||
root.filename = __filename = "#{options.fileName} (compiled)"
|
||||
# Clear the module cache
|
||||
root.moduleCache = {} if root.moduleCache
|
||||
# Compile
|
||||
root._compile exports.compile(code, options), root.filename
|
||||
|
||||
# Compile and evaluate a string of CoffeeScript (in a Node.js-like environment).
|
||||
# The CoffeeScript REPL uses this to run the input.
|
||||
exports.eval = (code, options) ->
|
||||
__filename = options.fileName
|
||||
__dirname = path.dirname __filename
|
||||
eval exports.compile(code, options)
|
||||
|
||||
# Instantiate a Lexer for our use here.
|
||||
lexer = new Lexer
|
||||
|
||||
# The real Lexer produces a generic stream of tokens. This object provides a
|
||||
# thin wrapper around it, compatible with the Jison API. We can then pass it
|
||||
@@ -70,15 +82,4 @@ parser.lexer =
|
||||
@pos = 0
|
||||
upcomingInput: -> ""
|
||||
|
||||
# Activate CoffeeScript in the browser by having it compile and evaluate
|
||||
# all script tags with a content-type of `text/coffeescript`. This happens
|
||||
# on page load. Unfortunately, the text contents of remote scripts cannot be
|
||||
# accessed from the browser, so only inline script tags will work.
|
||||
if document? and document.getElementsByTagName
|
||||
processScripts = ->
|
||||
for tag in document.getElementsByTagName('script') when tag.type is 'text/coffeescript'
|
||||
eval exports.compile tag.innerHTML
|
||||
if window.addEventListener
|
||||
window.addEventListener 'load', processScripts, false
|
||||
else if window.attachEvent
|
||||
window.attachEvent 'onload', processScripts
|
||||
parser.yy = require './nodes'
|
||||
|
||||
@@ -5,11 +5,17 @@
|
||||
# interactive REPL.
|
||||
|
||||
# External dependencies.
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
optparse = require './optparse'
|
||||
CoffeeScript = require './coffee-script'
|
||||
{spawn, exec} = require 'child_process'
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
optparse = require './optparse'
|
||||
CoffeeScript = require './coffee-script'
|
||||
{helpers} = require './helpers'
|
||||
{spawn, exec} = require 'child_process'
|
||||
{EventEmitter} = require 'events'
|
||||
|
||||
# Allow CoffeeScript to emit Node.js events, and add it to global scope.
|
||||
helpers.extend CoffeeScript, new EventEmitter
|
||||
global.CoffeeScript = CoffeeScript
|
||||
|
||||
# The help banner that is printed when `coffee` is called without arguments.
|
||||
BANNER = '''
|
||||
@@ -21,23 +27,24 @@ BANNER = '''
|
||||
|
||||
# The list of all the valid option flags that `coffee` knows how to handle.
|
||||
SWITCHES = [
|
||||
['-c', '--compile', 'compile to JavaScript and save as .js files']
|
||||
['-i', '--interactive', 'run an interactive CoffeeScript REPL']
|
||||
['-o', '--output [DIR]', 'set the directory for compiled JavaScript']
|
||||
['-w', '--watch', 'watch scripts for changes, and recompile']
|
||||
['-p', '--print', 'print the compiled JavaScript to stdout']
|
||||
['-l', '--lint', 'pipe the compiled JavaScript through JSLint']
|
||||
['-s', '--stdio', 'listen for and compile scripts over stdio']
|
||||
['-e', '--eval', 'compile a string from the command line']
|
||||
[ '--no-wrap', 'compile without the top-level function wrapper']
|
||||
['-t', '--tokens', 'print the tokens that the lexer produces']
|
||||
['-n', '--nodes', 'print the parse tree that Jison produces']
|
||||
['-v', '--version', 'display CoffeeScript version']
|
||||
['-h', '--help', 'display this help message']
|
||||
['-c', '--compile', 'compile to JavaScript and save as .js files']
|
||||
['-i', '--interactive', 'run an interactive CoffeeScript REPL']
|
||||
['-o', '--output [DIR]', 'set the directory for compiled JavaScript']
|
||||
['-w', '--watch', 'watch scripts for changes, and recompile']
|
||||
['-p', '--print', 'print the compiled JavaScript to stdout']
|
||||
['-l', '--lint', 'pipe the compiled JavaScript through JSLint']
|
||||
['-s', '--stdio', 'listen for and compile scripts over stdio']
|
||||
['-e', '--eval', 'compile a string from the command line']
|
||||
['-r', '--require [FILE*]', 'require a library before executing your script']
|
||||
[ '--no-wrap', 'compile without the top-level function wrapper']
|
||||
['-t', '--tokens', 'print the tokens that the lexer produces']
|
||||
['-n', '--nodes', 'print the parse tree that Jison produces']
|
||||
['-v', '--version', 'display CoffeeScript version']
|
||||
['-h', '--help', 'display this help message']
|
||||
]
|
||||
|
||||
# Top-level objects shared by all the functions.
|
||||
options = {}
|
||||
opts = {}
|
||||
sources = []
|
||||
optionParser = null
|
||||
|
||||
@@ -46,18 +53,18 @@ optionParser = null
|
||||
# `--` will be passed verbatim to your script as arguments in `process.argv`
|
||||
exports.run = ->
|
||||
parseOptions()
|
||||
return usage() if options.help
|
||||
return version() if options.version
|
||||
return require './repl' if options.interactive
|
||||
return compileStdio() if options.stdio
|
||||
return compileScript 'console', sources[0] if options.eval
|
||||
return usage() if opts.help
|
||||
return version() if opts.version
|
||||
return require './repl' if opts.interactive
|
||||
return compileStdio() if opts.stdio
|
||||
return compileScript 'console', sources[0] if opts.eval
|
||||
return require './repl' unless sources.length
|
||||
separator = sources.indexOf '--'
|
||||
flags = []
|
||||
if separator >= 0
|
||||
flags = sources[(separator + 1)...sources.length]
|
||||
sources = sources[0...separator]
|
||||
if options.run
|
||||
if opts.run
|
||||
flags = sources[1..sources.length].concat flags
|
||||
sources = [sources[0]]
|
||||
process.ARGV = process.argv = flags
|
||||
@@ -71,7 +78,7 @@ compileScripts = ->
|
||||
base = source
|
||||
compile = (source, topLevel) ->
|
||||
path.exists source, (exists) ->
|
||||
throw new Error "File not found: #source" unless exists
|
||||
throw new Error "File not found: #{source}" unless exists
|
||||
fs.stat source, (err, stats) ->
|
||||
if stats.isDirectory()
|
||||
fs.readdir source, (err, files) ->
|
||||
@@ -79,27 +86,37 @@ compileScripts = ->
|
||||
compile path.join(source, file)
|
||||
else if topLevel or path.extname(source) is '.coffee'
|
||||
fs.readFile source, (err, code) -> compileScript(source, code.toString(), base)
|
||||
watch source, base if options.watch
|
||||
watch source, base if opts.watch
|
||||
compile source, true
|
||||
|
||||
# Compile a single source script, containing the given code, according to the
|
||||
# requested options. If evaluating the script directly sets `__filename`,
|
||||
# `__dirname` and `module.filename` to be correct relative to the script's path.
|
||||
compileScript = (source, code, base) ->
|
||||
o = options
|
||||
codeOpts = compileOptions source
|
||||
compileScript = (file, input, base) ->
|
||||
o = opts
|
||||
options = compileOptions file
|
||||
if o.require
|
||||
require(if helpers.starts(req, '.') then fs.realpathSync(req) else req) for req in o.require
|
||||
try
|
||||
if o.tokens then printTokens CoffeeScript.tokens code
|
||||
else if o.nodes then puts CoffeeScript.nodes(code).toString()
|
||||
else if o.run then CoffeeScript.run code, codeOpts
|
||||
t = task = {file, input, options}
|
||||
CoffeeScript.emit 'compile', task
|
||||
if o.tokens then printTokens CoffeeScript.tokens t.input
|
||||
else if o.nodes then puts CoffeeScript.nodes(t.input).toString()
|
||||
else if o.run then CoffeeScript.run t.input, t.options
|
||||
else
|
||||
js = CoffeeScript.compile code, codeOpts
|
||||
if o.print then print js
|
||||
else if o.compile then writeJs source, js, base
|
||||
else if o.lint then lint js
|
||||
t.output = CoffeeScript.compile t.input, t.options
|
||||
CoffeeScript.emit 'success', task
|
||||
if o.print then print t.output
|
||||
else if o.compile then writeJs t.file, t.output, base
|
||||
else if o.lint then lint t.output
|
||||
catch err
|
||||
error(err.stack) and process.exit 1 unless o.watch
|
||||
puts err.message
|
||||
# Avoid using 'error' as it is a special event -- if there is no handler,
|
||||
# node will print a stack trace and exit the program.
|
||||
CoffeeScript.emit 'failure', err, task
|
||||
return if CoffeeScript.listeners('failure').length
|
||||
return puts err.message if o.watch
|
||||
error err.stack
|
||||
process.exit 1
|
||||
|
||||
# Attach the appropriate listeners to compile scripts incoming over **stdin**,
|
||||
# and write them back to **stdout**.
|
||||
@@ -116,8 +133,10 @@ compileStdio = ->
|
||||
# such as `--lint` or `--print`.
|
||||
watch = (source, base) ->
|
||||
fs.watchFile source, {persistent: true, interval: 500}, (curr, prev) ->
|
||||
return if curr.mtime.getTime() is prev.mtime.getTime()
|
||||
fs.readFile source, (err, code) -> compileScript(source, code.toString(), base)
|
||||
return if curr.size is prev.size and curr.mtime.getTime() is prev.mtime.getTime()
|
||||
fs.readFile source, (err, code) ->
|
||||
throw err if err
|
||||
compileScript(source, code.toString(), base)
|
||||
|
||||
# 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
|
||||
@@ -126,20 +145,21 @@ writeJs = (source, js, base) ->
|
||||
filename = path.basename(source, path.extname(source)) + '.js'
|
||||
srcDir = path.dirname source
|
||||
baseDir = srcDir.substring base.length
|
||||
dir = if options.output then path.join options.output, baseDir else srcDir
|
||||
dir = if opts.output then path.join opts.output, baseDir else srcDir
|
||||
jsPath = path.join dir, filename
|
||||
compile = ->
|
||||
return unless js.length
|
||||
js = ' ' if js.length <= 0
|
||||
fs.writeFile jsPath, js, (err) ->
|
||||
puts "Compiled #source" if options.compile and options.watch
|
||||
puts "Compiled #{source}" if opts.compile and opts.watch
|
||||
path.exists dir, (exists) ->
|
||||
if exists then compile() else exec "mkdir -p #dir", compile
|
||||
if exists then compile() else exec "mkdir -p #{dir}", compile
|
||||
|
||||
# Pipe compiled JS through JSLint (requires a working `jsl` command), printing
|
||||
# any errors or warnings that arise.
|
||||
lint = (js) ->
|
||||
printIt = (buffer) -> print buffer.toString()
|
||||
jsl = spawn 'jsl', ['-nologo', '-stdin']
|
||||
printIt = (buffer) -> puts buffer.toString().trim()
|
||||
conf = __dirname + '/../extras/jsl.conf'
|
||||
jsl = spawn 'jsl', ['-nologo', '-stdin', '-conf', conf]
|
||||
jsl.stdout.on 'data', printIt
|
||||
jsl.stderr.on 'data', printIt
|
||||
jsl.stdin.write js
|
||||
@@ -149,23 +169,23 @@ lint = (js) ->
|
||||
printTokens = (tokens) ->
|
||||
strings = for token in tokens
|
||||
[tag, value] = [token[0], token[1].toString().replace(/\n/, '\\n')]
|
||||
"[#tag #value]"
|
||||
"[#{tag} #{value}]"
|
||||
puts strings.join(' ')
|
||||
|
||||
# Use the [OptionParser module](optparse.html) to extract all options from
|
||||
# `process.argv` that are specified in `SWITCHES`.
|
||||
parseOptions = ->
|
||||
optionParser = new optparse.OptionParser SWITCHES, BANNER
|
||||
o = options = optionParser.parse(process.argv[2...process.argv.length])
|
||||
options.compile or= !!o.output
|
||||
options.run = not (o.compile or o.print or o.lint)
|
||||
options.print = !! (o.print or (o.eval or o.stdio and o.compile))
|
||||
sources = options.arguments
|
||||
optionParser = new optparse.OptionParser SWITCHES, BANNER
|
||||
o = opts = optionParser.parse(process.argv[2...process.argv.length])
|
||||
o.compile or= !!o.output
|
||||
o.run = not (o.compile or o.print or o.lint)
|
||||
o.print = !! (o.print or (o.eval or o.stdio and o.compile))
|
||||
sources = o.arguments
|
||||
|
||||
# The compile-time options to pass to the CoffeeScript compiler.
|
||||
compileOptions = (fileName) ->
|
||||
o = {fileName}
|
||||
o.noWrap = options['no-wrap']
|
||||
o.noWrap = opts['no-wrap']
|
||||
o
|
||||
|
||||
# Print the `--help` usage message and exit.
|
||||
@@ -175,5 +195,5 @@ usage = ->
|
||||
|
||||
# Print the `--version` message and exit.
|
||||
version = ->
|
||||
puts "CoffeeScript version #CoffeeScript.VERSION"
|
||||
puts "CoffeeScript version #{CoffeeScript.VERSION}"
|
||||
process.exit 0
|
||||
|
||||
@@ -32,8 +32,9 @@ unwrap = /function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/
|
||||
# previous nonterminal.
|
||||
o = (patternString, action, options) ->
|
||||
return [patternString, '$$ = $1;', options] unless action
|
||||
action = if match = (action + '').match(unwrap) then match[1] else "(#action())"
|
||||
[patternString, "$$ = #action;", options]
|
||||
action = if match = (action + '').match(unwrap) then match[1] else "(#{action}())"
|
||||
action = action.replace /\b(?:[A-Z][a-z]+Node|Expressions)\b/g, 'yy.$&'
|
||||
[patternString, "$$ = #{action};", options]
|
||||
|
||||
# Grammatical Rules
|
||||
# -----------------
|
||||
@@ -78,6 +79,7 @@ grammar =
|
||||
o "Throw"
|
||||
o "BREAK", -> new LiteralNode $1
|
||||
o "CONTINUE", -> new LiteralNode $1
|
||||
o "DEBUGGER", -> new LiteralNode $1
|
||||
]
|
||||
|
||||
# All the different types of expressions in our language. The basic unit of
|
||||
@@ -97,12 +99,11 @@ grammar =
|
||||
o "Switch"
|
||||
o "Extends"
|
||||
o "Class"
|
||||
o "Splat"
|
||||
o "Existence"
|
||||
o "Comment"
|
||||
]
|
||||
|
||||
# A an indented block of expressions. Note that the [Rewriter](rewriter.html)
|
||||
# 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: [
|
||||
@@ -286,6 +287,7 @@ grammar =
|
||||
ClassAssign: [
|
||||
o "AssignObj", -> $1
|
||||
o "ThisProperty : Expression", -> new AssignNode new ValueNode($1), $3, 'this'
|
||||
o "ThisProperty : INDENT Expression OUTDENT", -> new AssignNode new ValueNode($1), $4, 'this'
|
||||
]
|
||||
|
||||
# A list of assignments to a class.
|
||||
@@ -296,11 +298,9 @@ grammar =
|
||||
o "{ ClassBody }", -> $2
|
||||
]
|
||||
|
||||
# The three flavors of function call: normal, object instantiation with `new`,
|
||||
# and calling `super()`
|
||||
# The two flavors of function call: normal, and object instantiation with `new`.
|
||||
Call: [
|
||||
o "Invocation"
|
||||
o "Super"
|
||||
o "NEW Invocation", -> $2.newInstance()
|
||||
o "NEW Value", -> (new CallNode($2, [])).newInstance()
|
||||
]
|
||||
@@ -313,27 +313,35 @@ grammar =
|
||||
|
||||
# Ordinary function invocation, or a chained series of calls.
|
||||
Invocation: [
|
||||
o "Value Arguments", -> new CallNode $1, $2
|
||||
o "Invocation Arguments", -> new CallNode $1, $2
|
||||
o "Value OptFuncExist Arguments", -> new CallNode $1, $3, $2
|
||||
o "Invocation OptFuncExist Arguments", -> new CallNode $1, $3, $2
|
||||
o "SUPER", -> new CallNode 'super', [new SplatNode(new LiteralNode('arguments'))]
|
||||
o "SUPER Arguments", -> new CallNode 'super', $2
|
||||
]
|
||||
|
||||
# An optional existence check on a function.
|
||||
OptFuncExist: [
|
||||
o "", -> no
|
||||
o "FUNC_EXIST", -> yes
|
||||
]
|
||||
|
||||
# The list of arguments to a function call.
|
||||
Arguments: [
|
||||
o "CALL_START CALL_END", -> []
|
||||
o "CALL_START ArgList OptComma CALL_END", -> $2
|
||||
]
|
||||
|
||||
# Calling super.
|
||||
Super: [
|
||||
o "SUPER", -> new CallNode 'super', [new SplatNode(new LiteralNode('arguments'))]
|
||||
o "SUPER Arguments", -> new CallNode 'super', $2
|
||||
]
|
||||
|
||||
# A reference to the *this* current object.
|
||||
This: [
|
||||
o "THIS", -> new ValueNode new LiteralNode 'this'
|
||||
o "@", -> new ValueNode new LiteralNode 'this'
|
||||
]
|
||||
|
||||
RangeDots: [
|
||||
o ". .", -> 'inclusive'
|
||||
o ". . .", -> 'exclusive'
|
||||
]
|
||||
|
||||
# A reference to a property on *this*.
|
||||
ThisProperty: [
|
||||
o "@ Identifier", -> new ValueNode new LiteralNode('this'), [new AccessorNode($2)]
|
||||
@@ -341,18 +349,19 @@ grammar =
|
||||
|
||||
# The CoffeeScript range literal.
|
||||
Range: [
|
||||
o "[ Expression . . Expression ]", -> new RangeNode $2, $5
|
||||
o "[ Expression . . . Expression ]", -> new RangeNode $2, $6, true
|
||||
o "[ Expression RangeDots Expression ]", -> new RangeNode $2, $4, $3
|
||||
]
|
||||
|
||||
# The slice literal.
|
||||
Slice: [
|
||||
o "INDEX_START Expression . . Expression INDEX_END", -> new RangeNode $2, $5
|
||||
o "INDEX_START Expression . . . Expression INDEX_END", -> new RangeNode $2, $6, true
|
||||
o "INDEX_START Expression RangeDots Expression INDEX_END", -> new RangeNode $2, $4, $3
|
||||
o "INDEX_START Expression RangeDots INDEX_END", -> new RangeNode $2, null, $3
|
||||
o "INDEX_START RangeDots Expression INDEX_END", -> new RangeNode null, $3, $2
|
||||
]
|
||||
|
||||
# The array literal.
|
||||
Array: [
|
||||
o "[ ]", -> new ArrayNode []
|
||||
o "[ ArgList OptComma ]", -> new ArrayNode $2
|
||||
]
|
||||
|
||||
@@ -360,13 +369,19 @@ grammar =
|
||||
# as well as the contents of an array literal
|
||||
# (i.e. comma-separated expressions). Newlines work as well.
|
||||
ArgList: [
|
||||
o "", -> []
|
||||
o "Expression", -> [$1]
|
||||
o "ArgList , Expression", -> $1.concat [$3]
|
||||
o "ArgList OptComma TERMINATOR Expression", -> $1.concat [$4]
|
||||
o "Arg", -> [$1]
|
||||
o "ArgList , Arg", -> $1.concat [$3]
|
||||
o "ArgList OptComma TERMINATOR Arg", -> $1.concat [$4]
|
||||
o "INDENT ArgList OptComma OUTDENT", -> $2
|
||||
o "ArgList OptComma INDENT ArgList OptComma OUTDENT", -> $1.concat $4
|
||||
]
|
||||
|
||||
# Valid arguments are Expressions or Splats.
|
||||
Arg: [
|
||||
o "Expression"
|
||||
o "Splat"
|
||||
]
|
||||
|
||||
# Just simple, comma-separated, required arguments (no fancy syntax). We need
|
||||
# this to be separate from the **ArgList** for use in **Switch** blocks, where
|
||||
# having the newlines wouldn't make sense.
|
||||
@@ -399,6 +414,7 @@ grammar =
|
||||
# the trick.
|
||||
Parenthetical: [
|
||||
o "( Line )", -> new ParentheticalNode $2
|
||||
o "( )", -> new ParentheticalNode new LiteralNode ''
|
||||
]
|
||||
|
||||
# The condition portion of a while loop.
|
||||
@@ -471,26 +487,22 @@ grammar =
|
||||
o "IN Expression BY Expression WHEN Expression", -> source: $2, step: $4, guard: $6
|
||||
]
|
||||
|
||||
# The CoffeeScript switch/when/else block replaces the JavaScript
|
||||
# switch/case/default by compiling into an if-else chain.
|
||||
Switch: [
|
||||
o "SWITCH Expression INDENT Whens OUTDENT", -> $4.switchesOver $2
|
||||
o "SWITCH Expression INDENT Whens ELSE Block OUTDENT", -> $4.switchesOver($2).addElse $6, true
|
||||
o "SWITCH INDENT Whens OUTDENT", -> $3
|
||||
o "SWITCH INDENT Whens ELSE Block OUTDENT", -> $3.addElse $5, true
|
||||
o "SWITCH Expression INDENT Whens OUTDENT", -> new SwitchNode $2, $4
|
||||
o "SWITCH Expression INDENT Whens ELSE Block OUTDENT", -> new SwitchNode $2, $4, $6
|
||||
o "SWITCH INDENT Whens OUTDENT", -> new SwitchNode null, $3
|
||||
o "SWITCH INDENT Whens ELSE Block OUTDENT", -> new SwitchNode null, $3, $5
|
||||
]
|
||||
|
||||
# The inner list of whens is left recursive. At code-generation time, the
|
||||
# IfNode will rewrite them into a proper chain.
|
||||
Whens: [
|
||||
o "When"
|
||||
o "Whens When", -> $1.addElse $2
|
||||
o "Whens When", -> $1.concat $2
|
||||
]
|
||||
|
||||
# An individual **When** clause, with action.
|
||||
When: [
|
||||
o "LEADING_WHEN SimpleArgs Block", -> new IfNode $2, $3, statement: true
|
||||
o "LEADING_WHEN SimpleArgs Block TERMINATOR", -> new IfNode $2, $3, statement: true
|
||||
o "LEADING_WHEN SimpleArgs Block", -> [[$2, $3]]
|
||||
o "LEADING_WHEN SimpleArgs Block TERMINATOR", -> [[$2, $3]]
|
||||
]
|
||||
|
||||
# The most basic form of *if* is a condition and an action. The following
|
||||
@@ -507,10 +519,10 @@ grammar =
|
||||
# *if* and *unless*.
|
||||
If: [
|
||||
o "IfBlock"
|
||||
o "Statement IF Expression", -> new IfNode $3, Expressions.wrap([$1]), statement: true
|
||||
o "Expression IF Expression", -> new IfNode $3, Expressions.wrap([$1]), statement: true
|
||||
o "Statement UNLESS Expression", -> new IfNode $3, Expressions.wrap([$1]), statement: true, invert: true
|
||||
o "Expression UNLESS Expression", -> new IfNode $3, Expressions.wrap([$1]), statement: true, invert: true
|
||||
o "Statement POST_IF Expression", -> new IfNode $3, Expressions.wrap([$1]), statement: true
|
||||
o "Expression POST_IF Expression", -> new IfNode $3, Expressions.wrap([$1]), statement: true
|
||||
o "Statement POST_UNLESS Expression", -> new IfNode $3, Expressions.wrap([$1]), statement: true, invert: true
|
||||
o "Expression POST_UNLESS Expression", -> new IfNode $3, Expressions.wrap([$1]), statement: true, invert: true
|
||||
]
|
||||
|
||||
# Arithmetic and logical operators, working on one or more operands.
|
||||
@@ -520,58 +532,34 @@ grammar =
|
||||
# -type rule, but in order to make the precedence binding possible, separate
|
||||
# rules are necessary.
|
||||
Operation: [
|
||||
o "! Expression", -> new OpNode '!', $2
|
||||
o "!! Expression", -> new OpNode '!!', $2
|
||||
o("- Expression", (-> new OpNode('-', $2)), {prec: 'UMINUS'})
|
||||
o("+ Expression", (-> new OpNode('+', $2)), {prec: 'UPLUS'})
|
||||
o "~ Expression", -> new OpNode '~', $2
|
||||
o "UNARY Expression", -> new OpNode $1, $2
|
||||
o("- Expression", (-> new OpNode('-', $2)), {prec: 'UNARY'})
|
||||
o("+ Expression", (-> new OpNode('+', $2)), {prec: 'UNARY'})
|
||||
|
||||
o "-- Expression", -> new OpNode '--', $2
|
||||
o "++ Expression", -> new OpNode '++', $2
|
||||
o "DELETE Expression", -> new OpNode 'delete', $2
|
||||
o "TYPEOF Expression", -> new OpNode 'typeof', $2
|
||||
o "Expression --", -> new OpNode '--', $1, null, true
|
||||
o "Expression ++", -> new OpNode '++', $1, null, true
|
||||
|
||||
o "Expression * Expression", -> new OpNode '*', $1, $3
|
||||
o "Expression / Expression", -> new OpNode '/', $1, $3
|
||||
o "Expression % Expression", -> new OpNode '%', $1, $3
|
||||
|
||||
o "Expression ? Expression", -> new OpNode '?', $1, $3
|
||||
o "Expression + Expression", -> new OpNode '+', $1, $3
|
||||
o "Expression - Expression", -> new OpNode '-', $1, $3
|
||||
|
||||
o "Expression << Expression", -> new OpNode '<<', $1, $3
|
||||
o "Expression >> Expression", -> new OpNode '>>', $1, $3
|
||||
o "Expression >>> Expression", -> new OpNode '>>>', $1, $3
|
||||
o "Expression & Expression", -> new OpNode '&', $1, $3
|
||||
o "Expression | Expression", -> new OpNode '|', $1, $3
|
||||
o "Expression ^ Expression", -> new OpNode '^', $1, $3
|
||||
|
||||
o "Expression <= Expression", -> new OpNode '<=', $1, $3
|
||||
o "Expression < Expression", -> new OpNode '<', $1, $3
|
||||
o "Expression > Expression", -> new OpNode '>', $1, $3
|
||||
o "Expression >= Expression", -> new OpNode '>=', $1, $3
|
||||
|
||||
o "Expression == Expression", -> new OpNode '==', $1, $3
|
||||
o "Expression != Expression", -> new OpNode '!=', $1, $3
|
||||
|
||||
o "Expression && Expression", -> new OpNode '&&', $1, $3
|
||||
o "Expression || Expression", -> new OpNode '||', $1, $3
|
||||
o "Expression OP? Expression", -> new OpNode '?', $1, $3
|
||||
o "Expression MATH Expression", -> new OpNode $2, $1, $3
|
||||
o "Expression SHIFT Expression", -> new OpNode $2, $1, $3
|
||||
o "Expression COMPARE Expression", -> new OpNode $2, $1, $3
|
||||
o "Expression LOGIC Expression", -> new OpNode $2, $1, $3
|
||||
o "Value COMPOUND_ASSIGN Expression", -> new OpNode $2, $1, $3
|
||||
o "Value COMPOUND_ASSIGN INDENT Expression OUTDENT", -> new OpNode $2, $1, $4
|
||||
|
||||
o "Expression -= Expression", -> new OpNode '-=', $1, $3
|
||||
o "Expression += Expression", -> new OpNode '+=', $1, $3
|
||||
o "Expression /= Expression", -> new OpNode '/=', $1, $3
|
||||
o "Expression *= Expression", -> new OpNode '*=', $1, $3
|
||||
o "Expression %= Expression", -> new OpNode '%=', $1, $3
|
||||
o "Expression ||= Expression", -> new OpNode '||=', $1, $3
|
||||
o "Expression &&= Expression", -> new OpNode '&&=', $1, $3
|
||||
o "Expression ?= Expression", -> new OpNode '?=', $1, $3
|
||||
|
||||
o "Expression INSTANCEOF Expression", -> new OpNode 'instanceof', $1, $3
|
||||
o "Expression IN Expression", -> new InNode $1, $3
|
||||
o "Expression OF Expression", -> new OpNode 'in', $1, $3
|
||||
o "Expression ! IN Expression", -> new OpNode '!', new InNode $1, $4
|
||||
o "Expression ! OF Expression", -> new OpNode '!', new ParentheticalNode new OpNode 'in', $1, $4
|
||||
o "Expression INSTANCEOF Expression", -> new OpNode 'instanceof', $1, $3
|
||||
o "Expression UNARY IN Expression", -> new OpNode $2, new InNode $1, $4
|
||||
o "Expression UNARY OF Expression", -> new OpNode $2, new ParentheticalNode new OpNode 'in', $1, $4
|
||||
o "Expression UNARY INSTANCEOF Expression", -> new OpNode $2, new ParentheticalNode new OpNode 'instanceof', $1, $4
|
||||
]
|
||||
|
||||
|
||||
@@ -587,25 +575,24 @@ grammar =
|
||||
#
|
||||
# (2 + 3) * 4
|
||||
operators = [
|
||||
["left", '?']
|
||||
["nonassoc", 'UMINUS', 'UPLUS', '!', '!!', '~', '++', '--']
|
||||
["left", '*', '/', '%']
|
||||
["right", '?', 'NEW']
|
||||
["left", 'CALL_START', 'CALL_END']
|
||||
["nonassoc", '++', '--']
|
||||
["right", 'UNARY']
|
||||
["left", 'MATH']
|
||||
["left", '+', '-']
|
||||
["left", '<<', '>>', '>>>']
|
||||
["left", '&', '|', '^']
|
||||
["left", '<=', '<', '>', '>=']
|
||||
["right", 'DELETE', 'INSTANCEOF', 'TYPEOF']
|
||||
["left", 'SHIFT']
|
||||
["left", 'COMPARE']
|
||||
["left", 'INSTANCEOF']
|
||||
["left", '==', '!=']
|
||||
["left", '&&', '||', 'OP?']
|
||||
["right", '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=']
|
||||
["left", 'LOGIC']
|
||||
["right", 'COMPOUND_ASSIGN']
|
||||
["left", '.']
|
||||
["right", 'INDENT']
|
||||
["left", 'OUTDENT']
|
||||
["nonassoc", 'INDENT', 'OUTDENT']
|
||||
["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY', 'THROW']
|
||||
["right", 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'NEW', 'SUPER', 'CLASS']
|
||||
["left", 'EXTENDS']
|
||||
["right", 'IF', 'UNLESS', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS', 'EXTENDS']
|
||||
["right", '=', ':', 'RETURN']
|
||||
["right", '->', '=>', 'UNLESS', 'IF', 'ELSE']
|
||||
["right", '->', '=>', 'UNLESS', 'POST_IF', 'POST_UNLESS']
|
||||
]
|
||||
|
||||
# Wrapping Up
|
||||
@@ -627,9 +614,8 @@ for name, alternatives of grammar
|
||||
# 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 [Yacc](http://dinosaur.compilertools.net/yacc/index.html)).
|
||||
exports.parser = new Parser {
|
||||
exports.parser = new Parser
|
||||
tokens: tokens.join ' '
|
||||
bnf: grammar
|
||||
operators: operators.reverse()
|
||||
startSymbol: 'Root'
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
# the **Lexer**, **Rewriter**, and the **Nodes**. Merge objects, flatten
|
||||
# arrays, count characters, that sort of thing.
|
||||
|
||||
# Set up exported variables for both **Node.js** and the browser.
|
||||
this.exports = this unless process?
|
||||
helpers = exports.helpers = {}
|
||||
|
||||
# Cross-browser indexOf, so that IE can join the party.
|
||||
|
||||
158
src/lexer.coffee
158
src/lexer.coffee
@@ -7,17 +7,10 @@
|
||||
#
|
||||
# Which is a format that can be fed directly into [Jison](http://github.com/zaach/jison).
|
||||
|
||||
# Set up the Lexer for both Node.js and the browser, depending on where we are.
|
||||
if process?
|
||||
{Rewriter} = require('./rewriter')
|
||||
{helpers} = require('./helpers')
|
||||
else
|
||||
this.exports = this
|
||||
Rewriter = this.Rewriter
|
||||
helpers = this.helpers
|
||||
{Rewriter} = require './rewriter'
|
||||
|
||||
# Import the helpers we need.
|
||||
{include, count, starts, compact} = helpers
|
||||
{include, count, starts, compact} = require('./helpers').helpers
|
||||
|
||||
# The Lexer Class
|
||||
# ---------------
|
||||
@@ -46,11 +39,12 @@ exports.Lexer = class Lexer
|
||||
@i = 0 # Current character position we're parsing.
|
||||
@line = o.line or 0 # The current line.
|
||||
@indent = 0 # The current indentation level.
|
||||
@outdebt = 0 # The under-outdentation of the last outdent.
|
||||
@indebt = 0 # The over-indentation at the current level.
|
||||
@outdebt = 0 # The under-outdentation at the current level.
|
||||
@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[@i..]
|
||||
@extractNextToken()
|
||||
@closeIndentation()
|
||||
return @tokens if o.rewrite is off
|
||||
@@ -88,10 +82,11 @@ exports.Lexer = class Lexer
|
||||
tag = id.toUpperCase() if include(JS_KEYWORDS, id) or (not forcedIdentifier and include(COFFEE_KEYWORDS, id))
|
||||
tag = 'LEADING_WHEN' if tag is 'WHEN' and include LINE_BREAK, @tag()
|
||||
tag = 'ALL' if id is 'all' and @tag() is 'FOR'
|
||||
tag = 'UNARY' if include UNARY, tag
|
||||
if include(JS_FORBIDDEN, id)
|
||||
if forcedIdentifier
|
||||
tag = 'STRING'
|
||||
id = "\"#id\""
|
||||
id = "\"#{id}\""
|
||||
if forcedIdentifier is 'accessor'
|
||||
close_index = true
|
||||
@tokens.pop() if @tag() isnt '@'
|
||||
@@ -100,6 +95,8 @@ exports.Lexer = class Lexer
|
||||
@identifierError id
|
||||
unless forcedIdentifier
|
||||
tag = id = CONVERSIONS[id] if include COFFEE_ALIASES, id
|
||||
tag = 'LOGIC' if include LOGIC, id
|
||||
tag = 'UNARY' if id is '!'
|
||||
@token tag, id
|
||||
@token ']', ']' if close_index
|
||||
true
|
||||
@@ -120,7 +117,7 @@ exports.Lexer = class Lexer
|
||||
return false unless string =
|
||||
@balancedToken(['"', '"'], ['#{', '}']) or
|
||||
@balancedToken ["'", "'"]
|
||||
@interpolateString string.replace STRING_NEWLINES, " \\\n"
|
||||
@interpolateString string.replace /\n/g, '\\\n'
|
||||
@line += count string, "\n"
|
||||
@i += string.length
|
||||
true
|
||||
@@ -128,22 +125,22 @@ exports.Lexer = class Lexer
|
||||
# Matches heredocs, adjusting indentation to the correct level, as heredocs
|
||||
# preserve whitespace, but ignore indentation to the left.
|
||||
heredocToken: ->
|
||||
return false unless match = @chunk.match(HEREDOC)
|
||||
return false unless match = @chunk.match HEREDOC
|
||||
quote = match[1].substr 0, 1
|
||||
doc = @sanitizeHeredoc match[2] or match[4], {quote}
|
||||
@interpolateString "#quote#doc#quote", heredoc: yes
|
||||
doc = @sanitizeHeredoc match[2] or match[4] or '', {quote}
|
||||
@interpolateString quote + doc + quote, heredoc: yes
|
||||
@line += count match[1], "\n"
|
||||
@i += match[1].length
|
||||
true
|
||||
|
||||
# Matches and conumes comments.
|
||||
# Matches and consumes comments.
|
||||
commentToken: ->
|
||||
return false unless match = @chunk.match(COMMENT)
|
||||
@line += count match[1], "\n"
|
||||
@i += match[1].length
|
||||
if match[2]
|
||||
comment = @sanitizeHeredoc match[2], herecomment: true
|
||||
@token 'HERECOMMENT', comment.split MULTILINER
|
||||
@token 'HERECOMMENT', @sanitizeHeredoc match[2],
|
||||
herecomment: true, indent: Array(@indent + 1).join(' ')
|
||||
@token 'TERMINATOR', '\n'
|
||||
true
|
||||
|
||||
@@ -160,7 +157,8 @@ exports.Lexer = class Lexer
|
||||
# JavaScript and Ruby, borrow slash balancing from `@balancedToken`, and
|
||||
# borrow interpolation from `@interpolateString`.
|
||||
regexToken: ->
|
||||
return false unless @chunk.match REGEX_START
|
||||
return false unless first = @chunk.match REGEX_START
|
||||
return false if first[1] is ' ' and @tag() not in ['CALL_START', '=']
|
||||
return false if include NOT_REGEX, @tag()
|
||||
return false unless regex = @balancedToken ['/', '/']
|
||||
return false unless end = @chunk.substr(regex.length).match REGEX_END
|
||||
@@ -169,8 +167,8 @@ exports.Lexer = class Lexer
|
||||
str = regex.substring(1).split('/')[0]
|
||||
str = str.replace REGEX_ESCAPE, (escaped) -> '\\' + escaped
|
||||
@tokens = @tokens.concat [['(', '('], ['NEW', 'new'], ['IDENTIFIER', 'RegExp'], ['CALL_START', '(']]
|
||||
@interpolateString "\"#str\"", escapeQuotes: yes
|
||||
@tokens.splice @tokens.length, 0, [',', ','], ['STRING', "\"#flags\""] if flags
|
||||
@interpolateString "\"#{str}\"", escapeQuotes: yes
|
||||
@tokens.splice @tokens.length, 0, [',', ','], ['STRING', "\"#{flags}\""] if flags
|
||||
@tokens.splice @tokens.length, 0, [')', ')'], [')', ')']
|
||||
else
|
||||
@token 'REGEX', regex
|
||||
@@ -200,16 +198,19 @@ exports.Lexer = class Lexer
|
||||
size = indent.match(LAST_DENTS).reverse()[0].match(LAST_DENT)[1].length
|
||||
nextCharacter = @match NEXT_CHARACTER, 1
|
||||
noNewlines = nextCharacter is '.' or nextCharacter is ',' or @unfinished()
|
||||
if size is @indent
|
||||
if size - @indebt is @indent
|
||||
return @suppressNewlines() if noNewlines
|
||||
return @newlineToken indent
|
||||
else if size > @indent
|
||||
return @suppressNewlines() if noNewlines
|
||||
@outdebt = 0
|
||||
diff = size - @indent
|
||||
if noNewlines
|
||||
@indebt = size - @indent
|
||||
return @suppressNewlines()
|
||||
diff = size - @indent + @outdebt
|
||||
@token 'INDENT', diff
|
||||
@indents.push diff
|
||||
@outdebt = @indebt = 0
|
||||
else
|
||||
@indebt = 0
|
||||
@outdentToken @indent - size, noNewlines
|
||||
@indent = size
|
||||
true
|
||||
@@ -269,18 +270,23 @@ exports.Lexer = class Lexer
|
||||
@tagParameters() if value and value.match CODE
|
||||
value or= @chunk.substr 0, 1
|
||||
@i += value.length
|
||||
prevSpaced = @prev() and @prev().spaced
|
||||
spaced = (prev = @prev()) and prev.spaced
|
||||
tag = value
|
||||
if value is '='
|
||||
@assignmentError() if include JS_FORBIDDEN, @value()
|
||||
if @value() in ['or', 'and']
|
||||
return @tag 1, CONVERSIONS[@value()] + '='
|
||||
if value is ';'
|
||||
tag = 'TERMINATOR'
|
||||
else if value is '?' and prevSpaced
|
||||
tag = 'OP?'
|
||||
else if include(CALLABLE, @tag()) and not prevSpaced
|
||||
@tokens.splice(@tokens.length - 1, 1, ['COMPOUND_ASSIGN', CONVERSIONS[@value()] + '=', prev[2]])
|
||||
return true
|
||||
if value is ';' then tag = 'TERMINATOR'
|
||||
else if include(LOGIC, value) then tag = 'LOGIC'
|
||||
else if include(MATH, value) then tag = 'MATH'
|
||||
else if include(COMPARE, value) then tag = 'COMPARE'
|
||||
else if include(COMPOUND_ASSIGN, value) then tag = 'COMPOUND_ASSIGN'
|
||||
else if include(UNARY, value) then tag = 'UNARY'
|
||||
else if include(SHIFT, value) then tag = 'SHIFT'
|
||||
else if include(CALLABLE, @tag()) and not spaced
|
||||
if value is '('
|
||||
prev[0] = 'FUNC_EXIST' if prev[0] is '?'
|
||||
tag = 'CALL_START'
|
||||
else if value is '['
|
||||
tag = 'INDEX_START'
|
||||
@@ -312,13 +318,18 @@ exports.Lexer = class Lexer
|
||||
# Sanitize a heredoc or herecomment by escaping internal double quotes and
|
||||
# erasing all external indentation on the left-hand side.
|
||||
sanitizeHeredoc: (doc, options) ->
|
||||
while (match = HEREDOC_INDENT.exec(doc))
|
||||
attempt = if match[2]? then match[2] else match[3]
|
||||
indent = attempt if not indent or attempt.length < indent.length
|
||||
doc = doc.replace(new RegExp("^" +indent, 'gm'), '')
|
||||
indent = options.indent
|
||||
return doc if options.herecomment and not include doc, '\n'
|
||||
unless options.herecomment
|
||||
while (match = HEREDOC_INDENT.exec(doc)) isnt null
|
||||
attempt = if match[2]? then match[2] else match[3]
|
||||
indent = attempt if not indent? or attempt.length < indent.length
|
||||
indent or= ''
|
||||
doc = doc.replace(new RegExp("^" + indent, 'gm'), '')
|
||||
return doc if options.herecomment
|
||||
doc = doc.replace(/^\n/, '')
|
||||
doc.replace(MULTILINER, "\\n")
|
||||
.replace(new RegExp(options.quote, 'g'), "\\#options.quote")
|
||||
.replace(new RegExp(options.quote, 'g'), "\\#{options.quote}")
|
||||
|
||||
# A source of ambiguity in our grammar used to be parameter lists in function
|
||||
# definitions versus argument lists in function calls. Walk backwards, tagging
|
||||
@@ -343,7 +354,7 @@ exports.Lexer = class Lexer
|
||||
# The error for when you try to use a forbidden word in JavaScript as
|
||||
# an identifier.
|
||||
identifierError: (word) ->
|
||||
throw new Error "SyntaxError: Reserved word \"#word\" on line #{@line + 1}"
|
||||
throw new Error "SyntaxError: Reserved word \"#{word}\" on line #{@line + 1}"
|
||||
|
||||
# The error for when you try to assign to a reserved word in JavaScript,
|
||||
# like "function" or "default".
|
||||
@@ -385,7 +396,6 @@ exports.Lexer = class Lexer
|
||||
# [ECMA Harmony's interpolation syntax](http://wiki.ecmascript.org/doku.php?id=strawman:string_interpolation)
|
||||
# for substitution of bare variables as well as arbitrary expressions.
|
||||
#
|
||||
# "Hello #name."
|
||||
# "Hello #{name.capitalize()}."
|
||||
#
|
||||
# If it encounters an interpolation, this method will recursively create a
|
||||
@@ -396,35 +406,28 @@ exports.Lexer = class Lexer
|
||||
if str.length < 3 or not starts str, '"'
|
||||
@token 'STRING', str
|
||||
else
|
||||
lexer = new Lexer
|
||||
tokens = []
|
||||
quote = str.substring 0, 1
|
||||
[i, pi] = [1, 1]
|
||||
lexer = new Lexer
|
||||
tokens = []
|
||||
quote = str.substring 0, 1
|
||||
[i, pi] = [1, 1]
|
||||
while i < str.length - 1
|
||||
if starts str, '\\', i
|
||||
i += 1
|
||||
else if match = str.substring(i).match INTERPOLATION
|
||||
[group, interp] = match
|
||||
interp = "this.#{ interp.substring(1) }" if starts interp, '@'
|
||||
tokens.push ['STRING', "#quote#{ str.substring(pi, i) }#quote"] if pi < i
|
||||
tokens.push ['IDENTIFIER', interp]
|
||||
i += group.length - 1
|
||||
pi = i + 1
|
||||
else if (expr = @balancedString str.substring(i), [['#{', '}']])
|
||||
tokens.push ['STRING', "#quote#{ str.substring(pi, i) }#quote"] if pi < i
|
||||
else if expr = @balancedString(str.substring(i), [['#{', '}']])
|
||||
tokens.push ['STRING', quote + str.substring(pi, i) + quote] if pi < i
|
||||
inner = expr.substring(2, expr.length - 1)
|
||||
if inner.length
|
||||
inner = inner.replace new RegExp('\\\\' + quote, 'g'), quote if options.heredoc
|
||||
nested = lexer.tokenize "(#inner)", 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
|
||||
tokens.push ['STRING', "#quote#quote"]
|
||||
tokens.push ['STRING', quote + quote]
|
||||
i += expr.length - 1
|
||||
pi = i + 1
|
||||
i += 1
|
||||
tokens.push ['STRING', "#quote#{ str.substring(pi, i) }#quote"] if pi < i and pi < str.length - 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
|
||||
@@ -434,7 +437,7 @@ exports.Lexer = class Lexer
|
||||
@tokens = @tokens.concat value
|
||||
else if tag is 'STRING' and options.escapeQuotes
|
||||
escaped = value.substring(1, value.length - 1).replace(/"/g, '\\"')
|
||||
@token tag, "\"#escaped\""
|
||||
@token tag, "\"#{escaped}\""
|
||||
else
|
||||
@token tag, value
|
||||
@token '+', '+' if i < tokens.length - 1
|
||||
@@ -490,7 +493,7 @@ JS_KEYWORDS = [
|
||||
"for", "in", "while",
|
||||
"delete", "instanceof", "typeof",
|
||||
"switch", "super", "extends", "class",
|
||||
"this", "null"
|
||||
"this", "null", "debugger"
|
||||
]
|
||||
|
||||
# CoffeeScript-only keywords, which we're more relaxed about allowing. They can't
|
||||
@@ -518,31 +521,47 @@ JS_FORBIDDEN = JS_KEYWORDS.concat RESERVED
|
||||
# Token matching regexes.
|
||||
IDENTIFIER = /^([a-zA-Z\$_](\w|\$)*)/
|
||||
NUMBER = /^(((\b0(x|X)[0-9a-fA-F]+)|((\b[0-9]+(\.[0-9]+)?|\.[0-9]+)(e[+\-]?[0-9]+)?)))\b/i
|
||||
HEREDOC = /^("{6}|'{6}|"{3}\n?([\s\S]*?)\n?([ \t]*)"{3}|'{3}\n?([\s\S]*?)\n?([ \t]*)'{3})/
|
||||
INTERPOLATION = /^#([a-zA-Z_@]\w*(\.\w+)*)/
|
||||
OPERATOR = /^(-[\-=>]?|\+[+=]?|[*&|\/%=<>:!?]+)([ \t]*)/
|
||||
HEREDOC = /^("{6}|'{6}|"{3}([\s\S]*?)\n?([ \t]*)"{3}|'{3}([\s\S]*?)\n?([ \t]*)'{3})/
|
||||
OPERATOR = /^(-[\-=>]?|\+[+=]?|[*&|\/%=<>^:!?]+)([ \t]*)/
|
||||
WHITESPACE = /^([ \t]+)/
|
||||
COMMENT = /^(\s*\#{3}(?!#)[ \t]*\n+([\s\S]*?)[ \t]*\n+[ \t]*\#{3}|(\s*#(?!##[^#])[^\n]*)+)/
|
||||
COMMENT = /^(###([^#][\s\S]*?)(###[ \t]*\n|(###)?$)|(\s*#(?!##[^#])[^\n]*)+)/
|
||||
CODE = /^((-|=)>)/
|
||||
MULTI_DENT = /^((\n([ \t]*))+)(\.)?/
|
||||
LAST_DENTS = /\n([ \t]*)/g
|
||||
LAST_DENT = /\n([ \t]*)/
|
||||
|
||||
# Regex-matching-regexes.
|
||||
REGEX_START = /^\/[^\/ ]/
|
||||
REGEX_INTERPOLATION= /([^\\]#[a-zA-Z_@]|[^\\]#\{.*[^\\]\})/
|
||||
REGEX_END = /^(([imgy]{1,4})\b|\W|$)/
|
||||
REGEX_ESCAPE = /\\[^\$]/g
|
||||
REGEX_START = /^\/([^\/])/
|
||||
REGEX_INTERPOLATION = /([^\\]#\{.*[^\\]\})/
|
||||
REGEX_END = /^(([imgy]{1,4})\b|\W|$)/
|
||||
REGEX_ESCAPE = /\\[^\$]/g
|
||||
|
||||
# Token cleaning regexes.
|
||||
JS_CLEANER = /(^`|`$)/g
|
||||
MULTILINER = /\n/g
|
||||
STRING_NEWLINES = /\n[ \t]*/g
|
||||
NO_NEWLINE = /^([+\*&|\/\-%=<>!.\\][<>=&|]*|and|or|is|isnt|not|delete|typeof|instanceof)$/
|
||||
HEREDOC_INDENT = /(\n+([ \t]*)|^([ \t]+))/g
|
||||
ASSIGNED = /^\s*([a-zA-Z\$_@]\w*[ \t]*?[:=][^=])/
|
||||
ASSIGNED = /^\s*(([a-zA-Z\$_@]\w*|["'][^\r\n]+?["']|\d+)[ \t]*?[:=][^:=])/
|
||||
NEXT_CHARACTER = /^\s*(\S)/
|
||||
|
||||
# Compound assignment tokens.
|
||||
COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|=']
|
||||
|
||||
# Unary tokens.
|
||||
UNARY = ['UMINUS', 'UPLUS', '!', '!!', '~', 'TYPEOF', 'DELETE']
|
||||
|
||||
# Logical tokens.
|
||||
LOGIC = ['&', '|', '^', '&&', '||']
|
||||
|
||||
# Bit-shifting tokens.
|
||||
SHIFT = ['<<', '>>', '>>>']
|
||||
|
||||
# Comparison tokens.
|
||||
COMPARE = ['<=', '<', '>', '>=']
|
||||
|
||||
# Mathmatical tokens.
|
||||
MATH = ['*', '/', '%']
|
||||
|
||||
# Tokens which a regular expression will never immediately follow, but which
|
||||
# a division operator might.
|
||||
#
|
||||
@@ -562,11 +581,10 @@ CALLABLE = ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING', '@', 'THIS', '?', ':
|
||||
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR']
|
||||
|
||||
# Conversions from CoffeeScript operators into JavaScript ones.
|
||||
CONVERSIONS = {
|
||||
CONVERSIONS =
|
||||
'and': '&&'
|
||||
'or': '||'
|
||||
'is': '=='
|
||||
'isnt': '!='
|
||||
'not': '!'
|
||||
'===': '=='
|
||||
}
|
||||
|
||||
595
src/nodes.coffee
595
src/nodes.coffee
File diff suppressed because it is too large
Load Diff
@@ -30,10 +30,11 @@ exports.OptionParser = class OptionParser
|
||||
matchedRule = no
|
||||
for rule in @rules
|
||||
if rule.shortFlag is arg or rule.longFlag is arg
|
||||
options[rule.name] = if rule.hasArgument then args[i += 1] else true
|
||||
value = if rule.hasArgument then args[i += 1] else true
|
||||
options[rule.name] = if rule.isList then (options[rule.name] or []).concat value else value
|
||||
matchedRule = yes
|
||||
break
|
||||
throw new Error "unrecognized option: #arg" if isOption and not matchedRule
|
||||
throw new Error "unrecognized option: #{arg}" if isOption and not matchedRule
|
||||
if not isOption
|
||||
options.arguments = args[i...args.length]
|
||||
break
|
||||
@@ -43,12 +44,12 @@ exports.OptionParser = class OptionParser
|
||||
# of the valid options, for `--help` and such.
|
||||
help: ->
|
||||
lines = ['Available options:']
|
||||
lines.unshift "#@banner\n" if @banner
|
||||
lines.unshift "#{@banner}\n" if @banner
|
||||
for rule in @rules
|
||||
spaces = 15 - rule.longFlag.length
|
||||
spaces = if spaces > 0 then (' ' for i in [0..spaces]).join('') else ''
|
||||
spaces = if spaces > 0 then Array(spaces + 1).join(' ') else ''
|
||||
letPart = if rule.shortFlag then rule.shortFlag + ', ' else ' '
|
||||
lines.push " #letPart#rule.longFlag#spaces#rule.description"
|
||||
lines.push ' ' + letPart + rule.longFlag + spaces + rule.description
|
||||
"\n#{ lines.join('\n') }\n"
|
||||
|
||||
# Helpers
|
||||
@@ -58,7 +59,7 @@ exports.OptionParser = class OptionParser
|
||||
LONG_FLAG = /^(--\w[\w\-]+)/
|
||||
SHORT_FLAG = /^(-\w)/
|
||||
MULTI_FLAG = /^-(\w{2,})/
|
||||
OPTIONAL = /\[(.+)\]/
|
||||
OPTIONAL = /\[(\w+(\*?))\]/
|
||||
|
||||
# Build and return the list of option rules. If the optional *short-flag* is
|
||||
# unspecified, leave it out by padding with `null`.
|
||||
@@ -69,15 +70,17 @@ buildRules = (rules) ->
|
||||
|
||||
# Build a rule from a `-o` short flag, a `--output [DIR]` long flag, and the
|
||||
# description of what the option does.
|
||||
buildRule = (shortFlag, longFlag, description) ->
|
||||
match = longFlag.match(OPTIONAL)
|
||||
longFlag = longFlag.match(LONG_FLAG)[1]
|
||||
buildRule = (shortFlag, longFlag, description, options) ->
|
||||
match = longFlag.match(OPTIONAL)
|
||||
longFlag = longFlag.match(LONG_FLAG)[1]
|
||||
options or= {}
|
||||
{
|
||||
name: longFlag.substr 2
|
||||
shortFlag: shortFlag
|
||||
longFlag: longFlag
|
||||
description: description
|
||||
hasArgument: !!(match and match[1])
|
||||
isList: !!(match and match[2])
|
||||
}
|
||||
|
||||
# Normalize arguments by expanding merged flags into multiple flags. This allows
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# and evaluates it. Good for simple tests, or poking around the **Node.js** API.
|
||||
# Using it looks like this:
|
||||
#
|
||||
# coffee> puts "#num bottles of beer" for num in [99..1]
|
||||
# coffee> puts "#{num} bottles of beer" for num in [99..1]
|
||||
|
||||
# Require the **coffee-script** module to get access to the compiler.
|
||||
CoffeeScript = require './coffee-script'
|
||||
@@ -20,7 +20,7 @@ helpers.extend global, quit: -> process.exit(0)
|
||||
# of exiting.
|
||||
run = (buffer) ->
|
||||
try
|
||||
val = CoffeeScript.run buffer.toString(), noWrap: true, globals: true, fileName: 'repl'
|
||||
val = CoffeeScript.eval buffer.toString(), noWrap: true, globals: true, fileName: 'repl'
|
||||
puts inspect val if val isnt undefined
|
||||
catch err
|
||||
puts err.stack or err.toString()
|
||||
|
||||
@@ -5,15 +5,8 @@
|
||||
# shorthand into the unambiguous long form, add implicit indentation and
|
||||
# parentheses, balance incorrect nestings, and generally clean things up.
|
||||
|
||||
# Set up exported variables for both Node.js and the browser.
|
||||
if process?
|
||||
{helpers} = require('./helpers')
|
||||
else
|
||||
this.exports = this
|
||||
helpers = this.helpers
|
||||
|
||||
# Import the helpers we need.
|
||||
{include} = helpers
|
||||
{include} = require('./helpers').helpers
|
||||
|
||||
# The **Rewriter** class is used by the [Lexer](lexer.html), directly against
|
||||
# its internal array of tokens.
|
||||
@@ -32,8 +25,10 @@ exports.Rewriter = class Rewriter
|
||||
@adjustComments()
|
||||
@removeLeadingNewlines()
|
||||
@removeMidExpressionNewlines()
|
||||
@closeOpenCallsAndIndexes()
|
||||
@closeOpenCalls()
|
||||
@closeOpenIndexes()
|
||||
@addImplicitIndentation()
|
||||
@tagPostfixConditionals()
|
||||
@addImplicitBraces()
|
||||
@addImplicitParentheses()
|
||||
@ensureBalance BALANCED_PAIRS
|
||||
@@ -49,16 +44,27 @@ exports.Rewriter = class Rewriter
|
||||
i = 0
|
||||
loop
|
||||
break unless @tokens[i]
|
||||
move = block @tokens[i - 1], @tokens[i], @tokens[i + 1], i
|
||||
move = block.call this, @tokens[i], i
|
||||
i += move
|
||||
true
|
||||
|
||||
detectEnd: (i, condition, action) ->
|
||||
levels = 0
|
||||
loop
|
||||
token = @tokens[i]
|
||||
return action.call this, token, i if levels is 0 and condition.call this, token, i
|
||||
return action.call this, token, i - 1 if not token or levels < 0
|
||||
levels += 1 if include EXPRESSION_START, token[0]
|
||||
levels -= 1 if include EXPRESSION_END, token[0]
|
||||
i += 1
|
||||
i - 1
|
||||
|
||||
# Massage newlines and indentations so that comments don't have to be
|
||||
# correctly indented, or appear on a line of their own.
|
||||
adjustComments: ->
|
||||
@scanTokens (prev, token, post, i) =>
|
||||
@scanTokens (token, i) ->
|
||||
return 1 unless token[0] is 'HERECOMMENT'
|
||||
[before, after] = [@tokens[i - 2], @tokens[i + 2]]
|
||||
[before, prev, post, after] = [@tokens[i - 2], @tokens[i - 1], @tokens[i + 1], @tokens[i + 2]]
|
||||
if after and after[0] is 'INDENT'
|
||||
@tokens.splice i + 2, 1
|
||||
if before and before[0] is 'OUTDENT' and post and prev[0] is post[0] is 'TERMINATOR'
|
||||
@@ -83,73 +89,60 @@ exports.Rewriter = class Rewriter
|
||||
# Some blocks occur in the middle of expressions -- when we're expecting
|
||||
# this, remove their trailing newlines.
|
||||
removeMidExpressionNewlines: ->
|
||||
@scanTokens (prev, token, post, i) =>
|
||||
return 1 unless post and include(EXPRESSION_CLOSE, post[0]) and token[0] is 'TERMINATOR'
|
||||
@scanTokens (token, i) ->
|
||||
return 1 unless include(EXPRESSION_CLOSE, @tag(i + 1)) and token[0] is 'TERMINATOR'
|
||||
@tokens.splice i, 1
|
||||
return 0
|
||||
|
||||
# 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.
|
||||
closeOpenCallsAndIndexes: ->
|
||||
parens = [0]
|
||||
brackets = [0]
|
||||
@scanTokens (prev, token, post, i) =>
|
||||
switch token[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 ')'
|
||||
if parens[parens.length - 1] is 0
|
||||
parens.pop()
|
||||
token[0] = 'CALL_END'
|
||||
else
|
||||
parens[parens.length - 1] -= 1
|
||||
when ']'
|
||||
if brackets[brackets.length - 1] == 0
|
||||
brackets.pop()
|
||||
token[0] = 'INDEX_END'
|
||||
else
|
||||
brackets[brackets.length - 1] -= 1
|
||||
# The lexer has tagged the opening parenthesis of a method call. Match it with
|
||||
# its paired close. We have the mis-nested outdent case included here for
|
||||
# calls that close on the same line, just before their outdent.
|
||||
closeOpenCalls: ->
|
||||
@scanTokens (token, i) ->
|
||||
if token[0] is 'CALL_START'
|
||||
condition = (token, i) ->
|
||||
(token[0] in [')', 'CALL_END']) or (token[0] is 'OUTDENT' and @tokens[i - 1][0] is ')')
|
||||
action = (token, i) ->
|
||||
idx = if token[0] is 'OUTDENT' then i - 1 else i
|
||||
@tokens[idx][0] = 'CALL_END'
|
||||
@detectEnd i + 1, condition, action
|
||||
return 1
|
||||
|
||||
# The lexer has tagged the opening parenthesis of an indexing operation call.
|
||||
# Match it with its paired close.
|
||||
closeOpenIndexes: ->
|
||||
@scanTokens (token, i) ->
|
||||
if token[0] is 'INDEX_START'
|
||||
condition = (token, i) -> token[0] in [']', 'INDEX_END']
|
||||
action = (token, i) -> token[0] = 'INDEX_END'
|
||||
@detectEnd i + 1, condition, action
|
||||
return 1
|
||||
|
||||
# Object literals may be written with implicit braces, for simple cases.
|
||||
# Insert the missing braces here, so that the parser doesn't have to.
|
||||
addImplicitBraces: ->
|
||||
stack = [0]
|
||||
running = no
|
||||
closeBrackets = (i) =>
|
||||
len = stack.length - 1
|
||||
for tmp in [0...stack[len]]
|
||||
@tokens.splice(i, 0, ['}', '}', @tokens[i][2]])
|
||||
size = stack[len] + 1
|
||||
stack[len] = 0
|
||||
size
|
||||
@scanTokens (prev, token, post, i) =>
|
||||
tag = token[0]
|
||||
len = stack.length - 1
|
||||
before = @tokens[i - 2]
|
||||
after = @tokens[i + 2]
|
||||
open = stack[len] > 0
|
||||
if (tag is 'TERMINATOR' and not ((after and after[0] is ':') or (post and post[0] is '@' and @tokens[i + 3] and @tokens[i + 3][0] is ':'))) or
|
||||
(running and tag is ',' and post and (post[0] not in ['IDENTIFIER', 'STRING', '@', 'TERMINATOR']))
|
||||
running = no
|
||||
return closeBrackets(if post and post[0] is 'OUTDENT' then i + 1 else i)
|
||||
else if include EXPRESSION_START, tag
|
||||
stack.push(if tag is '{' then 1 else 0)
|
||||
return 2 if tag is '{' and post and post[0] is 'INDENT'
|
||||
else if include EXPRESSION_END, tag
|
||||
return 1 if tag is 'OUTDENT' and post and post[0] is '}'
|
||||
size = closeBrackets(i) if tag is 'OUTDENT'
|
||||
stack[len - 1] += stack.pop()
|
||||
stack[len - 1] -= 1 if tag is '}'
|
||||
return size if tag is 'OUTDENT'
|
||||
else if tag is ':' and not open
|
||||
idx = if before and before[0] is '@' then i - 2 else i - 1
|
||||
@tokens.splice idx, 0, ['{', '{', token[2]]
|
||||
stack[stack.length - 1] += 1
|
||||
running = yes
|
||||
stack = []
|
||||
@scanTokens (token, i) ->
|
||||
if include EXPRESSION_START, token[0]
|
||||
stack.push(if (token[0] is 'INDENT' and (@tag(i - 1) is '{')) then '{' else token[0])
|
||||
if include EXPRESSION_END, token[0]
|
||||
stack.pop()
|
||||
last = stack[stack.length - 1]
|
||||
if token[0] is ':' and (not last or last[0] isnt '{')
|
||||
stack.push '{'
|
||||
idx = if @tag(i - 2) is '@' then i - 2 else i - 1
|
||||
idx -= 2 if @tag(idx - 2) is 'HERECOMMENT'
|
||||
tok = ['{', '{', token[2]]
|
||||
tok.generated = yes
|
||||
@tokens.splice idx, 0, tok
|
||||
condition = (token, i) ->
|
||||
[one, two, three] = @tokens.slice(i + 1, i + 4)
|
||||
return false if 'HERECOMMENT' in [@tag(i + 1), @tag(i - 1)]
|
||||
((token[0] in ['TERMINATOR', 'OUTDENT']) and not ((two and two[0] is ':') or (one and one[0] is '@' and three and three[0] is ':'))) or
|
||||
(token[0] is ',' and one and (one[0] not in ['IDENTIFIER', 'STRING', '@', 'TERMINATOR', 'OUTDENT']))
|
||||
action = (token, i) ->
|
||||
@tokens.splice i, 0, ['}', '}', token[2]]
|
||||
@detectEnd i + 2, condition, action
|
||||
return 2
|
||||
return 1
|
||||
|
||||
@@ -157,43 +150,33 @@ exports.Rewriter = class Rewriter
|
||||
# Insert the implicit parentheses here, so that the parser doesn't have to
|
||||
# deal with them.
|
||||
addImplicitParentheses: ->
|
||||
stack = [0]
|
||||
closeCalls = (i) =>
|
||||
for tmp in [0...stack[stack.length - 1]]
|
||||
@tokens.splice(i, 0, ['CALL_END', ')', @tokens[i][2]])
|
||||
size = stack[stack.length - 1] + 1
|
||||
stack[stack.length - 1] = 0
|
||||
size
|
||||
@scanTokens (prev, token, post, i) =>
|
||||
tag = token[0]
|
||||
before = @tokens[i - 2] and @tokens[i - 2][0]
|
||||
stack[stack.length - 2] += stack.pop() if tag is 'OUTDENT'
|
||||
open = stack[stack.length - 1] > 0
|
||||
if prev and prev.spaced and include(IMPLICIT_FUNC, prev[0]) and include(IMPLICIT_CALL, tag) and
|
||||
not (tag is '!' and (post[0] in ['IN', 'OF']))
|
||||
classLine = no
|
||||
@scanTokens (token, i) ->
|
||||
classLine = yes if token[0] is 'CLASS'
|
||||
prev = @tokens[i - 1]
|
||||
next = @tokens[i + 1]
|
||||
idx = 1
|
||||
callObject = not classLine and token[0] is 'INDENT' and next and next.generated and next[0] is '{' and prev and include(IMPLICIT_FUNC, prev[0])
|
||||
idx = 2 if callObject
|
||||
seenSingle = no
|
||||
classLine = no if include(LINEBREAKS, token[0])
|
||||
token.call = yes if prev and not prev.spaced and token[0] is '?'
|
||||
if prev and (prev.spaced and (include(IMPLICIT_FUNC, prev[0]) or prev.call) and include(IMPLICIT_CALL, token[0]) and
|
||||
not (token[0] is 'UNARY' and (@tag(i + 1) in ['IN', 'OF', 'INSTANCEOF']))) or callObject
|
||||
@tokens.splice i, 0, ['CALL_START', '(', token[2]]
|
||||
stack[stack.length - 1] += 1
|
||||
stack.push 0 if include(EXPRESSION_START, tag)
|
||||
condition = (token, i) ->
|
||||
return yes if not seenSingle and token.fromThen
|
||||
seenSingle = yes if token[0] in ['IF', 'ELSE', 'UNLESS', '->', '=>']
|
||||
post = @tokens[i + 1]
|
||||
(not token.generated and @tokens[i - 1][0] isnt ',' and include(IMPLICIT_END, token[0]) and
|
||||
not (token[0] is 'INDENT' and (include(IMPLICIT_BLOCK, @tag(i - 1)) or @tag(i - 2) is 'CLASS' or (post and post.generated and post[0] is '{')))) or
|
||||
token[0] is 'PROPERTY_ACCESS' and @tag(i - 1) is 'OUTDENT'
|
||||
action = (token, i) ->
|
||||
idx = if token[0] is 'OUTDENT' then i + 1 else i
|
||||
@tokens.splice idx, 0, ['CALL_END', ')', token[2]]
|
||||
@detectEnd i + idx, condition, action
|
||||
prev[0] = 'FUNC_EXIST' if prev[0] is '?'
|
||||
return 2
|
||||
if include(EXPRESSION_START, tag)
|
||||
if tag is 'INDENT' and !token.generated and open and not
|
||||
((prev and include(IMPLICIT_BLOCK, prev[0])) or before and before is 'CLASS')
|
||||
size = closeCalls(i)
|
||||
stack.push 0
|
||||
return size
|
||||
stack.push 0
|
||||
return 1
|
||||
if open and !token.generated and prev[0] isnt ',' and (!post or include(IMPLICIT_END, tag))
|
||||
j = 1; j++ while (nx = @tokens[i + j])? and include(IMPLICIT_END, nx[0])
|
||||
if nx? and nx[0] is ',' and @tokens[i + j - 1][0] is 'OUTDENT'
|
||||
@tokens.splice(i, 1) if tag is 'TERMINATOR'
|
||||
else
|
||||
size = closeCalls(i)
|
||||
stack.pop() if tag isnt 'OUTDENT' and include EXPRESSION_END, tag
|
||||
return size
|
||||
if tag isnt 'OUTDENT' and include EXPRESSION_END, tag
|
||||
stack[stack.length - 2] += stack.pop()
|
||||
return 1
|
||||
return 1
|
||||
|
||||
# Because our grammar is LALR(1), it can't handle some single-line
|
||||
@@ -201,46 +184,52 @@ exports.Rewriter = class Rewriter
|
||||
# blocks, so it doesn't need to. ')' can close a single-line block,
|
||||
# but we need to make sure it's balanced.
|
||||
addImplicitIndentation: ->
|
||||
@scanTokens (prev, token, post, i) =>
|
||||
if token[0] is 'ELSE' and prev[0] isnt 'OUTDENT'
|
||||
@scanTokens (token, i) ->
|
||||
if token[0] is 'ELSE' and @tag(i - 1) isnt 'OUTDENT'
|
||||
@tokens.splice i, 0, @indentation(token)...
|
||||
return 2
|
||||
if token[0] is 'CATCH' and
|
||||
(@tokens[i + 2][0] is 'TERMINATOR' or @tokens[i + 2][0] is 'FINALLY')
|
||||
(@tag(i + 2) is 'TERMINATOR' or @tag(i + 2) is 'FINALLY')
|
||||
@tokens.splice i + 2, 0, @indentation(token)...
|
||||
return 4
|
||||
return 1 unless include(SINGLE_LINERS, token[0]) and
|
||||
post[0] isnt 'INDENT' and
|
||||
not (token[0] is 'ELSE' and post[0] is 'IF')
|
||||
starter = token[0]
|
||||
[indent, outdent] = @indentation token
|
||||
indent.generated = outdent.generated = true
|
||||
@tokens.splice i + 1, 0, indent
|
||||
idx = i + 1
|
||||
parens = 0
|
||||
loop
|
||||
idx += 1
|
||||
tok = @tokens[idx]
|
||||
pre = @tokens[idx - 1]
|
||||
if (not tok or
|
||||
(include(SINGLE_CLOSERS, tok[0]) and tok[1] isnt ';' and parens is 0) or
|
||||
(tok[0] is ')' and parens is 0)) and
|
||||
not (tok[0] is 'ELSE' and starter not in ['IF', 'THEN'])
|
||||
insertion = if pre[0] is "," then idx - 1 else idx
|
||||
@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
|
||||
return 0
|
||||
if include(SINGLE_LINERS, token[0]) and @tag(i + 1) isnt 'INDENT' and
|
||||
not (token[0] is 'ELSE' and @tag(i + 1) is 'IF')
|
||||
starter = token[0]
|
||||
[indent, outdent] = @indentation token
|
||||
indent.fromThen = true if starter is 'THEN'
|
||||
indent.generated = outdent.generated = true
|
||||
@tokens.splice i + 1, 0, indent
|
||||
condition = (token, i) ->
|
||||
(include(SINGLE_CLOSERS, token[0]) and token[1] isnt ';') and
|
||||
not (token[0] is 'ELSE' and starter not in ['IF', 'THEN'])
|
||||
action = (token, i) ->
|
||||
idx = if @tokens[i - 1][0] is ',' then i - 1 else i
|
||||
@tokens.splice idx, 0, outdent
|
||||
@detectEnd i + 2, condition, action
|
||||
@tokens.splice i, 1 if token[0] is 'THEN'
|
||||
return 2
|
||||
return 1
|
||||
|
||||
# Tag postfix conditionals as such, so that we can parse them with a
|
||||
# different precedence.
|
||||
tagPostfixConditionals: ->
|
||||
@scanTokens (token, i) ->
|
||||
if token[0] in ['IF', 'UNLESS']
|
||||
original = token
|
||||
condition = (token, i) ->
|
||||
token[0] in ['TERMINATOR', 'INDENT']
|
||||
action = (token, i) ->
|
||||
original[0] = 'POST_' + original[0] if token[0] isnt 'INDENT'
|
||||
@detectEnd i + 1, condition, action
|
||||
return 1
|
||||
return 1
|
||||
|
||||
# Ensure that all listed pairs of tokens are correctly balanced throughout
|
||||
# the course of the token stream.
|
||||
ensureBalance: (pairs) ->
|
||||
levels = {}
|
||||
openLine = {}
|
||||
@scanTokens (prev, token, post, i) =>
|
||||
@scanTokens (token, i) ->
|
||||
for pair in pairs
|
||||
[open, close] = pair
|
||||
levels[open] or= 0
|
||||
@@ -254,7 +243,7 @@ exports.Rewriter = class Rewriter
|
||||
if unclosed.length
|
||||
open = unclosed[0]
|
||||
line = openLine[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:
|
||||
#
|
||||
@@ -276,7 +265,7 @@ exports.Rewriter = class Rewriter
|
||||
stack = []
|
||||
debt = {}
|
||||
(debt[key] = 0) for key, val of INVERSES
|
||||
@scanTokens (prev, token, post, i) =>
|
||||
@scanTokens (token, i) ->
|
||||
tag = token[0]
|
||||
inv = INVERSES[token[0]]
|
||||
if include EXPRESSION_START, tag
|
||||
@@ -307,6 +296,10 @@ exports.Rewriter = class Rewriter
|
||||
indentation: (token) ->
|
||||
[['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]]]
|
||||
|
||||
# Look up a tag by token index.
|
||||
tag: (i) ->
|
||||
@tokens[i] and @tokens[i][0]
|
||||
|
||||
# Constants
|
||||
# ---------
|
||||
|
||||
@@ -331,23 +324,26 @@ EXPRESSION_END = pair[1] for pair in BALANCED_PAIRS
|
||||
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', '@']
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS']
|
||||
|
||||
# If preceded by an `IMPLICIT_FUNC`, indicates a function invocation.
|
||||
IMPLICIT_CALL = [
|
||||
'IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS',
|
||||
'TRY', 'DELETE', 'TYPEOF', 'SWITCH', 'THIS', 'NULL',
|
||||
'IF', 'UNLESS', 'TRY', 'SWITCH', 'THIS', 'NULL', 'UNARY'
|
||||
'TRUE', 'FALSE', 'YES', 'NO', 'ON', 'OFF',
|
||||
'!', '!!', '@', '->', '=>', '[', '(', '{'
|
||||
'@', '->', '=>', '[', '(', '{'
|
||||
]
|
||||
|
||||
# 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.
|
||||
IMPLICIT_END = ['IF', 'UNLESS', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'TERMINATOR', 'INDENT'].concat EXPRESSION_END
|
||||
IMPLICIT_END = ['POST_IF', 'POST_UNLESS', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'TERMINATOR', 'INDENT']
|
||||
|
||||
# Single-line flavors of block expressions that have unclosed endings.
|
||||
# The grammar can't disambiguate them, so we insert the implicit indentation.
|
||||
SINGLE_LINERS = ['ELSE', "->", "=>", 'TRY', 'FINALLY', 'THEN']
|
||||
SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN']
|
||||
|
||||
# Tokens that end a line.
|
||||
LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT']
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# variables are new and need to be declared with `var`, and which are shared
|
||||
# with the outside.
|
||||
|
||||
# Set up exported variables for both **Node.js** and the browser.
|
||||
this.exports = this unless process?
|
||||
# Import the helpers we plan to use.
|
||||
{extend} = require('./helpers').helpers
|
||||
|
||||
exports.Scope = class Scope
|
||||
|
||||
@@ -21,15 +21,24 @@ exports.Scope = class Scope
|
||||
[@parent, @expressions, @method] = [parent, expressions, method]
|
||||
@variables = {}
|
||||
if @parent
|
||||
@tempVar = @parent.tempVar
|
||||
@garbage = @parent.garbage
|
||||
else
|
||||
@garbage = []
|
||||
Scope.root = this
|
||||
@tempVar = '_a'
|
||||
|
||||
# Create a new garbage level
|
||||
startLevel: ->
|
||||
@garbage.push []
|
||||
|
||||
# Return to the previous garbage level and erase referenced temporary
|
||||
# variables in current level from scope.
|
||||
endLevel: ->
|
||||
(@variables[name] = 'reuse') for name in @garbage.pop() when @variables[name] is 'var'
|
||||
|
||||
# Look up a variable name in lexical scope, and declare it if it does not
|
||||
# already exist.
|
||||
find: (name) ->
|
||||
return true if @check name
|
||||
find: (name, options) ->
|
||||
return true if @check name, options
|
||||
@variables[name] = 'var'
|
||||
false
|
||||
|
||||
@@ -44,19 +53,28 @@ exports.Scope = class Scope
|
||||
parameter: (name) ->
|
||||
@variables[name] = 'param'
|
||||
|
||||
# Just check to see if a variable has already been declared, without reserving.
|
||||
check: (name) ->
|
||||
return true if @variables.hasOwnProperty name
|
||||
# Just check to see if a variable has already been declared, without reserving,
|
||||
# walks up to the root scope.
|
||||
check: (name, options) ->
|
||||
immediate = Object::hasOwnProperty.call @variables, name
|
||||
return immediate if immediate or (options and options.immediate)
|
||||
!!(@parent and @parent.check(name))
|
||||
|
||||
# Generate a temporary variable name at the given index.
|
||||
temporary: (type, index) ->
|
||||
if type.length > 1
|
||||
'_' + type + if index > 1 then index else ''
|
||||
else
|
||||
'_' + (index + parseInt type, 36).toString(36).replace /\d/g, 'a'
|
||||
|
||||
# If we need to store an intermediate result, find an available name for a
|
||||
# compiler-generated variable. `_a`, `_b`, and so on...
|
||||
freeVariable: ->
|
||||
while @check @tempVar
|
||||
ordinal = 1 + parseInt @tempVar.substr(1), 36
|
||||
@tempVar = '_' + ordinal.toString(36).replace(/\d/g, 'a')
|
||||
@variables[@tempVar] = 'var'
|
||||
@tempVar
|
||||
# compiler-generated variable. `_var`, `_var2`, and so on...
|
||||
freeVariable: (type) ->
|
||||
index = 0
|
||||
index++ while @check(temp = @temporary type, index) and @variables[temp] isnt 'reuse'
|
||||
@variables[temp] = 'var'
|
||||
@garbage[@garbage.length - 1].push temp if @garbage.length
|
||||
temp
|
||||
|
||||
# Ensure that an assignment is made at the top of this scope
|
||||
# (or at the top-level scope, if requested).
|
||||
@@ -66,7 +84,7 @@ exports.Scope = class Scope
|
||||
# Does this scope reference any variables that need to be declared in the
|
||||
# given function body?
|
||||
hasDeclarations: (body) ->
|
||||
body is @expressions and @any (k, val) -> val is 'var'
|
||||
body is @expressions and @any (k, val) -> val is 'var' or val is 'reuse'
|
||||
|
||||
# Does this scope reference any assignments that need to be declared at the
|
||||
# top of the given function body?
|
||||
@@ -75,17 +93,17 @@ exports.Scope = class Scope
|
||||
|
||||
# Return the list of variables first declared in this scope.
|
||||
declaredVariables: ->
|
||||
(key for key, val of @variables when val is 'var').sort()
|
||||
(key for key, val of @variables when val is 'var' or val is 'reuse').sort()
|
||||
|
||||
# Return the list of assignments that are supposed to be made at the top
|
||||
# of this scope.
|
||||
assignedVariables: ->
|
||||
"#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.
|
||||
compiledDeclarations: ->
|
||||
@declaredVariables().join ', '
|
||||
|
||||
# Compile the JavaScript for all of the variable assignments in this scope.
|
||||
# Compile the JavaScript forall of the variable assignments in this scope.
|
||||
compiledAssignments: ->
|
||||
@assignedVariables().join ', '
|
||||
|
||||
@@ -6,8 +6,8 @@ x1 = y1 = 20
|
||||
|
||||
ok area(x, y, x1, y1) is 100
|
||||
|
||||
ok(area(x, y,
|
||||
x1, y1) is 100)
|
||||
# ok(area(x, y,
|
||||
# x1, y1) is 100)
|
||||
|
||||
ok(area(
|
||||
x
|
||||
|
||||
@@ -8,11 +8,10 @@ ok results.join(' ') is '1 4 9'
|
||||
# Chained blocks, with proper indentation levels:
|
||||
results = []
|
||||
|
||||
counter = {
|
||||
counter =
|
||||
tick: (func) ->
|
||||
results.push func()
|
||||
this
|
||||
}
|
||||
|
||||
counter
|
||||
.tick ->
|
||||
@@ -28,8 +27,8 @@ ok results.join(' ') is '3 2 1'
|
||||
# Make incorrect indentation safe.
|
||||
func = ->
|
||||
obj = {
|
||||
key: 10
|
||||
}
|
||||
key: 10
|
||||
}
|
||||
obj.key - 5
|
||||
|
||||
ok func() is 5
|
||||
@@ -53,3 +52,17 @@ obj
|
||||
)
|
||||
|
||||
ok result is 3
|
||||
|
||||
|
||||
# Test newline-supressed call chains with nested functions.
|
||||
obj =
|
||||
call: -> this
|
||||
func = ->
|
||||
obj
|
||||
.call ->
|
||||
one two
|
||||
.call ->
|
||||
three four
|
||||
101
|
||||
|
||||
ok func() is 101
|
||||
|
||||
@@ -45,3 +45,12 @@ func(
|
||||
[]],
|
||||
[[]]]],
|
||||
[]])
|
||||
|
||||
id = (x) -> x
|
||||
|
||||
greeting = id(
|
||||
"""
|
||||
Hello
|
||||
""")
|
||||
|
||||
ok greeting is "Hello"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Test classes with a four-level inheritance chain.
|
||||
class Base
|
||||
func: (string) ->
|
||||
"zero/#string"
|
||||
"zero/#{string}"
|
||||
|
||||
@static: (string) ->
|
||||
"static/#string"
|
||||
"static/#{string}"
|
||||
|
||||
class FirstChild extends Base
|
||||
func: (string) ->
|
||||
@@ -27,6 +27,13 @@ result = (new ThirdChild).func 'four'
|
||||
ok result is 'zero/one/two/three/four'
|
||||
ok Base.static('word') is 'static/word'
|
||||
|
||||
FirstChild::func = (string) ->
|
||||
super('one/').length + string
|
||||
|
||||
result = (new ThirdChild).func 'four'
|
||||
|
||||
ok result is '9two/three/four'
|
||||
|
||||
|
||||
class TopClass
|
||||
constructor: (arg) ->
|
||||
@@ -48,7 +55,11 @@ class OneClass
|
||||
|
||||
class TwoClass extends OneClass
|
||||
|
||||
ok (new TwoClass('three')).name is 'three'
|
||||
Function.prototype.new = -> new this arguments...
|
||||
|
||||
ok (TwoClass.new('three')).name is 'three'
|
||||
|
||||
delete Function.prototype.new
|
||||
|
||||
|
||||
# And now the same tests, but written in the manual style:
|
||||
@@ -56,7 +67,7 @@ Base = ->
|
||||
Base::func = (string) ->
|
||||
'zero/' + string
|
||||
Base::['func-func'] = (string) ->
|
||||
"dynamic-#string"
|
||||
"dynamic-#{string}"
|
||||
|
||||
FirstChild = ->
|
||||
FirstChild extends Base
|
||||
@@ -131,13 +142,17 @@ ok instance.name() is 'class'
|
||||
|
||||
|
||||
# Classes with methods that are pre-bound to the instance.
|
||||
# ... or statically, to the class.
|
||||
class Dog
|
||||
|
||||
constructor: (name) ->
|
||||
@name = name
|
||||
|
||||
bark: =>
|
||||
"#@name woofs!"
|
||||
"#{@name} woofs!"
|
||||
|
||||
@static: =>
|
||||
new this('Dog')
|
||||
|
||||
spark = new Dog('Spark')
|
||||
fido = new Dog('Fido')
|
||||
@@ -145,6 +160,10 @@ fido.bark = spark.bark
|
||||
|
||||
ok fido.bark() is 'Spark woofs!'
|
||||
|
||||
obj = func: Dog.static
|
||||
|
||||
ok obj.func().name is 'Dog'
|
||||
|
||||
|
||||
# Testing a bound function in a bound function.
|
||||
class Mini
|
||||
@@ -164,7 +183,7 @@ class Connection
|
||||
[@one, @two, @three] = [one, two, three]
|
||||
|
||||
out: ->
|
||||
"#@one-#@two-#@three"
|
||||
"#{@one}-#{@two}-#{@three}"
|
||||
|
||||
list = [3, 2, 1]
|
||||
conn = new Connection list...
|
||||
@@ -199,13 +218,13 @@ class Element extends Base
|
||||
@node = node
|
||||
|
||||
ok Element.extended is Base.extended
|
||||
ok Element.__superClass__ is Base.prototype
|
||||
ok Element.__super__ is Base.prototype
|
||||
|
||||
class MyElement extends Element
|
||||
|
||||
ok MyElement.extended is Base.extended
|
||||
ok MyElement.fromHTML is Element.fromHTML
|
||||
ok MyElement.__superClass__ is Element.prototype
|
||||
ok MyElement.__super__ is Element.prototype
|
||||
|
||||
|
||||
# Test classes wrapped in decorators.
|
||||
@@ -226,4 +245,14 @@ obj =
|
||||
method: -> 'value'
|
||||
|
||||
instance = new obj.klass
|
||||
ok instance.method() is 'value'
|
||||
ok instance.method() is 'value'
|
||||
|
||||
|
||||
# Implicit objects as static properties.
|
||||
class Static
|
||||
@static:
|
||||
one: 1
|
||||
two: 2
|
||||
|
||||
ok Static.static.one is 1
|
||||
ok Static.static.two is 2
|
||||
|
||||
@@ -144,3 +144,23 @@ fn = ->
|
||||
###
|
||||
|
||||
fn2 = ->
|
||||
|
||||
|
||||
class A
|
||||
b: ->
|
||||
|
||||
###
|
||||
Comment
|
||||
###
|
||||
c: ->
|
||||
|
||||
ok A.prototype.c instanceof Function
|
||||
|
||||
class A
|
||||
###
|
||||
Comment
|
||||
###
|
||||
b: ->
|
||||
c: ->
|
||||
|
||||
ok A.prototype.b instanceof Function
|
||||
|
||||
@@ -12,3 +12,4 @@ CoffeeScript.run("resultArray.push i for i of global", {noWrap: on, globals: on,
|
||||
|
||||
ok 'setInterval' in global.resultArray
|
||||
|
||||
ok 'passed' is CoffeeScript.eval '"passed"', noWrap: on, globals: on, fileName: 'tests'
|
||||
|
||||
@@ -71,6 +71,13 @@ ok obj.two() is "I'm two"
|
||||
ok obj.three() is "I'm three"
|
||||
|
||||
|
||||
# Ensure that local variables are closed over for range comprehensions.
|
||||
funcs = for i in [1..3]
|
||||
-> -i
|
||||
|
||||
ok (func() for func in funcs).join(' ') is '-1 -2 -3'
|
||||
|
||||
|
||||
# Even when referenced in the filter.
|
||||
list = ['one', 'two', 'three']
|
||||
|
||||
@@ -134,3 +141,14 @@ ok all.sort().join(' ') is 'Whiskers cream tabby'
|
||||
exxes = 'x' for [0...10]
|
||||
ok exxes.join(' ') is 'x x x x x x x x x x'
|
||||
|
||||
|
||||
# Comprehensions safely redeclare parameters if they're not present in closest
|
||||
# scope.
|
||||
rule = (x) -> x
|
||||
|
||||
learn = ->
|
||||
rule for rule in [1, 2, 3]
|
||||
|
||||
ok learn().join(' ') is '1 2 3'
|
||||
|
||||
ok rule(101) is 101
|
||||
@@ -17,9 +17,15 @@ ok a is 10 and b is 10
|
||||
# The existential operator.
|
||||
z = null
|
||||
x = z ? "EX"
|
||||
|
||||
ok z is null and x is "EX"
|
||||
|
||||
i = 9
|
||||
func = -> i += 1
|
||||
result = func() ? 101
|
||||
ok result is 10
|
||||
|
||||
ok (non ? existent ? variables ? 1) is 1
|
||||
|
||||
|
||||
# Only evaluate once.
|
||||
counter = 0
|
||||
@@ -69,6 +75,24 @@ result = value?.toString().toLowerCase()
|
||||
|
||||
ok result is '10'
|
||||
|
||||
ok(process.exit.nothing?.property() or 101)
|
||||
|
||||
counter = 0
|
||||
func = ->
|
||||
counter += 1
|
||||
'prop'
|
||||
obj =
|
||||
prop: -> this
|
||||
value: 25
|
||||
|
||||
ok obj[func()]()[func()]()[func()]()?.value is 25
|
||||
ok counter is 3
|
||||
|
||||
|
||||
# Soaks inner values.
|
||||
ident = (obj) -> obj
|
||||
ok ident(non?.existent().method()) is undefined
|
||||
|
||||
|
||||
# Soaks constructor invocations.
|
||||
a = 0
|
||||
@@ -98,3 +122,28 @@ ok x is - 1
|
||||
# Things that compile to ternaries should force parentheses, like operators do.
|
||||
duration = if options?.animated then 150 else 0
|
||||
ok duration is 0
|
||||
|
||||
|
||||
# Function soaks.
|
||||
plus1 = (x) -> x + 1
|
||||
count = 0
|
||||
obj = {
|
||||
counter: -> count += 1; this
|
||||
returnThis: -> this
|
||||
}
|
||||
|
||||
ok plus1?(41) is 42
|
||||
ok (plus1? 41) is 42
|
||||
ok plus2?(41) is undefined
|
||||
ok (plus2? 41) is undefined
|
||||
ok obj.returnThis?() is obj
|
||||
ok obj.counter().counter().returnThis?() is obj
|
||||
ok count is 2
|
||||
|
||||
maybe_close = (f, arg) -> if typeof f is 'function' then () -> f(arg) else -1
|
||||
|
||||
ok maybe_close(plus1, 41)?() is 42
|
||||
ok (maybe_close plus1, 41)?() is 42
|
||||
ok (maybe_close 'string', 41)?() is undefined
|
||||
|
||||
ok 2?(3) is undefined
|
||||
|
||||
@@ -25,4 +25,16 @@ obj = {
|
||||
}
|
||||
|
||||
ok obj.num is obj.func()
|
||||
ok obj.num is obj.result
|
||||
ok obj.num is obj.result
|
||||
|
||||
|
||||
# Should be able to look at prototypes on keywords.
|
||||
obj =
|
||||
withAt: -> @::prop
|
||||
withThis: -> this::prop
|
||||
proto:
|
||||
prop: 100
|
||||
|
||||
obj.prototype = obj.proto
|
||||
ok obj.withAt() is 100
|
||||
ok obj.withThis() is 100
|
||||
@@ -220,3 +220,34 @@ obj =
|
||||
ok obj.func(101, 102, 103, 104) is undefined
|
||||
ok obj.param is 101
|
||||
ok obj.rest.join(' ') is '102 103 104'
|
||||
|
||||
|
||||
# `@` and `this` should both be able to invoke a method.
|
||||
func = (arg) -> ok arg is true
|
||||
func.withAt = -> @ true
|
||||
func.withThis = -> this true
|
||||
|
||||
func.withAt()
|
||||
func.withThis()
|
||||
|
||||
|
||||
# Ensure that constructors invoked with splats return a new object.
|
||||
args = [1, 2, 3]
|
||||
Type = (@args) ->
|
||||
type = new Type args
|
||||
|
||||
ok type and type instanceof Type
|
||||
ok type.args and type.args instanceof Array
|
||||
ok v is args[i] for v, i in type.args
|
||||
|
||||
Type1 = (@a, @b, @c) ->
|
||||
type1 = new Type1 args...
|
||||
|
||||
ok type1 and type1 instanceof Type1
|
||||
ok type1.a is args[0] and type1.b is args[1] and type1.c is args[2]
|
||||
|
||||
|
||||
# Ensure that constructors invoked with splats cache the function.
|
||||
called = 0
|
||||
get = -> if called++ then false else class Type
|
||||
new get() args...
|
||||
|
||||
@@ -15,6 +15,15 @@ a = '''
|
||||
ok a is "a\n \"b\nc"
|
||||
|
||||
|
||||
a = """
|
||||
a
|
||||
b
|
||||
c
|
||||
"""
|
||||
|
||||
ok a is "a\n b\n c"
|
||||
|
||||
|
||||
a = '''one-liner'''
|
||||
|
||||
ok a is 'one-liner'
|
||||
@@ -55,17 +64,17 @@ ok a is 'more"than"one"quote'
|
||||
val = 10
|
||||
|
||||
a = """
|
||||
basic heredoc #val
|
||||
basic heredoc #{val}
|
||||
on two lines
|
||||
"""
|
||||
|
||||
b = '''
|
||||
basic heredoc #val
|
||||
basic heredoc #{val}
|
||||
on two lines
|
||||
'''
|
||||
|
||||
ok a is "basic heredoc 10\non two lines"
|
||||
ok b is "basic heredoc \#val\non two lines"
|
||||
ok b is "basic heredoc \#{val}\non two lines"
|
||||
|
||||
|
||||
a = '''here's an apostrophe'''
|
||||
|
||||
@@ -64,10 +64,20 @@ ok result is undefined
|
||||
|
||||
# Return an if with no else.
|
||||
func = ->
|
||||
return (if false then callback())
|
||||
return if false then callback()
|
||||
|
||||
ok func() is null
|
||||
|
||||
func = ->
|
||||
return unless false then 100 else -100
|
||||
|
||||
ok func() is 100
|
||||
|
||||
ident = (x) -> x
|
||||
result = ident if false then 300 else 100
|
||||
|
||||
ok result is 100
|
||||
|
||||
|
||||
# If-to-ternary with instanceof requires parentheses (no comment).
|
||||
if {} instanceof Object
|
||||
@@ -80,3 +90,43 @@ try
|
||||
ok yes
|
||||
catch e
|
||||
ok no
|
||||
|
||||
|
||||
# If-to-ternary as part of a larger operation requires parens.
|
||||
x = 1
|
||||
result = x + if false then 10 else 1
|
||||
ok result is 2
|
||||
|
||||
|
||||
# If/else indented within an assignment.
|
||||
func = ->
|
||||
a =
|
||||
if false
|
||||
3
|
||||
else
|
||||
5
|
||||
101
|
||||
a
|
||||
|
||||
ok func() is 5
|
||||
|
||||
|
||||
# Unmatched 'then' should catch implicit calls.
|
||||
i = 1
|
||||
isTrue = (x) -> x is true
|
||||
|
||||
if isTrue yes then i += 1
|
||||
|
||||
ok i is 2
|
||||
|
||||
# If/else with a suppressed indentation via assignment.
|
||||
result =
|
||||
if false then 10
|
||||
else if no then 20
|
||||
else if 0 then 30
|
||||
else if NaN then 40
|
||||
else 50 +
|
||||
if false then 10
|
||||
else 20
|
||||
|
||||
ok result is 70
|
||||
|
||||
@@ -54,14 +54,14 @@ trailingComma = {k1: "v1", k2: 4, k3: (-> true),}
|
||||
ok trailingComma.k3() and (trailingComma.k2 is 4) and (trailingComma.k1 is "v1")
|
||||
|
||||
|
||||
money$ = 'dollars'
|
||||
money$ = '(((dollars)))'
|
||||
|
||||
ok money$ is 'dollars'
|
||||
ok money$ is '\(\(\(dollars\)\)\)'
|
||||
|
||||
|
||||
multiline = "one
|
||||
two
|
||||
three"
|
||||
two
|
||||
three"
|
||||
|
||||
ok multiline is 'one two three'
|
||||
|
||||
@@ -96,6 +96,10 @@ ok obj.is()
|
||||
ok not obj.not()
|
||||
|
||||
|
||||
# Top-level object literal doesn't break things.
|
||||
obj: 1
|
||||
|
||||
|
||||
# Funky indentation within non-comma-seperated arrays.
|
||||
result = [['a']
|
||||
{b: 'c'}]
|
||||
@@ -161,9 +165,31 @@ ok obj.options.value is yes
|
||||
ok obj.fn() is null
|
||||
|
||||
|
||||
# Implicit arguments to function calls:
|
||||
func = (obj) -> obj.a
|
||||
|
||||
result = func
|
||||
a: 10
|
||||
|
||||
ok result is 10
|
||||
|
||||
result = func
|
||||
"a": 20
|
||||
|
||||
ok result is 20
|
||||
|
||||
third = (a, b, c) -> c
|
||||
obj =
|
||||
one: 'one'
|
||||
two: third 'one', 'two', 'three'
|
||||
|
||||
ok obj.one is 'one'
|
||||
ok obj.two is 'three'
|
||||
|
||||
|
||||
# Implicit objects with wacky indentation:
|
||||
obj =
|
||||
reverse: (obj) ->
|
||||
'reverse': (obj) ->
|
||||
Array.prototype.reverse.call obj
|
||||
abc: ->
|
||||
@reverse(
|
||||
@@ -189,4 +215,27 @@ ok obj.one[2].a is 'b'
|
||||
ok (key for key of obj.red).length is 2
|
||||
ok obj.red.orange.yellow.green is 'blue'
|
||||
ok obj.red.indigo is 'violet'
|
||||
ok obj.misdent.toString() is ',,,'
|
||||
ok obj.misdent.toString() is ',,,'
|
||||
|
||||
second = (x, y) -> y
|
||||
obj = then second 'the',
|
||||
1: 1
|
||||
two:
|
||||
three: ->
|
||||
four five,
|
||||
six: seven
|
||||
three: 3
|
||||
|
||||
ok obj[1] is 1
|
||||
ok obj.three is 3
|
||||
|
||||
|
||||
# Implicit objects as part of chained calls.
|
||||
identity = (x) -> x.a
|
||||
|
||||
b = identity identity identity
|
||||
a:
|
||||
a:
|
||||
a: 100
|
||||
|
||||
ok b is 100
|
||||
|
||||
@@ -93,4 +93,68 @@ ok list.join(' ') is '0 5 10'
|
||||
count = 0
|
||||
|
||||
list[key()] ?= 100
|
||||
ok list.join(' ') is '0 100 5 10'
|
||||
ok list.join(' ') is '0 100 5 10'
|
||||
|
||||
count = 0
|
||||
key = ->
|
||||
count += 1
|
||||
key
|
||||
|
||||
key().val or= 100
|
||||
|
||||
ok key.val is 100
|
||||
ok count is 1
|
||||
|
||||
key().val ?= 200
|
||||
|
||||
ok key.val is 100
|
||||
ok count is 2
|
||||
|
||||
|
||||
# Ensure that RHS is treated as a group.
|
||||
a = b = false
|
||||
a and= b or true
|
||||
ok a is false
|
||||
|
||||
|
||||
# Bitwise operators:
|
||||
ok (10 & 3) is 2
|
||||
ok (10 | 3) is 11
|
||||
ok (10 ^ 3) is 9
|
||||
ok (10 << 3) is 80
|
||||
ok (10 >> 3) is 1
|
||||
ok (10 >>> 3) is 1
|
||||
|
||||
num = 10; ok (num <<= 3) is 80
|
||||
num = 10; ok (num >>= 3) is 1
|
||||
num = 10; ok (num >>>= 3) is 1
|
||||
num = 10; ok (num &= 3) is 2
|
||||
num = 10; ok (num ^= 3) is 9
|
||||
num = 10; ok (num |= 3) is 11
|
||||
|
||||
|
||||
# Compound assignment with implicit objects.
|
||||
obj = undefined
|
||||
obj ?=
|
||||
one: 1
|
||||
|
||||
ok obj.one is 1
|
||||
|
||||
obj and=
|
||||
two: 2
|
||||
|
||||
ok not obj.one
|
||||
ok obj.two is 2
|
||||
|
||||
|
||||
# Compound assignment as a sub expression.
|
||||
[a, b, c] = [1, 2, 3]
|
||||
ok (a + b += c) is 6
|
||||
ok a is 1
|
||||
ok b is 5
|
||||
ok c is 3
|
||||
|
||||
|
||||
# Instanceof.
|
||||
ok new String instanceof String
|
||||
ok new Number not instanceof String
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
opt = new OptionParser [
|
||||
['-r', '--required [DIR]', 'desc required']
|
||||
['-o', '--optional', 'desc optional']
|
||||
['-l', '--list [FILES*]', 'desc list']
|
||||
]
|
||||
|
||||
result = opt.parse ['one', 'two', 'three', '-r', 'dir']
|
||||
@@ -18,3 +19,9 @@ ok result.optional is true
|
||||
ok result.required is 'folder'
|
||||
ok result.arguments.join(' ') is 'one two'
|
||||
|
||||
result = opt.parse ['-l', 'one.txt', '-l', 'two.txt', 'three']
|
||||
|
||||
ok result.list instanceof Array
|
||||
ok result.list.join(' ') is 'one.txt two.txt'
|
||||
ok result.arguments.join(' ') is 'three'
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ persons = {
|
||||
Christopher: { name: "Stan" }
|
||||
}
|
||||
|
||||
join1 = "#key: #name" for key, { name } of persons
|
||||
join1 = "#{key}: #{name}" for key, { name } of persons
|
||||
|
||||
deepEqual join1, ["George: Bob", "Bob: Alice", "Christopher: Stan"]
|
||||
|
||||
@@ -129,11 +129,21 @@ persons = [
|
||||
{ name: "Stan", parent: { name: "Christopher" } }
|
||||
]
|
||||
|
||||
join2 = "#parent: #name" for { name, parent: { name: parent } } in persons
|
||||
join2 = "#{parent}: #{name}" for { name, parent: { name: parent } } in persons
|
||||
|
||||
deepEqual join1, join2
|
||||
|
||||
persons = [['Bob', ['George']], ['Alice', ['Bob']], ['Stan', ['Christopher']]]
|
||||
join3 = "#parent: #name" for [name, [parent]] in persons
|
||||
join3 = "#{parent}: #{name}" for [name, [parent]] in persons
|
||||
|
||||
deepEqual join2, join3
|
||||
|
||||
|
||||
# Pattern matching doesn't clash with implicit block objects.
|
||||
obj = a: 101
|
||||
func -> true
|
||||
|
||||
if func func
|
||||
{a} = obj
|
||||
|
||||
ok a is 101
|
||||
|
||||
@@ -56,3 +56,20 @@ array[5..10] = [0, 0, 0]
|
||||
ok array.join(' ') is '0 1 2 3 4 0 0 0'
|
||||
|
||||
|
||||
# Slices and splices that omit their beginning or end.
|
||||
array = [0..10]
|
||||
|
||||
ok array[7..].join(' ') is '7 8 9 10'
|
||||
ok array[-2..].join(' ') is '9 10'
|
||||
|
||||
ok array[...3].join(' ') is '0 1 2'
|
||||
ok array[..-5].join(' ') is '0 1 2 3 4 5 6'
|
||||
|
||||
array[3..] = [9, 8, 7]
|
||||
|
||||
ok array.join(' ') is '0 1 2 9 8 7'
|
||||
|
||||
array[...3] = [7, 8, 9]
|
||||
|
||||
ok array.join(' ') is '7 8 9 9 8 7'
|
||||
|
||||
|
||||
@@ -4,17 +4,17 @@ name = 'Moe'
|
||||
ok not not '"Moe"'.match(/^"#{name}"$/i)
|
||||
ok '"Moe!"'.match(/^"#{name}"$/i) is null
|
||||
|
||||
ok not not 'Moe'.match(/^#name$/)
|
||||
ok 'Moe!'.match(/^#name/)
|
||||
ok not not 'Moe'.match(/^#{name}$/)
|
||||
ok 'Moe!'.match(/^#{name}/)
|
||||
|
||||
ok 'Moe!'.match(/#{"#{"#{"#name"}"}"}/imgy)
|
||||
ok 'Moe!'.match(/#{"#{"#{"#{name}"}"}"}/imgy)
|
||||
|
||||
ok '$a$b$c'.match(/\$A\$B\$C/i)
|
||||
|
||||
a = 1
|
||||
b = 2
|
||||
c = 3
|
||||
ok '123'.match(/#a#b#c/i)
|
||||
ok '123'.match(/#{a}#{b}#{c}/i)
|
||||
|
||||
[a, b, c] = [1, 2, /\d+/]
|
||||
ok (/#a#b#c$/i).toString() is '/12/\\d+/$/i'
|
||||
ok (/#{a}#{b}#{c}$/i).toString() is '/12/\\d+/$/i'
|
||||
|
||||
@@ -20,4 +20,9 @@ obj = {
|
||||
}
|
||||
id = 2
|
||||
|
||||
ok ' '.match(/ /)[0] is ' '
|
||||
|
||||
regexp = / /
|
||||
ok ' '.match regexp
|
||||
|
||||
ok (obj.width()/id - obj.height()/id) is -5
|
||||
|
||||
@@ -1,45 +1,31 @@
|
||||
hello = 'Hello'
|
||||
world = 'World'
|
||||
ok '#hello #world!' is '#hello #world!'
|
||||
ok '#{hello} #{world}!' is '#{hello} #{world}!'
|
||||
ok "#hello #world!" is 'Hello World!'
|
||||
ok "#{hello} #{world}!" is 'Hello World!'
|
||||
ok "[#hello#world]" is '[HelloWorld]'
|
||||
ok "[#{hello}#{world}]" is '[HelloWorld]'
|
||||
ok "#hello##world" is 'Hello#World'
|
||||
ok "#{hello}##{world}" is 'Hello#World'
|
||||
ok "Hello #{ 1 + 2 } World" is 'Hello 3 World'
|
||||
ok "#hello #{ 1 + 2 } #world" is "Hello 3 World"
|
||||
ok "#{hello} #{ 1 + 2 } #{world}" is "Hello 3 World"
|
||||
|
||||
|
||||
[s, t, r, i, n, g] = ['s', 't', 'r', 'i', 'n', 'g']
|
||||
ok "#s#t#r#i#n#g" is 'string'
|
||||
ok "#{s}#{t}#{r}#{i}#{n}#{g}" is 'string'
|
||||
ok "\#s\#t\#r\#i\#n\#g" is '#s#t#r#i#n#g'
|
||||
ok "\\#s\\#t\\#r\\#i\\#n\\#g" is '\\s\\t\\r\\i\\n\\g'
|
||||
ok "\#{s}\#{t}\#{r}\#{i}\#{n}\#{g}" is '#{s}#{t}#{r}#{i}#{n}#{g}'
|
||||
ok "\#string" is '#string'
|
||||
ok "\#{string}" is '#{string}'
|
||||
|
||||
|
||||
ok "\#Escaping first" is '#Escaping first'
|
||||
ok "\#{Escaping} first" is '#{Escaping} first'
|
||||
ok "Escaping \#in middle" is 'Escaping #in middle'
|
||||
ok "Escaping \#{in} middle" is 'Escaping #{in} middle'
|
||||
ok "Escaping \#last" is 'Escaping #last'
|
||||
ok "Escaping \#{last}" is 'Escaping #{last}'
|
||||
|
||||
|
||||
ok "##" is '##'
|
||||
ok "#{}" is ''
|
||||
ok "#{}A#{} #{} #{}B#{}" is 'A B'
|
||||
ok "\\\\\##" is '\\\\\##'
|
||||
ok "\\\#{}" is '\\#{}'
|
||||
|
||||
|
||||
ok "I won #20 last night." is 'I won #20 last night.'
|
||||
ok "I won ##{20} last night." is 'I won #20 last night.'
|
||||
ok "I won ##20 last night." is 'I won ##20 last night.'
|
||||
ok "I won ##{'#20'} last night." is 'I won ##20 last night.'
|
||||
|
||||
|
||||
@@ -54,8 +40,8 @@ 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')
|
||||
hi: -> "Hello #{@name}."
|
||||
cya: -> "Hello #{@name}.".replace('Hello','Goodbye')
|
||||
}
|
||||
ok obj.hi() is "Hello Joe."
|
||||
ok obj.cya() is "Goodbye Joe."
|
||||
@@ -65,10 +51,9 @@ ok "With #{"quotes"}" is 'With quotes'
|
||||
ok 'With #{"quotes"}' is 'With #{"quotes"}'
|
||||
|
||||
ok "Where is #{obj["name"] + '?'}" is 'Where is Joe?'
|
||||
ok "Where is #obj.name?" is 'Where is Joe?'
|
||||
|
||||
ok "Where is #{"the nested #{obj["name"]}"}?" is 'Where is the nested Joe?'
|
||||
ok "Hello #{world ? "#hello"}" is 'Hello World'
|
||||
ok "Hello #{world ? "#{hello}"}" is 'Hello World'
|
||||
|
||||
ok "Hello #{"#{"#{obj["name"]}" + '!'}"}" is 'Hello Joe!'
|
||||
|
||||
@@ -82,7 +67,7 @@ ok a is "Hello Joe"
|
||||
a = 1
|
||||
b = 2
|
||||
c = 3
|
||||
ok "#a#b#c" is '123'
|
||||
ok "#{a}#{b}#{c}" is '123'
|
||||
|
||||
|
||||
result = null
|
||||
|
||||
Reference in New Issue
Block a user