mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-01-14 09:17:55 -05:00
Compare commits
465 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
677c7edf3f | ||
|
|
e56af4967c | ||
|
|
1f7af35368 | ||
|
|
08ab4abd43 | ||
|
|
a810eb29db | ||
|
|
3881324007 | ||
|
|
af3b356d70 | ||
|
|
24676eea71 | ||
|
|
7e2eb997a8 | ||
|
|
ec570c46bf | ||
|
|
8eedfe4bc6 | ||
|
|
800fb81d1b | ||
|
|
e020f5849c | ||
|
|
698784e103 | ||
|
|
f7345ffaac | ||
|
|
b7faa4a7f2 | ||
|
|
0fcfb80be4 | ||
|
|
38a9b7166b | ||
|
|
3b28f52ff7 | ||
|
|
7725fe338e | ||
|
|
2ed66f6e8b | ||
|
|
9aaf789c21 | ||
|
|
d5cf339b83 | ||
|
|
6bc7b56e6e | ||
|
|
e4db6d47c2 | ||
|
|
ce4e00e5ae | ||
|
|
06ca2ef726 | ||
|
|
8d853a6d58 | ||
|
|
de768aefc3 | ||
|
|
4b284f6687 | ||
|
|
d0948e5586 | ||
|
|
b0a45e5b93 | ||
|
|
6f91331626 | ||
|
|
4ecb1bb2ed | ||
|
|
3bcca99cba | ||
|
|
5612a59b30 | ||
|
|
88ea66b4c9 | ||
|
|
b61399fbde | ||
|
|
a8db2bcf10 | ||
|
|
e14f4c5db1 | ||
|
|
1948b0c7c7 | ||
|
|
4b4b0e630e | ||
|
|
d9071a80a0 | ||
|
|
969740a263 | ||
|
|
0222d90fa3 | ||
|
|
a133e018cc | ||
|
|
c2d1ae06c5 | ||
|
|
59e41f195b | ||
|
|
7987d4e5ce | ||
|
|
a8e331a778 | ||
|
|
eb97652537 | ||
|
|
0a4fe7ed97 | ||
|
|
676e893c14 | ||
|
|
e37056192b | ||
|
|
8321f6bfe3 | ||
|
|
b3d1c238eb | ||
|
|
61d9bd7e5e | ||
|
|
1fbb6e8734 | ||
|
|
59de6b505a | ||
|
|
ea1411cd07 | ||
|
|
c5fd64c72a | ||
|
|
45f442bd73 | ||
|
|
b8a4adbdc7 | ||
|
|
47fdcebb01 | ||
|
|
8cdd8de360 | ||
|
|
7402aea9f2 | ||
|
|
300c711af1 | ||
|
|
39b8bbc39b | ||
|
|
90f96af720 | ||
|
|
710b2b5fdc | ||
|
|
a577b81eb3 | ||
|
|
a5478b0712 | ||
|
|
12587d8295 | ||
|
|
e17bb4ff11 | ||
|
|
aba19841ee | ||
|
|
0288dba46c | ||
|
|
5a306785ba | ||
|
|
c200b95f6a | ||
|
|
2cccd621ea | ||
|
|
385b18f588 | ||
|
|
bf1f9f4b95 | ||
|
|
4c3271728d | ||
|
|
57231ae75d | ||
|
|
97c2a70593 | ||
|
|
485346f0e5 | ||
|
|
a8d4c3a567 | ||
|
|
dfb3a13246 | ||
|
|
f84eb9ed47 | ||
|
|
8136c5f3de | ||
|
|
45669e08c6 | ||
|
|
a5db69e1af | ||
|
|
8aceef20e1 | ||
|
|
7e3c71ed19 | ||
|
|
9d09bee6fb | ||
|
|
cd6ee373ff | ||
|
|
4d0acc9b02 | ||
|
|
393fbf1b66 | ||
|
|
3324b03a5d | ||
|
|
eb91f9922d | ||
|
|
9a7420ccd0 | ||
|
|
be72120311 | ||
|
|
c452c3a101 | ||
|
|
0b3bb66708 | ||
|
|
d0d0fa4d10 | ||
|
|
6222ed622f | ||
|
|
1a03e98057 | ||
|
|
46cea93fc3 | ||
|
|
d64b8fd9d8 | ||
|
|
c051daee2f | ||
|
|
ae70d10996 | ||
|
|
52e6399e02 | ||
|
|
ac05f62f2f | ||
|
|
4d935efd09 | ||
|
|
fa8cc7976a | ||
|
|
ee4e34bf6d | ||
|
|
c8e0f8b149 | ||
|
|
b47188763c | ||
|
|
5e5c9df5c4 | ||
|
|
1a97f599dd | ||
|
|
3b264c9572 | ||
|
|
144c096ae6 | ||
|
|
adbcd320b2 | ||
|
|
17ba44056e | ||
|
|
502abade7c | ||
|
|
b746c9018e | ||
|
|
92af641827 | ||
|
|
b5606a247d | ||
|
|
d62baf5a5d | ||
|
|
e17567866a | ||
|
|
76f9596f22 | ||
|
|
2a3a713811 | ||
|
|
175ebb3cd8 | ||
|
|
95367a4a63 | ||
|
|
8950c3c4c8 | ||
|
|
2d1abd099d | ||
|
|
a894db35fd | ||
|
|
328a14014c | ||
|
|
315a2c63fa | ||
|
|
ca4ea7649d | ||
|
|
08c877ec7b | ||
|
|
212ad45be4 | ||
|
|
e9b37c7578 | ||
|
|
1438cecfad | ||
|
|
49824ce1a6 | ||
|
|
bc0ec9dc07 | ||
|
|
5957b9f155 | ||
|
|
72e6e828f1 | ||
|
|
01b4393fa7 | ||
|
|
bf2a5386f9 | ||
|
|
fb4d4a609b | ||
|
|
1cddb2aa88 | ||
|
|
aac9679282 | ||
|
|
90472685e8 | ||
|
|
7bb764b3e4 | ||
|
|
1aed9c545f | ||
|
|
c937e49689 | ||
|
|
0d860516ac | ||
|
|
4ced1d65b4 | ||
|
|
92540d5e85 | ||
|
|
ea982a627e | ||
|
|
835ecac8db | ||
|
|
c3bbb48041 | ||
|
|
2e842f0146 | ||
|
|
8de2fb9009 | ||
|
|
17e177405a | ||
|
|
ef67561fb3 | ||
|
|
df97effb9c | ||
|
|
8317960f81 | ||
|
|
065bf54094 | ||
|
|
f36acc27e5 | ||
|
|
491ad6de95 | ||
|
|
3eedf8ed1b | ||
|
|
75b260e495 | ||
|
|
2351948291 | ||
|
|
538e518d76 | ||
|
|
de955dacc4 | ||
|
|
19ed63129e | ||
|
|
2e744a1c1b | ||
|
|
89534b88b1 | ||
|
|
c067808b54 | ||
|
|
59ae79d8fb | ||
|
|
ad1c5e1884 | ||
|
|
9958cedd89 | ||
|
|
d1aaed4430 | ||
|
|
89debc87b2 | ||
|
|
9d2c81ea54 | ||
|
|
44765907b3 | ||
|
|
4a85f3d499 | ||
|
|
f99b5ad463 | ||
|
|
8fc631269b | ||
|
|
a1975583a7 | ||
|
|
1c628e7883 | ||
|
|
3605168e85 | ||
|
|
f86fca2739 | ||
|
|
0410748e2d | ||
|
|
2172878f21 | ||
|
|
d3a51fbfa1 | ||
|
|
aae2405de4 | ||
|
|
2b578367a9 | ||
|
|
f9b028b78c | ||
|
|
572aa4e98f | ||
|
|
864275f07e | ||
|
|
998a7c8cb0 | ||
|
|
6d7a04228f | ||
|
|
4a8c2e8a13 | ||
|
|
f3a60edc5d | ||
|
|
1e1146d61d | ||
|
|
832e1d8cb8 | ||
|
|
4936211a9c | ||
|
|
f0d731009f | ||
|
|
a6248d03e5 | ||
|
|
a934cf4947 | ||
|
|
c498b7090e | ||
|
|
ca9e45e8af | ||
|
|
97096696a2 | ||
|
|
27fb3763b4 | ||
|
|
da43c70488 | ||
|
|
76ade0cb4d | ||
|
|
09e1526bca | ||
|
|
7d1fbeb708 | ||
|
|
15217c705e | ||
|
|
9f108e87eb | ||
|
|
1e786d6d8b | ||
|
|
0557eb9b93 | ||
|
|
241f6f3068 | ||
|
|
326656245a | ||
|
|
177ec92c39 | ||
|
|
711dacae5f | ||
|
|
c19183118e | ||
|
|
0af132d0c6 | ||
|
|
83c0e77ca8 | ||
|
|
1e315b5a33 | ||
|
|
6e0e0767f9 | ||
|
|
6df50399a9 | ||
|
|
7b9a8998cf | ||
|
|
7de5253318 | ||
|
|
eaf4a71d32 | ||
|
|
4dd40034ed | ||
|
|
030476d335 | ||
|
|
45aae5e322 | ||
|
|
9763839ed1 | ||
|
|
7ee10e06be | ||
|
|
8f3ea1d0c5 | ||
|
|
b9b87f7d8e | ||
|
|
c9b6e82e2c | ||
|
|
c8f969b4a2 | ||
|
|
ecd1c77f48 | ||
|
|
ad93d2fe4d | ||
|
|
5a4d401582 | ||
|
|
590c069158 | ||
|
|
94185e3f70 | ||
|
|
9adcd16ec6 | ||
|
|
74bcd898e7 | ||
|
|
296808d4d3 | ||
|
|
b7519cb834 | ||
|
|
7d6c050048 | ||
|
|
16f9a2e6b7 | ||
|
|
cbfe7f5822 | ||
|
|
895cd88761 | ||
|
|
f2ea18b0ba | ||
|
|
162f6b9d5c | ||
|
|
4f8ae3ccbe | ||
|
|
acd9be3863 | ||
|
|
ddf18ae34c | ||
|
|
0da61ec47e | ||
|
|
80230414a2 | ||
|
|
ce7c0d176b | ||
|
|
4ec79732f1 | ||
|
|
cc3c314988 | ||
|
|
8553a89af2 | ||
|
|
566321d67a | ||
|
|
a2778bf06d | ||
|
|
29eff23490 | ||
|
|
4ebaa82563 | ||
|
|
69911209ea | ||
|
|
92688c89ef | ||
|
|
fe04f8ce6b | ||
|
|
b72641693d | ||
|
|
0c6ee52cfc | ||
|
|
1f87094628 | ||
|
|
3b22018296 | ||
|
|
5be437deb9 | ||
|
|
8d098194dd | ||
|
|
256525bfa2 | ||
|
|
79e4f30f69 | ||
|
|
884637468e | ||
|
|
6fd7810d89 | ||
|
|
2f97d0d9b1 | ||
|
|
1bb9c57767 | ||
|
|
d880b8b8f2 | ||
|
|
7129f518a4 | ||
|
|
fa6f1c2fb1 | ||
|
|
2bd1c3acca | ||
|
|
70cfc9500e | ||
|
|
61b011cc28 | ||
|
|
391135b1a5 | ||
|
|
12d8d70573 | ||
|
|
04c5aeda2d | ||
|
|
25438be207 | ||
|
|
33f51d76f4 | ||
|
|
e3021909c2 | ||
|
|
61dee1beba | ||
|
|
21e954eec3 | ||
|
|
0b3054a348 | ||
|
|
02f4cb75dd | ||
|
|
3aeb8c6bdb | ||
|
|
8c2b2c7f80 | ||
|
|
745c635a55 | ||
|
|
c7dd31846d | ||
|
|
e87fa4293d | ||
|
|
b269884f8d | ||
|
|
3fed9761a6 | ||
|
|
6ccf196b61 | ||
|
|
a4bd8dc623 | ||
|
|
34f01408c9 | ||
|
|
73074daa07 | ||
|
|
119b80d449 | ||
|
|
60b3103314 | ||
|
|
75ffb9dc84 | ||
|
|
b306d40bf1 | ||
|
|
a27f146338 | ||
|
|
74995358cd | ||
|
|
35da6c32b7 | ||
|
|
701a5c7cb9 | ||
|
|
3c3e7f666b | ||
|
|
89dfa1fd7a | ||
|
|
1da00f0ee3 | ||
|
|
5809a1637f | ||
|
|
e47bea34d5 | ||
|
|
709f17c278 | ||
|
|
3c597dde72 | ||
|
|
0379431812 | ||
|
|
3f9fd85afb | ||
|
|
7b0a235c71 | ||
|
|
55cac23976 | ||
|
|
22a16a3e33 | ||
|
|
db555d12ea | ||
|
|
b9f1390405 | ||
|
|
f2d0aee656 | ||
|
|
2a47727641 | ||
|
|
ccb7f63b8a | ||
|
|
1f9bb6a1c4 | ||
|
|
21b5d2cac5 | ||
|
|
56eeeebed1 | ||
|
|
54627f6807 | ||
|
|
5754d36fdd | ||
|
|
3d14d362a8 | ||
|
|
472e027463 | ||
|
|
b297510d2b | ||
|
|
4932d25540 | ||
|
|
b6c3b743f0 | ||
|
|
1b4edd0e37 | ||
|
|
dcb00b4fe8 | ||
|
|
b33b688373 | ||
|
|
4b97b15c0c | ||
|
|
93c0774036 | ||
|
|
645885d72d | ||
|
|
b5af5f66fb | ||
|
|
fb04f8900a | ||
|
|
3396dce2bb | ||
|
|
3291bd2a4a | ||
|
|
121f01c06f | ||
|
|
6cac2d57ba | ||
|
|
c04b43e047 | ||
|
|
ff20732dd7 | ||
|
|
81af8f296e | ||
|
|
830d1fb42b | ||
|
|
e19cb48d3d | ||
|
|
f755580b11 | ||
|
|
81955005b9 | ||
|
|
62a871773b | ||
|
|
5e52e7f19e | ||
|
|
4c66a6a642 | ||
|
|
9e1deecf13 | ||
|
|
1ce93ccceb | ||
|
|
4b04f8bec1 | ||
|
|
5528bc7b2d | ||
|
|
912f3b19f7 | ||
|
|
9e5e85780b | ||
|
|
10aa3b3ae3 | ||
|
|
bcf7b3f95b | ||
|
|
07f1c784a4 | ||
|
|
465994cff9 | ||
|
|
697ad6cbda | ||
|
|
a840671015 | ||
|
|
7f0ab8308d | ||
|
|
270b9fde04 | ||
|
|
993c9899cb | ||
|
|
c8246e95f1 | ||
|
|
f08de1ed4c | ||
|
|
90f2e0dbb9 | ||
|
|
80a3bd8951 | ||
|
|
b0aec3cbe2 | ||
|
|
5f5e0634dd | ||
|
|
049e605016 | ||
|
|
4687c3e140 | ||
|
|
6d74e223be | ||
|
|
221427a6b4 | ||
|
|
3bf892128d | ||
|
|
abd7f939f2 | ||
|
|
299e9918b9 | ||
|
|
eea83ff613 | ||
|
|
9eceab667c | ||
|
|
026e7649d5 | ||
|
|
c807da7664 | ||
|
|
dde5db621d | ||
|
|
6b95cb4ee0 | ||
|
|
a5f69ef716 | ||
|
|
accccb5f39 | ||
|
|
f8ddccd7d0 | ||
|
|
e06e882962 | ||
|
|
c3f74ca4f1 | ||
|
|
532464f7ae | ||
|
|
570fb013e2 | ||
|
|
71ace9d8d0 | ||
|
|
1cf0326183 | ||
|
|
5b9ebd19d5 | ||
|
|
6ce869b3fb | ||
|
|
06b50ecb98 | ||
|
|
0bc7719572 | ||
|
|
9028f79a27 | ||
|
|
a3e1693a75 | ||
|
|
060b3e23c1 | ||
|
|
612c238157 | ||
|
|
8adbc75811 | ||
|
|
7485e5482c | ||
|
|
659a5436a5 | ||
|
|
c6d7a27848 | ||
|
|
094b198d5d | ||
|
|
22b97a3b54 | ||
|
|
a4f7a5e248 | ||
|
|
45d8cf163e | ||
|
|
d46daa1d7c | ||
|
|
4906cf1aff | ||
|
|
f74fae58e3 | ||
|
|
1602e0e823 | ||
|
|
202ebf06ff | ||
|
|
3e3b71724d | ||
|
|
893fb98522 | ||
|
|
e267226438 | ||
|
|
62626b712b | ||
|
|
7bdf14b210 | ||
|
|
87420e6504 | ||
|
|
c73a3ec356 | ||
|
|
2e23e6a2dc | ||
|
|
5b3ef78101 | ||
|
|
9b262d56a5 | ||
|
|
453b43992d | ||
|
|
a5e3617015 | ||
|
|
c4ad6d1ee6 | ||
|
|
f9cde1b46d | ||
|
|
03bc897b39 | ||
|
|
83fd84745d | ||
|
|
e977967eb5 | ||
|
|
15b00cb3ca | ||
|
|
18e5f72a84 | ||
|
|
47682de0f0 | ||
|
|
b4ea43cbd0 | ||
|
|
08341286a3 | ||
|
|
4c3b0b9a74 | ||
|
|
d250e9e9cc | ||
|
|
75be5eed62 | ||
|
|
e2f86678a4 | ||
|
|
fe7d5dfd19 | ||
|
|
965034e16e |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
raw
|
||||
presentation
|
||||
test.coffee
|
||||
parser.output
|
||||
|
||||
112
Cakefile
112
Cakefile
@@ -1,24 +1,42 @@
|
||||
fs: require 'fs'
|
||||
coffee: require 'coffee-script'
|
||||
fs: require 'fs'
|
||||
{helpers}: require('./lib/helpers')
|
||||
CoffeeScript: require './lib/coffee-script'
|
||||
{spawn, exec}: require('child_process')
|
||||
|
||||
# ANSI Terminal Colors.
|
||||
red: '\033[0;31m'
|
||||
green: '\033[0;32m'
|
||||
reset: '\033[0m'
|
||||
|
||||
# Run a CoffeeScript through our node/coffee interpreter.
|
||||
run: (args) ->
|
||||
proc: process.createChildProcess 'bin/coffee', args
|
||||
proc.addListener 'error', (err) -> if err then puts err
|
||||
proc: spawn 'bin/coffee', args
|
||||
proc.stderr.addListener 'data', (buffer) -> puts buffer.toString()
|
||||
proc.addListener 'exit', (status) -> process.exit(1) if status != 0
|
||||
|
||||
# Log a message with a color.
|
||||
log: (message, color, explanation) ->
|
||||
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'
|
||||
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"
|
||||
exec([
|
||||
'mkdir -p ' + lib
|
||||
'cp -rf bin lib LICENSE README package.json src vendor ' + lib
|
||||
'ln -sf ' + lib + '/bin/coffee ' + base + '/bin/coffee'
|
||||
'ln -sf ' + lib + '/bin/cake ' + base + '/bin/cake'
|
||||
"mkdir -p $lib $bin"
|
||||
"cp -rf bin lib LICENSE README package.json src $lib"
|
||||
"ln -sf $lib/bin/coffee $bin/coffee"
|
||||
"ln -sf $lib/bin/cake $bin/cake"
|
||||
"mkdir -p ~/.node_libraries"
|
||||
"ln -sf $lib/lib $node"
|
||||
].join(' && '), (err, stdout, stderr) ->
|
||||
if err then print stderr
|
||||
if err then print stderr else log 'done', green
|
||||
)
|
||||
|
||||
|
||||
@@ -28,46 +46,74 @@ task 'build', 'build the CoffeeScript language from source', ->
|
||||
run ['-c', '-o', 'lib'].concat(files)
|
||||
|
||||
|
||||
task 'build:full', 'rebuild the source twice, and run the tests', ->
|
||||
exec 'bin/cake build && bin/cake build && bin/cake test', (err, stdout, stderr) ->
|
||||
print stdout if stdout
|
||||
print stderr if stderr
|
||||
throw err if err
|
||||
|
||||
|
||||
task 'build:parser', 'rebuild the Jison parser (run build first)', ->
|
||||
require.paths.unshift 'vendor/jison/lib'
|
||||
parser: require('grammar').parser
|
||||
require 'jison'
|
||||
parser: require('./lib/grammar').parser
|
||||
js: parser.generate()
|
||||
parser_path: 'lib/parser.js'
|
||||
fs.writeFile parser_path, js
|
||||
parserPath: 'lib/parser.js'
|
||||
fs.writeFile parserPath, js
|
||||
|
||||
|
||||
task 'build:ultraviolet', 'build and install the Ultraviolet syntax highlighter', ->
|
||||
exec 'plist2syntax extras/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage', (err) ->
|
||||
exec 'plist2syntax ../coffee-script-tmbundle/Syntaxes/CoffeeScript.tmLanguage', (err) ->
|
||||
throw err if err
|
||||
exec 'sudo mv coffeescript.yaml /usr/local/lib/ruby/gems/1.8/gems/ultraviolet-0.10.2/syntax/coffeescript.syntax'
|
||||
|
||||
|
||||
task 'build:underscore', 'rebuild the Underscore.coffee documentation page', ->
|
||||
exec 'uv -s coffeescript -t idle -h examples/underscore.coffee > documentation/underscore.html'
|
||||
|
||||
|
||||
task 'build:browser', 'rebuild the merged script for inclusion in the browser', ->
|
||||
exec 'rake browser', (err) ->
|
||||
throw err if err
|
||||
|
||||
|
||||
task 'doc', 'watch and continually rebuild the documentation', ->
|
||||
task 'doc:site', 'watch and continually rebuild the documentation for the website', ->
|
||||
exec 'rake doc'
|
||||
|
||||
|
||||
task 'doc:source', 'rebuild the internal documentation', ->
|
||||
exec 'docco src/*.coffee && cp -rf docs documentation && rm -r docs', (err) ->
|
||||
throw err if err
|
||||
|
||||
|
||||
task 'doc:underscore', 'rebuild the Underscore.coffee documentation page', ->
|
||||
exec 'docco examples/underscore.coffee && cp -rf docs documentation && rm -r docs', (err) ->
|
||||
throw err if err
|
||||
|
||||
|
||||
task 'loc', 'count the lines of source code in CoffeeScript', ->
|
||||
exec "cat src/*.coffee | grep -v '^\\( *#\\|\\s*$\\)' | wc -l | tr -s ' '", (err, stdout) ->
|
||||
print stdout
|
||||
|
||||
|
||||
task 'test', 'run the CoffeeScript language test suite', ->
|
||||
process.mixin require 'assert'
|
||||
test_count: 0
|
||||
start_time: new Date()
|
||||
[original_ok, original_throws]: [ok, throws]
|
||||
process.mixin {
|
||||
ok: (args...) -> test_count += 1; original_ok(args...)
|
||||
throws: (args...) -> test_count += 1; original_throws(args...)
|
||||
helpers.extend global, require 'assert'
|
||||
passedTests: failedTests: 0
|
||||
startTime: new Date()
|
||||
originalOk: ok
|
||||
helpers.extend global, {
|
||||
ok: (args...) -> passedTests += 1; originalOk(args...)
|
||||
CoffeeScript: CoffeeScript
|
||||
}
|
||||
process.addListener 'exit', ->
|
||||
time: ((new Date() - start_time) / 1000).toFixed(2)
|
||||
puts '\033[0;32mpassed ' + test_count + ' tests in ' + time + ' seconds\033[0m'
|
||||
time: ((new Date() - startTime) / 1000).toFixed(2)
|
||||
message: "passed $passedTests tests in $time seconds$reset"
|
||||
if failedTests
|
||||
log "failed $failedTests and $message", red
|
||||
else
|
||||
log message, green
|
||||
fs.readdir 'test', (err, files) ->
|
||||
for file in files
|
||||
fs.readFile 'test/' + file, (err, source) ->
|
||||
js: coffee.compile source
|
||||
process.compile js, file
|
||||
files.forEach (file) ->
|
||||
return unless file.match(/\.coffee$/i)
|
||||
source: path.join 'test', file
|
||||
fs.readFile source, (err, code) ->
|
||||
try
|
||||
CoffeeScript.run code.toString(), {source: source}
|
||||
catch err
|
||||
failedTests += 1
|
||||
log "failed $source", red, '\n' + err.stack.toString()
|
||||
|
||||
22
README
22
README
@@ -39,4 +39,24 @@
|
||||
|
||||
The source repository:
|
||||
git://github.com/jashkenas/coffee-script.git
|
||||
|
||||
|
||||
|
||||
Contributors:
|
||||
|
||||
Stan Angeloff (StanAngeloff)
|
||||
Jeremy Ashkenas (jashkenas)
|
||||
Zach Carter (zaach)
|
||||
Tim Cuthbertson (gfxmonk)
|
||||
Mathieu D'Amours (matehat)
|
||||
Chris Hoffman (cehoffman)
|
||||
Jason Huggins (hugs)
|
||||
Timothy Jones (Tesco)
|
||||
Chris Lloyd (chrislloyd)
|
||||
Matt Lyon (mattly)
|
||||
Jeff Olson (olsonjeffery)
|
||||
Nathan Ostgard (noonat)
|
||||
Samuel Reis (grgh)
|
||||
Tom Robinson (tlrobinson)
|
||||
Tim Smart (Tim-Smart)
|
||||
Dr. Nic Williams (drnic)
|
||||
|
||||
14
Rakefile
14
Rakefile
@@ -4,6 +4,16 @@ require 'rake/testtask'
|
||||
require 'rubygems'
|
||||
require 'yui/compressor'
|
||||
|
||||
HEADER = <<-EOS
|
||||
/**
|
||||
* CoffeeScript Compiler v0.7.0
|
||||
* http://coffeescript.org
|
||||
*
|
||||
* Copyright 2010, Jeremy Ashkenas
|
||||
* Released under the MIT License
|
||||
*/
|
||||
EOS
|
||||
|
||||
desc "Build the documentation page"
|
||||
task :doc do
|
||||
source = 'documentation/index.html.erb'
|
||||
@@ -23,9 +33,9 @@ end
|
||||
|
||||
desc "Build the single concatenated and minified script for the browser"
|
||||
task :browser do
|
||||
sources = %w(rewriter.js lexer.js parser.js scope.js nodes.js coffee-script.js)
|
||||
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(code) }
|
||||
File.open('extras/coffee-script.js', 'w+') {|f| f.write(HEADER + code) }
|
||||
end
|
||||
|
||||
|
||||
5
bin/cake
5
bin/cake
@@ -1,9 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
process.mixin(require('sys'));
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
|
||||
|
||||
require.paths.unshift(lib);
|
||||
require('cake').run();
|
||||
require(lib + '/helpers').helpers.extend(global, require('sys'));
|
||||
require(lib + '/cake').run();
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
process.mixin(require('sys'));
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
|
||||
|
||||
require.paths.unshift(lib);
|
||||
require('command_line').run();
|
||||
require(lib + '/helpers').helpers.extend(global, require('sys'));
|
||||
require(lib + '/command').run();
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
launch() if ignition is on
|
||||
|
||||
volume: 10 if band isnt spinal_tap
|
||||
volume: 10 if band isnt SpinalTap
|
||||
|
||||
let_the_wild_rumpus_begin() unless answer is no
|
||||
letTheWildRumpusBegin() unless answer is no
|
||||
|
||||
if car.speed < speed_limit then accelerate()
|
||||
if car.speed < limit then accelerate()
|
||||
|
||||
winner: yes if pick in [47, 92, 13]
|
||||
|
||||
print "My name is " + @name
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
backwards: ->
|
||||
alert arguments.reverse()
|
||||
|
||||
backwards "stairway", "to", "heaven"
|
||||
@@ -1,5 +1,3 @@
|
||||
process.mixin require 'assert'
|
||||
|
||||
task 'test', 'run each of the unit tests', ->
|
||||
for test in test_files
|
||||
for test in files
|
||||
fs.readFile test, (err, code) -> eval coffee.compile code
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
mood: greatly_improved if singing
|
||||
mood: greatlyImproved if singing
|
||||
|
||||
if happy and knows_it
|
||||
claps_hands()
|
||||
cha_cha_cha()
|
||||
if happy and knowsIt
|
||||
clapsHands()
|
||||
chaChaCha()
|
||||
|
||||
date: if friday then sue else jill
|
||||
|
||||
expensive ||= do_the_math()
|
||||
options: or defaultOptions
|
||||
@@ -1,8 +1,8 @@
|
||||
grade: (student) ->
|
||||
if student.excellent_work
|
||||
if student.excellentWork
|
||||
"A+"
|
||||
else if student.okay_stuff
|
||||
if student.tried_hard then "B" else "B-"
|
||||
else if student.okayStuff
|
||||
if student.triedHard then "B" else "B-"
|
||||
else
|
||||
"C"
|
||||
|
||||
|
||||
2
documentation/coffee/interpolation.coffee
Normal file
2
documentation/coffee/interpolation.coffee
Normal file
@@ -0,0 +1,2 @@
|
||||
author: "Wittgenstein"
|
||||
quote: "A picture is a fact. -- $author"
|
||||
6
documentation/coffee/interpolation_expression.coffee
Normal file
6
documentation/coffee/interpolation_expression.coffee
Normal file
@@ -0,0 +1,6 @@
|
||||
sentence: "${ 22 / 7 } is a decent approximation of π"
|
||||
|
||||
sep: "[.\\/\\- ]"
|
||||
dates: /\d+$sep\d+$sep\d+/g
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
weather_report: (location) ->
|
||||
weatherReport: (location) ->
|
||||
# Make an Ajax request to fetch the weather...
|
||||
[location, 72, "Mostly Sunny"]
|
||||
|
||||
[city, temp, forecast]: weather_report "Berkeley, CA"
|
||||
[city, temp, forecast]: weatherReport "Berkeley, CA"
|
||||
@@ -1,4 +1,4 @@
|
||||
years_old: {max: 10, ida: 9, tim: 11}
|
||||
yearsOld: {max: 10, ida: 9, tim: 11}
|
||||
|
||||
ages: for child, age of years_old
|
||||
ages: for child, age of yearsOld
|
||||
child + " is " + age
|
||||
@@ -10,4 +10,4 @@ futurists: {
|
||||
}
|
||||
}
|
||||
|
||||
{poet: {name: poet, address: [street, city]}}: futurists
|
||||
{poet: {name, address: [street, city]}}: futurists
|
||||
1
documentation/coffee/objects_reserved.coffee
Normal file
1
documentation/coffee/objects_reserved.coffee
Normal file
@@ -0,0 +1 @@
|
||||
$('.account').css {class: 'active'}
|
||||
@@ -1,9 +1,9 @@
|
||||
# Assignment:
|
||||
number: 42
|
||||
opposite_day: true
|
||||
opposite: true
|
||||
|
||||
# Conditions:
|
||||
number: -42 if opposite_day
|
||||
number: -42 if opposite
|
||||
|
||||
# Functions:
|
||||
square: (x) -> x * x
|
||||
@@ -26,4 +26,4 @@ race: (winner, runners...) ->
|
||||
alert "I knew it!" if elvis?
|
||||
|
||||
# Array comprehensions:
|
||||
cubed_list: math.cube num for num in list
|
||||
cubes: math.cube num for num in list
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
bait: 1000
|
||||
and_switch: 0
|
||||
theBait: 1000
|
||||
theSwitch: 0
|
||||
|
||||
[bait, and_switch]: [and_switch, bait]
|
||||
[theBait, theSwitch]: [theSwitch, theBait]
|
||||
7
documentation/coffee/patterns_and_splats.coffee
Normal file
7
documentation/coffee/patterns_and_splats.coffee
Normal file
@@ -0,0 +1,7 @@
|
||||
tag: "<impossible>"
|
||||
|
||||
[open, contents..., close]: tag.split("")
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
countdown: num for num in [10..1]
|
||||
countdown: num for num in [10..1] by -1
|
||||
|
||||
egg_delivery: ->
|
||||
deliverEggs: ->
|
||||
for i in [0...eggs.length] by 12
|
||||
dozen_eggs: eggs[i...i+12]
|
||||
deliver new egg_carton(dozen)
|
||||
dozen: eggs[i...i+12]
|
||||
deliver new eggCarton(dozen)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
num: 1
|
||||
change_numbers: ->
|
||||
new_num: -1
|
||||
num: 10
|
||||
new_num: change_numbers()
|
||||
outer: 1
|
||||
changeNumbers: ->
|
||||
inner: -1
|
||||
outer: 10
|
||||
inner: changeNumbers()
|
||||
@@ -1,6 +1,6 @@
|
||||
numbers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
|
||||
three_to_six: numbers[3..6]
|
||||
threeToSix: numbers[3..6]
|
||||
|
||||
numbers_copy: numbers[0...numbers.length]
|
||||
copy: numbers[0...numbers.length]
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
lottery.draw_winner()?.address?.zipcode
|
||||
lottery.drawWinner()?.address?.zipcode
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
gold: silver: the_field: "unknown"
|
||||
gold: silver: rest: "unknown"
|
||||
|
||||
award_medals: (first, second, rest...) ->
|
||||
gold: first
|
||||
silver: second
|
||||
the_field: rest
|
||||
awardMedals: (first, second, rest...) ->
|
||||
gold: first
|
||||
silver: second
|
||||
rest: rest
|
||||
|
||||
contenders: [
|
||||
"Michael Phelps"
|
||||
@@ -18,8 +18,8 @@ contenders: [
|
||||
"Usain Bolt"
|
||||
]
|
||||
|
||||
award_medals contenders...
|
||||
awardMedals contenders...
|
||||
|
||||
alert "Gold: " + gold
|
||||
alert "Silver: " + silver
|
||||
alert "The Field: " + the_field
|
||||
alert "The Field: " + rest
|
||||
@@ -1,4 +1,4 @@
|
||||
moby_dick: "Call me Ishmael. Some years ago --
|
||||
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
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
switch day
|
||||
when "Mon" then go_to_work()
|
||||
when "Tue" then go_to_the_park()
|
||||
when "Thu" then go_ice_fishing()
|
||||
when "Mon" then goToWork()
|
||||
when "Tue" then goToThePark()
|
||||
when "Thu" then goIceFishing()
|
||||
when "Fri", "Sat"
|
||||
if day is bingo_day
|
||||
go_to_bingo()
|
||||
go_dancing()
|
||||
when "Sun" then go_to_church()
|
||||
else go_to_work()
|
||||
if day is bingoDay
|
||||
goToBingo()
|
||||
goDancing()
|
||||
when "Sun" then goToChurch()
|
||||
else goToWork()
|
||||
@@ -1,7 +1,7 @@
|
||||
try
|
||||
all_hell_breaks_loose()
|
||||
cats_and_dogs_living_together()
|
||||
allHellBreaksLoose()
|
||||
catsAndDogsLivingTogether()
|
||||
catch error
|
||||
print error
|
||||
finally
|
||||
clean_up()
|
||||
cleanUp()
|
||||
@@ -1,10 +1,10 @@
|
||||
# Econ 101
|
||||
if this.studying_economics
|
||||
while supply > demand then buy()
|
||||
while supply < demand then sell()
|
||||
if this.studyingEconomics
|
||||
buy() while supply > demand
|
||||
sell() until supply > demand
|
||||
|
||||
# Nursery Rhyme
|
||||
num: 6
|
||||
lyrics: while num -= 1
|
||||
lyrics: while num: - 1
|
||||
num + " little monkeys, jumping on the bed.
|
||||
One fell out and bumped his head."
|
||||
|
||||
@@ -8,7 +8,7 @@ div.container {
|
||||
width: 950px;
|
||||
margin: 100px 0 50px 50px;
|
||||
}
|
||||
p {
|
||||
p, li {
|
||||
width: 625px;
|
||||
}
|
||||
a {
|
||||
@@ -105,6 +105,7 @@ div.code {
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
height: 50px;
|
||||
min-width: 490px;
|
||||
left: 40px; right: 40px; top: 25px;
|
||||
background: #ddd;
|
||||
padding-left: 235px;
|
||||
@@ -124,7 +125,7 @@ div.code {
|
||||
#error {
|
||||
position: absolute;
|
||||
-webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px;
|
||||
right: 15px; top: 15px; left: 565px;
|
||||
right: 15px; top: 15px; left: 722px;
|
||||
height: 15px;
|
||||
padding: 2px 5px;
|
||||
background: #fdcdcc;
|
||||
@@ -142,14 +143,14 @@ div.code {
|
||||
float: left;
|
||||
padding: 0 20px;
|
||||
border: 1px solid #bbb;
|
||||
border-top: 0; border-bottom: 0;
|
||||
border-top: 0; border-bottom: 0; border-left-width: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
body.full_screen .navigation {
|
||||
position: static;
|
||||
}
|
||||
.navigation.try {
|
||||
border-left: 0;
|
||||
.navigation.toc {
|
||||
border-left-width: 1px;
|
||||
}
|
||||
.navigation:hover,
|
||||
.navigation.active {
|
||||
@@ -206,7 +207,7 @@ div.code {
|
||||
}
|
||||
.navigation .contents a {
|
||||
display: block;
|
||||
width: 300px;
|
||||
width: 290px;
|
||||
text-transform: none;
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
|
||||
45
documentation/docs/cake.html
Normal file
45
documentation/docs/cake.html
Normal file
@@ -0,0 +1,45 @@
|
||||
<!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>
|
||||
(<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>
|
||||
|
||||
<p>Running <code>cake</code> with no arguments will print out a list of all the tasks in the
|
||||
current directory's Cakefile.</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">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">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></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>Keep track of the list of defined tasks, the accepted options, and so on.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">tasks: </span><span class="p">{}</span>
|
||||
<span class="nv">options: </span><span class="p">{}</span>
|
||||
<span class="nv">switches: </span><span class="p">[]</span>
|
||||
<span class="nv">oparse: </span><span class="kc">null</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Mixin the top-level Cake functions for Cakefiles to use directly.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">helpers</span><span class="p">.</span><span class="nx">extend</span> <span class="nx">global</span><span class="p">,</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Define a Cake task with a short name, an optional sentence description,
|
||||
and the function to run as the action itself.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">task: </span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">description</span><span class="p">,</span> <span class="nx">action</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="p">[</span><span class="nx">action</span><span class="p">,</span> <span class="nx">description</span><span class="p">]</span><span class="o">:</span> <span class="p">[</span><span class="nx">description</span><span class="p">,</span> <span class="nx">action</span><span class="p">]</span> <span class="nx">unless</span> <span class="nx">action</span>
|
||||
<span class="nx">tasks</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span><span class="o">:</span> <span class="p">{</span><span class="nx">name</span><span class="p">,</span> <span class="nx">description</span><span class="p">,</span> <span class="nx">action</span><span class="p">}</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Define an option that the Cakefile accepts. The parsed options hash,
|
||||
containing all of the command-line options passed, will be made available
|
||||
as the first argument to the action.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">option: </span><span class="p">(</span><span class="nx">letter</span><span class="p">,</span> <span class="nx">flag</span><span class="p">,</span> <span class="nx">description</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">switches</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="nx">letter</span><span class="p">,</span> <span class="nx">flag</span><span class="p">,</span> <span class="nx">description</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Invoke another task in the current Cakefile.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">invoke: </span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">missingTask</span> <span class="nx">name</span> <span class="nx">unless</span> <span class="nx">tasks</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span>
|
||||
<span class="nx">tasks</span><span class="p">[</span><span class="nx">name</span><span class="p">].</span><span class="nx">action</span> <span class="nx">options</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>Run <code>cake</code>. Executes all of the tasks you pass, in order. Note that Node's
|
||||
asynchrony may cause tasks to execute in a different order than you'd expect.
|
||||
If no tasks are passed, print the help screen.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run: </span><span class="o">-></span>
|
||||
<span class="nx">path</span><span class="p">.</span><span class="nx">exists</span> <span class="s1">'Cakefile'</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="p">(</span><span class="s2">"Cakefile not found in ${process.cwd()}"</span><span class="p">)</span> <span class="nx">unless</span> <span class="nx">exists</span>
|
||||
<span class="nv">args: </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">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="s1">'Cakefile'</span><span class="p">).</span><span class="nx">toString</span><span class="p">(),</span> <span class="p">{</span><span class="nv">source: </span><span class="s1">'Cakefile'</span><span class="p">}</span>
|
||||
<span class="nv">oparse: </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="k">return</span> <span class="nx">printTasks</span><span class="p">()</span> <span class="nx">unless</span> <span class="nx">args</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">options: </span><span class="nx">oparse</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">args</span><span class="p">)</span>
|
||||
<span class="nx">invoke</span> <span class="nx">arg</span> <span class="k">for</span> <span class="nx">arg</span> <span class="k">in</span> <span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Display the list of Cake tasks in a format similar to <code>rake -T</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">printTasks: </span><span class="o">-></span>
|
||||
<span class="nx">puts</span> <span class="s1">''</span>
|
||||
<span class="k">for</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">task</span> <span class="k">of</span> <span class="nx">tasks</span>
|
||||
<span class="nv">spaces: </span><span class="mi">20</span> <span class="o">-</span> <span class="nx">name</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">spaces: </span><span class="k">if</span> <span class="nx">spaces</span> <span class="o">></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="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">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>
|
||||
60
documentation/docs/coffee-script.html
Normal file
60
documentation/docs/coffee-script.html
Normal file
@@ -0,0 +1,60 @@
|
||||
<!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
|
||||
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.7.0'</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Instantiate a Lexer for our use here.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lexer: </span><span class="k">new</span> <span class="nx">Lexer</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
|
||||
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="nv">options: </span><span class="o">or</span> <span class="p">{}</span>
|
||||
<span class="k">try</span>
|
||||
<span class="p">(</span><span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="nx">code</span><span class="p">).</span><span class="nx">compile</span> <span class="nx">options</span>
|
||||
<span class="k">catch</span> <span class="nx">err</span>
|
||||
<span class="nv">err.message: </span><span class="s2">"In $options.source, $err.message"</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">source</span>
|
||||
<span class="k">throw</span> <span class="nx">err</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Tokenize a string of CoffeeScript code, and return the array of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.tokens: </span><span class="p">(</span><span class="nx">code</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="nx">code</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Tokenize and parse a string of CoffeeScript code, and return the AST. You can
|
||||
then compile it by calling <code>.compile()</code> on the root, or traverse it by using
|
||||
<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">source</span>
|
||||
<span class="nv">__dirname: </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span><span class="p">(</span><span class="nx">__filename</span><span class="p">)</span>
|
||||
<span class="nb">eval</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span>
|
||||
<span class="p">)</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>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="p">{</span>
|
||||
<span class="nv">lex: </span><span class="o">-></span>
|
||||
<span class="nv">token: </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">@pos</span><span class="p">]</span> <span class="o">or</span> <span class="p">[</span><span class="s2">""</span><span class="p">]</span>
|
||||
<span class="vi">@pos: </span><span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nv">yylineno: </span><span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nv">yytext: </span> <span class="nx">token</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nv">setInput: </span><span class="p">(</span><span class="nx">tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="vi">@tokens: </span><span class="nx">tokens</span>
|
||||
<span class="vi">@pos: </span><span class="mi">0</span>
|
||||
<span class="nv">upcomingInput: </span><span class="o">-></span> <span class="s2">""</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>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>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
128
documentation/docs/command.html
Normal file
128
documentation/docs/command.html
Normal file
@@ -0,0 +1,128 @@
|
||||
<!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
|
||||
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="p">(</span><span class="s1">'child_process'</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>The help banner that is printed when <code>coffee</code> is called without arguments.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BANNER: </span><span class="s1">'''</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="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.
|
||||
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">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="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
|
||||
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="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>
|
||||
<span class="k">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">files</span>
|
||||
<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
|
||||
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>
|
||||
<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="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>,
|
||||
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="nx">addListener</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="nv">code: </span><span class="o">+</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span> <span class="k">if</span> <span class="nx">buffer</span>
|
||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">'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
|
||||
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="nv">persistent: </span><span class="kc">true</span><span class="p">,</span> <span class="nv">interval: </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
|
||||
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">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="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">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
|
||||
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="nx">jsl</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">addListener</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="nx">addListener</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="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
|
||||
<code>process.argv</code> that are specified in <code>SWITCHES</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">parseOptions: </span><span class="o">-></span>
|
||||
<span class="nv">optionParser: </span><span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">SWITCHES</span><span class="p">,</span> <span class="nx">BANNER</span>
|
||||
<span class="nv">o: options: </span> <span class="nx">optionParser</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">)</span>
|
||||
<span class="nv">options.run: </span> <span class="o">not</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">lint</span><span class="p">)</span>
|
||||
<span class="nv">options.print: </span><span class="o">!!</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nb">eval</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">stdio</span> <span class="o">and</span> <span class="nx">o</span><span class="p">.</span><span class="nx">compile</span><span class="p">))</span>
|
||||
<span class="nv">sources: </span> <span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span><span class="p">[</span><span class="mi">2</span><span class="p">...</span><span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span><span class="p">.</span><span class="nx">length</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>The compile-time options to pass to the CoffeeScript compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileOptions: </span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">o: </span><span class="p">{</span><span class="nx">source</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="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> </tbody> </table> </div> </body> </html>
|
||||
185
documentation/docs/docco.css
Normal file
185
documentation/docs/docco.css
Normal file
@@ -0,0 +1,185 @@
|
||||
/*--------------------- Layout and Typography ----------------------------*/
|
||||
body {
|
||||
font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #252519;
|
||||
margin: 0; padding: 0;
|
||||
}
|
||||
a {
|
||||
color: #261a3b;
|
||||
}
|
||||
a:visited {
|
||||
color: #261a3b;
|
||||
}
|
||||
p {
|
||||
margin: 0 0 15px 0;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin: 40px 0 15px 0;
|
||||
}
|
||||
h3, h4, h5, h6 {
|
||||
margin-top: 20px;
|
||||
}
|
||||
#container {
|
||||
position: relative;
|
||||
}
|
||||
#background {
|
||||
position: fixed;
|
||||
top: 0; left: 580px; right: 0; bottom: 0;
|
||||
background: #f5f5ff;
|
||||
border-left: 1px solid #e5e5ee;
|
||||
z-index: -1;
|
||||
}
|
||||
#jump_to, #jump_page {
|
||||
background: white;
|
||||
-webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;
|
||||
-webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px;
|
||||
font: 10px Arial;
|
||||
text-transform: uppercase;
|
||||
cursor: pointer;
|
||||
text-align: right;
|
||||
}
|
||||
#jump_to, #jump_wrapper {
|
||||
position: fixed;
|
||||
right: 0; top: 0;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
#jump_wrapper {
|
||||
padding: 0;
|
||||
display: none;
|
||||
}
|
||||
#jump_to:hover #jump_wrapper {
|
||||
display: block;
|
||||
}
|
||||
#jump_page {
|
||||
padding: 5px 0 3px;
|
||||
margin: 0 0 25px 25px;
|
||||
}
|
||||
#jump_page .source {
|
||||
display: block;
|
||||
padding: 5px 10px;
|
||||
text-decoration: none;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
#jump_page .source:hover {
|
||||
background: #f5f5ff;
|
||||
}
|
||||
#jump_page .source:first-child {
|
||||
}
|
||||
table td {
|
||||
border: 0;
|
||||
outline: 0;
|
||||
}
|
||||
td.docs, th.docs {
|
||||
max-width: 500px;
|
||||
min-width: 500px;
|
||||
min-height: 5px;
|
||||
padding: 10px 25px 1px 50px;
|
||||
vertical-align: top;
|
||||
text-align: left;
|
||||
}
|
||||
.docs pre {
|
||||
margin: 15px 0 15px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
.docs p tt, .docs p code {
|
||||
background: #f8f8ff;
|
||||
border: 1px solid #dedede;
|
||||
font-size: 12px;
|
||||
padding: 0 0.2em;
|
||||
}
|
||||
.octowrap {
|
||||
position: relative;
|
||||
}
|
||||
.octothorpe {
|
||||
font: 12px Arial;
|
||||
text-decoration: none;
|
||||
color: #454545;
|
||||
position: absolute;
|
||||
top: 3px; left: -20px;
|
||||
padding: 1px 2px;
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
}
|
||||
td.docs:hover .octothorpe {
|
||||
opacity: 1;
|
||||
}
|
||||
td.code, th.code {
|
||||
padding: 14px 15px 16px 50px;
|
||||
width: 100%;
|
||||
vertical-align: top;
|
||||
background: #f5f5ff;
|
||||
border-left: 1px solid #e5e5ee;
|
||||
}
|
||||
pre, tt, code {
|
||||
font-size: 12px; line-height: 18px;
|
||||
font-family: Monaco, Consolas, "Lucida Console", monospace;
|
||||
margin: 0; padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------- Syntax Highlighting -----------------------------*/
|
||||
td.linenos { background-color: #f0f0f0; padding-right: 10px; }
|
||||
span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
|
||||
body .hll { background-color: #ffffcc }
|
||||
body .c { color: #408080; font-style: italic } /* Comment */
|
||||
body .err { border: 1px solid #FF0000 } /* Error */
|
||||
body .k { color: #954121 } /* Keyword */
|
||||
body .o { color: #666666 } /* Operator */
|
||||
body .cm { color: #408080; font-style: italic } /* Comment.Multiline */
|
||||
body .cp { color: #BC7A00 } /* Comment.Preproc */
|
||||
body .c1 { color: #408080; font-style: italic } /* Comment.Single */
|
||||
body .cs { color: #408080; font-style: italic } /* Comment.Special */
|
||||
body .gd { color: #A00000 } /* Generic.Deleted */
|
||||
body .ge { font-style: italic } /* Generic.Emph */
|
||||
body .gr { color: #FF0000 } /* Generic.Error */
|
||||
body .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||
body .gi { color: #00A000 } /* Generic.Inserted */
|
||||
body .go { color: #808080 } /* Generic.Output */
|
||||
body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
|
||||
body .gs { font-weight: bold } /* Generic.Strong */
|
||||
body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||
body .gt { color: #0040D0 } /* Generic.Traceback */
|
||||
body .kc { color: #954121 } /* Keyword.Constant */
|
||||
body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */
|
||||
body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */
|
||||
body .kp { color: #954121 } /* Keyword.Pseudo */
|
||||
body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */
|
||||
body .kt { color: #B00040 } /* Keyword.Type */
|
||||
body .m { color: #666666 } /* Literal.Number */
|
||||
body .s { color: #219161 } /* Literal.String */
|
||||
body .na { color: #7D9029 } /* Name.Attribute */
|
||||
body .nb { color: #954121 } /* Name.Builtin */
|
||||
body .nc { color: #0000FF; font-weight: bold } /* Name.Class */
|
||||
body .no { color: #880000 } /* Name.Constant */
|
||||
body .nd { color: #AA22FF } /* Name.Decorator */
|
||||
body .ni { color: #999999; font-weight: bold } /* Name.Entity */
|
||||
body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
|
||||
body .nf { color: #0000FF } /* Name.Function */
|
||||
body .nl { color: #A0A000 } /* Name.Label */
|
||||
body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
|
||||
body .nt { color: #954121; font-weight: bold } /* Name.Tag */
|
||||
body .nv { color: #19469D } /* Name.Variable */
|
||||
body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
|
||||
body .w { color: #bbbbbb } /* Text.Whitespace */
|
||||
body .mf { color: #666666 } /* Literal.Number.Float */
|
||||
body .mh { color: #666666 } /* Literal.Number.Hex */
|
||||
body .mi { color: #666666 } /* Literal.Number.Integer */
|
||||
body .mo { color: #666666 } /* Literal.Number.Oct */
|
||||
body .sb { color: #219161 } /* Literal.String.Backtick */
|
||||
body .sc { color: #219161 } /* Literal.String.Char */
|
||||
body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */
|
||||
body .s2 { color: #219161 } /* Literal.String.Double */
|
||||
body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
|
||||
body .sh { color: #219161 } /* Literal.String.Heredoc */
|
||||
body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
|
||||
body .sx { color: #954121 } /* Literal.String.Other */
|
||||
body .sr { color: #BB6688 } /* Literal.String.Regex */
|
||||
body .s1 { color: #219161 } /* Literal.String.Single */
|
||||
body .ss { color: #19469D } /* Literal.String.Symbol */
|
||||
body .bp { color: #954121 } /* Name.Builtin.Pseudo */
|
||||
body .vc { color: #19469D } /* Name.Variable.Class */
|
||||
body .vg { color: #19469D } /* Name.Variable.Global */
|
||||
body .vi { color: #19469D } /* Name.Variable.Instance */
|
||||
body .il { color: #666666 } /* Literal.Number.Integer.Long */
|
||||
410
documentation/docs/grammar.html
Normal file
410
documentation/docs/grammar.html
Normal file
@@ -0,0 +1,410 @@
|
||||
<!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>
|
||||
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>
|
||||
type grammars. To create the Jison parser, we list the pattern to match
|
||||
on the left-hand side, and the action to take (usually the creation of syntax
|
||||
tree nodes) on the right. As the parser runs, it
|
||||
shifts tokens from our token stream, from left to right, and
|
||||
<a href="http://en.wikipedia.org/wiki/Bottom-up_parsing">attempts to match</a>
|
||||
the token sequence against the rules below. When a match can be made, it
|
||||
reduces into the <a href="http://en.wikipedia.org/wiki/Terminal_and_nonterminal_symbols">nonterminal</a>
|
||||
(the enclosing name at the top), and we proceed from there.</p>
|
||||
|
||||
<p>If you run the <code>cake build:parser</code> command, Jison constructs a parse table
|
||||
from our rules and saves it into <code>lib/parser.js</code>.</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>The only dependency is on the <strong>Jison.Parser</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">Parser: </span><span class="nx">require</span><span class="p">(</span><span class="s1">'jison'</span><span class="p">).</span><span class="nx">Parser</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <h2>Jison DSL</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Since we're going to be wrapped in a function by Jison in any case, if our
|
||||
action immediately returns a value, we can optimize by removing the function
|
||||
wrapper and just returning the value directly.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">unwrap: </span><span class="sr">/function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Our handy DSL for Jison grammar generation, thanks to
|
||||
<a href="http://github.com/creationix">Tim Caswell</a>. For every rule in the grammar,
|
||||
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
|
||||
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>
|
||||
|
||||
<pre><code>"Expression UNLESS Expression"
|
||||
</code></pre>
|
||||
|
||||
<p><code>$1</code> would be the value of the first <code>Expression</code>, <code>$2</code> would be the token
|
||||
for the <code>UNLESS</code> terminal, and <code>$3</code> would be the value of the second
|
||||
<code>Expression</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">grammar: </span><span class="p">{</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>The <strong>Root</strong> is the top-level node in the syntax tree. Since we parse bottom-up,
|
||||
all parsing must end here.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Root: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">""</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Expressions</span><span class="p">()</span>
|
||||
<span class="nx">o</span> <span class="s2">"TERMINATOR"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Expressions</span><span class="p">()</span>
|
||||
<span class="nx">o</span> <span class="s2">"Body"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Block TERMINATOR"</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Any list of statements and expressions, seperated by line breaks or semicolons.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Body: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Line"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"Body TERMINATOR Line"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">push</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Body TERMINATOR"</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Expressions and statements, which make up a line in a body.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Line: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Statement"</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Pure statements which cannot be expressions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Statement: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Return"</span>
|
||||
<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="p">]</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>All the different types of expressions in our language. The basic unit of
|
||||
CoffeeScript is the <strong>Expression</strong> -- everything that can be an expression
|
||||
is one. Expressions serve as the building blocks of many other rules, making
|
||||
them somewhat circular.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Expression: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Value"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Call"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Code"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Operation"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Assign"</span>
|
||||
<span class="nx">o</span> <span class="s2">"If"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Try"</span>
|
||||
<span class="nx">o</span> <span class="s2">"While"</span>
|
||||
<span class="nx">o</span> <span class="s2">"For"</span>
|
||||
<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="p">]</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>A an indented block of expressions. Note that the <a href="rewriter.html">Rewriter</a>
|
||||
will convert some postfix forms into blocks for us, by adjusting the
|
||||
token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Block: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"INDENT Body OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"INDENT OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Expressions</span><span class="p">()</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</a> </div> <p>A literal identifier, a variable name or property.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Identifier: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"IDENTIFIER"</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-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>Alphanumerics are separated from the other <strong>Literal</strong> matchers because
|
||||
they can also serve as keys in object literals.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">AlphaNumeric: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"NUMBER"</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">"STRING"</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-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</a> </div> <p>All of our immediate values. These can (in general), be passed straight
|
||||
through and printed to JavaScript.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Literal: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"AlphaNumeric"</span>
|
||||
<span class="nx">o</span> <span class="s2">"JS"</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">"REGEX"</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">"TRUE"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s2">"FALSE"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="kc">false</span>
|
||||
<span class="nx">o</span> <span class="s2">"YES"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s2">"NO"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="kc">false</span>
|
||||
<span class="nx">o</span> <span class="s2">"ON"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s2">"OFF"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="kc">false</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>Assignment of a variable, property, or index to a value.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Assign: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Assignable ASSIGN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">AssignNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-18">#</a> </div> <p>Assignment when it happens within an object literal. The difference from
|
||||
the ordinary <strong>Assign</strong> is that these allow numbers and strings as keys.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">AssignObj: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Identifier"</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">"AlphaNumeric"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Identifier ASSIGN 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">'object'</span>
|
||||
<span class="nx">o</span> <span class="s2">"AlphaNumeric ASSIGN 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">'object'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-19">#</a> </div> <p>A return statement from a function body.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Return: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"RETURN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ReturnNode</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"RETURN"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ReturnNode</span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="s1">'null'</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><a href="http://jashkenas.github.com/coffee-script/#existence">The existential operator</a>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Existence: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression ?"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ExistenceNode</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-21">#</a> </div> <p>The <strong>Code</strong> node is the function literal. It's defined by an indented block
|
||||
of <strong>Expressions</strong> preceded by a function arrow, with an optional parameter
|
||||
list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Code: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"PARAM_START ParamList PARAM_END FuncGlyph Block"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">CodeNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$5</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s2">"FuncGlyph Block"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">CodeNode</span> <span class="p">[],</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-22">#</a> </div> <p>CoffeeScript has two different symbols for functions. <code>-></code> is for ordinary
|
||||
functions, and <code>=></code> is for functions bound to the current value of <em>this</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">FuncGlyph: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"->"</span><span class="p">,</span> <span class="o">-></span> <span class="s1">'func'</span>
|
||||
<span class="nx">o</span> <span class="s2">"=>"</span><span class="p">,</span> <span class="o">-></span> <span class="s1">'boundfunc'</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>An optional, trailing comma.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">OptComma: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">''</span>
|
||||
<span class="nx">o</span> <span class="s1">','</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-24">#</a> </div> <p>The list of parameters that a function accepts can be of any length.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ParamList: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">""</span><span class="p">,</span> <span class="o">-></span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s2">"Param"</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">"ParamList , Param"</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="p">]</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-25">#</a> </div> <p>A single parameter in a function definition can be ordinary, or a splat
|
||||
that hoovers up the remaining arguments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Param: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"PARAM"</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">"Param . . ."</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">SplatNode</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-26">#</a> </div> <p>A splat that occurs outside of a parameter list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Splat: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression . . ."</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">SplatNode</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-27">#</a> </div> <p>Variables and properties that can be assigned to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">SimpleAssignable: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Identifier"</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">"Value Accessor"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">push</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"Invocation Accessor"</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> <span class="p">[</span><span class="nx">$2</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"ThisProperty"</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-28">#</a> </div> <p>Everything that can be assigned to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Assignable: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"SimpleAssignable"</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-29"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-29">#</a> </div> <p>The types of things that can be treated as values -- assigned to, invoked
|
||||
as functions, indexed into, named as a class, etc.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Value: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Assignable"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Literal"</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">"Parenthetical"</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">"Range"</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">"This"</span>
|
||||
<span class="nx">o</span> <span class="s2">"NULL"</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">'null'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-30">#</a> </div> <p>The general group of accessors into an object, by property, by prototype
|
||||
or by array index or slice.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Accessor: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"PROPERTY_ACCESS Identifier"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">AccessorNode</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"PROTOTYPE_ACCESS Identifier"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">AccessorNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="s1">'prototype'</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">AccessorNode</span><span class="p">(</span><span class="k">new</span> <span class="nx">LiteralNode</span><span class="p">(</span><span class="s1">'prototype'</span><span class="p">))</span>
|
||||
<span class="nx">o</span> <span class="s2">"SOAK_ACCESS Identifier"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">AccessorNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="s1">'soak'</span>
|
||||
<span class="nx">o</span> <span class="s2">"Index"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Slice"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">SliceNode</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-31">#</a> </div> <p>Indexing into an object or array using bracket notation.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Index: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"INDEX_START Expression INDEX_END"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">IndexNode</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"INDEX_SOAK Index"</span><span class="p">,</span> <span class="o">-></span> <span class="nv">$2.soakNode: </span><span class="kc">yes</span><span class="p">;</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"INDEX_PROTO Index"</span><span class="p">,</span> <span class="o">-></span> <span class="nv">$2.proto: </span><span class="kc">yes</span><span class="p">;</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-32">#</a> </div> <p>In CoffeeScript, an object literal is simply a list of assignments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nb">Object</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"{ AssignList OptComma }"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ObjectNode</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-33">#</a> </div> <p>Assignment of properties within an object literal can be separated by
|
||||
comma, as in JavaScript, or simply by newline.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">AssignList: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">""</span><span class="p">,</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="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"AssignList , AssignObj"</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">"AssignList OptComma TERMINATOR AssignObj"</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">"AssignList OptComma INDENT AssignList 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-34"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-34">#</a> </div> <p>Class definitions have optional bodies of prototype property assignments,
|
||||
and optional references to the superclass.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Class: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"CLASS SimpleAssignable"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ClassNode</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"CLASS SimpleAssignable EXTENDS Value"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ClassNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s2">"CLASS SimpleAssignable INDENT ClassBody OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ClassNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s2">"CLASS SimpleAssignable EXTENDS Value INDENT ClassBody OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ClassNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$6</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-35">#</a> </div> <p>Assignments that can happen directly inside a class declaration.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ClassAssign: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"AssignObj"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s2">"ThisProperty ASSIGN 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="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>A list of assignments to a class.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ClassBody: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">""</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="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>The three flavors of function call: normal, object instantiation with <code>new</code>,
|
||||
and calling <code>super()</code></p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Call: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Invocation"</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">"Super"</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>Extending an object by setting its prototype chain to reference a parent
|
||||
object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Extends: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"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-39"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-39">#</a> </div> <p>Ordinary function invocation, or a chained series of calls.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Invocation: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"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-40"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-40">#</a> </div> <p>The list of arguments to a function call.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Arguments: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"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-41"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-41">#</a> </div> <p>Calling super.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Super: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"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-42"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-42">#</a> </div> <p>A reference to the <em>this</em> current object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">This: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"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></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 a property on <em>this</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ThisProperty: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"@ 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-44"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-44">#</a> </div> <p>The CoffeeScript range literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Range: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"[ 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="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 slice literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Slice: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"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="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 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">"[ 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-47"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-47">#</a> </div> <p>The <strong>ArgList</strong> is both the list of objects passed into a function call,
|
||||
as well as the contents of an array literal
|
||||
(i.e. comma-separated expressions). Newlines work as well.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ArgList: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">""</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">"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-48"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-48">#</a> </div> <p>Just simple, comma-separated, required arguments (no fancy syntax). We need
|
||||
this to be separate from the <strong>ArgList</strong> for use in <strong>Switch</strong> blocks, where
|
||||
having the newlines wouldn't make sense.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">SimpleArgs: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"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-49"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-49">#</a> </div> <p>The variants of <em>try/catch/finally</em> exception handling blocks.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Try: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"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-50"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-50">#</a> </div> <p>A catch clause names its error and runs a block of code.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Catch: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"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-51"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-51">#</a> </div> <p>Throw an exception object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Throw: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"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-52"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-52">#</a> </div> <p>Parenthetical expressions. Note that the <strong>Parenthetical</strong> is a <strong>Value</strong>,
|
||||
not an <strong>Expression</strong>, so if you need to use an expression in a place
|
||||
where only values are accepted, wrapping it in parentheses will always do
|
||||
the trick.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Parenthetical: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"( 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-53"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-53">#</a> </div> <p>The condition portion of a while loop.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">WhileSource: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"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="p">{</span><span class="nv">guard : </span><span class="nx">$4</span><span class="p">}</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="p">{</span><span class="nv">invert: </span><span class="kc">true</span><span class="p">}</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="p">{</span><span class="nv">invert: </span><span class="kc">true</span><span class="p">,</span> <span class="nv">guard: </span><span class="nx">$4</span><span class="p">}</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 while loop can either be normal, with a block of expressions to execute,
|
||||
or postfix, with a single expression. There is no do..while.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">While: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"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>
|
||||
<span class="nx">o</span> <span class="s2">"Expression 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>
|
||||
<span class="nx">o</span> <span class="s2">"Loop"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nv">Loop: </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-55"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-55">#</a> </div> <p>Array, object, and range comprehensions, at the most generic level.
|
||||
Comprehensions can either be normal, with a block of expressions to execute,
|
||||
or postfix, with a single expression.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">For: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Statement FOR ForVariables ForSource"</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">$4</span><span class="p">,</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression FOR ForVariables ForSource"</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">$4</span><span class="p">,</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"FOR ForVariables ForSource Block"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ForNode</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-56">#</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="nv">ForValue: </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-57"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-57">#</a> </div> <p>An array or range comprehension has variables for the current element and
|
||||
(optional) reference to the current index. Or, <em>key, value</em>, in the case
|
||||
of object comprehensions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ForVariables: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"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-58"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-58">#</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="nv">ForSource: </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="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"OF Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">object: </span><span class="kc">true</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"IN Expression WHEN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">guard: </span><span class="nx">$4</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"OF Expression WHEN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">guard: </span><span class="nx">$4</span><span class="p">,</span> <span class="nv">object: </span><span class="kc">true</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"IN Expression BY Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">step: </span> <span class="nx">$4</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"IN Expression WHEN Expression BY Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">guard: </span><span class="nx">$4</span><span class="p">,</span> <span class="nv">step: </span> <span class="nx">$6</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"IN Expression BY Expression WHEN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">step: </span> <span class="nx">$4</span><span class="p">,</span> <span class="nv">guard: </span><span class="nx">$6</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 CoffeeScript switch/when/else block replaces the JavaScript
|
||||
switch/case/default by compiling into an if-else chain.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Switch: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"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-60"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-60">#</a> </div> <p>The inner list of whens is left recursive. At code-generation time, the
|
||||
IfNode will rewrite them into a proper chain.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Whens: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"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-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="nv">When: </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="p">{</span><span class="nv">statement: </span><span class="kc">true</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="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="p">{</span><span class="nv">statement: </span><span class="kc">true</span><span class="p">}</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-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="nv">IfBlock: </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="p">{</span><span class="nv">invert: </span><span class="kc">true</span><span class="p">}</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-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="nv">If: </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="p">{</span><span class="nv">statement: </span><span class="kc">true</span><span class="p">}</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="p">{</span><span class="nv">statement: </span><span class="kc">true</span><span class="p">}</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="p">{</span><span class="nv">statement: </span><span class="kc">true</span><span class="p">,</span> <span class="nv">invert: </span><span class="kc">true</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"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="p">{</span><span class="nv">statement: </span><span class="kc">true</span><span class="p">,</span> <span class="nv">invert: </span><span class="kc">true</span><span class="p">}</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-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="nv">Operation: </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="nv">prec: </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="nv">prec: </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">"-- 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 -= 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>
|
||||
|
||||
<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)
|
||||
</code></pre>
|
||||
|
||||
<p>And not:</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">"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">'=='</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="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">'.'</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">"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">'ASSIGN'</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-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>
|
||||
<span class="k">for</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">alternatives</span> <span class="k">of</span> <span class="nx">grammar</span>
|
||||
<span class="nx">grammar</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span><span class="o">:</span> <span class="k">for</span> <span class="nx">alt</span> <span class="k">in</span> <span class="nx">alternatives</span>
|
||||
<span class="k">for</span> <span class="nx">token</span> <span class="k">in</span> <span class="nx">alt</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">split</span> <span class="s1">' '</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-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>
|
||||
<span class="nv">tokens: </span> <span class="nx">tokens</span><span class="p">.</span><span class="nx">join</span> <span class="s1">' '</span>
|
||||
<span class="nv">bnf: </span> <span class="nx">grammar</span>
|
||||
<span class="nv">operators: </span> <span class="nx">operators</span><span class="p">.</span><span class="nx">reverse</span><span class="p">()</span>
|
||||
<span class="nv">startSymbol: </span> <span class="s1">'Root'</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
36
documentation/docs/helpers.html
Normal file
36
documentation/docs/helpers.html
Normal file
@@ -0,0 +1,36 @@
|
||||
<!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
|
||||
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>
|
||||
<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>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="nv">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-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">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">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-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">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-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>
|
||||
<span class="nx">val</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
3
documentation/docs/index.html
Normal file
3
documentation/docs/index.html
Normal file
@@ -0,0 +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>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
413
documentation/docs/lexer.html
Normal file
413
documentation/docs/lexer.html
Normal file
@@ -0,0 +1,413 @@
|
||||
<!DOCTYPE html> <html> <head> <title>lexer.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> lexer.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 Lexer. Uses a series of token-matching regexes to attempt
|
||||
matches against the beginning of the source code. When a match is found,
|
||||
a token is produced, we consume the match, and start again. Tokens are in the
|
||||
form:</p>
|
||||
|
||||
<pre><code>[tag, value, lineNumber]
|
||||
</code></pre>
|
||||
|
||||
<p>Which is a format that can be fed directly into <a href="http://github.com/zaach/jison">Jison</a>.</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 the Lexer for both Node.js and the browser, depending on where we are.</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">Rewriter</span><span class="p">}</span><span class="o">:</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'./rewriter'</span><span class="p">)</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">Rewriter: </span> <span class="k">this</span><span class="p">.</span><span class="nx">Rewriter</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="nx">count</span><span class="p">,</span> <span class="nx">starts</span><span class="p">,</span> <span class="nx">compact</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> <h2>The Lexer Class</h2> </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>The Lexer class reads a stream of CoffeeScript and divvys it up into tagged
|
||||
tokens. Some potential ambiguity in the grammar has been avoided by
|
||||
pushing some extra smarts into the Lexer.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Lexer: </span><span class="nx">class</span> <span class="nx">Lexer</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p><strong>tokenize</strong> is the Lexer's main method. Scan by attempting to match tokens
|
||||
one at a time, using a regular expression anchored at the start of the
|
||||
remaining code, or a custom recursive token-matching method
|
||||
(for interpolations). When the next token has been recorded, we move forward
|
||||
within the code past the token, and begin again.</p>
|
||||
|
||||
<p>Each tokenizing method is responsible for incrementing <code>@i</code> by the number of
|
||||
characters it has consumed. <code>@i</code> can be thought of as our finger on the page
|
||||
of source.</p>
|
||||
|
||||
<p>Before returning the token stream, run it through the <a href="rewriter.html">Rewriter</a>
|
||||
unless explicitly asked not to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tokenize: </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">code : </span><span class="nx">code</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/(\r|\s+$)/g</span><span class="p">,</span> <span class="s1">''</span>
|
||||
<span class="nv">o : </span><span class="nx">options</span> <span class="o">or</span> <span class="p">{}</span>
|
||||
<span class="vi">@code : </span><span class="nx">code</span> <span class="c1"># The remainder of the source code.</span>
|
||||
<span class="vi">@i : </span><span class="mi">0</span> <span class="c1"># Current character position we're parsing.</span>
|
||||
<span class="vi">@line : </span><span class="nx">o</span><span class="p">.</span><span class="nx">line</span> <span class="o">or</span> <span class="mi">0</span> <span class="c1"># The current line.</span>
|
||||
<span class="vi">@indent : </span><span class="mi">0</span> <span class="c1"># The current indentation level.</span>
|
||||
<span class="vi">@outdebt : </span><span class="mi">0</span> <span class="c1"># The under-outdentation of the last outdent.</span>
|
||||
<span class="vi">@indents : </span><span class="p">[]</span> <span class="c1"># The stack of all current indentation levels.</span>
|
||||
<span class="vi">@tokens : </span><span class="p">[]</span> <span class="c1"># Stream of parsed tokens in the form ['TYPE', value, line]</span>
|
||||
<span class="k">while</span> <span class="nx">@i</span> <span class="o"><</span> <span class="nx">@code</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="vi">@chunk: </span><span class="nx">@code</span><span class="p">.</span><span class="nx">slice</span> <span class="nx">@i</span>
|
||||
<span class="nx">@extractNextToken</span><span class="p">()</span>
|
||||
<span class="nx">@closeIndentation</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="nx">@tokens</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">rewrite</span> <span class="o">is</span> <span class="kc">off</span>
|
||||
<span class="p">(</span><span class="k">new</span> <span class="nx">Rewriter</span><span class="p">()).</span><span class="nx">rewrite</span> <span class="nx">@tokens</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>At every position, run through this list of attempted matches,
|
||||
short-circuiting if any of them succeed. Their order determines precedence:
|
||||
<code>@literalToken</code> is the fallback catch-all.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">extractNextToken: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@identifierToken</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@commentToken</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@whitespaceToken</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@lineToken</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@heredocToken</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@stringToken</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@numberToken</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@regexToken</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@jsToken</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="nx">@literalToken</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <h2>Tokenizers</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Matches identifying literals: variables, keywords, method names, etc.
|
||||
Check to ensure that JavaScript reserved words aren't being used as
|
||||
identifiers. Because CoffeeScript reserves a handful of keywords that are
|
||||
allowed in JavaScript, we're careful not to tag them as keywords when
|
||||
referenced as property names here, so you can still do <code>jQuery.is()</code> even
|
||||
though <code>is</code> means <code>===</code> otherwise.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">identifierToken: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">id: </span><span class="nx">@match</span> <span class="nx">IDENTIFIER</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">id</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">forcedIdentifier: </span><span class="nx">@tagAccessor</span><span class="p">()</span> <span class="o">or</span> <span class="nx">@match</span> <span class="nx">ASSIGNED</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="nv">tag: </span><span class="s1">'IDENTIFIER'</span>
|
||||
<span class="nv">tag: </span><span class="nx">id</span><span class="p">.</span><span class="nx">toUpperCase</span><span class="p">()</span> <span class="k">if</span> <span class="nx">include</span><span class="p">(</span><span class="nx">JS_KEYWORDS</span><span class="p">,</span> <span class="nx">id</span><span class="p">)</span> <span class="o">or</span> <span class="p">(</span><span class="o">not</span> <span class="nx">forcedIdentifier</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">COFFEE_KEYWORDS</span><span class="p">,</span> <span class="nx">id</span><span class="p">))</span>
|
||||
<span class="nv">tag: </span><span class="s1">'LEADING_WHEN'</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'WHEN'</span> <span class="o">and</span> <span class="nx">include</span> <span class="nx">LINE_BREAK</span><span class="p">,</span> <span class="nx">@tag</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="nx">include</span><span class="p">(</span><span class="nx">JS_FORBIDDEN</span><span class="p">,</span> <span class="nx">id</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="nx">forcedIdentifier</span>
|
||||
<span class="nv">tag: </span><span class="s1">'STRING'</span>
|
||||
<span class="nv">id: </span> <span class="s2">"'$id'"</span>
|
||||
<span class="k">if</span> <span class="nx">forcedIdentifier</span> <span class="o">is</span> <span class="s1">'accessor'</span>
|
||||
<span class="nv">close_index: </span><span class="kc">true</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span> <span class="k">if</span> <span class="nx">@tag</span><span class="p">()</span> <span class="o">isnt</span> <span class="s1">'@'</span>
|
||||
<span class="nx">@token</span> <span class="s1">'INDEX_START'</span><span class="p">,</span> <span class="s1">'['</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">include</span><span class="p">(</span><span class="nx">RESERVED</span><span class="p">,</span> <span class="nx">id</span><span class="p">)</span>
|
||||
<span class="nx">@identifierError</span> <span class="nx">id</span>
|
||||
<span class="nx">unless</span> <span class="nx">forcedIdentifier</span>
|
||||
<span class="nv">tag: id: </span><span class="nx">CONVERSIONS</span><span class="p">[</span><span class="nx">id</span><span class="p">]</span> <span class="k">if</span> <span class="nx">include</span> <span class="nx">COFFEE_ALIASES</span><span class="p">,</span> <span class="nx">id</span>
|
||||
<span class="k">return</span> <span class="nx">@tagHalfAssignment</span> <span class="nx">tag</span> <span class="k">if</span> <span class="nx">@prev</span><span class="p">()</span> <span class="o">and</span> <span class="nx">@prev</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'ASSIGN'</span> <span class="o">and</span> <span class="nx">include</span> <span class="nx">HALF_ASSIGNMENTS</span><span class="p">,</span> <span class="nx">tag</span>
|
||||
<span class="nx">@token</span> <span class="nx">tag</span><span class="p">,</span> <span class="nx">id</span>
|
||||
<span class="nx">@token</span> <span class="s1">']'</span><span class="p">,</span> <span class="s1">']'</span> <span class="k">if</span> <span class="nx">close_index</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Matches numbers, including decimals, hex, and exponential notation.
|
||||
Be careful not to interfere with ranges-in-progress.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">numberToken: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">number: </span><span class="nx">@match</span> <span class="nx">NUMBER</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="k">if</span> <span class="nx">@tag</span><span class="p">()</span> <span class="o">is</span> <span class="s1">'.'</span> <span class="o">and</span> <span class="nx">starts</span> <span class="nx">number</span><span class="p">,</span> <span class="s1">'.'</span>
|
||||
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">number</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nx">@token</span> <span class="s1">'NUMBER'</span><span class="p">,</span> <span class="nx">number</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Matches strings, including multi-line strings. Ensures that quotation marks
|
||||
are balanced within the string's contents, and within nested interpolations.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">stringToken: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nx">starts</span><span class="p">(</span><span class="nx">@chunk</span><span class="p">,</span> <span class="s1">'"'</span><span class="p">)</span> <span class="o">or</span> <span class="nx">starts</span><span class="p">(</span><span class="nx">@chunk</span><span class="p">,</span> <span class="s2">"'"</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">string:</span>
|
||||
<span class="nx">@balancedToken</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="o">or</span>
|
||||
<span class="nx">@balancedToken</span> <span class="p">[</span><span class="s2">"'"</span><span class="p">,</span> <span class="s2">"'"</span><span class="p">]</span>
|
||||
<span class="nx">@interpolateString</span> <span class="nx">string</span><span class="p">.</span><span class="nx">replace</span> <span class="nx">STRING_NEWLINES</span><span class="p">,</span> <span class="s2">" \\\n"</span>
|
||||
<span class="vi">@line: </span><span class="o">+</span> <span class="nx">count</span> <span class="nx">string</span><span class="p">,</span> <span class="s2">"\n"</span>
|
||||
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">string</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>Matches heredocs, adjusting indentation to the correct level, as heredocs
|
||||
preserve whitespace, but ignore indentation to the left.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">heredocToken: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">match: </span><span class="nx">@chunk</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">HEREDOC</span><span class="p">)</span>
|
||||
<span class="nv">quote: </span><span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">substr</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="nv">doc: </span><span class="nx">@sanitizeHeredoc</span> <span class="nx">match</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">or</span> <span class="nx">match</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="p">{</span><span class="nx">quote</span><span class="p">}</span>
|
||||
<span class="nx">@interpolateString</span> <span class="s2">"$quote$doc$quote"</span>
|
||||
<span class="vi">@line: </span><span class="o">+</span> <span class="nx">count</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="s2">"\n"</span>
|
||||
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">length</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>Matches and conumes comments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">commentToken: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">match: </span><span class="nx">@chunk</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">COMMENT</span><span class="p">)</span>
|
||||
<span class="vi">@line: </span><span class="o">+</span> <span class="nx">count</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="s2">"\n"</span>
|
||||
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">length</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</a> </div> <p>Matches JavaScript interpolated directly into the source via backticks.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">jsToken: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nx">starts</span> <span class="nx">@chunk</span><span class="p">,</span> <span class="s1">'`'</span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">script: </span><span class="nx">@balancedToken</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="s1">'JS'</span><span class="p">,</span> <span class="nx">script</span><span class="p">.</span><span class="nx">replace</span> <span class="nx">JS_CLEANER</span><span class="p">,</span> <span class="s1">''</span>
|
||||
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">script</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>Matches regular expression literals. Lexing regular expressions is difficult
|
||||
to distinguish from division, so we borrow some basic heuristics from
|
||||
JavaScript and Ruby, borrow slash balancing from <code>@balancedToken</code>, and
|
||||
borrow interpolation from <code>@interpolateString</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">regexToken: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nx">@chunk</span><span class="p">.</span><span class="nx">match</span> <span class="nx">REGEX_START</span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="k">if</span> <span class="nx">include</span> <span class="nx">NOT_REGEX</span><span class="p">,</span> <span class="nx">@tag</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">regex: </span><span class="nx">@balancedToken</span> <span class="p">[</span><span class="s1">'/'</span><span class="p">,</span> <span class="s1">'/'</span><span class="p">]</span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">end: </span><span class="nx">@chunk</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="nx">regex</span><span class="p">.</span><span class="nx">length</span><span class="p">).</span><span class="nx">match</span> <span class="nx">REGEX_END</span>
|
||||
<span class="nv">regex: </span><span class="o">+</span> <span class="nv">flags: </span><span class="nx">end</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="k">if</span> <span class="nx">end</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="nx">regex</span><span class="p">.</span><span class="nx">match</span> <span class="nx">REGEX_INTERPOLATION</span>
|
||||
<span class="nv">str: </span><span class="nx">regex</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">1</span><span class="p">).</span><span class="nx">split</span><span class="p">(</span><span class="s1">'/'</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nv">str: </span><span class="nx">str</span><span class="p">.</span><span class="nx">replace</span> <span class="nx">REGEX_ESCAPE</span><span class="p">,</span> <span class="p">(</span><span class="nx">escaped</span><span class="p">)</span> <span class="o">-></span> <span class="s1">'\\'</span> <span class="o">+</span> <span class="nx">escaped</span>
|
||||
<span class="vi">@tokens: </span><span class="nx">@tokens</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[[</span><span class="s1">'('</span><span class="p">,</span> <span class="s1">'('</span><span class="p">],</span> <span class="p">[</span><span class="s1">'NEW'</span><span class="p">,</span> <span class="s1">'new'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'RegExp'</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">@interpolateString</span> <span class="s2">"\"$str\""</span><span class="p">,</span> <span class="kc">yes</span>
|
||||
<span class="vi">@tokens: </span><span class="nx">@tokens</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[[</span><span class="s1">','</span><span class="p">,</span> <span class="s1">','</span><span class="p">],</span> <span class="p">[</span><span class="s1">'STRING'</span><span class="p">,</span> <span class="s2">"\"$flags\""</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="k">else</span>
|
||||
<span class="nx">@token</span> <span class="s1">'REGEX'</span><span class="p">,</span> <span class="nx">regex</span>
|
||||
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">regex</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</a> </div> <p>Matches a token in which which the passed delimiter pairs must be correctly
|
||||
balanced (ie. strings, JS literals).</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">balancedToken: </span><span class="p">(</span><span class="nx">delimited</span><span class="p">...)</span> <span class="o">-></span>
|
||||
<span class="nx">@balancedString</span> <span class="nx">@chunk</span><span class="p">,</span> <span class="nx">delimited</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>Matches newlines, indents, and outdents, and determines which is which.
|
||||
If we can detect that the current line is continued onto the the next line,
|
||||
then the newline is suppressed:</p>
|
||||
|
||||
<pre><code>elements
|
||||
.each( ... )
|
||||
.map( ... )
|
||||
</code></pre>
|
||||
|
||||
<p>Keeps track of the level of indentation, because a single outdent token
|
||||
can close multiple indents, so we need to know how far in we happen to be.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">lineToken: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">indent: </span><span class="nx">@match</span> <span class="nx">MULTI_DENT</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="vi">@line: </span><span class="o">+</span> <span class="nx">count</span> <span class="nx">indent</span><span class="p">,</span> <span class="s2">"\n"</span>
|
||||
<span class="vi">@i : </span><span class="o">+</span> <span class="nx">indent</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">prev: </span><span class="nx">@prev</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
|
||||
<span class="nv">size: </span><span class="nx">indent</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">LAST_DENTS</span><span class="p">).</span><span class="nx">reverse</span><span class="p">()[</span><span class="mi">0</span><span class="p">].</span><span class="nx">match</span><span class="p">(</span><span class="nx">LAST_DENT</span><span class="p">)[</span><span class="mi">1</span><span class="p">].</span><span class="nx">length</span>
|
||||
<span class="nv">nextCharacter: </span><span class="nx">@match</span> <span class="nx">NEXT_CHARACTER</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="nv">noNewlines: </span><span class="nx">nextCharacter</span> <span class="o">is</span> <span class="s1">'.'</span> <span class="o">or</span> <span class="nx">nextCharacter</span> <span class="o">is</span> <span class="s1">','</span> <span class="o">or</span> <span class="nx">@unfinished</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="nx">size</span> <span class="o">is</span> <span class="nx">@indent</span>
|
||||
<span class="k">return</span> <span class="nx">@suppressNewlines</span><span class="p">()</span> <span class="k">if</span> <span class="nx">noNewlines</span>
|
||||
<span class="k">return</span> <span class="nx">@newlineToken</span> <span class="nx">indent</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">size</span> <span class="o">></span> <span class="nx">@indent</span>
|
||||
<span class="k">return</span> <span class="nx">@suppressNewlines</span><span class="p">()</span> <span class="k">if</span> <span class="nx">noNewlines</span>
|
||||
<span class="nv">diff: </span><span class="nx">size</span> <span class="o">-</span> <span class="nx">@indent</span>
|
||||
<span class="nx">@token</span> <span class="s1">'INDENT'</span><span class="p">,</span> <span class="nx">diff</span>
|
||||
<span class="nx">@indents</span><span class="p">.</span><span class="nx">push</span> <span class="nx">diff</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">@outdentToken</span> <span class="nx">@indent</span> <span class="o">-</span> <span class="nx">size</span><span class="p">,</span> <span class="nx">noNewlines</span>
|
||||
<span class="vi">@indent: </span><span class="nx">size</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-18">#</a> </div> <p>Record an outdent token or multiple tokens, if we happen to be moving back
|
||||
inwards past several recorded indents.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">outdentToken: </span><span class="p">(</span><span class="nx">moveOut</span><span class="p">,</span> <span class="nx">noNewlines</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">moveOut</span> <span class="o">></span> <span class="o">-</span><span class="nx">@outdebt</span>
|
||||
<span class="k">while</span> <span class="nx">moveOut</span> <span class="o">></span> <span class="mi">0</span> <span class="o">and</span> <span class="nx">@indents</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">lastIndent: </span><span class="nx">@indents</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="nx">@token</span> <span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="nx">lastIndent</span>
|
||||
<span class="nv">moveOut: </span><span class="o">-</span> <span class="nx">lastIndent</span>
|
||||
<span class="k">else</span>
|
||||
<span class="vi">@outdebt: </span><span class="o">+</span> <span class="nx">moveOut</span>
|
||||
<span class="vi">@outdebt: </span><span class="nx">moveOut</span> <span class="nx">unless</span> <span class="nx">noNewlines</span>
|
||||
<span class="nx">@token</span> <span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s2">"\n"</span> <span class="nx">unless</span> <span class="nx">@tag</span><span class="p">()</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span> <span class="o">or</span> <span class="nx">noNewlines</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-19">#</a> </div> <p>Matches and consumes non-meaningful whitespace. Tag the previous token
|
||||
as being "spaced", because there are some cases where it makes a difference.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">whitespaceToken: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">space: </span><span class="nx">@match</span> <span class="nx">WHITESPACE</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="nv">prev: </span><span class="nx">@prev</span><span class="p">()</span>
|
||||
<span class="nv">prev.spaced: </span><span class="kc">true</span> <span class="k">if</span> <span class="nx">prev</span>
|
||||
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">space</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-20">#</a> </div> <p>Generate a newline token. Consecutive newlines get merged together.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">newlineToken: </span><span class="p">(</span><span class="nx">newlines</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@token</span> <span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s2">"\n"</span> <span class="nx">unless</span> <span class="nx">@tag</span><span class="p">()</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-21">#</a> </div> <p>Use a <code>\</code> at a line-ending to suppress the newline.
|
||||
The slash is removed here once its job is done.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">suppressNewlines: </span><span class="o">-></span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span> <span class="k">if</span> <span class="nx">@value</span><span class="p">()</span> <span class="o">is</span> <span class="s2">"\\"</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-22">#</a> </div> <p>We treat all other single characters as a token. Eg.: <code>( ) , . !</code>
|
||||
Multi-character operators are also literal tokens, so that Jison can assign
|
||||
the proper order of operations. There are some symbols that we tag specially
|
||||
here. <code>;</code> and newlines are both treated as a <code>TERMINATOR</code>, we distinguish
|
||||
parentheses that indicate a method call from regular parentheses, and so on.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">literalToken: </span><span class="o">-></span>
|
||||
<span class="nv">match: </span><span class="nx">@chunk</span><span class="p">.</span><span class="nx">match</span> <span class="nx">OPERATOR</span>
|
||||
<span class="nv">value: </span><span class="nx">match</span> <span class="o">and</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nv">space: </span><span class="nx">match</span> <span class="o">and</span> <span class="nx">match</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="nx">@tagParameters</span><span class="p">()</span> <span class="k">if</span> <span class="nx">value</span> <span class="o">and</span> <span class="nx">value</span><span class="p">.</span><span class="nx">match</span> <span class="nx">CODE</span>
|
||||
<span class="nv">value: </span><span class="o">or</span> <span class="nx">@chunk</span><span class="p">.</span><span class="nx">substr</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="nv">prevSpaced: </span><span class="nx">@prev</span><span class="p">()</span> <span class="o">and</span> <span class="nx">@prev</span><span class="p">().</span><span class="nx">spaced</span>
|
||||
<span class="nv">tag: </span><span class="nx">value</span>
|
||||
<span class="k">if</span> <span class="nx">value</span><span class="p">.</span><span class="nx">match</span> <span class="nx">ASSIGNMENT</span>
|
||||
<span class="nv">tag: </span><span class="s1">'ASSIGN'</span>
|
||||
<span class="nx">@assignmentError</span><span class="p">()</span> <span class="k">if</span> <span class="nx">include</span> <span class="nx">JS_FORBIDDEN</span><span class="p">,</span> <span class="nx">@value</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">value</span> <span class="o">is</span> <span class="s1">';'</span>
|
||||
<span class="nv">tag: </span><span class="s1">'TERMINATOR'</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">include</span><span class="p">(</span><span class="nx">CALLABLE</span><span class="p">,</span> <span class="nx">@tag</span><span class="p">())</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">prevSpaced</span>
|
||||
<span class="k">if</span> <span class="nx">value</span> <span class="o">is</span> <span class="s1">'('</span>
|
||||
<span class="nv">tag: </span><span class="s1">'CALL_START'</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">value</span> <span class="o">is</span> <span class="s1">'['</span>
|
||||
<span class="nv">tag: </span><span class="s1">'INDEX_START'</span>
|
||||
<span class="nx">@tag</span> <span class="mi">1</span><span class="p">,</span> <span class="s1">'INDEX_SOAK'</span> <span class="k">if</span> <span class="nx">@tag</span><span class="p">()</span> <span class="o">is</span> <span class="s1">'?'</span>
|
||||
<span class="nx">@tag</span> <span class="mi">1</span><span class="p">,</span> <span class="s1">'INDEX_PROTO'</span> <span class="k">if</span> <span class="nx">@tag</span><span class="p">()</span> <span class="o">is</span> <span class="s1">'::'</span>
|
||||
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">value</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="k">return</span> <span class="nx">@tagHalfAssignment</span> <span class="nx">tag</span> <span class="k">if</span> <span class="nx">space</span> <span class="o">and</span> <span class="nx">prevSpaced</span> <span class="o">and</span> <span class="nx">@prev</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'ASSIGN'</span> <span class="o">and</span> <span class="nx">include</span> <span class="nx">HALF_ASSIGNMENTS</span><span class="p">,</span> <span class="nx">tag</span>
|
||||
<span class="nx">@token</span> <span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-23">#</a> </div> <h2>Token Manipulators</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-24">#</a> </div> <p>As we consume a new <code>IDENTIFIER</code>, look at the previous token to determine
|
||||
if it's a special kind of accessor. Return <code>true</code> if any type of accessor
|
||||
is the previous token.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tagAccessor: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="k">if</span> <span class="p">(</span><span class="o">not</span> <span class="nv">prev: </span><span class="nx">@prev</span><span class="p">())</span> <span class="o">or</span> <span class="p">(</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="p">)</span>
|
||||
<span class="nv">accessor: </span><span class="k">if</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'::'</span>
|
||||
<span class="nx">@tag</span> <span class="mi">1</span><span class="p">,</span> <span class="s1">'PROTOTYPE_ACCESS'</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'.'</span> <span class="o">and</span> <span class="o">not</span> <span class="p">(</span><span class="nx">@value</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'.'</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="nx">@tag</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'?'</span>
|
||||
<span class="nx">@tag</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s1">'SOAK_ACCESS'</span><span class="p">)</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">@tag</span> <span class="mi">1</span><span class="p">,</span> <span class="s1">'PROPERTY_ACCESS'</span>
|
||||
<span class="k">else</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">if</span> <span class="nx">accessor</span> <span class="k">then</span> <span class="s1">'accessor'</span> <span class="k">else</span> <span class="kc">false</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-25">#</a> </div> <p>Sanitize a heredoc by escaping internal double quotes and
|
||||
erasing all external indentation on the left-hand side.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">sanitizeHeredoc: </span><span class="p">(</span><span class="nx">doc</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">while</span> <span class="nv">match: </span><span class="nx">HEREDOC_INDENT</span><span class="p">.</span><span class="nx">exec</span> <span class="nx">doc</span>
|
||||
<span class="nv">attempt: </span><span class="k">if</span> <span class="nx">match</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">?</span> <span class="k">then</span> <span class="nx">match</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="k">else</span> <span class="nx">match</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span>
|
||||
<span class="nv">indent: </span><span class="nx">attempt</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">indent</span> <span class="o">or</span> <span class="nx">attempt</span><span class="p">.</span><span class="nx">length</span> <span class="o"><</span> <span class="nx">indent</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nx">doc</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="s2">"^"</span> <span class="o">+</span><span class="nx">indent</span><span class="p">,</span> <span class="s1">'gm'</span><span class="p">),</span> <span class="s1">''</span><span class="p">)</span>
|
||||
<span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="nx">MULTILINER</span><span class="p">,</span> <span class="s2">"\\n"</span><span class="p">)</span>
|
||||
<span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">quote</span><span class="p">,</span> <span class="s1">'g'</span><span class="p">),</span> <span class="s2">"\\$options.quote"</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>Tag a half assignment.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tagHalfAssignment: </span><span class="p">(</span><span class="nx">tag</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">last: </span><span class="nx">@tokens</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s2">"$tag="</span><span class="p">,</span> <span class="s2">"$tag="</span><span class="p">,</span> <span class="nx">last</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-27">#</a> </div> <p>A source of ambiguity in our grammar used to be parameter lists in function
|
||||
definitions versus argument lists in function calls. Walk backwards, tagging
|
||||
parameters specially in order to make things easier for the parser.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tagParameters: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@tag</span><span class="p">()</span> <span class="o">isnt</span> <span class="s1">')'</span>
|
||||
<span class="nv">i: </span><span class="mi">0</span>
|
||||
<span class="nx">loop</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="nv">tok: </span><span class="nx">@prev</span> <span class="nx">i</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">tok</span>
|
||||
<span class="k">switch</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="k">when</span> <span class="s1">'IDENTIFIER'</span> <span class="k">then</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">:</span> <span class="s1">'PARAM'</span>
|
||||
<span class="k">when</span> <span class="s1">')'</span> <span class="k">then</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">:</span> <span class="s1">'PARAM_END'</span>
|
||||
<span class="k">when</span> <span class="s1">'('</span><span class="p">,</span> <span class="s1">'CALL_START'</span> <span class="k">then</span> <span class="k">return</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">:</span> <span class="s1">'PARAM_START'</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-28">#</a> </div> <p>Close up all remaining open blocks at the end of the file.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">closeIndentation: </span><span class="o">-></span>
|
||||
<span class="nx">@outdentToken</span> <span class="nx">@indent</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-29">#</a> </div> <p>The error for when you try to use a forbidden word in JavaScript as
|
||||
an identifier.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">identifierError: </span><span class="p">(</span><span class="nx">word</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">"SyntaxError: Reserved word \"$word\" on line ${@line + 1}"</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-30">#</a> </div> <p>The error for when you try to assign to a reserved word in JavaScript,
|
||||
like "function" or "default".</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">assignmentError: </span><span class="o">-></span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"SyntaxError: Reserved word \"${@value()}\" on line ${@line + 1} can't be assigned"</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-31">#</a> </div> <p>Matches a balanced group such as a single or double-quoted string. Pass in
|
||||
a series of delimiters, all of which must be nested correctly within the
|
||||
contents of the string. This method allows us to have strings within
|
||||
interpolations within strings, ad infinitum.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">balancedString: </span><span class="p">(</span><span class="nx">str</span><span class="p">,</span> <span class="nx">delimited</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">options: </span><span class="o">or</span> <span class="p">{}</span>
|
||||
<span class="nv">slash: </span><span class="nx">delimited</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">'/'</span>
|
||||
<span class="nv">levels: </span><span class="p">[]</span>
|
||||
<span class="nv">i: </span><span class="mi">0</span>
|
||||
<span class="k">while</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">str</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="k">if</span> <span class="nx">levels</span><span class="p">.</span><span class="nx">length</span> <span class="o">and</span> <span class="nx">starts</span> <span class="nx">str</span><span class="p">,</span> <span class="s1">'\\'</span><span class="p">,</span> <span class="nx">i</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="k">else</span>
|
||||
<span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">delimited</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="k">if</span> <span class="nx">levels</span><span class="p">.</span><span class="nx">length</span> <span class="o">and</span> <span class="nx">starts</span><span class="p">(</span><span class="nx">str</span><span class="p">,</span> <span class="nx">close</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">and</span> <span class="nx">levels</span><span class="p">[</span><span class="nx">levels</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="nx">pair</span>
|
||||
<span class="nx">levels</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="nx">close</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">levels</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="k">break</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">starts</span> <span class="nx">str</span><span class="p">,</span> <span class="nx">open</span><span class="p">,</span> <span class="nx">i</span>
|
||||
<span class="nx">levels</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">pair</span><span class="p">)</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="nx">open</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="k">break</span>
|
||||
<span class="k">break</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">levels</span><span class="p">.</span><span class="nx">length</span> <span class="o">or</span> <span class="nx">slash</span> <span class="o">and</span> <span class="nx">starts</span> <span class="nx">str</span><span class="p">,</span> <span class="s1">'\n'</span><span class="p">,</span> <span class="nx">i</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="k">if</span> <span class="nx">levels</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="k">if</span> <span class="nx">slash</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"SyntaxError: Unterminated ${levels.pop()[0]} starting on line ${@line + 1}"</span>
|
||||
<span class="k">if</span> <span class="o">not</span> <span class="nx">i</span> <span class="k">then</span> <span class="kc">false</span> <span class="k">else</span> <span class="nx">str</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-32">#</a> </div> <p>Expand variables and expressions inside double-quoted strings using
|
||||
<a href="http://wiki.ecmascript.org/doku.php?id=strawman:string_interpolation">ECMA Harmony's interpolation syntax</a>
|
||||
for substitution of bare variables as well as arbitrary expressions.</p>
|
||||
|
||||
<pre><code>"Hello $name."
|
||||
"Hello ${name.capitalize()}."
|
||||
</code></pre>
|
||||
|
||||
<p>If it encounters an interpolation, this method will recursively create a
|
||||
new Lexer, tokenize the interpolated contents, and merge them into the
|
||||
token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">interpolateString: </span><span class="p">(</span><span class="nx">str</span><span class="p">,</span> <span class="nx">escapeQuotes</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">str</span><span class="p">.</span><span class="nx">length</span> <span class="o"><</span> <span class="mi">3</span> <span class="o">or</span> <span class="o">not</span> <span class="nx">starts</span> <span class="nx">str</span><span class="p">,</span> <span class="s1">'"'</span>
|
||||
<span class="nx">@token</span> <span class="s1">'STRING'</span><span class="p">,</span> <span class="nx">str</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">lexer: </span> <span class="k">new</span> <span class="nx">Lexer</span><span class="p">()</span>
|
||||
<span class="nv">tokens: </span> <span class="p">[]</span>
|
||||
<span class="nv">quote: </span> <span class="nx">str</span><span class="p">.</span><span class="nx">substring</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="p">[</span><span class="nx">i</span><span class="p">,</span> <span class="nx">pi</span><span class="p">]</span><span class="o">:</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
|
||||
<span class="k">while</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">str</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="k">if</span> <span class="nx">starts</span> <span class="nx">str</span><span class="p">,</span> <span class="s1">'\\'</span><span class="p">,</span> <span class="nx">i</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nv">match: </span><span class="nx">str</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="nx">i</span><span class="p">).</span><span class="nx">match</span> <span class="nx">INTERPOLATION</span>
|
||||
<span class="p">[</span><span class="nx">group</span><span class="p">,</span> <span class="nx">interp</span><span class="p">]</span><span class="o">:</span> <span class="nx">match</span>
|
||||
<span class="nv">interp: </span><span class="s2">"this.${ interp.substring(1) }"</span> <span class="k">if</span> <span class="nx">starts</span> <span class="nx">interp</span><span class="p">,</span> <span class="s1">'@'</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">'STRING'</span><span class="p">,</span> <span class="s2">"$quote${ str.substring(pi, i) }$quote"</span><span class="p">]</span> <span class="k">if</span> <span class="nx">pi</span> <span class="o"><</span> <span class="nx">i</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="nx">interp</span><span class="p">]</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="nx">group</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nv">pi: </span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nv">expr: </span><span class="nx">@balancedString</span> <span class="nx">str</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="nx">i</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">push</span> <span class="p">[</span><span class="s1">'STRING'</span><span class="p">,</span> <span class="s2">"$quote${ str.substring(pi, i) }$quote"</span><span class="p">]</span> <span class="k">if</span> <span class="nx">pi</span> <span class="o"><</span> <span class="nx">i</span>
|
||||
<span class="nv">inner: </span><span class="nx">expr</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="nx">inner</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">nested: </span><span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="s2">"($inner)"</span><span class="p">,</span> <span class="p">{</span><span class="nv">line: </span><span class="nx">@line</span><span class="p">}</span>
|
||||
<span class="p">(</span><span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">:</span> <span class="s1">')'</span><span class="p">)</span> <span class="k">for</span> <span class="nx">tok</span><span class="p">,</span> <span class="nx">idx</span> <span class="k">in</span> <span class="nx">nested</span> <span class="k">when</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'CALL_END'</span>
|
||||
<span class="nx">nested</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">'TOKENS'</span><span class="p">,</span> <span class="nx">nested</span><span class="p">]</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">'STRING'</span><span class="p">,</span> <span class="s2">"$quote$quote"</span><span class="p">]</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nv">pi: </span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">'STRING'</span><span class="p">,</span> <span class="s2">"$quote${ str.substring(pi, i) }$quote"</span><span class="p">]</span> <span class="k">if</span> <span class="nx">pi</span> <span class="o"><</span> <span class="nx">i</span> <span class="o">and</span> <span class="nx">pi</span> <span class="o"><</span> <span class="nx">str</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">unshift</span> <span class="p">[</span><span class="s1">'STRING'</span><span class="p">,</span> <span class="s1">'""'</span><span class="p">]</span> <span class="nx">unless</span> <span class="nx">tokens</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'STRING'</span>
|
||||
<span class="nv">interpolated: </span><span class="nx">tokens</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">1</span>
|
||||
<span class="nx">@token</span> <span class="s1">'('</span><span class="p">,</span> <span class="s1">'('</span> <span class="k">if</span> <span class="nx">interpolated</span>
|
||||
<span class="k">for</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">tokens</span>
|
||||
<span class="p">[</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span><span class="p">]</span><span class="o">:</span> <span class="nx">token</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'TOKENS'</span>
|
||||
<span class="vi">@tokens: </span><span class="nx">@tokens</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">value</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'STRING'</span> <span class="o">and</span> <span class="nx">escapeQuotes</span>
|
||||
<span class="nv">escaped: </span><span class="nx">value</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nx">value</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">).</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/"/g</span><span class="p">,</span> <span class="s1">'\\"'</span><span class="p">)</span>
|
||||
<span class="nx">@token</span> <span class="nx">tag</span><span class="p">,</span> <span class="s2">"\"$escaped\""</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">@token</span> <span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span>
|
||||
<span class="nx">@token</span> <span class="s1">'+'</span><span class="p">,</span> <span class="s1">'+'</span> <span class="k">if</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">tokens</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nx">@token</span> <span class="s1">')'</span><span class="p">,</span> <span class="s1">')'</span> <span class="k">if</span> <span class="nx">interpolated</span>
|
||||
<span class="nx">tokens</span></pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-33">#</a> </div> <h2>Helpers</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-34">#</a> </div> <p>Add a token to the results, taking note of the line number.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">token: </span><span class="p">(</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">@line</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-35">#</a> </div> <p>Peek at a tag in the current token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tag: </span><span class="p">(</span><span class="nx">index</span><span class="p">,</span> <span class="nx">newTag</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="nx">unless</span> <span class="nv">tok: </span><span class="nx">@prev</span> <span class="nx">index</span>
|
||||
<span class="k">return</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">:</span> <span class="nx">newTag</span> <span class="k">if</span> <span class="nx">newTag</span><span class="o">?</span>
|
||||
<span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-36">#</a> </div> <p>Peek at a value in the current token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">value: </span><span class="p">(</span><span class="nx">index</span><span class="p">,</span> <span class="nx">val</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="nx">unless</span> <span class="nv">tok: </span><span class="nx">@prev</span> <span class="nx">index</span>
|
||||
<span class="k">return</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">:</span> <span class="nx">val</span> <span class="k">if</span> <span class="nx">val</span><span class="o">?</span>
|
||||
<span class="nx">tok</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-37"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-37">#</a> </div> <p>Peek at a previous token, entire.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">prev: </span><span class="p">(</span><span class="nx">index</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@tokens</span><span class="p">[</span><span class="nx">@tokens</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="p">(</span><span class="nx">index</span> <span class="o">or</span> <span class="mi">1</span><span class="p">)]</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-38">#</a> </div> <p>Attempt to match a string against the current chunk, returning the indexed
|
||||
match if successful, and <code>false</code> otherwise.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">match: </span><span class="p">(</span><span class="nx">regex</span><span class="p">,</span> <span class="nx">index</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">m: </span><span class="nx">@chunk</span><span class="p">.</span><span class="nx">match</span> <span class="nx">regex</span>
|
||||
<span class="k">if</span> <span class="nx">m</span> <span class="k">then</span> <span class="nx">m</span><span class="p">[</span><span class="nx">index</span><span class="p">]</span> <span class="k">else</span> <span class="kc">false</span></pre></div> </td> </tr> <tr id="section-39"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-39">#</a> </div> <p>Are we in the midst of an unfinished expression?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">unfinished: </span><span class="o">-></span>
|
||||
<span class="nv">prev: </span><span class="nx">@prev</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
|
||||
<span class="nx">@value</span><span class="p">()</span> <span class="o">and</span> <span class="nx">@value</span><span class="p">().</span><span class="nx">match</span> <span class="o">and</span> <span class="nx">@value</span><span class="p">().</span><span class="nx">match</span><span class="p">(</span><span class="nx">NO_NEWLINE</span><span class="p">)</span> <span class="o">and</span>
|
||||
<span class="nx">prev</span> <span class="o">and</span> <span class="p">(</span><span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'.'</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@value</span><span class="p">().</span><span class="nx">match</span><span class="p">(</span><span class="nx">CODE</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-40">#</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-41">#</a> </div> <p>Keywords that CoffeeScript shares in common with JavaScript.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">JS_KEYWORDS: </span><span class="p">[</span>
|
||||
<span class="s2">"if"</span><span class="p">,</span> <span class="s2">"else"</span><span class="p">,</span>
|
||||
<span class="s2">"true"</span><span class="p">,</span> <span class="s2">"false"</span><span class="p">,</span>
|
||||
<span class="s2">"new"</span><span class="p">,</span> <span class="s2">"return"</span><span class="p">,</span>
|
||||
<span class="s2">"try"</span><span class="p">,</span> <span class="s2">"catch"</span><span class="p">,</span> <span class="s2">"finally"</span><span class="p">,</span> <span class="s2">"throw"</span><span class="p">,</span>
|
||||
<span class="s2">"break"</span><span class="p">,</span> <span class="s2">"continue"</span><span class="p">,</span>
|
||||
<span class="s2">"for"</span><span class="p">,</span> <span class="s2">"in"</span><span class="p">,</span> <span class="s2">"while"</span><span class="p">,</span>
|
||||
<span class="s2">"delete"</span><span class="p">,</span> <span class="s2">"instanceof"</span><span class="p">,</span> <span class="s2">"typeof"</span><span class="p">,</span>
|
||||
<span class="s2">"switch"</span><span class="p">,</span> <span class="s2">"super"</span><span class="p">,</span> <span class="s2">"extends"</span><span class="p">,</span> <span class="s2">"class"</span><span class="p">,</span>
|
||||
<span class="s2">"this"</span><span class="p">,</span> <span class="s2">"null"</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>CoffeeScript-only keywords, which we're more relaxed about allowing. They can't
|
||||
be used standalone, but you can reference them as an attached property.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">COFFEE_ALIASES: </span> <span class="p">[</span><span class="s2">"and"</span><span class="p">,</span> <span class="s2">"or"</span><span class="p">,</span> <span class="s2">"is"</span><span class="p">,</span> <span class="s2">"isnt"</span><span class="p">,</span> <span class="s2">"not"</span><span class="p">]</span>
|
||||
<span class="nv">COFFEE_KEYWORDS: </span><span class="nx">COFFEE_ALIASES</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[</span>
|
||||
<span class="s2">"then"</span><span class="p">,</span> <span class="s2">"unless"</span><span class="p">,</span> <span class="s2">"until"</span><span class="p">,</span> <span class="s2">"loop"</span><span class="p">,</span>
|
||||
<span class="s2">"yes"</span><span class="p">,</span> <span class="s2">"no"</span><span class="p">,</span> <span class="s2">"on"</span><span class="p">,</span> <span class="s2">"off"</span><span class="p">,</span>
|
||||
<span class="s2">"of"</span><span class="p">,</span> <span class="s2">"by"</span><span class="p">,</span> <span class="s2">"where"</span><span class="p">,</span> <span class="s2">"when"</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-43">#</a> </div> <p>The list of keywords that are reserved by JavaScript, but not used, or are
|
||||
used by CoffeeScript internally. We throw an error when these are encountered,
|
||||
to avoid having a JavaScript error at runtime.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">RESERVED: </span><span class="p">[</span>
|
||||
<span class="s2">"case"</span><span class="p">,</span> <span class="s2">"default"</span><span class="p">,</span> <span class="s2">"do"</span><span class="p">,</span> <span class="s2">"function"</span><span class="p">,</span> <span class="s2">"var"</span><span class="p">,</span> <span class="s2">"void"</span><span class="p">,</span> <span class="s2">"with"</span>
|
||||
<span class="s2">"const"</span><span class="p">,</span> <span class="s2">"let"</span><span class="p">,</span> <span class="s2">"enum"</span><span class="p">,</span> <span class="s2">"export"</span><span class="p">,</span> <span class="s2">"import"</span><span class="p">,</span> <span class="s2">"native"</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-44">#</a> </div> <p>The superset of both JavaScript keywords and reserved words, none of which may
|
||||
be used as identifiers or properties.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">JS_FORBIDDEN: </span><span class="nx">JS_KEYWORDS</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">RESERVED</span></pre></div> </td> </tr> <tr id="section-45"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-45">#</a> </div> <p>Token matching regexes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IDENTIFIER : </span><span class="sr">/^([a-zA-Z\$_](\w|\$)*)/</span>
|
||||
<span class="nv">NUMBER : </span><span class="sr">/^(((\b0(x|X)[0-9a-fA-F]+)|((\b[0-9]+(\.[0-9]+)?|\.[0-9]+)(e[+\-]?[0-9]+)?)))\b/i</span>
|
||||
<span class="nv">HEREDOC : </span><span class="sr">/^("{6}|'{6}|"{3}\n?([\s\S]*?)\n?([ \t]*)"{3}|'{3}\n?([\s\S]*?)\n?([ \t]*)'{3})/</span>
|
||||
<span class="nv">INTERPOLATION : </span><span class="sr">/^\$([a-zA-Z_@]\w*(\.\w+)*)/</span>
|
||||
<span class="nv">OPERATOR : </span><span class="sr">/^([+\*&|\/\-%=<>:!?]+)([ \t]*)/</span>
|
||||
<span class="nv">WHITESPACE : </span><span class="sr">/^([ \t]+)/</span>
|
||||
<span class="nv">COMMENT : </span><span class="sr">/^(\s*#{3}(?!#)[ \t]*\n+([\s\S]*?)[ \t]*\n+[ \t]*#{3}|(\s*#[^\n]*)+)/</span>
|
||||
<span class="nv">CODE : </span><span class="sr">/^((-|=)>)/</span>
|
||||
<span class="nv">MULTI_DENT : </span><span class="sr">/^((\n([ \t]*))+)(\.)?/</span>
|
||||
<span class="nv">LAST_DENTS : </span><span class="sr">/\n([ \t]*)/g</span>
|
||||
<span class="nv">LAST_DENT : </span><span class="sr">/\n([ \t]*)/</span>
|
||||
<span class="nv">ASSIGNMENT : </span><span class="sr">/^[:=]$/</span></pre></div> </td> </tr> <tr id="section-46"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-46">#</a> </div> <p>Regex-matching-regexes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">REGEX_START : </span><span class="sr">/^\/[^\/ ]/</span>
|
||||
<span class="nv">REGEX_INTERPOLATION: </span><span class="sr">/([^\\]\$[a-zA-Z_@]|[^\\]\$\{.*[^\\]\})/</span>
|
||||
<span class="nv">REGEX_END : </span><span class="sr">/^(([imgy]{1,4})\b|\W|$)/</span>
|
||||
<span class="nv">REGEX_ESCAPE : </span><span class="sr">/\\[^\$]/g</span></pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-47">#</a> </div> <p>Token cleaning regexes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">JS_CLEANER : </span><span class="sr">/(^`|`$)/g</span>
|
||||
<span class="nv">MULTILINER : </span><span class="sr">/\n/g</span>
|
||||
<span class="nv">STRING_NEWLINES : </span><span class="sr">/\n[ \t]*/g</span>
|
||||
<span class="nv">NO_NEWLINE : </span><span class="sr">/^([+\*&|\/\-%=<>:!.\\][<>=&|]*|and|or|is|isnt|not|delete|typeof|instanceof)$/</span>
|
||||
<span class="nv">HEREDOC_INDENT : </span><span class="sr">/(\n+([ \t]*)|^([ \t]+))/g</span>
|
||||
<span class="nv">ASSIGNED : </span><span class="sr">/^([a-zA-Z\$_]\w*[ \t]*?[:=])/</span>
|
||||
<span class="nv">NEXT_CHARACTER : </span><span class="sr">/^\s*(\S)/</span></pre></div> </td> </tr> <tr id="section-48"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-48">#</a> </div> <p>Tokens which a regular expression will never immediately follow, but which
|
||||
a division operator might.</p>
|
||||
|
||||
<p>See: http://www.mozilla.org/js/language/js20-2002-04/rationale/syntax.html#regular-expressions</p>
|
||||
|
||||
<p>Our list is shorter, due to sans-parentheses method calls.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">NOT_REGEX: </span><span class="p">[</span>
|
||||
<span class="s1">'NUMBER'</span><span class="p">,</span> <span class="s1">'REGEX'</span><span class="p">,</span> <span class="s1">'++'</span><span class="p">,</span> <span class="s1">'--'</span><span class="p">,</span> <span class="s1">'FALSE'</span><span class="p">,</span> <span class="s1">'NULL'</span><span class="p">,</span> <span class="s1">'TRUE'</span><span class="p">,</span> <span class="s1">']'</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>Tokens which could legitimately be invoked or indexed. A opening
|
||||
parentheses or bracket following these tokens will be recorded as the start
|
||||
of a function invocation or indexing operation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CALLABLE: </span><span class="p">[</span><span class="s1">'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">']'</span><span class="p">,</span> <span class="s1">'}'</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">'THIS'</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-50"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-50">#</a> </div> <p>Tokens that, when immediately preceding a <code>WHEN</code>, indicate that the <code>WHEN</code>
|
||||
occurs at the start of a line. We disambiguate these from trailing whens to
|
||||
avoid an ambiguity in the grammar.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">LINE_BREAK: </span><span class="p">[</span><span class="s1">'INDENT'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="s1">'TERMINATOR'</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>Half-assignments...</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">HALF_ASSIGNMENTS: </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-52"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-52">#</a> </div> <p>Conversions from CoffeeScript operators into JavaScript ones.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CONVERSIONS: </span><span class="p">{</span>
|
||||
<span class="s1">'and'</span><span class="o">:</span> <span class="s1">'&&'</span>
|
||||
<span class="s1">'or'</span><span class="o">:</span> <span class="s1">'||'</span>
|
||||
<span class="s1">'is'</span><span class="o">:</span> <span class="s1">'=='</span>
|
||||
<span class="s1">'isnt'</span><span class="o">:</span> <span class="s1">'!='</span>
|
||||
<span class="s1">'not'</span><span class="o">:</span> <span class="s1">'!'</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
1051
documentation/docs/nodes.html
Normal file
1051
documentation/docs/nodes.html
Normal file
File diff suppressed because it is too large
Load Diff
67
documentation/docs/optparse.html
Normal file
67
documentation/docs/optparse.html
Normal file
@@ -0,0 +1,67 @@
|
||||
<!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.
|
||||
Use it like so:</p>
|
||||
|
||||
<pre><code>parser: new OptionParser switches, helpBanner
|
||||
options: parser.parse process.argv
|
||||
</code></pre> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.OptionParser: </span><span class="nx">class</span> <span class="nx">OptionParser</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-2">#</a> </div> <p>Initialize with a list of valid options, in the form:</p>
|
||||
|
||||
<pre><code>[short-flag, long-flag, description]
|
||||
</code></pre>
|
||||
|
||||
<p>Along with an an optional banner for the usage help.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">rules</span><span class="p">,</span> <span class="nx">banner</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="vi">@banner: </span> <span class="nx">banner</span>
|
||||
<span class="vi">@rules: </span> <span class="nx">buildRules</span><span class="p">(</span><span class="nx">rules</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>Parse the list of arguments, populating an <code>options</code> object with all of the
|
||||
specified options, and returning it. <code>options.arguments</code> will be an array
|
||||
containing the remaning non-option arguments. This is a simpler API than
|
||||
many option parsers that allow you to attach callback actions for every
|
||||
flag. Instead, you're responsible for interpreting the options object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">parse: </span><span class="p">(</span><span class="nx">args</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">options: </span><span class="p">{</span><span class="nv">arguments: </span><span class="p">[]}</span>
|
||||
<span class="nv">args: </span><span class="nx">normalizeArguments</span> <span class="nx">args</span>
|
||||
<span class="k">while</span> <span class="p">(</span><span class="nv">arg: </span><span class="nx">args</span><span class="p">.</span><span class="nx">shift</span><span class="p">())</span>
|
||||
<span class="nv">isOption: </span><span class="o">!!</span><span class="p">(</span><span class="nx">arg</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">LONG_FLAG</span><span class="p">)</span> <span class="o">or</span> <span class="nx">arg</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">SHORT_FLAG</span><span class="p">))</span>
|
||||
<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">shift</span><span class="p">()</span> <span class="k">else</span> <span class="kc">true</span>
|
||||
<span class="nv">matchedRule: </span><span class="kc">yes</span>
|
||||
<span class="k">break</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"unrecognized option: $arg"</span> <span class="k">if</span> <span class="nx">isOption</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">matchedRule</span>
|
||||
<span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">arg</span> <span class="nx">unless</span> <span class="nx">isOption</span>
|
||||
<span class="nx">options</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Return the help text for this <strong>OptionParser</strong>, listing and describing all
|
||||
of the valid options, for <code>--help</code> and such.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">help: </span><span class="o">-></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="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">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="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
|
||||
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>
|
||||
<span class="p">{</span>
|
||||
<span class="nv">name: </span> <span class="nx">longFlag</span><span class="p">.</span><span class="nx">substr</span> <span class="mi">2</span>
|
||||
<span class="nv">shortFlag: </span> <span class="nx">shortFlag</span>
|
||||
<span class="nv">longFlag: </span> <span class="nx">longFlag</span>
|
||||
<span class="nv">description: </span> <span class="nx">description</span>
|
||||
<span class="nv">hasArgument: </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="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>
|
||||
<span class="nv">result: </span><span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="nx">arg</span> <span class="k">in</span> <span class="nx">args</span>
|
||||
<span class="k">if</span> <span class="nv">match: </span><span class="nx">arg</span><span class="p">.</span><span class="nx">match</span> <span class="nx">MULTI_FLAG</span>
|
||||
<span class="nx">result</span><span class="p">.</span><span class="nx">push</span> <span class="s1">'-'</span> <span class="o">+</span> <span class="nx">l</span> <span class="k">for</span> <span class="nx">l</span> <span class="k">in</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">split</span> <span class="s1">''</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">result</span><span class="p">.</span><span class="nx">push</span> <span class="nx">arg</span>
|
||||
<span class="nx">result</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
25
documentation/docs/repl.html
Normal file
25
documentation/docs/repl.html
Normal file
@@ -0,0 +1,25 @@
|
||||
<!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
|
||||
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]
|
||||
</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="p">{</span>
|
||||
<span class="nv">quit: </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>
|
||||
<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="p">{</span><span class="nv">noWrap: </span><span class="kc">true</span><span class="p">,</span> <span class="nv">globals: </span><span class="kc">true</span><span class="p">,</span> <span class="nv">source: </span><span class="s1">'repl'</span><span class="p">}</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>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</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>Create the REPL by listening to <strong>stdin</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">repl: </span><span class="nx">readline</span><span class="p">.</span><span class="nx">createInterface</span> <span class="nx">stdio</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="s1">'coffee> '</span>
|
||||
<span class="nx">stdio</span><span class="p">.</span><span class="nx">addListener</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">repl</span><span class="p">.</span><span class="nx">write</span> <span class="nx">buffer</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">'close'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">stdio</span><span class="p">.</span><span class="nx">destroy</span><span class="p">()</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">'line'</span><span class="p">,</span> <span class="nx">run</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
214
documentation/docs/rewriter.html
Normal file
214
documentation/docs/rewriter.html
Normal file
@@ -0,0 +1,214 @@
|
||||
<!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,
|
||||
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>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
|
||||
corrected before implicit parentheses can be wrapped around blocks of code.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">rewrite: </span><span class="p">(</span><span class="nx">tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="vi">@tokens: </span><span class="nx">tokens</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">@addImplicitIndentation</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-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Rewrite the token stream, looking one token ahead and behind.
|
||||
Allow the return value of the block to tell us how many tokens to move
|
||||
forwards (or backwards) in the stream, to make sure we don't miss anything
|
||||
as tokens are inserted and removed, and the stream changes length under
|
||||
our feet.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">scanTokens: </span><span class="p">(</span><span class="nx">block</span><span class="p">)</span> <span class="o">-></span>
|
||||
<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">i: </span><span class="o">+</span> <span class="nx">move</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Leading newlines would introduce an ambiguity in the grammar, so we
|
||||
dispatch them here.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">removeLeadingNewlines: </span><span class="o">-></span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">shift</span><span class="p">()</span> <span class="k">while</span> <span class="nx">@tokens</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">and</span> <span class="nx">@tokens</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Some blocks occur in the middle of expressions -- when we're expecting
|
||||
this, remove their trailing newlines.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">removeMidExpressionNewlines: </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">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="k">return</span> <span class="mi">0</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>The lexer has tagged the opening parenthesis of a method call, and the
|
||||
opening bracket of an indexing operation. Match them with their paired
|
||||
close.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">closeOpenCallsAndIndexes: </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="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="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="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="o">-</span> <span class="mi">1</span>
|
||||
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Methods may be optionally called without parentheses, for simple cases.
|
||||
Insert the implicit parentheses here, so that the parser doesn't have to
|
||||
deal with them.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">addImplicitParentheses: </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="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="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="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="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="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="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="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="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="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-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Because our grammar is LALR(1), it can't handle some single-line
|
||||
expressions that lack ending delimiters. The <strong>Rewriter</strong> adds the implicit
|
||||
blocks, so it doesn't need to. ')' can close a single-line block,
|
||||
but we need to make sure it's balanced.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">addImplicitIndentation: </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">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">'INDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]],</span> <span class="p">[</span><span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="k">return</span> <span class="mi">2</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="nv">indent: </span><span class="p">[</span><span class="s1">'INDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="nv">indent.generated: </span><span class="kc">true</span>
|
||||
<span class="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="nv">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="nv">outdent: </span><span class="p">[</span><span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="nv">outdent.generated: </span><span class="kc">true</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">insertion</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">outdent</span>
|
||||
<span class="k">break</span>
|
||||
<span class="nv">parens: </span><span class="o">+</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'('</span>
|
||||
<span class="nv">parens: </span><span class="o">-</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">')'</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-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>Ensure that all listed pairs of tokens are correctly balanced throughout
|
||||
the course of the token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ensureBalance: </span><span class="p">(</span><span class="nx">pairs</span><span class="p">)</span> <span class="o">-></span>
|
||||
<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="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">pairs</span>
|
||||
<span class="p">[</span><span class="nx">open</span><span class="p">,</span> <span class="nx">close</span><span class="p">]</span><span class="o">:</span> <span class="nx">pair</span>
|
||||
<span class="nx">levels</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span><span class="o">:</span> <span class="o">or</span> <span class="mi">0</span>
|
||||
<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="nx">open</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="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="k">if</span> <span class="nx">levels</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span>
|
||||
<span class="nx">levels</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span><span class="o">:</span> <span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="nx">levels</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span><span class="o">:</span> <span class="o">-</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="nx">close</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s2">"too many ${token[1]} on line ${token[2] + 1}"</span><span class="p">)</span> <span class="k">if</span> <span class="nx">levels</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span> <span class="o"><</span> <span class="mi">0</span>
|
||||
<span class="k">return</span> <span class="mi">1</span>
|
||||
<span class="nv">unclosed: </span><span class="nx">key</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">value</span> <span class="k">of</span> <span class="nx">levels</span> <span class="k">when</span> <span class="nx">value</span> <span class="o">></span> <span class="mi">0</span>
|
||||
<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-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>We'd like to support syntax like this:</p>
|
||||
|
||||
<pre><code>el.click((event) ->
|
||||
el.hide())
|
||||
</code></pre>
|
||||
|
||||
<p>In order to accomplish this, move outdents that follow closing parens
|
||||
inwards, safely. The steps to accomplish this are:</p>
|
||||
|
||||
<ol>
|
||||
<li>Check that all paired tokens are balanced and in order.</li>
|
||||
<li>Rewrite the stream with a stack: if you see an <code>EXPRESSION_START</code>, add it
|
||||
to the stack. If you see an <code>EXPRESSION_END</code>, pop the stack and replace
|
||||
it with the inverse of what we've just popped.</li>
|
||||
<li>Keep track of "debt" for tokens that we manufacture, to make sure we end
|
||||
up balanced in the end.</li>
|
||||
<li>Be careful not to alter array or parentheses delimiters with overzealous
|
||||
rewriting.</li>
|
||||
</ol> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">rewriteClosingParens: </span><span class="o">-></span>
|
||||
<span class="nv">stack: </span><span class="p">[]</span>
|
||||
<span class="nv">debt: </span> <span class="p">{}</span>
|
||||
<span class="p">(</span><span class="nx">debt</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span><span class="o">:</span> <span class="mi">0</span><span class="p">)</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">INVERSES</span>
|
||||
<span class="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">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>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="nx">token</span>
|
||||
<span class="k">return</span> <span class="mi">1</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">if</span> <span class="nx">debt</span><span class="p">[</span><span class="nx">inv</span><span class="p">]</span> <span class="o">></span> <span class="mi">0</span>
|
||||
<span class="nx">debt</span><span class="p">[</span><span class="nx">inv</span><span class="p">]</span><span class="o">:</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="k">return</span> <span class="mi">0</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">match: </span><span class="nx">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="nv">mtag: </span> <span class="nx">match</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nv">oppos: </span><span class="nx">INVERSES</span><span class="p">[</span><span class="nx">mtag</span><span class="p">]</span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="nx">oppos</span>
|
||||
<span class="nx">debt</span><span class="p">[</span><span class="nx">mtag</span><span class="p">]</span><span class="o">:</span> <span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="nv">val: </span><span class="p">[</span><span class="nx">oppos</span><span class="p">,</span> <span class="k">if</span> <span class="nx">mtag</span> <span class="o">is</span> <span class="s1">'INDENT'</span> <span class="k">then</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">else</span> <span class="nx">oppos</span><span class="p">]</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">2</span><span class="p">]</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="nx">mtag</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">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">val</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">match</span><span class="p">)</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="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-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>List of the token pairs that must be balanced.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BALANCED_PAIRS: </span><span class="p">[[</span><span class="s1">'('</span><span class="p">,</span> <span class="s1">')'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'['</span><span class="p">,</span> <span class="s1">']'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'{'</span><span class="p">,</span> <span class="s1">'}'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'INDENT'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">],</span>
|
||||
<span class="p">[</span><span class="s1">'PARAM_START'</span><span class="p">,</span> <span class="s1">'PARAM_END'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'CALL_START'</span><span class="p">,</span> <span class="s1">'CALL_END'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'INDEX_START'</span><span class="p">,</span> <span class="s1">'INDEX_END'</span><span class="p">]]</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</a> </div> <p>The inverse mappings of <code>BALANCED_PAIRS</code> we're trying to fix up, so we can
|
||||
look things up from either end.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">INVERSES: </span><span class="p">{}</span>
|
||||
<span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span>
|
||||
<span class="nx">INVERSES</span><span class="p">[</span><span class="nx">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span><span class="o">:</span> <span class="nx">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nx">INVERSES</span><span class="p">[</span><span class="nx">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]]</span><span class="o">:</span> <span class="nx">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>The tokens that signal the start of a balanced pair.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_START: </span><span class="nx">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-18">#</a> </div> <p>The tokens that signal the end of a balanced pair.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_END: </span> <span class="nx">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-19">#</a> </div> <p>Tokens that indicate the close of a clause of an expression.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_CLOSE: </span><span class="p">[</span><span class="s1">'CATCH'</span><span class="p">,</span> <span class="s1">'WHEN'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">,</span> <span class="s1">'FINALLY'</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">EXPRESSION_END</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-20">#</a> </div> <p>Tokens that, if followed by an <code>IMPLICIT_CALL</code>, indicate a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_FUNC: </span> <span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'SUPER'</span><span class="p">,</span> <span class="s1">')'</span><span class="p">,</span> <span class="s1">'CALL_END'</span><span class="p">,</span> <span class="s1">']'</span><span class="p">,</span> <span class="s1">'INDEX_END'</span><span class="p">,</span> <span class="s1">'@'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-21">#</a> </div> <p>If preceded by an <code>IMPLICIT_FUNC</code>, indicates a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_CALL: </span> <span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'NUMBER'</span><span class="p">,</span> <span class="s1">'STRING'</span><span class="p">,</span> <span class="s1">'JS'</span><span class="p">,</span> <span class="s1">'REGEX'</span><span class="p">,</span> <span class="s1">'NEW'</span><span class="p">,</span> <span class="s1">'PARAM_START'</span><span class="p">,</span>
|
||||
<span class="s1">'TRY'</span><span class="p">,</span> <span class="s1">'DELETE'</span><span class="p">,</span> <span class="s1">'TYPEOF'</span><span class="p">,</span> <span class="s1">'SWITCH'</span><span class="p">,</span>
|
||||
<span class="s1">'TRUE'</span><span class="p">,</span> <span class="s1">'FALSE'</span><span class="p">,</span> <span class="s1">'YES'</span><span class="p">,</span> <span class="s1">'NO'</span><span class="p">,</span> <span class="s1">'ON'</span><span class="p">,</span> <span class="s1">'OFF'</span><span class="p">,</span> <span class="s1">'!'</span><span class="p">,</span> <span class="s1">'!!'</span><span class="p">,</span>
|
||||
<span class="s1">'THIS'</span><span class="p">,</span> <span class="s1">'NULL'</span><span class="p">,</span>
|
||||
<span class="s1">'@'</span><span class="p">,</span> <span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">,</span> <span class="s1">'['</span><span class="p">,</span> <span class="s1">'('</span><span class="p">,</span> <span class="s1">'{'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-22">#</a> </div> <p>Tokens indicating that the implicit call must enclose a block of expressions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_BLOCK: </span><span class="p">[</span><span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">,</span> <span class="s1">'{'</span><span class="p">,</span> <span class="s1">'['</span><span class="p">,</span> <span class="s1">','</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-23">#</a> </div> <p>Tokens that always mark the end of an implicit call for single-liners.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_END: </span> <span class="p">[</span><span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'UNLESS'</span><span class="p">,</span> <span class="s1">'FOR'</span><span class="p">,</span> <span class="s1">'WHILE'</span><span class="p">,</span> <span class="s1">'UNTIL'</span><span class="p">,</span> <span class="s1">'LOOP'</span><span class="p">,</span> <span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'INDENT'</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">EXPRESSION_END</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-24">#</a> </div> <p>Single-line flavors of block expressions that have unclosed endings.
|
||||
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>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
48
documentation/docs/scope.html
Normal file
48
documentation/docs/scope.html
Normal file
@@ -0,0 +1,48 @@
|
||||
<!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
|
||||
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>
|
||||
|
||||
<span class="nv">exports.Scope: </span><span class="nx">class</span> <span class="nx">Scope</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>The top-level <strong>Scope</strong> object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="vi">@root: </span><span class="kc">null</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Initialize a scope with its parent, for lookups up the chain,
|
||||
as well as a reference to the <strong>Expressions</strong> node is belongs to, which is
|
||||
where it should declare its variables, and a reference to the function that
|
||||
it wraps.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">parent</span><span class="p">,</span> <span class="nx">expressions</span><span class="p">,</span> <span class="nx">method</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="p">[</span><span class="nx">@parent</span><span class="p">,</span> <span class="nx">@expressions</span><span class="p">,</span> <span class="nx">@method</span><span class="p">]</span><span class="o">:</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="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="nv">find: </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="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="nv">any: </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
|
||||
scope. No <code>var</code> required for internal references.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">parameter: </span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></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="nv">check: </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="nv">freeVariable: </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
|
||||
(or at the top-level scope, if requested).</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">assign: </span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@variables</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span><span class="o">:</span> <span class="p">{</span><span class="nv">value: </span><span class="nx">value</span><span class="p">,</span> <span class="nv">assigned: </span><span class="kc">true</span><span class="p">}</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Does this scope reference any variables that need to be declared in the
|
||||
given function body?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">hasDeclarations: </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
|
||||
top of the given function body?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">hasAssignments: </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="nv">declaredVariables: </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
|
||||
of this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">assignedVariables: </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="nv">compiledDeclarations: </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="nv">compiledAssignments: </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>
|
||||
282
documentation/docs/underscore.html
Normal file
282
documentation/docs/underscore.html
Normal file
File diff suppressed because one or more lines are too long
@@ -30,7 +30,7 @@
|
||||
|
||||
<div id="flybar">
|
||||
<a id="logo" href="#top"> </a>
|
||||
<div class="navigation">
|
||||
<div class="navigation toc">
|
||||
<div class="button">
|
||||
Table of Contents
|
||||
</div>
|
||||
@@ -46,8 +46,7 @@
|
||||
<a href="#conditionals">Conditionals, Ternaries, and Conditional Assignment</a>
|
||||
<a href="#aliases">Aliases</a>
|
||||
<a href="#splats">Splats...</a>
|
||||
<a href="#arguments">Arguments are Arrays</a>
|
||||
<a href="#while">While Loops</a>
|
||||
<a href="#while">While, Until, and Loop</a>
|
||||
<a href="#comprehensions">Comprehensions (Arrays, Objects, and Ranges)</a>
|
||||
<a href="#slice_splice">Array Slicing and Splicing with Ranges</a>
|
||||
<a href="#expressions">Everything is an Expression</a>
|
||||
@@ -59,10 +58,12 @@
|
||||
<a href="#switch">Switch/When/Else</a>
|
||||
<a href="#try">Try/Catch/Finally</a>
|
||||
<a href="#comparisons">Chained Comparisons</a>
|
||||
<a href="#interpolation">String and RegExp Interpolation</a>
|
||||
<a href="#strings">Multiline Strings and Heredocs</a>
|
||||
<a href="#cake">Cake, and Cakefiles</a>
|
||||
<a href="#scripts">"text/coffeescript" Script Tags</a>
|
||||
<a href="#resources">Resources</a>
|
||||
<a href="#webchat">Web Chat (IRC)</a>
|
||||
<a href="#change_log">Change Log</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -75,7 +76,7 @@
|
||||
<div id="repl_source_wrap"><textarea id="repl_source">reverse: (string) ->
|
||||
string.split('').reverse().join ''
|
||||
|
||||
alert reverse '!tpircseeffoC'</textarea></div>
|
||||
alert reverse '.eeffoC yrT'</textarea></div>
|
||||
<pre id="repl_results"></pre>
|
||||
<button class="full_screen">go full screen</button>
|
||||
<button class="minimize">minimize</button>
|
||||
@@ -84,6 +85,24 @@ alert reverse '!tpircseeffoC'</textarea></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navigation annotated">
|
||||
<div class="button">
|
||||
Annotated Source
|
||||
</div>
|
||||
<div class="contents">
|
||||
<a href="documentation/docs/grammar.html">Grammar Rules — src/grammar</a>
|
||||
<a href="documentation/docs/lexer.html">Lexing Tokens — src/lexer</a>
|
||||
<a href="documentation/docs/rewriter.html">The Rewriter — src/rewriter</a>
|
||||
<a href="documentation/docs/nodes.html">The Syntax Tree — src/nodes</a>
|
||||
<a href="documentation/docs/scope.html">Lexical Scope — src/scope</a>
|
||||
<a href="documentation/docs/helpers.html">Helpers & Utility Functions — src/helpers</a>
|
||||
<a href="documentation/docs/coffee-script.html">The CoffeeScript Module — src/coffee-script</a>
|
||||
<a href="documentation/docs/cake.html">Cake & Cakefiles — src/cake</a>
|
||||
<a href="documentation/docs/command.html">"coffee" Command-Line Utility — src/command</a>
|
||||
<a href="documentation/docs/optparse.html">Option Parsing — src/optparse</a>
|
||||
<a href="documentation/docs/repl.html">Interactive REPL — src/repl</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="error" style="display:none;"></div>
|
||||
</div>
|
||||
|
||||
@@ -105,13 +124,12 @@ alert reverse '!tpircseeffoC'</textarea></div>
|
||||
it compiles into clean JavaScript (the good parts) that can use existing
|
||||
JavaScript libraries seamlessly, and passes through
|
||||
<a href="http://www.jslint.com/">JSLint</a> without warnings. The compiled
|
||||
output is quite readable — pretty-printed, with comments
|
||||
preserved intact.
|
||||
output is pretty-printed and quite readable.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Latest Version:</b>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/0.5.4">0.5.4</a>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/0.7.0">0.7.0</a>
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
@@ -121,11 +139,11 @@ alert reverse '!tpircseeffoC'</textarea></div>
|
||||
|
||||
<p><i>CoffeeScript on the left, compiled JavaScript output on the right.</i></p>
|
||||
|
||||
<%= code_for('overview', 'cubed_list') %>
|
||||
<%= code_for('overview', 'cubes') %>
|
||||
|
||||
<p>
|
||||
For a longer CoffeeScript example, check out
|
||||
<a href="documentation/underscore.html">Underscore.coffee</a>, a port
|
||||
<a href="documentation/docs/underscore.html">Underscore.coffee</a>, a port
|
||||
of the <a href="http://documentcloud.github.com/underscore/">Underscore.js</a>
|
||||
library of helper functions. Underscore.coffee can pass the entire Underscore.js
|
||||
test suite. The CoffeeScript version is faster than the original for a number
|
||||
@@ -143,7 +161,7 @@ alert reverse '!tpircseeffoC'</textarea></div>
|
||||
|
||||
<p>
|
||||
The CoffeeScript compiler is written in pure CoffeeScript, using a
|
||||
<a href="http://github.com/jashkenas/coffee-script/blob/master/src/grammar.coffee">small DSL</a>
|
||||
<a href="documentation/docs/grammar.html">small DSL</a>
|
||||
on top of the <a href="http://github.com/zaach/jison">Jison parser generator</a>, and is available
|
||||
as a <a href="http://nodejs.org/">Node.js</a> utility. The core compiler however,
|
||||
does not depend on Node, and can be run in other server-side-JavaScript environments,
|
||||
@@ -152,13 +170,12 @@ alert reverse '!tpircseeffoC'</textarea></div>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To install, first make sure you have a working version of
|
||||
<a href="http://nodejs.org/">Node.js</a> greater than version 0.1.30 (Node
|
||||
moves quickly, using the latest master is your best bet).
|
||||
To install, first make sure you have a working copy of the latest tagged version of
|
||||
<a href="http://nodejs.org/">Node.js</a>, currently <b>0.1.90</b> or higher.
|
||||
Then clone the CoffeeScript
|
||||
<a href="http://github.com/jashkenas/coffee-script">source repository</a>
|
||||
from GitHub, or download the latest
|
||||
release: <a href="http://github.com/jashkenas/coffee-script/tarball/0.5.4">0.5.4</a>.
|
||||
release: <a href="http://github.com/jashkenas/coffee-script/tarball/0.7.0">0.7.0</a>.
|
||||
To install the CoffeeScript compiler system-wide
|
||||
under <tt>/usr/local</tt>, open the directory and run:
|
||||
</p>
|
||||
@@ -187,6 +204,8 @@ sudo bin/cake install</pre>
|
||||
<td width="25%"><code>-i, --interactive</code></td>
|
||||
<td>
|
||||
Launch an interactive CoffeeScript session to try short snippets.
|
||||
More pleasant if wrapped with
|
||||
<a href="http://utopia.knoware.nl/~hlub/uck/rlwrap/rlwrap.html">rlwrap</a>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -225,14 +244,14 @@ sudo bin/cake install</pre>
|
||||
<td>
|
||||
Pipe in CoffeeScript to STDIN and get back JavaScript over STDOUT.
|
||||
Good for use with processes written in other languages. An example:<br />
|
||||
<tt>cat src/cake.coffee | coffee -s</tt>
|
||||
<tt>cat src/cake.coffee | coffee -sc</tt>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>-e, --eval</code></td>
|
||||
<td>
|
||||
Compile and print a little snippet of CoffeeScript directly from the
|
||||
command line. For example:<br /><tt>coffee -e "square: (x) -> x * x"</tt>
|
||||
command line. For example:<br /><tt>coffee -e "puts num for num in [10..1]"</tt>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -312,7 +331,8 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
|
||||
<p>
|
||||
You don't need to use parentheses to invoke a function if you're passing
|
||||
arguments:<br /><tt>print "coffee"</tt>
|
||||
arguments:<br /><tt>print "coffee"</tt>. Implicit parentheses wrap forwards
|
||||
to the end of the line, or block expression.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -359,6 +379,12 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
and match the two styles.
|
||||
</p>
|
||||
<%= code_for('objects_and_arrays', 'song.join(",")') %>
|
||||
<p>
|
||||
In JavaScript, you can't use reserved words, like <tt>class</tt>, as properties
|
||||
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>
|
||||
<%= code_for('objects_reserved') %>
|
||||
|
||||
<p>
|
||||
<span id="lexical_scope" class="bookmark"></span>
|
||||
@@ -367,7 +393,7 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
are properly declared within lexical scope — you never need to write
|
||||
<tt>var</tt> yourself.
|
||||
</p>
|
||||
<%= code_for('scope', 'new_num') %>
|
||||
<%= code_for('scope', 'inner') %>
|
||||
<p>
|
||||
Notice how the all of the variable declarations have been pushed up to
|
||||
the top of the closest scope, the first time they appear.
|
||||
@@ -376,6 +402,13 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
should not be able to change the value of the external variable of the same name, and
|
||||
therefore has a declaration of its own.
|
||||
</p>
|
||||
<p>
|
||||
This behavior is effectively identical to Ruby's scope for local variables.
|
||||
Because you don't have direct access to the <tt>var</tt> keyword,
|
||||
it's impossible to shadow an outer variable on purpose, you may only refer
|
||||
to it. So be careful that you're not reusing the name of an external
|
||||
variable accidentally, if you're writing a deeply nested function.
|
||||
</p>
|
||||
<p>
|
||||
Although suppressed within this documentation for clarity, all
|
||||
CoffeeScript output is wrapped in an anonymous function:
|
||||
@@ -405,10 +438,9 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
</p>
|
||||
<%= code_for('conditionals') %>
|
||||
<p>
|
||||
The conditional assignment operators are included: <tt>||=</tt>,
|
||||
which only assigns a value to a variable if the variable's current value
|
||||
is falsy, and <tt>&&=</tt>, which only replaces the value of
|
||||
truthy variables.
|
||||
You can assign a variable to a half-expression to perform an operation
|
||||
like Ruby's <tt>||=</tt>, which only assigns a value to a variable
|
||||
if the variable's current value is falsy.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -443,6 +475,10 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
<p>
|
||||
As a shortcut for <tt>this.property</tt>, you can use <tt>@property</tt>.
|
||||
</p>
|
||||
<p>
|
||||
You can use <tt>in</tt> to test for array presence, and <tt>of</tt> to
|
||||
test for JavaScript object-key presence.
|
||||
</p>
|
||||
<%= code_for('aliases') %>
|
||||
|
||||
<p>
|
||||
@@ -455,19 +491,9 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
</p>
|
||||
<%= code_for('splats', true) %>
|
||||
|
||||
<p>
|
||||
<span id="arguments" class="bookmark"></span>
|
||||
<b class="header">Arguments are Arrays</b>
|
||||
If you reference the <b>arguments object</b> directly, it will be converted
|
||||
into a real Array, making all of the
|
||||
<a href="https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array">Array methods</a>
|
||||
available.
|
||||
</p>
|
||||
<%= code_for('arguments', true) %>
|
||||
|
||||
<p>
|
||||
<span id="while" class="bookmark"></span>
|
||||
<b class="header">While Loops</b>
|
||||
<b class="header">While, Until, and Loop</b>
|
||||
The only low-level loop that CoffeeScript provides is the <b>while</b> loop. The
|
||||
main difference from JavaScript is that the <b>while</b> loop can be used
|
||||
as an expression, returning an array containing the result of each iteration
|
||||
@@ -475,8 +501,10 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
</p>
|
||||
<%= code_for('while', 'lyrics.join("\n")') %>
|
||||
<p>
|
||||
For readability, the <b>until</b> keyword is equivalent to <tt>while not</tt>,
|
||||
and the <b>loop</b> keyword is equivalent to <tt>while true</tt>.
|
||||
Other JavaScript loops, such as <b>for</b> loops and <b>do-while</b> loops
|
||||
can be mimicked by variations on <b>while</b>, but the hope is that you
|
||||
can be mimicked by variations on <b>loop</b>, but the hope is that you
|
||||
won't need to do that with CoffeeScript, either because you're using
|
||||
<b>each</b> (<b>forEach</b>) style iterators, or...
|
||||
</p>
|
||||
@@ -495,8 +523,7 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
<p>
|
||||
If you know the start and end of your loop, or would like to step through
|
||||
in fixed-size increments, you can use a range to specify the start and
|
||||
end of your comprehension. (The long line-breaking "for" definitions in
|
||||
the compiled JS below allow ranges to count downwards, as well as upwards).
|
||||
end of your comprehension.
|
||||
</p>
|
||||
<%= code_for('range_comprehensions', 'countdown') %>
|
||||
<p>
|
||||
@@ -516,7 +543,7 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
the slice, and the second is the index of the last one. Three dots signify
|
||||
a range that excludes the end.
|
||||
</p>
|
||||
<%= code_for('slices', 'numbers_copy') %>
|
||||
<%= code_for('slices', 'copy') %>
|
||||
<p>
|
||||
The same syntax can be used with assignment to replace a segment of an
|
||||
array with new values (to splice it).
|
||||
@@ -618,11 +645,15 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
<p>
|
||||
If structuring your prototypes classically isn't your cup of tea, CoffeeScript
|
||||
provides a couple of lower-level conveniences. The <tt>extends</tt> operator
|
||||
helps with proper prototype setup, as seen above, <tt>::</tt> gives you
|
||||
helps with proper prototype setup, <tt>::</tt> gives you
|
||||
quick access to an object's prototype, and <tt>super()</tt>
|
||||
is converted into a call against the immediate ancestor's method of the same name.
|
||||
</p>
|
||||
<%= code_for('prototypes', '"one_two".dasherize()') %>
|
||||
<p>
|
||||
Finally, you may assign Class-level (static) properties within a class
|
||||
definition by using<br /><tt>@property: value</tt>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<span id="pattern_matching" class="bookmark"></span>
|
||||
@@ -635,7 +666,7 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
on the right to the variables on the left. In the simplest case, it can be
|
||||
used for parallel assignment:
|
||||
</p>
|
||||
<%= code_for('parallel_assignment', 'bait') %>
|
||||
<%= code_for('parallel_assignment', 'theBait') %>
|
||||
<p>
|
||||
But it's also helpful for dealing with functions that return multiple
|
||||
values.
|
||||
@@ -645,12 +676,24 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
Pattern matching can be used with any depth of array and object nesting,
|
||||
to help pull out deeply nested properties.
|
||||
</p>
|
||||
<%= code_for('object_extraction', 'poet + " — " + street') %>
|
||||
<%= code_for('object_extraction', 'name + " — " + street') %>
|
||||
<p>
|
||||
Pattern matching can even be combined with splats.
|
||||
</p>
|
||||
<%= code_for('patterns_and_splats', 'contents.join("")') %>
|
||||
|
||||
<p>
|
||||
<span id="fat_arrow" class="bookmark"></span>
|
||||
<b class="header">Function binding</b>
|
||||
The fat arrow <tt>=></tt> can be used to both define a function, and to bind
|
||||
In JavaScript, the <tt>this</tt> keyword is dynamically scoped to mean the
|
||||
object that the current function is attached to. If you pass a function as
|
||||
as callback, or attach it to a different object, the original value of <tt>this</tt>
|
||||
will be lost. If you're not familiar with this behavior,
|
||||
<a href="http://www.digital-web.com/articles/scope_in_javascript/">this Digital Web article</a>
|
||||
gives a good overview of the quirks.
|
||||
</p>
|
||||
<p>
|
||||
The fat arrow <tt>=></tt> can be used to both define a function, and to bind
|
||||
it to the current value of <tt>this</tt>, right on the spot. This is helpful
|
||||
when using callback-based libraries like Prototype or jQuery, for creating
|
||||
iterator functions to pass to <tt>each</tt>, or event-handler functions
|
||||
@@ -658,6 +701,11 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
properties of the <tt>this</tt> where they're defined.
|
||||
</p>
|
||||
<%= code_for('fat_arrow') %>
|
||||
<p>
|
||||
If we had used <tt>-></tt> in the callback above, <tt>@customer</tt> would
|
||||
have referred to the undefined "customer" property of the DOM element,
|
||||
and trying to call <tt>purchase()</tt> on it would have raised an exception.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<span id="embedded" class="bookmark"></span>
|
||||
@@ -704,12 +752,26 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
</p>
|
||||
<%= code_for('comparisons', 'healthy') %>
|
||||
|
||||
<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 marking
|
||||
them with a dollar sign.
|
||||
</p>
|
||||
<%= code_for('interpolation', 'quote') %>
|
||||
<p>
|
||||
And arbitrary expressions can be interpolated by using brackets <tt>${ ... }</tt><br />
|
||||
Interpolation works the same way within regular expressions.
|
||||
</p>
|
||||
<%= code_for('interpolation_expression', 'sentence') %>
|
||||
|
||||
<p>
|
||||
<span id="strings" class="bookmark"></span>
|
||||
<b class="header">Multiline Strings and Heredocs</b>
|
||||
Multiline strings are allowed in CoffeeScript.
|
||||
</p>
|
||||
<%= code_for('strings', 'moby_dick') %>
|
||||
<%= code_for('strings', 'mobyDick') %>
|
||||
<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
|
||||
@@ -717,6 +779,9 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
you can keep it all aligned with the body of your code.
|
||||
</p>
|
||||
<%= code_for('heredocs') %>
|
||||
<p>
|
||||
Double-quoted heredocs, like double-quoted strings, allow interpolation.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<span id="cake" class="bookmark"></span>
|
||||
@@ -779,7 +844,12 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
<tt>bin/cake test</tt> to run the test suite,<br />
|
||||
<tt>bin/cake build</tt> to rebuild the CoffeeScript compiler, and <br />
|
||||
<tt>bin/cake build:parser</tt> to regenerate the Jison parser if you're
|
||||
working on the grammar.
|
||||
working on the grammar. <br /><br />
|
||||
<tt>git checkout lib && bin/cake build:full</tt> is a good command to run when you're working
|
||||
on the core language. It'll refresh the lib directory
|
||||
(in case you broke something), build your altered compiler, use that to
|
||||
rebuild itself (a good sanity test) and then run all of the tests. If
|
||||
they pass, there's a good chance you've made a successful change.
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://github.com/jashkenas/coffee-script/issues">CoffeeScript Issues</a><br />
|
||||
@@ -790,23 +860,151 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
IRC client of your choice, or on
|
||||
<a href="http://webchat.freenode.net/">webchat.freenode.net</a>.
|
||||
</li>
|
||||
<li>
|
||||
<b>yeungda</b>'s <a href="http://github.com/yeungda/jcoffeescript">JCoffeeScript</a>
|
||||
— A Java Library that uses Rhino to compile CoffeeScript, allowing
|
||||
compilation within Java projects or on systems that Node.js doesn't support.
|
||||
</li>
|
||||
<li>
|
||||
<b>defunkt</b>'s <a href="http://github.com/defunkt/coffee-mode">CoffeeScript Major Mode</a>
|
||||
— a Emacs major mode that provides syntax highlighting, indentation
|
||||
support, and some bonus commands.
|
||||
</li>
|
||||
<li>
|
||||
<b>jashkenas</b>'s <a href="http://github.com/jashkenas/coffee-script-tmbundle">CoffeeScript TextMate Bundle</a>
|
||||
— which provides syntax highlighting, snippet expansion, and the
|
||||
ability to run bits of CoffeeScript from within TextMate itself.
|
||||
</li>
|
||||
<li>
|
||||
<b>kchmck</b>'s <a href="http://github.com/kchmck/vim-coffee-script">Vim CoffeeScript</a>
|
||||
— which adds Vim syntax highlighting and indentation support.
|
||||
</li>
|
||||
<li>
|
||||
<b>yeungda</b>'s <a href="http://yeungda.github.com/coffeescript-idea/">coffeescript-idea</a>
|
||||
— a plugin for IntelliJ IDEA and RubyMine providing syntax highlighting.
|
||||
</li>
|
||||
<li>
|
||||
<b>mattly</b>'s <a href="http://github.com/mattly/rack-coffee">rack-coffee</a>
|
||||
— a small Rack middleware for serving CoffeeScript files as
|
||||
compiled JavaScript on the fly.
|
||||
</li>
|
||||
<li>
|
||||
<b>jnicklas</b>'s <a href="http://github.com/jnicklas/bistro_car">BistroCar</a>
|
||||
— a plugin that serves and bundles CoffeeScript from within your
|
||||
Rails application.
|
||||
</li>
|
||||
<li>
|
||||
<b>sutto</b>'s <a href="http://github.com/Sutto/barista">Barista</a>
|
||||
— a BistroCar alternative that integrates well with
|
||||
<a href="http://documentcloud.github.com/jammit">Jammit</a> and Rails 3.
|
||||
</li>
|
||||
<li>
|
||||
<b>inem</b> and <b>gerad</b>'s <a href="http://github.com/gerad/coffee-haml-filter">coffee-haml-filter</a>
|
||||
— a custom filter for rendering CoffeeScript inline within
|
||||
<a href="http://haml-lang.com/">HAML</a> templates.
|
||||
</li>
|
||||
<li>
|
||||
<b>jashkenas</b>'s <a href="http://jashkenas.github.com/docco/">Docco</a>
|
||||
— A quick-and-dirty literate-programming-style documentation generator
|
||||
for CoffeeScript. Used to produce the annotated source.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
<span id="webchat" class="bookmark"></span>
|
||||
Web Chat (IRC)
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
Quick help and advice can usually be found in the CoffeeScript IRC room.
|
||||
Join <tt>#coffeescript</tt> on <tt>irc.freenode.net</tt>, or click the
|
||||
button below to open a webchat session on this page.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<button id="open_webchat">click to open #coffeescript</button>
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<span id="change_log" class="bookmark"></span>
|
||||
Change Log
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.7.0</b>
|
||||
Official CoffeeScript variable style is now camelCase, as in JavaScript.
|
||||
Reserved words are now allowed as object keys, and will be quoted for you.
|
||||
Range comprehensions now generate cleaner code, but you have to specify <tt>by -1</tt>
|
||||
if you'd like to iterate downward. Reporting of syntax errors is greatly
|
||||
improved from the previous release. Running <tt>coffee</tt> with no arguments
|
||||
now launches the REPL, with Readline support. The <tt>&-</tt> bind operator
|
||||
has been removed from CoffeeScript. The <tt>loop</tt> keyword was added,
|
||||
which is equivalent to a <tt>while true</tt> loop. Comprehensions that contain
|
||||
closures will now close over their variables, like the semantics of a <tt>forEach</tt>.
|
||||
You can now use bound function in class definitions (bound to the instance).
|
||||
For consistency, <tt>a in b</tt> is now an array presence check, and <tt>a of b</tt>
|
||||
is an object-key check. Comments are no longer passed through to the generated
|
||||
JavaScript.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.6.2</b>
|
||||
The <tt>coffee</tt> command will now preserve directory structure when
|
||||
compiling a directory full of scripts. Fixed two omissions that were preventing
|
||||
the CoffeeScript compiler from running live within Internet Explorer.
|
||||
There's now a syntax for block comments, similar in spirit to CoffeeScript's heredocs.
|
||||
ECMA Harmony DRY-style pattern matching is now supported, where the name
|
||||
of the property is the same as the name of the value: <tt>{name, length}: func</tt>.
|
||||
Pattern matching is now allowed within comprehension variables. <tt>unless</tt>
|
||||
is now allowed in block form. <tt>until</tt> loops were added, as the inverse
|
||||
of <tt>while</tt> loops. <tt>switch</tt> statements are now allowed without
|
||||
switch object clauses. Compatible
|
||||
with Node.js <b>v0.1.95</b>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.6.1</b>
|
||||
Upgraded CoffeeScript for compatibility with the new Node.js <b>v0.1.90</b>
|
||||
series.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.6.0</b>
|
||||
Trailing commas are now allowed, a-la Python. Static
|
||||
properties may be assigned directly within class definitions,
|
||||
using <tt>@property</tt> notation.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.6</b>
|
||||
Interpolation can now be used within regular expressions and heredocs, as well as
|
||||
strings. Added the <tt><-</tt> bind operator.
|
||||
Allowing assignment to half-expressions instead of special <tt>||=</tt>-style
|
||||
operators. The arguments object is no longer automatically converted into
|
||||
an array. After requiring <tt>coffee-script</tt>, Node.js can now directly
|
||||
load <tt>.coffee</tt> files, thanks to <b>registerExtension</b>. Multiple
|
||||
splats can now be used in function calls, arrays, and pattern matching.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.5</b>
|
||||
String interpolation, contributed by
|
||||
<a href="http://github.com/StanAngeloff">Stan Angeloff</a>.
|
||||
Since <tt>--run</tt> has been the default since <b>0.5.3</b>, updating
|
||||
<tt>--stdio</tt> and <tt>--eval</tt> to run by default, pass <tt>--compile</tt>
|
||||
as well if you'd like to print the result.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.4</b>
|
||||
Bugfix that corrects the Node.js global constants <tt>__filename</tt> and
|
||||
<tt>__dirname</tt>. Tweaks for more flexible parsing of nested function
|
||||
literals and improperly-indented comments. Updates for the latest Node.js API.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.3</b>
|
||||
CoffeeScript now has a syntax for defining classes. Many of the core
|
||||
CoffeeScript now has a syntax for defining classes. Many of the core
|
||||
components (Nodes, Lexer, Rewriter, Scope, Optparse) are using them.
|
||||
Cakefiles can use <tt>optparse.coffee</tt> to define options for tasks.
|
||||
<tt>--run</tt> is now the default flag for the <tt>coffee</tt> command,
|
||||
@@ -1000,7 +1198,7 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
source: $('#repl_source').val()
|
||||
window.compiled_js: ''
|
||||
try
|
||||
window.compiled_js: CoffeeScript.compile source, {no_wrap: true}
|
||||
window.compiled_js: CoffeeScript.compile source, {noWrap: true}
|
||||
$('#repl_results').text window.compiled_js
|
||||
$('#error').hide();
|
||||
catch error
|
||||
@@ -1041,6 +1239,9 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
$('.navigation .minimize').click ->
|
||||
document.body.className: 'minimized'
|
||||
|
||||
$('#open_webchat').click ->
|
||||
$(this).replaceWith $('<iframe src="http://webchat.freenode.net/?channels=coffeescript" width="625" height="400"></iframe>')
|
||||
|
||||
compile_source()
|
||||
|
||||
</script>
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
(function(){
|
||||
var volume;
|
||||
var volume, winner;
|
||||
if (ignition === true) {
|
||||
launch();
|
||||
}
|
||||
if (band !== spinal_tap) {
|
||||
if (band !== SpinalTap) {
|
||||
volume = 10;
|
||||
}
|
||||
if (!(answer === false)) {
|
||||
let_the_wild_rumpus_begin();
|
||||
letTheWildRumpusBegin();
|
||||
}
|
||||
car.speed < limit ? accelerate() : null;
|
||||
if (47 === pick || 92 === pick || 13 === pick) {
|
||||
winner = true;
|
||||
}
|
||||
car.speed < speed_limit ? accelerate() : null;
|
||||
print("My name is " + this.name);
|
||||
})();
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
(function(){
|
||||
var backwards;
|
||||
backwards = function backwards() {
|
||||
arguments = Array.prototype.slice.call(arguments, 0);
|
||||
return alert(arguments.reverse());
|
||||
};
|
||||
backwards("stairway", "to", "heaven");
|
||||
})();
|
||||
@@ -1,21 +1,19 @@
|
||||
(function(){
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, food, lunch, roid, roid2;
|
||||
// Eat lunch.
|
||||
lunch = (function() {
|
||||
_a = []; _b = ['toast', 'cheese', 'wine'];
|
||||
for (_c = 0, _d = _b.length; _c < _d; _c++) {
|
||||
food = _b[_c];
|
||||
_a = []; _c = ['toast', 'cheese', 'wine'];
|
||||
for (_b = 0, _d = _c.length; _b < _d; _b++) {
|
||||
food = _c[_b];
|
||||
_a.push(eat(food));
|
||||
}
|
||||
return _a;
|
||||
}).call(this);
|
||||
// Naive collision detection.
|
||||
_e = asteroids;
|
||||
for (_f = 0, _g = _e.length; _f < _g; _f++) {
|
||||
roid = _e[_f];
|
||||
_h = asteroids;
|
||||
for (_i = 0, _j = _h.length; _i < _j; _i++) {
|
||||
roid2 = _h[_i];
|
||||
})();
|
||||
_f = asteroids;
|
||||
for (_e = 0, _g = _f.length; _e < _g; _e++) {
|
||||
roid = _f[_e];
|
||||
_i = asteroids;
|
||||
for (_h = 0, _j = _i.length; _h < _j; _h++) {
|
||||
roid2 = _i[_h];
|
||||
if (roid !== roid2) {
|
||||
if (roid.overlaps(roid2)) {
|
||||
roid.explode();
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
(function(){
|
||||
process.mixin(require('assert'));
|
||||
task('test', 'run each of the unit tests', function() {
|
||||
var _a, _b, _c, _d, test;
|
||||
_a = []; _b = test_files;
|
||||
for (_c = 0, _d = _b.length; _c < _d; _c++) {
|
||||
test = _b[_c];
|
||||
_a.push(fs.readFile(test, function(err, code) {
|
||||
return eval(coffee.compile(code));
|
||||
}));
|
||||
var _a, _b, _c, _d;
|
||||
_a = []; _c = files;
|
||||
for (_b = 0, _d = _c.length; _b < _d; _b++) {
|
||||
(function() {
|
||||
var test = _c[_b];
|
||||
return _a.push(fs.readFile(test, function(err, code) {
|
||||
return eval(coffee.compile(code));
|
||||
}));
|
||||
})();
|
||||
}
|
||||
return _a;
|
||||
});
|
||||
|
||||
@@ -7,28 +7,31 @@
|
||||
child.prototype = new ctor();
|
||||
child.prototype.constructor = child;
|
||||
};
|
||||
Animal = function Animal() { };
|
||||
Animal.prototype.move = function move(meters) {
|
||||
Animal = function() { };
|
||||
Animal.prototype.move = function(meters) {
|
||||
return alert(this.name + " moved " + meters + "m.");
|
||||
};
|
||||
Snake = function Snake(name) {
|
||||
|
||||
Snake = function(name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
};
|
||||
__extends(Snake, Animal);
|
||||
Snake.prototype.move = function move() {
|
||||
Snake.prototype.move = function() {
|
||||
alert("Slithering...");
|
||||
return Snake.__superClass__.move.call(this, 5);
|
||||
};
|
||||
Horse = function Horse(name) {
|
||||
|
||||
Horse = function(name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
};
|
||||
__extends(Horse, Animal);
|
||||
Horse.prototype.move = function move() {
|
||||
Horse.prototype.move = function() {
|
||||
alert("Galloping...");
|
||||
return Horse.__superClass__.move.call(this, 45);
|
||||
};
|
||||
|
||||
sam = new Snake("Sammy the Python");
|
||||
tom = new Horse("Tommy the Palomino");
|
||||
sam.move();
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
(function(){
|
||||
var date, expensive, mood;
|
||||
var date, mood, options;
|
||||
if (singing) {
|
||||
mood = greatly_improved;
|
||||
mood = greatlyImproved;
|
||||
}
|
||||
if (happy && knows_it) {
|
||||
claps_hands();
|
||||
cha_cha_cha();
|
||||
if (happy && knowsIt) {
|
||||
clapsHands();
|
||||
chaChaCha();
|
||||
}
|
||||
date = friday ? sue : jill;
|
||||
expensive = expensive || do_the_math();
|
||||
options = options || defaultOptions;
|
||||
})();
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
(function(){
|
||||
var eldest, grade;
|
||||
grade = function grade(student) {
|
||||
if (student.excellent_work) {
|
||||
grade = function(student) {
|
||||
if (student.excellentWork) {
|
||||
return "A+";
|
||||
} else if (student.okay_stuff) {
|
||||
return student.tried_hard ? "B" : "B-";
|
||||
} else if (student.okayStuff) {
|
||||
if (student.triedHard) {
|
||||
return "B";
|
||||
} else {
|
||||
return "B-";
|
||||
}
|
||||
} else {
|
||||
return "C";
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
(function(){
|
||||
var one, six, three, two;
|
||||
six = ((one = 1)) + ((two = 2)) + ((three = 3));
|
||||
six = (one = 1) + (two = 2) + (three = 3);
|
||||
})();
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
(function(){
|
||||
var _a, _b, globals, name;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
// The first ten global properties.
|
||||
globals = (function() {
|
||||
_a = []; _b = window;
|
||||
for (name in _b) { if (__hasProp.call(_b, name)) {
|
||||
_a.push(name);
|
||||
}}
|
||||
return _a;
|
||||
}).call(this).slice(0, 10);
|
||||
})().slice(0, 10);
|
||||
})();
|
||||
|
||||
@@ -5,5 +5,5 @@
|
||||
} catch (error) {
|
||||
return "And the error is ... " + error;
|
||||
}
|
||||
}).call(this));
|
||||
})());
|
||||
})();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
(function(){
|
||||
var Account;
|
||||
Account = function Account(customer, cart) {
|
||||
Account = function(customer, cart) {
|
||||
this.customer = customer;
|
||||
this.cart = cart;
|
||||
return $('.shopping_cart').bind('click', (function(__this) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
(function(){
|
||||
var cube, square;
|
||||
square = function square(x) {
|
||||
square = function(x) {
|
||||
return x * x;
|
||||
};
|
||||
cube = function cube(x) {
|
||||
cube = function(x) {
|
||||
return square(x) * x;
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
(function(){
|
||||
var html;
|
||||
html = "<strong>\n cup of coffeescript\n</strong>";
|
||||
html = '<strong>\n cup of coffeescript\n</strong>';
|
||||
})();
|
||||
|
||||
5
documentation/js/interpolation.js
Normal file
5
documentation/js/interpolation.js
Normal file
@@ -0,0 +1,5 @@
|
||||
(function(){
|
||||
var author, quote;
|
||||
author = "Wittgenstein";
|
||||
quote = ("A picture is a fact. -- " + author);
|
||||
})();
|
||||
6
documentation/js/interpolation_expression.js
Normal file
6
documentation/js/interpolation_expression.js
Normal file
@@ -0,0 +1,6 @@
|
||||
(function(){
|
||||
var dates, sentence, sep;
|
||||
sentence = ("" + (22 / 7) + " is a decent approximation of π");
|
||||
sep = "[.\\/\\- ]";
|
||||
dates = (new RegExp(("\\d+" + sep + "\\d+" + sep + "\\d+"), "g"));
|
||||
})();
|
||||
@@ -1,10 +1,9 @@
|
||||
(function(){
|
||||
var _a, city, forecast, temp, weather_report;
|
||||
weather_report = function weather_report(location) {
|
||||
// Make an Ajax request to fetch the weather...
|
||||
var _a, city, forecast, temp, weatherReport;
|
||||
weatherReport = function(location) {
|
||||
return [location, 72, "Mostly Sunny"];
|
||||
};
|
||||
_a = weather_report("Berkeley, CA");
|
||||
_a = weatherReport("Berkeley, CA");
|
||||
city = _a[0];
|
||||
temp = _a[1];
|
||||
forecast = _a[2];
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
(function(){
|
||||
var _a, _b, age, ages, child, years_old;
|
||||
var _a, _b, age, ages, child, yearsOld;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
years_old = {
|
||||
yearsOld = {
|
||||
max: 10,
|
||||
ida: 9,
|
||||
tim: 11
|
||||
};
|
||||
ages = (function() {
|
||||
_a = []; _b = years_old;
|
||||
_a = []; _b = yearsOld;
|
||||
for (child in _b) { if (__hasProp.call(_b, child)) {
|
||||
age = _b[child];
|
||||
_a.push(child + " is " + age);
|
||||
}}
|
||||
return _a;
|
||||
}).call(this);
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(function(){
|
||||
var _a, _b, _c, city, futurists, poet, street;
|
||||
var _a, _b, _c, city, futurists, name, street;
|
||||
futurists = {
|
||||
sculptor: "Umberto Boccioni",
|
||||
painter: "Vladimir Burliuk",
|
||||
@@ -10,7 +10,7 @@
|
||||
};
|
||||
_a = futurists;
|
||||
_b = _a.poet;
|
||||
poet = _b.name;
|
||||
name = _b.name;
|
||||
_c = _b.address;
|
||||
street = _c[0];
|
||||
city = _c[1];
|
||||
|
||||
5
documentation/js/objects_reserved.js
Normal file
5
documentation/js/objects_reserved.js
Normal file
@@ -0,0 +1,5 @@
|
||||
(function(){
|
||||
$('.account').css({
|
||||
'class': 'active'
|
||||
});
|
||||
})();
|
||||
@@ -1,43 +1,37 @@
|
||||
(function(){
|
||||
var _a, _b, _c, _d, cubed_list, list, math, num, number, opposite_day, race, square;
|
||||
// Assignment:
|
||||
var _a, _b, _c, _d, cubes, list, math, num, number, opposite, race, square;
|
||||
var __slice = Array.prototype.slice;
|
||||
number = 42;
|
||||
opposite_day = true;
|
||||
// Conditions:
|
||||
if (opposite_day) {
|
||||
opposite = true;
|
||||
if (opposite) {
|
||||
number = -42;
|
||||
}
|
||||
// Functions:
|
||||
square = function square(x) {
|
||||
square = function(x) {
|
||||
return x * x;
|
||||
};
|
||||
// Arrays:
|
||||
list = [1, 2, 3, 4, 5];
|
||||
// Objects:
|
||||
math = {
|
||||
root: Math.sqrt,
|
||||
square: square,
|
||||
cube: function cube(x) {
|
||||
cube: function(x) {
|
||||
return x * square(x);
|
||||
}
|
||||
};
|
||||
// Splats:
|
||||
race = function race(winner) {
|
||||
race = function(winner) {
|
||||
var runners;
|
||||
runners = Array.prototype.slice.call(arguments, 1);
|
||||
var _a = arguments.length, _b = _a >= 2;
|
||||
runners = __slice.call(arguments, 1, _a - 0);
|
||||
return print(winner, runners);
|
||||
};
|
||||
// Existence:
|
||||
if ((typeof elvis !== "undefined" && elvis !== null)) {
|
||||
if (typeof elvis !== "undefined" && elvis !== null) {
|
||||
alert("I knew it!");
|
||||
}
|
||||
// Array comprehensions:
|
||||
cubed_list = (function() {
|
||||
_a = []; _b = list;
|
||||
for (_c = 0, _d = _b.length; _c < _d; _c++) {
|
||||
num = _b[_c];
|
||||
cubes = (function() {
|
||||
_a = []; _c = list;
|
||||
for (_b = 0, _d = _c.length; _b < _d; _b++) {
|
||||
num = _c[_b];
|
||||
_a.push(math.cube(num));
|
||||
}
|
||||
return _a;
|
||||
}).call(this);
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
(function(){
|
||||
var _a, and_switch, bait;
|
||||
bait = 1000;
|
||||
and_switch = 0;
|
||||
_a = [and_switch, bait];
|
||||
bait = _a[0];
|
||||
and_switch = _a[1];
|
||||
var _a, theBait, theSwitch;
|
||||
theBait = 1000;
|
||||
theSwitch = 0;
|
||||
_a = [theSwitch, theBait];
|
||||
theBait = _a[0];
|
||||
theSwitch = _a[1];
|
||||
})();
|
||||
|
||||
9
documentation/js/patterns_and_splats.js
Normal file
9
documentation/js/patterns_and_splats.js
Normal file
@@ -0,0 +1,9 @@
|
||||
(function(){
|
||||
var _a, 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];
|
||||
})();
|
||||
2
documentation/js/prototypes.js
vendored
2
documentation/js/prototypes.js
vendored
@@ -1,5 +1,5 @@
|
||||
(function(){
|
||||
String.prototype.dasherize = function dasherize() {
|
||||
String.prototype.dasherize = function() {
|
||||
return this.replace(/_/g, "-");
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
(function(){
|
||||
var _a, _b, _c, _d, _e, countdown, egg_delivery, num;
|
||||
var _a, countdown, deliverEggs, num;
|
||||
countdown = (function() {
|
||||
_a = []; _d = 10; _e = 1;
|
||||
for (_c = 0, num = _d; (_d <= _e ? num <= _e : num >= _e); (_d <= _e ? num += 1 : num -= 1), _c++) {
|
||||
_a = [];
|
||||
for (num = 10; num >= 1; num += -1) {
|
||||
_a.push(num);
|
||||
}
|
||||
return _a;
|
||||
}).call(this);
|
||||
egg_delivery = function egg_delivery() {
|
||||
var _f, _g, _h, _i, _j, dozen_eggs, i;
|
||||
_f = []; _i = 0; _j = eggs.length;
|
||||
for (_h = 0, i = _i; (_i <= _j ? i < _j : i > _j); (_i <= _j ? i += 12 : i -= 12), _h++) {
|
||||
_f.push((function() {
|
||||
dozen_eggs = eggs.slice(i, i + 12);
|
||||
return deliver(new egg_carton(dozen));
|
||||
}).call(this));
|
||||
})();
|
||||
deliverEggs = function() {
|
||||
var _b, _c, dozen, i;
|
||||
_b = []; (_c = eggs.length);
|
||||
|
||||
for (i = 0; i < _c; i += 12) {
|
||||
_b.push((function() {
|
||||
dozen = eggs.slice(i, i + 12);
|
||||
return deliver(new eggCarton(dozen));
|
||||
})());
|
||||
}
|
||||
return _f;
|
||||
return _b;
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
(function(){
|
||||
var change_numbers, new_num, num;
|
||||
num = 1;
|
||||
change_numbers = function change_numbers() {
|
||||
var new_num;
|
||||
new_num = -1;
|
||||
return num = 10;
|
||||
var changeNumbers, inner, outer;
|
||||
outer = 1;
|
||||
changeNumbers = function() {
|
||||
var inner;
|
||||
inner = -1;
|
||||
outer = 10;
|
||||
return outer;
|
||||
};
|
||||
new_num = change_numbers();
|
||||
inner = changeNumbers();
|
||||
})();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
(function(){
|
||||
var numbers, numbers_copy, three_to_six;
|
||||
var copy, numbers, threeToSix;
|
||||
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
three_to_six = numbers.slice(3, 6 + 1);
|
||||
numbers_copy = numbers.slice(0, numbers.length);
|
||||
threeToSix = numbers.slice(3, 6 + 1);
|
||||
copy = numbers.slice(0, numbers.length);
|
||||
})();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
(function(){
|
||||
var _a;
|
||||
(_a = lottery.draw_winner()) == undefined ? undefined : _a.address == undefined ? undefined : _a.address.zipcode;
|
||||
typeof (_a = (lottery.drawWinner())) === "undefined" || _a == undefined ? undefined : _a.address == undefined ? undefined : _a.address.zipcode;
|
||||
})();
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
(function(){
|
||||
var award_medals, contenders, gold, silver, the_field;
|
||||
gold = (silver = (the_field = "unknown"));
|
||||
award_medals = function award_medals(first, second) {
|
||||
var rest;
|
||||
rest = Array.prototype.slice.call(arguments, 2);
|
||||
var awardMedals, contenders, gold, rest, silver;
|
||||
var __slice = Array.prototype.slice;
|
||||
gold = (silver = (rest = "unknown"));
|
||||
awardMedals = function(first, second) {
|
||||
var _a = arguments.length, _b = _a >= 3;
|
||||
rest = __slice.call(arguments, 2, _a - 0);
|
||||
gold = first;
|
||||
silver = second;
|
||||
return the_field = rest;
|
||||
rest = rest;
|
||||
return rest;
|
||||
};
|
||||
contenders = ["Michael Phelps", "Liu Xiang", "Yao Ming", "Allyson Felix", "Shawn Johnson", "Roman Sebrle", "Guo Jingjing", "Tyson Gay", "Asafa Powell", "Usain Bolt"];
|
||||
award_medals.apply(this, contenders);
|
||||
awardMedals.apply(this, contenders);
|
||||
alert("Gold: " + gold);
|
||||
alert("Silver: " + silver);
|
||||
alert("The Field: " + the_field);
|
||||
alert("The Field: " + rest);
|
||||
})();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
(function(){
|
||||
var moby_dick;
|
||||
moby_dick = "Call me Ishmael. Some years ago -- \
|
||||
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 \
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
(function(){
|
||||
if (day === "Mon") {
|
||||
go_to_work();
|
||||
goToWork();
|
||||
} else if (day === "Tue") {
|
||||
go_to_the_park();
|
||||
goToThePark();
|
||||
} else if (day === "Thu") {
|
||||
go_ice_fishing();
|
||||
goIceFishing();
|
||||
} else if (day === "Fri" || day === "Sat") {
|
||||
if (day === bingo_day) {
|
||||
go_to_bingo();
|
||||
go_dancing();
|
||||
if (day === bingoDay) {
|
||||
goToBingo();
|
||||
goDancing();
|
||||
}
|
||||
} else if (day === "Sun") {
|
||||
go_to_church();
|
||||
goToChurch();
|
||||
} else {
|
||||
go_to_work();
|
||||
goToWork();
|
||||
}
|
||||
})();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
(function(){
|
||||
try {
|
||||
all_hell_breaks_loose();
|
||||
cats_and_dogs_living_together();
|
||||
allHellBreaksLoose();
|
||||
catsAndDogsLivingTogether();
|
||||
} catch (error) {
|
||||
print(error);
|
||||
} finally {
|
||||
clean_up();
|
||||
cleanUp();
|
||||
}
|
||||
})();
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
(function(){
|
||||
var _a, lyrics, num;
|
||||
// Econ 101
|
||||
if (this.studying_economics) {
|
||||
if (this.studyingEconomics) {
|
||||
while (supply > demand) {
|
||||
buy();
|
||||
}
|
||||
while (supply < demand) {
|
||||
while (!(supply > demand)) {
|
||||
sell();
|
||||
}
|
||||
}
|
||||
// Nursery Rhyme
|
||||
num = 6;
|
||||
lyrics = (function() {
|
||||
_a = [];
|
||||
@@ -18,5 +16,5 @@
|
||||
One fell out and bumped his head.");
|
||||
}
|
||||
return _a;
|
||||
}).call(this);
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -1,668 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
||||
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
||||
<link rel="stylesheet" type="text/css" media="screen,projection,print" href="css/idle.css" />
|
||||
<title>Underscore.coffee</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<pre class="idle"><span class="line-numbers"> 1 </span>
|
||||
<span class="line-numbers"> 2 </span> <span class="Comment"><span class="Comment">#</span> Underscore.coffee</span>
|
||||
<span class="line-numbers"> 3 </span> <span class="Comment"><span class="Comment">#</span> (c) 2010 Jeremy Ashkenas, DocumentCloud Inc.</span>
|
||||
<span class="line-numbers"> 4 </span> <span class="Comment"><span class="Comment">#</span> Underscore is freely distributable under the terms of the MIT license.</span>
|
||||
<span class="line-numbers"> 5 </span> <span class="Comment"><span class="Comment">#</span> Portions of Underscore are inspired by or borrowed from Prototype.js,</span>
|
||||
<span class="line-numbers"> 6 </span> <span class="Comment"><span class="Comment">#</span> Oliver Steele's Functional, and John Resig's Micro-Templating.</span>
|
||||
<span class="line-numbers"> 7 </span> <span class="Comment"><span class="Comment">#</span> For all details and documentation:</span>
|
||||
<span class="line-numbers"> 8 </span> <span class="Comment"><span class="Comment">#</span> http://documentcloud.github.com/underscore/</span>
|
||||
<span class="line-numbers"> 9 </span>
|
||||
<span class="line-numbers"> 10 </span>
|
||||
<span class="line-numbers"> 11 </span> <span class="Comment"><span class="Comment">#</span> ------------------------- Baseline setup ---------------------------------</span>
|
||||
<span class="line-numbers"> 12 </span>
|
||||
<span class="line-numbers"> 13 </span> <span class="Comment"><span class="Comment">#</span> Establish the root object, "window" in the browser, or "global" on the server.</span>
|
||||
<span class="line-numbers"> 14 </span> <span class="FunctionName">root</span><span class="Keyword">:</span> <span class="Variable">this</span>
|
||||
<span class="line-numbers"> 15 </span>
|
||||
<span class="line-numbers"> 16 </span>
|
||||
<span class="line-numbers"> 17 </span> <span class="Comment"><span class="Comment">#</span> Save the previous value of the "_" variable.</span>
|
||||
<span class="line-numbers"> 18 </span> <span class="FunctionName">previousUnderscore</span><span class="Keyword">:</span> root._
|
||||
<span class="line-numbers"> 19 </span>
|
||||
<span class="line-numbers"> 20 </span>
|
||||
<span class="line-numbers"> 21 </span> <span class="Comment"><span class="Comment">#</span> Establish the object that gets thrown to break out of a loop iteration.</span>
|
||||
<span class="line-numbers"> 22 </span> <span class="FunctionName">breaker</span><span class="Keyword">:</span> <span class="Keyword">if</span> <span class="Keyword">typeof</span>(StopIteration) <span class="Keyword">is</span> <span class="String"><span class="String">'</span>undefined<span class="String">'</span></span> <span class="Keyword">then</span> <span class="String"><span class="String">'</span>__break__<span class="String">'</span></span> <span class="Keyword">else</span> StopIteration
|
||||
<span class="line-numbers"> 23 </span>
|
||||
<span class="line-numbers"> 24 </span>
|
||||
<span class="line-numbers"> 25 </span> <span class="Comment"><span class="Comment">#</span> Quick regexp-escaping function, because JS doesn't have RegExp.escape().</span>
|
||||
<span class="line-numbers"> 26 </span> <span class="FunctionName">escapeRegExp</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">string</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> string.replace(<span class="String"><span class="String">/</span>([.*+?^${}()|[<span class="UserDefinedConstant">\]</span><span class="UserDefinedConstant">\/</span><span class="UserDefinedConstant">\\</span>])<span class="String">/</span>g</span>, <span class="String"><span class="String">'</span><span class="UserDefinedConstant">\\</span>$1<span class="String">'</span></span>)
|
||||
<span class="line-numbers"> 27 </span>
|
||||
<span class="line-numbers"> 28 </span>
|
||||
<span class="line-numbers"> 29 </span> <span class="Comment"><span class="Comment">#</span> Save bytes in the minified (but not gzipped) version:</span>
|
||||
<span class="line-numbers"> 30 </span> <span class="FunctionName">ArrayProto</span><span class="Keyword">:</span> Array.prototype
|
||||
<span class="line-numbers"> 31 </span> <span class="FunctionName">ObjProto</span><span class="Keyword">:</span> Object.prototype
|
||||
<span class="line-numbers"> 32 </span>
|
||||
<span class="line-numbers"> 33 </span>
|
||||
<span class="line-numbers"> 34 </span> <span class="Comment"><span class="Comment">#</span>Create quick reference variables for speed access to core prototypes.</span>
|
||||
<span class="line-numbers"> 35 </span> <span class="FunctionName">slice</span><span class="Keyword">:</span> ArrayProto.slice
|
||||
<span class="line-numbers"> 36 </span> <span class="FunctionName">unshift</span><span class="Keyword">:</span> ArrayProto.unshift
|
||||
<span class="line-numbers"> 37 </span> <span class="FunctionName">toString</span><span class="Keyword">:</span> ObjProto.toString
|
||||
<span class="line-numbers"> 38 </span> <span class="FunctionName">hasOwnProperty</span><span class="Keyword">:</span> ObjProto.hasOwnProperty
|
||||
<span class="line-numbers"> 39 </span> <span class="FunctionName">propertyIsEnumerable</span><span class="Keyword">:</span> ObjProto.propertyIsEnumerable
|
||||
<span class="line-numbers"> 40 </span>
|
||||
<span class="line-numbers"> 41 </span>
|
||||
<span class="line-numbers"> 42 </span> <span class="Comment"><span class="Comment">#</span> All ECMA5 native implementations we hope to use are declared here.</span>
|
||||
<span class="line-numbers"> 43 </span> <span class="FunctionName">nativeForEach</span><span class="Keyword">:</span> ArrayProto.forEach
|
||||
<span class="line-numbers"> 44 </span> <span class="FunctionName">nativeMap</span><span class="Keyword">:</span> ArrayProto.map
|
||||
<span class="line-numbers"> 45 </span> <span class="FunctionName">nativeReduce</span><span class="Keyword">:</span> ArrayProto.reduce
|
||||
<span class="line-numbers"> 46 </span> <span class="FunctionName">nativeReduceRight</span><span class="Keyword">:</span> ArrayProto.reduceRight
|
||||
<span class="line-numbers"> 47 </span> <span class="FunctionName">nativeFilter</span><span class="Keyword">:</span> ArrayProto.filter
|
||||
<span class="line-numbers"> 48 </span> <span class="FunctionName">nativeEvery</span><span class="Keyword">:</span> ArrayProto.every
|
||||
<span class="line-numbers"> 49 </span> <span class="FunctionName">nativeSome</span><span class="Keyword">:</span> ArrayProto.some
|
||||
<span class="line-numbers"> 50 </span> <span class="FunctionName">nativeIndexOf</span><span class="Keyword">:</span> ArrayProto.indexOf
|
||||
<span class="line-numbers"> 51 </span> <span class="FunctionName">nativeLastIndexOf</span><span class="Keyword">:</span> ArrayProto.lastIndexOf
|
||||
<span class="line-numbers"> 52 </span> <span class="FunctionName">nativeIsArray</span><span class="Keyword">:</span> Array.isArray
|
||||
<span class="line-numbers"> 53 </span> <span class="FunctionName">nativeKeys</span><span class="Keyword">:</span> Object.keys
|
||||
<span class="line-numbers"> 54 </span>
|
||||
<span class="line-numbers"> 55 </span>
|
||||
<span class="line-numbers"> 56 </span> <span class="Comment"><span class="Comment">#</span> Create a safe reference to the Underscore object for use below.</span>
|
||||
<span class="line-numbers"> 57 </span> <span class="FunctionName">_</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> <span class="Keyword">new</span> <span class="TypeName">wrapper</span>(obj)
|
||||
<span class="line-numbers"> 58 </span>
|
||||
<span class="line-numbers"> 59 </span>
|
||||
<span class="line-numbers"> 60 </span> <span class="Comment"><span class="Comment">#</span> Export the Underscore object for CommonJS.</span>
|
||||
<span class="line-numbers"> 61 </span> <span class="Keyword">if</span> <span class="Keyword">typeof</span>(exports) <span class="Keyword">!</span><span class="Keyword">=</span> <span class="String"><span class="String">'</span>undefined<span class="String">'</span></span> <span class="Keyword">then</span> <span class="FunctionName">exports._</span><span class="Keyword">:</span> _
|
||||
<span class="line-numbers"> 62 </span>
|
||||
<span class="line-numbers"> 63 </span>
|
||||
<span class="line-numbers"> 64 </span> <span class="Comment"><span class="Comment">#</span> Export Underscore to global scope.</span>
|
||||
<span class="line-numbers"> 65 </span> <span class="FunctionName">root._</span><span class="Keyword">:</span> _
|
||||
<span class="line-numbers"> 66 </span>
|
||||
<span class="line-numbers"> 67 </span>
|
||||
<span class="line-numbers"> 68 </span> <span class="Comment"><span class="Comment">#</span> Current version.</span>
|
||||
<span class="line-numbers"> 69 </span> <span class="FunctionName">_.VERSION</span><span class="Keyword">:</span> <span class="String"><span class="String">'</span>0.6.0<span class="String">'</span></span>
|
||||
<span class="line-numbers"> 70 </span>
|
||||
<span class="line-numbers"> 71 </span>
|
||||
<span class="line-numbers"> 72 </span> <span class="Comment"><span class="Comment">#</span> ------------------------ Collection Functions: ---------------------------</span>
|
||||
<span class="line-numbers"> 73 </span>
|
||||
<span class="line-numbers"> 74 </span> <span class="Comment"><span class="Comment">#</span> The cornerstone, an each implementation.</span>
|
||||
<span class="line-numbers"> 75 </span> <span class="Comment"><span class="Comment">#</span> Handles objects implementing forEach, arrays, and raw objects.</span>
|
||||
<span class="line-numbers"> 76 </span> <span class="FunctionName">_.each</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 77 </span> <span class="Keyword">try</span>
|
||||
<span class="line-numbers"> 78 </span> <span class="Keyword">if</span> nativeForEach <span class="Keyword">and</span> obj.forEach <span class="Keyword">is</span> nativeForEach
|
||||
<span class="line-numbers"> 79 </span> obj.forEach iterator, context
|
||||
<span class="line-numbers"> 80 </span> <span class="Keyword">else</span> <span class="Keyword">if</span> _.isNumber obj.length
|
||||
<span class="line-numbers"> 81 </span> iterator.call(context, obj[i], i, obj) <span class="Keyword">for</span> i <span class="Keyword">in</span> [<span class="Number">0</span>...obj.length]
|
||||
<span class="line-numbers"> 82 </span> <span class="Keyword">else</span>
|
||||
<span class="line-numbers"> 83 </span> iterator.call(context, val, key, obj) <span class="Keyword">for</span> key, val <span class="Keyword">of</span> obj
|
||||
<span class="line-numbers"> 84 </span> <span class="Keyword">catch</span> e
|
||||
<span class="line-numbers"> 85 </span> <span class="Keyword">throw</span> e <span class="Keyword">if</span> e <span class="Keyword">isnt</span> breaker
|
||||
<span class="line-numbers"> 86 </span> obj
|
||||
<span class="line-numbers"> 87 </span>
|
||||
<span class="line-numbers"> 88 </span>
|
||||
<span class="line-numbers"> 89 </span> <span class="Comment"><span class="Comment">#</span> Return the results of applying the iterator to each element. Use JavaScript</span>
|
||||
<span class="line-numbers"> 90 </span> <span class="Comment"><span class="Comment">#</span> 1.6's version of map, if possible.</span>
|
||||
<span class="line-numbers"> 91 </span> <span class="FunctionName">_.map</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 92 </span> <span class="Keyword">return</span> obj.map(iterator, context) <span class="Keyword">if</span> nativeMap <span class="Keyword">and</span> obj.map <span class="Keyword">is</span> nativeMap
|
||||
<span class="line-numbers"> 93 </span> <span class="FunctionName">results</span><span class="Keyword">:</span> []
|
||||
<span class="line-numbers"> 94 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 95 </span> results.push iterator.call context, value, index, list
|
||||
<span class="line-numbers"> 96 </span> results
|
||||
<span class="line-numbers"> 97 </span>
|
||||
<span class="line-numbers"> 98 </span>
|
||||
<span class="line-numbers"> 99 </span> <span class="Comment"><span class="Comment">#</span> Reduce builds up a single result from a list of values. Also known as</span>
|
||||
<span class="line-numbers"> 100 </span> <span class="Comment"><span class="Comment">#</span> inject, or foldl. Uses JavaScript 1.8's version of reduce, if possible.</span>
|
||||
<span class="line-numbers"> 101 </span> <span class="FunctionName">_.reduce</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, memo, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 102 </span> <span class="Keyword">return</span> obj.reduce(_.bind(iterator, context), memo) <span class="Keyword">if</span> nativeReduce <span class="Keyword">and</span> obj.reduce <span class="Keyword">is</span> nativeReduce
|
||||
<span class="line-numbers"> 103 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 104 </span> <span class="FunctionName">memo</span><span class="Keyword">:</span> iterator.call context, memo, value, index, list
|
||||
<span class="line-numbers"> 105 </span> memo
|
||||
<span class="line-numbers"> 106 </span>
|
||||
<span class="line-numbers"> 107 </span>
|
||||
<span class="line-numbers"> 108 </span> <span class="Comment"><span class="Comment">#</span> The right-associative version of reduce, also known as foldr. Uses</span>
|
||||
<span class="line-numbers"> 109 </span> <span class="Comment"><span class="Comment">#</span> JavaScript 1.8's version of reduceRight, if available.</span>
|
||||
<span class="line-numbers"> 110 </span> <span class="FunctionName">_.reduceRight</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, memo, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 111 </span> <span class="Keyword">return</span> obj.reduceRight(_.bind(iterator, context), memo) <span class="Keyword">if</span> nativeReduceRight <span class="Keyword">and</span> obj.reduceRight <span class="Keyword">is</span> nativeReduceRight
|
||||
<span class="line-numbers"> 112 </span> _.each _.clone(_.toArray(obj)).reverse(), <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 113 </span> <span class="FunctionName">memo</span><span class="Keyword">:</span> iterator.call context, memo, value, index, obj
|
||||
<span class="line-numbers"> 114 </span> memo
|
||||
<span class="line-numbers"> 115 </span>
|
||||
<span class="line-numbers"> 116 </span>
|
||||
<span class="line-numbers"> 117 </span> <span class="Comment"><span class="Comment">#</span> Return the first value which passes a truth test.</span>
|
||||
<span class="line-numbers"> 118 </span> <span class="FunctionName">_.detect</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 119 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> <span class="BuiltInConstant">null</span>
|
||||
<span class="line-numbers"> 120 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 121 </span> <span class="Keyword">if</span> iterator.call context, value, index, list
|
||||
<span class="line-numbers"> 122 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> value
|
||||
<span class="line-numbers"> 123 </span> _.breakLoop()
|
||||
<span class="line-numbers"> 124 </span> result
|
||||
<span class="line-numbers"> 125 </span>
|
||||
<span class="line-numbers"> 126 </span>
|
||||
<span class="line-numbers"> 127 </span> <span class="Comment"><span class="Comment">#</span> Return all the elements that pass a truth test. Use JavaScript 1.6's</span>
|
||||
<span class="line-numbers"> 128 </span> <span class="Comment"><span class="Comment">#</span> filter(), if it exists.</span>
|
||||
<span class="line-numbers"> 129 </span> <span class="FunctionName">_.filter</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 130 </span> <span class="Keyword">return</span> obj.filter iterator, context <span class="Keyword">if</span> nativeFilter <span class="Keyword">and</span> obj.filter <span class="Keyword">is</span> nativeFilter
|
||||
<span class="line-numbers"> 131 </span> <span class="FunctionName">results</span><span class="Keyword">:</span> []
|
||||
<span class="line-numbers"> 132 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 133 </span> results.push value <span class="Keyword">if</span> iterator.call context, value, index, list
|
||||
<span class="line-numbers"> 134 </span> results
|
||||
<span class="line-numbers"> 135 </span>
|
||||
<span class="line-numbers"> 136 </span>
|
||||
<span class="line-numbers"> 137 </span> <span class="Comment"><span class="Comment">#</span> Return all the elements for which a truth test fails.</span>
|
||||
<span class="line-numbers"> 138 </span> <span class="FunctionName">_.reject</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 139 </span> <span class="FunctionName">results</span><span class="Keyword">:</span> []
|
||||
<span class="line-numbers"> 140 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 141 </span> results.push value <span class="Keyword">if</span> <span class="Keyword">not</span> iterator.call context, value, index, list
|
||||
<span class="line-numbers"> 142 </span> results
|
||||
<span class="line-numbers"> 143 </span>
|
||||
<span class="line-numbers"> 144 </span>
|
||||
<span class="line-numbers"> 145 </span> <span class="Comment"><span class="Comment">#</span> Determine whether all of the elements match a truth test. Delegate to</span>
|
||||
<span class="line-numbers"> 146 </span> <span class="Comment"><span class="Comment">#</span> JavaScript 1.6's every(), if it is present.</span>
|
||||
<span class="line-numbers"> 147 </span> <span class="FunctionName">_.every</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 148 </span> iterator <span class="Keyword">||</span><span class="Keyword">=</span> _.identity
|
||||
<span class="line-numbers"> 149 </span> <span class="Keyword">return</span> obj.every iterator, context <span class="Keyword">if</span> nativeEvery <span class="Keyword">and</span> obj.every <span class="Keyword">is</span> nativeEvery
|
||||
<span class="line-numbers"> 150 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> <span class="BuiltInConstant">true</span>
|
||||
<span class="line-numbers"> 151 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 152 </span> _.breakLoop() <span class="Keyword">unless</span> (<span class="FunctionName">result</span><span class="Keyword">:</span> result <span class="Keyword">and</span> iterator.call(context, value, index, list))
|
||||
<span class="line-numbers"> 153 </span> result
|
||||
<span class="line-numbers"> 154 </span>
|
||||
<span class="line-numbers"> 155 </span>
|
||||
<span class="line-numbers"> 156 </span> <span class="Comment"><span class="Comment">#</span> Determine if at least one element in the object matches a truth test. Use</span>
|
||||
<span class="line-numbers"> 157 </span> <span class="Comment"><span class="Comment">#</span> JavaScript 1.6's some(), if it exists.</span>
|
||||
<span class="line-numbers"> 158 </span> <span class="FunctionName">_.some</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 159 </span> iterator <span class="Keyword">||</span><span class="Keyword">=</span> _.identity
|
||||
<span class="line-numbers"> 160 </span> <span class="Keyword">return</span> obj.some iterator, context <span class="Keyword">if</span> nativeSome <span class="Keyword">and</span> obj.some <span class="Keyword">is</span> nativeSome
|
||||
<span class="line-numbers"> 161 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> <span class="BuiltInConstant">false</span>
|
||||
<span class="line-numbers"> 162 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 163 </span> _.breakLoop() <span class="Keyword">if</span> (<span class="FunctionName">result</span><span class="Keyword">:</span> iterator.call(context, value, index, list))
|
||||
<span class="line-numbers"> 164 </span> result
|
||||
<span class="line-numbers"> 165 </span>
|
||||
<span class="line-numbers"> 166 </span>
|
||||
<span class="line-numbers"> 167 </span> <span class="Comment"><span class="Comment">#</span> Determine if a given value is included in the array or object,</span>
|
||||
<span class="line-numbers"> 168 </span> <span class="Comment"><span class="Comment">#</span> based on '==='.</span>
|
||||
<span class="line-numbers"> 169 </span> <span class="FunctionName">_.include</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, target</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 170 </span> <span class="Keyword">return</span> _.indexOf(obj, target) <span class="Keyword">isnt</span> <span class="Keyword">-</span><span class="Number">1</span> <span class="Keyword">if</span> nativeIndexOf <span class="Keyword">and</span> obj.indexOf <span class="Keyword">is</span> nativeIndexOf
|
||||
<span class="line-numbers"> 171 </span> <span class="Keyword">for</span> key, val <span class="Keyword">of</span> obj
|
||||
<span class="line-numbers"> 172 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">true</span> <span class="Keyword">if</span> val <span class="Keyword">is</span> target
|
||||
<span class="line-numbers"> 173 </span> <span class="BuiltInConstant">false</span>
|
||||
<span class="line-numbers"> 174 </span>
|
||||
<span class="line-numbers"> 175 </span>
|
||||
<span class="line-numbers"> 176 </span> <span class="Comment"><span class="Comment">#</span> Invoke a method with arguments on every item in a collection.</span>
|
||||
<span class="line-numbers"> 177 </span> <span class="FunctionName">_.invoke</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, method</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 178 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> _.rest arguments, <span class="Number">2</span>
|
||||
<span class="line-numbers"> 179 </span> (<span class="Keyword">if</span> method <span class="Keyword">then</span> val[method] <span class="Keyword">else</span> val).apply(val, args) <span class="Keyword">for</span> val <span class="Keyword">in</span> obj
|
||||
<span class="line-numbers"> 180 </span>
|
||||
<span class="line-numbers"> 181 </span>
|
||||
<span class="line-numbers"> 182 </span> <span class="Comment"><span class="Comment">#</span> Convenience version of a common use case of map: fetching a property.</span>
|
||||
<span class="line-numbers"> 183 </span> <span class="FunctionName">_.pluck</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, key</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 184 </span> _.map(obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">val</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> val[key])
|
||||
<span class="line-numbers"> 185 </span>
|
||||
<span class="line-numbers"> 186 </span>
|
||||
<span class="line-numbers"> 187 </span> <span class="Comment"><span class="Comment">#</span> Return the maximum item or (item-based computation).</span>
|
||||
<span class="line-numbers"> 188 </span> <span class="FunctionName">_.max</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 189 </span> <span class="Keyword">return</span> Math.max.apply(Math, obj) <span class="Keyword">if</span> <span class="Keyword">not</span> iterator <span class="Keyword">and</span> _.isArray(obj)
|
||||
<span class="line-numbers"> 190 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> {<span class="FunctionName">computed</span><span class="Keyword">:</span> <span class="Keyword">-</span><span class="BuiltInConstant">Infinity</span>}
|
||||
<span class="line-numbers"> 191 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 192 </span> <span class="FunctionName">computed</span><span class="Keyword">:</span> <span class="Keyword">if</span> iterator <span class="Keyword">then</span> iterator.call(context, value, index, list) <span class="Keyword">else</span> value
|
||||
<span class="line-numbers"> 193 </span> computed <span class="Keyword">>=</span> result.computed <span class="Keyword">and</span> (<span class="FunctionName">result</span><span class="Keyword">:</span> {<span class="FunctionName">value</span><span class="Keyword">:</span> value, <span class="FunctionName">computed</span><span class="Keyword">:</span> computed})
|
||||
<span class="line-numbers"> 194 </span> result.value
|
||||
<span class="line-numbers"> 195 </span>
|
||||
<span class="line-numbers"> 196 </span>
|
||||
<span class="line-numbers"> 197 </span> <span class="Comment"><span class="Comment">#</span> Return the minimum element (or element-based computation).</span>
|
||||
<span class="line-numbers"> 198 </span> <span class="FunctionName">_.min</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 199 </span> <span class="Keyword">return</span> Math.min.apply(Math, obj) <span class="Keyword">if</span> <span class="Keyword">not</span> iterator <span class="Keyword">and</span> _.isArray(obj)
|
||||
<span class="line-numbers"> 200 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> {<span class="FunctionName">computed</span><span class="Keyword">:</span> <span class="BuiltInConstant">Infinity</span>}
|
||||
<span class="line-numbers"> 201 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 202 </span> <span class="FunctionName">computed</span><span class="Keyword">:</span> <span class="Keyword">if</span> iterator <span class="Keyword">then</span> iterator.call(context, value, index, list) <span class="Keyword">else</span> value
|
||||
<span class="line-numbers"> 203 </span> computed <span class="Keyword"><</span> result.computed <span class="Keyword">and</span> (<span class="FunctionName">result</span><span class="Keyword">:</span> {<span class="FunctionName">value</span><span class="Keyword">:</span> value, <span class="FunctionName">computed</span><span class="Keyword">:</span> computed})
|
||||
<span class="line-numbers"> 204 </span> result.value
|
||||
<span class="line-numbers"> 205 </span>
|
||||
<span class="line-numbers"> 206 </span>
|
||||
<span class="line-numbers"> 207 </span> <span class="Comment"><span class="Comment">#</span> Sort the object's values by a criterion produced by an iterator.</span>
|
||||
<span class="line-numbers"> 208 </span> <span class="FunctionName">_.sortBy</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 209 </span> _.pluck(((_.map obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 210 </span> {<span class="FunctionName">value</span><span class="Keyword">:</span> value, <span class="FunctionName">criteria</span><span class="Keyword">:</span> iterator.call(context, value, index, list)}
|
||||
<span class="line-numbers"> 211 </span> ).sort(<span class="FunctionArgument">(</span><span class="FunctionArgument">left, right</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 212 </span> <span class="FunctionName">a</span><span class="Keyword">:</span> left.criteria; <span class="FunctionName">b</span><span class="Keyword">:</span> right.criteria
|
||||
<span class="line-numbers"> 213 </span> <span class="Keyword">if</span> a <span class="Keyword"><</span> b <span class="Keyword">then</span> <span class="Keyword">-</span><span class="Number">1</span> <span class="Keyword">else</span> <span class="Keyword">if</span> a <span class="Keyword">></span> b <span class="Keyword">then</span> <span class="Number">1</span> <span class="Keyword">else</span> <span class="Number">0</span>
|
||||
<span class="line-numbers"> 214 </span> )), <span class="String"><span class="String">'</span>value<span class="String">'</span></span>)
|
||||
<span class="line-numbers"> 215 </span>
|
||||
<span class="line-numbers"> 216 </span>
|
||||
<span class="line-numbers"> 217 </span> <span class="Comment"><span class="Comment">#</span> Use a comparator function to figure out at what index an object should</span>
|
||||
<span class="line-numbers"> 218 </span> <span class="Comment"><span class="Comment">#</span> be inserted so as to maintain order. Uses binary search.</span>
|
||||
<span class="line-numbers"> 219 </span> <span class="FunctionName">_.sortedIndex</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array, obj, iterator</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 220 </span> iterator <span class="Keyword">||</span><span class="Keyword">=</span> _.identity
|
||||
<span class="line-numbers"> 221 </span> <span class="FunctionName">low</span><span class="Keyword">:</span> <span class="Number">0</span>
|
||||
<span class="line-numbers"> 222 </span> <span class="FunctionName">high</span><span class="Keyword">:</span> array.length
|
||||
<span class="line-numbers"> 223 </span> <span class="Keyword">while</span> low <span class="Keyword"><</span> high
|
||||
<span class="line-numbers"> 224 </span> <span class="FunctionName">mid</span><span class="Keyword">:</span> (low <span class="Keyword">+</span> high) <span class="Keyword">></span><span class="Keyword">></span> <span class="Number">1</span>
|
||||
<span class="line-numbers"> 225 </span> <span class="Keyword">if</span> iterator(array[mid]) <span class="Keyword"><</span> iterator(obj) <span class="Keyword">then</span> <span class="FunctionName">low</span><span class="Keyword">:</span> mid <span class="Keyword">+</span> <span class="Number">1</span> <span class="Keyword">else</span> <span class="FunctionName">high</span><span class="Keyword">:</span> mid
|
||||
<span class="line-numbers"> 226 </span> low
|
||||
<span class="line-numbers"> 227 </span>
|
||||
<span class="line-numbers"> 228 </span>
|
||||
<span class="line-numbers"> 229 </span> <span class="Comment"><span class="Comment">#</span> Convert anything iterable into a real, live array.</span>
|
||||
<span class="line-numbers"> 230 </span> <span class="FunctionName">_.toArray</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">iterable</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 231 </span> <span class="Keyword">return</span> [] <span class="Keyword">if</span> (<span class="Keyword">!</span>iterable)
|
||||
<span class="line-numbers"> 232 </span> <span class="Keyword">return</span> iterable.toArray() <span class="Keyword">if</span> (iterable.toArray)
|
||||
<span class="line-numbers"> 233 </span> <span class="Keyword">return</span> iterable <span class="Keyword">if</span> (_.isArray(iterable))
|
||||
<span class="line-numbers"> 234 </span> <span class="Keyword">return</span> slice.call(iterable) <span class="Keyword">if</span> (_.isArguments(iterable))
|
||||
<span class="line-numbers"> 235 </span> _.values(iterable)
|
||||
<span class="line-numbers"> 236 </span>
|
||||
<span class="line-numbers"> 237 </span>
|
||||
<span class="line-numbers"> 238 </span> <span class="Comment"><span class="Comment">#</span> Return the number of elements in an object.</span>
|
||||
<span class="line-numbers"> 239 </span> <span class="FunctionName">_.size</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> _.toArray(obj).length
|
||||
<span class="line-numbers"> 240 </span>
|
||||
<span class="line-numbers"> 241 </span>
|
||||
<span class="line-numbers"> 242 </span> <span class="Comment"><span class="Comment">#</span> -------------------------- Array Functions: ------------------------------</span>
|
||||
<span class="line-numbers"> 243 </span>
|
||||
<span class="line-numbers"> 244 </span> <span class="Comment"><span class="Comment">#</span> Get the first element of an array. Passing "n" will return the first N</span>
|
||||
<span class="line-numbers"> 245 </span> <span class="Comment"><span class="Comment">#</span> values in the array. Aliased as "head". The "guard" check allows it to work</span>
|
||||
<span class="line-numbers"> 246 </span> <span class="Comment"><span class="Comment">#</span> with _.map.</span>
|
||||
<span class="line-numbers"> 247 </span> <span class="FunctionName">_.first</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array, n, guard</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 248 </span> <span class="Keyword">if</span> n <span class="Keyword">and</span> <span class="Keyword">not</span> guard <span class="Keyword">then</span> slice.call(array, <span class="Number">0</span>, n) <span class="Keyword">else</span> array[<span class="Number">0</span>]
|
||||
<span class="line-numbers"> 249 </span>
|
||||
<span class="line-numbers"> 250 </span>
|
||||
<span class="line-numbers"> 251 </span> <span class="Comment"><span class="Comment">#</span> Returns everything but the first entry of the array. Aliased as "tail".</span>
|
||||
<span class="line-numbers"> 252 </span> <span class="Comment"><span class="Comment">#</span> Especially useful on the arguments object. Passing an "index" will return</span>
|
||||
<span class="line-numbers"> 253 </span> <span class="Comment"><span class="Comment">#</span> the rest of the values in the array from that index onward. The "guard"</span>
|
||||
<span class="line-numbers"> 254 </span> <span class="Comment"><span class="Comment">#</span> check allows it to work with _.map.</span>
|
||||
<span class="line-numbers"> 255 </span> <span class="FunctionName">_.rest</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array, index, guard</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 256 </span> slice.call(array, <span class="Keyword">if</span> _.isUndefined(index) <span class="Keyword">or</span> guard <span class="Keyword">then</span> <span class="Number">1</span> <span class="Keyword">else</span> index)
|
||||
<span class="line-numbers"> 257 </span>
|
||||
<span class="line-numbers"> 258 </span>
|
||||
<span class="line-numbers"> 259 </span> <span class="Comment"><span class="Comment">#</span> Get the last element of an array.</span>
|
||||
<span class="line-numbers"> 260 </span> <span class="FunctionName">_.last</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> array[array.length <span class="Keyword">-</span> <span class="Number">1</span>]
|
||||
<span class="line-numbers"> 261 </span>
|
||||
<span class="line-numbers"> 262 </span>
|
||||
<span class="line-numbers"> 263 </span> <span class="Comment"><span class="Comment">#</span> Trim out all falsy values from an array.</span>
|
||||
<span class="line-numbers"> 264 </span> <span class="FunctionName">_.compact</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> item <span class="Keyword">for</span> item <span class="Keyword">in</span> array <span class="Keyword">when</span> item
|
||||
<span class="line-numbers"> 265 </span>
|
||||
<span class="line-numbers"> 266 </span>
|
||||
<span class="line-numbers"> 267 </span> <span class="Comment"><span class="Comment">#</span> Return a completely flattened version of an array.</span>
|
||||
<span class="line-numbers"> 268 </span> <span class="FunctionName">_.flatten</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 269 </span> _.reduce array, [], <span class="FunctionArgument">(</span><span class="FunctionArgument">memo, value</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 270 </span> <span class="Keyword">return</span> memo.concat(_.flatten(value)) <span class="Keyword">if</span> _.isArray value
|
||||
<span class="line-numbers"> 271 </span> memo.push value
|
||||
<span class="line-numbers"> 272 </span> memo
|
||||
<span class="line-numbers"> 273 </span>
|
||||
<span class="line-numbers"> 274 </span>
|
||||
<span class="line-numbers"> 275 </span> <span class="Comment"><span class="Comment">#</span> Return a version of the array that does not contain the specified value(s).</span>
|
||||
<span class="line-numbers"> 276 </span> <span class="FunctionName">_.without</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 277 </span> <span class="FunctionName">values</span><span class="Keyword">:</span> _.rest arguments
|
||||
<span class="line-numbers"> 278 </span> val <span class="Keyword">for</span> val <span class="Keyword">in</span> _.toArray(array) <span class="Keyword">when</span> <span class="Keyword">not</span> _.include values, val
|
||||
<span class="line-numbers"> 279 </span>
|
||||
<span class="line-numbers"> 280 </span>
|
||||
<span class="line-numbers"> 281 </span> <span class="Comment"><span class="Comment">#</span> Produce a duplicate-free version of the array. If the array has already</span>
|
||||
<span class="line-numbers"> 282 </span> <span class="Comment"><span class="Comment">#</span> been sorted, you have the option of using a faster algorithm.</span>
|
||||
<span class="line-numbers"> 283 </span> <span class="FunctionName">_.uniq</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array, isSorted</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 284 </span> <span class="FunctionName">memo</span><span class="Keyword">:</span> []
|
||||
<span class="line-numbers"> 285 </span> <span class="Keyword">for</span> el, i <span class="Keyword">in</span> _.toArray array
|
||||
<span class="line-numbers"> 286 </span> memo.push el <span class="Keyword">if</span> i <span class="Keyword">is</span> <span class="Number">0</span> <span class="Keyword">||</span> (<span class="Keyword">if</span> isSorted <span class="Keyword">is</span> <span class="BuiltInConstant">true</span> <span class="Keyword">then</span> _.last(memo) <span class="Keyword">isnt</span> el <span class="Keyword">else</span> <span class="Keyword">not</span> _.include(memo, el))
|
||||
<span class="line-numbers"> 287 </span> memo
|
||||
<span class="line-numbers"> 288 </span>
|
||||
<span class="line-numbers"> 289 </span>
|
||||
<span class="line-numbers"> 290 </span> <span class="Comment"><span class="Comment">#</span> Produce an array that contains every item shared between all the</span>
|
||||
<span class="line-numbers"> 291 </span> <span class="Comment"><span class="Comment">#</span> passed-in arrays.</span>
|
||||
<span class="line-numbers"> 292 </span> <span class="FunctionName">_.intersect</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 293 </span> <span class="FunctionName">rest</span><span class="Keyword">:</span> _.rest arguments
|
||||
<span class="line-numbers"> 294 </span> _.select _.uniq(array), <span class="FunctionArgument">(</span><span class="FunctionArgument">item</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 295 </span> _.all rest, <span class="FunctionArgument">(</span><span class="FunctionArgument">other</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 296 </span> _.indexOf(other, item) <span class="Keyword">>=</span> <span class="Number">0</span>
|
||||
<span class="line-numbers"> 297 </span>
|
||||
<span class="line-numbers"> 298 </span>
|
||||
<span class="line-numbers"> 299 </span> <span class="Comment"><span class="Comment">#</span> Zip together multiple lists into a single array -- elements that share</span>
|
||||
<span class="line-numbers"> 300 </span> <span class="Comment"><span class="Comment">#</span> an index go together.</span>
|
||||
<span class="line-numbers"> 301 </span> <span class="FunctionName">_.zip</span><span class="Keyword">:</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 302 </span> <span class="FunctionName">length</span><span class="Keyword">:</span> _.max _.pluck arguments, <span class="String"><span class="String">'</span>length<span class="String">'</span></span>
|
||||
<span class="line-numbers"> 303 </span> <span class="FunctionName">results</span><span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Array</span> length
|
||||
<span class="line-numbers"> 304 </span> <span class="Keyword">for</span> i <span class="Keyword">in</span> [<span class="Number">0</span>...length]
|
||||
<span class="line-numbers"> 305 </span> results[i]<span class="Keyword">:</span> _.pluck arguments, String i
|
||||
<span class="line-numbers"> 306 </span> results
|
||||
<span class="line-numbers"> 307 </span>
|
||||
<span class="line-numbers"> 308 </span>
|
||||
<span class="line-numbers"> 309 </span> <span class="Comment"><span class="Comment">#</span> If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),</span>
|
||||
<span class="line-numbers"> 310 </span> <span class="Comment"><span class="Comment">#</span> we need this function. Return the position of the first occurence of an</span>
|
||||
<span class="line-numbers"> 311 </span> <span class="Comment"><span class="Comment">#</span> item in an array, or -1 if the item is not included in the array.</span>
|
||||
<span class="line-numbers"> 312 </span> <span class="FunctionName">_.indexOf</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array, item</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 313 </span> <span class="Keyword">return</span> array.indexOf item <span class="Keyword">if</span> nativeIndexOf <span class="Keyword">and</span> array.indexOf <span class="Keyword">is</span> nativeIndexOf
|
||||
<span class="line-numbers"> 314 </span> <span class="FunctionName">i</span><span class="Keyword">:</span> <span class="Number">0</span>; <span class="FunctionName">l</span><span class="Keyword">:</span> array.length
|
||||
<span class="line-numbers"> 315 </span> <span class="Keyword">while</span> l <span class="Keyword">-</span> i
|
||||
<span class="line-numbers"> 316 </span> <span class="Keyword">if</span> array[i] <span class="Keyword">is</span> item <span class="Keyword">then</span> <span class="Keyword">return</span> i <span class="Keyword">else</span> i<span class="Keyword">++</span>
|
||||
<span class="line-numbers"> 317 </span> <span class="Keyword">-</span><span class="Number">1</span>
|
||||
<span class="line-numbers"> 318 </span>
|
||||
<span class="line-numbers"> 319 </span>
|
||||
<span class="line-numbers"> 320 </span> <span class="Comment"><span class="Comment">#</span> Provide JavaScript 1.6's lastIndexOf, delegating to the native function,</span>
|
||||
<span class="line-numbers"> 321 </span> <span class="Comment"><span class="Comment">#</span> if possible.</span>
|
||||
<span class="line-numbers"> 322 </span> <span class="FunctionName">_.lastIndexOf</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array, item</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 323 </span> <span class="Keyword">return</span> array.lastIndexOf(item) <span class="Keyword">if</span> nativeLastIndexOf <span class="Keyword">and</span> array.lastIndexOf <span class="Keyword">is</span> nativeLastIndexOf
|
||||
<span class="line-numbers"> 324 </span> <span class="FunctionName">i</span><span class="Keyword">:</span> array.length
|
||||
<span class="line-numbers"> 325 </span> <span class="Keyword">while</span> i
|
||||
<span class="line-numbers"> 326 </span> <span class="Keyword">if</span> array[i] <span class="Keyword">is</span> item <span class="Keyword">then</span> <span class="Keyword">return</span> i <span class="Keyword">else</span> i<span class="Keyword">--</span>
|
||||
<span class="line-numbers"> 327 </span> <span class="Keyword">-</span><span class="Number">1</span>
|
||||
<span class="line-numbers"> 328 </span>
|
||||
<span class="line-numbers"> 329 </span>
|
||||
<span class="line-numbers"> 330 </span> <span class="Comment"><span class="Comment">#</span> Generate an integer Array containing an arithmetic progression. A port of</span>
|
||||
<span class="line-numbers"> 331 </span> <span class="Comment"><span class="Comment">#</span> the native Python range() function. See:</span>
|
||||
<span class="line-numbers"> 332 </span> <span class="Comment"><span class="Comment">#</span> http://docs.python.org/library/functions.html#range</span>
|
||||
<span class="line-numbers"> 333 </span> <span class="FunctionName">_.range</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">start, stop, step</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 334 </span> <span class="FunctionName">a</span><span class="Keyword">:</span> arguments
|
||||
<span class="line-numbers"> 335 </span> <span class="FunctionName">solo</span><span class="Keyword">:</span> a.length <span class="Keyword"><=</span> <span class="Number">1</span>
|
||||
<span class="line-numbers"> 336 </span> <span class="FunctionName">i</span><span class="Keyword">:</span> <span class="FunctionName">start</span><span class="Keyword">:</span> <span class="Keyword">if</span> solo <span class="Keyword">then</span> <span class="Number">0</span> <span class="Keyword">else</span> a[<span class="Number">0</span>]
|
||||
<span class="line-numbers"> 337 </span> <span class="FunctionName">stop</span><span class="Keyword">:</span> <span class="Keyword">if</span> solo <span class="Keyword">then</span> a[<span class="Number">0</span>] <span class="Keyword">else</span> a[<span class="Number">1</span>]
|
||||
<span class="line-numbers"> 338 </span> <span class="FunctionName">step</span><span class="Keyword">:</span> a[<span class="Number">2</span>] <span class="Keyword">or</span> <span class="Number">1</span>
|
||||
<span class="line-numbers"> 339 </span> <span class="FunctionName">len</span><span class="Keyword">:</span> Math.ceil((stop <span class="Keyword">-</span> start) <span class="Keyword">/</span> step)
|
||||
<span class="line-numbers"> 340 </span> <span class="Keyword">return</span> [] <span class="Keyword">if</span> len <span class="Keyword"><=</span> <span class="Number">0</span>
|
||||
<span class="line-numbers"> 341 </span> <span class="FunctionName">range</span><span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Array</span> len
|
||||
<span class="line-numbers"> 342 </span> <span class="FunctionName">idx</span><span class="Keyword">:</span> <span class="Number">0</span>
|
||||
<span class="line-numbers"> 343 </span> <span class="Keyword">while</span> <span class="BuiltInConstant">true</span>
|
||||
<span class="line-numbers"> 344 </span> <span class="Keyword">return</span> range <span class="Keyword">if</span> (<span class="Keyword">if</span> step <span class="Keyword">></span> <span class="Number">0</span> <span class="Keyword">then</span> i <span class="Keyword">-</span> stop <span class="Keyword">else</span> stop <span class="Keyword">-</span> i) <span class="Keyword">>=</span> <span class="Number">0</span>
|
||||
<span class="line-numbers"> 345 </span> range[idx]<span class="Keyword">:</span> i
|
||||
<span class="line-numbers"> 346 </span> idx<span class="Keyword">++</span>
|
||||
<span class="line-numbers"> 347 </span> i<span class="Keyword">+</span><span class="Keyword">=</span> step
|
||||
<span class="line-numbers"> 348 </span>
|
||||
<span class="line-numbers"> 349 </span>
|
||||
<span class="line-numbers"> 350 </span> <span class="Comment"><span class="Comment">#</span> ----------------------- Function Functions: -----------------------------</span>
|
||||
<span class="line-numbers"> 351 </span>
|
||||
<span class="line-numbers"> 352 </span> <span class="Comment"><span class="Comment">#</span> Create a function bound to a given object (assigning 'this', and arguments,</span>
|
||||
<span class="line-numbers"> 353 </span> <span class="Comment"><span class="Comment">#</span> optionally). Binding with arguments is also known as 'curry'.</span>
|
||||
<span class="line-numbers"> 354 </span> <span class="FunctionName">_.bind</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">func, obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 355 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> _.rest arguments, <span class="Number">2</span>
|
||||
<span class="line-numbers"> 356 </span> <span class="Storage">-></span> func.apply obj <span class="Keyword">or</span> root, args.concat arguments
|
||||
<span class="line-numbers"> 357 </span>
|
||||
<span class="line-numbers"> 358 </span>
|
||||
<span class="line-numbers"> 359 </span> <span class="Comment"><span class="Comment">#</span> Bind all of an object's methods to that object. Useful for ensuring that</span>
|
||||
<span class="line-numbers"> 360 </span> <span class="Comment"><span class="Comment">#</span> all callbacks defined on an object belong to it.</span>
|
||||
<span class="line-numbers"> 361 </span> <span class="FunctionName">_.bindAll</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 362 </span> <span class="FunctionName">funcs</span><span class="Keyword">:</span> <span class="Keyword">if</span> arguments.length <span class="Keyword">></span> <span class="Number">1</span> <span class="Keyword">then</span> _.rest(arguments) <span class="Keyword">else</span> _.functions(obj)
|
||||
<span class="line-numbers"> 363 </span> _.each funcs, <span class="FunctionArgument">(</span><span class="FunctionArgument">f</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> obj[f]<span class="Keyword">:</span> _.bind obj[f], obj
|
||||
<span class="line-numbers"> 364 </span> obj
|
||||
<span class="line-numbers"> 365 </span>
|
||||
<span class="line-numbers"> 366 </span>
|
||||
<span class="line-numbers"> 367 </span> <span class="Comment"><span class="Comment">#</span> Delays a function for the given number of milliseconds, and then calls</span>
|
||||
<span class="line-numbers"> 368 </span> <span class="Comment"><span class="Comment">#</span> it with the arguments supplied.</span>
|
||||
<span class="line-numbers"> 369 </span> <span class="FunctionName">_.delay</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">func, wait</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 370 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> _.rest arguments, <span class="Number">2</span>
|
||||
<span class="line-numbers"> 371 </span> setTimeout((<span class="Storage">-></span> func.apply(func, args)), wait)
|
||||
<span class="line-numbers"> 372 </span>
|
||||
<span class="line-numbers"> 373 </span>
|
||||
<span class="line-numbers"> 374 </span> <span class="Comment"><span class="Comment">#</span> Defers a function, scheduling it to run after the current call stack has</span>
|
||||
<span class="line-numbers"> 375 </span> <span class="Comment"><span class="Comment">#</span> cleared.</span>
|
||||
<span class="line-numbers"> 376 </span> <span class="FunctionName">_.defer</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">func</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 377 </span> _.delay.apply _, [func, <span class="Number">1</span>].concat _.rest arguments
|
||||
<span class="line-numbers"> 378 </span>
|
||||
<span class="line-numbers"> 379 </span>
|
||||
<span class="line-numbers"> 380 </span> <span class="Comment"><span class="Comment">#</span> Returns the first function passed as an argument to the second,</span>
|
||||
<span class="line-numbers"> 381 </span> <span class="Comment"><span class="Comment">#</span> allowing you to adjust arguments, run code before and after, and</span>
|
||||
<span class="line-numbers"> 382 </span> <span class="Comment"><span class="Comment">#</span> conditionally execute the original function.</span>
|
||||
<span class="line-numbers"> 383 </span> <span class="FunctionName">_.wrap</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">func, wrapper</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 384 </span> <span class="Storage">-></span> wrapper.apply wrapper, [func].concat arguments
|
||||
<span class="line-numbers"> 385 </span>
|
||||
<span class="line-numbers"> 386 </span>
|
||||
<span class="line-numbers"> 387 </span> <span class="Comment"><span class="Comment">#</span> Returns a function that is the composition of a list of functions, each</span>
|
||||
<span class="line-numbers"> 388 </span> <span class="Comment"><span class="Comment">#</span> consuming the return value of the function that follows.</span>
|
||||
<span class="line-numbers"> 389 </span> <span class="FunctionName">_.compose</span><span class="Keyword">:</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 390 </span> <span class="FunctionName">funcs</span><span class="Keyword">:</span> arguments
|
||||
<span class="line-numbers"> 391 </span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 392 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> arguments
|
||||
<span class="line-numbers"> 393 </span> <span class="Keyword">for</span> i <span class="Keyword">in</span> [(funcs.length <span class="Keyword">-</span> <span class="Number">1</span>)..<span class="Number">0</span>]
|
||||
<span class="line-numbers"> 394 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> [funcs[i].apply(<span class="Variable">this</span>, args)]
|
||||
<span class="line-numbers"> 395 </span> args[<span class="Number">0</span>]
|
||||
<span class="line-numbers"> 396 </span>
|
||||
<span class="line-numbers"> 397 </span>
|
||||
<span class="line-numbers"> 398 </span> <span class="Comment"><span class="Comment">#</span> ------------------------- Object Functions: ----------------------------</span>
|
||||
<span class="line-numbers"> 399 </span>
|
||||
<span class="line-numbers"> 400 </span> <span class="Comment"><span class="Comment">#</span> Retrieve the names of an object's properties.</span>
|
||||
<span class="line-numbers"> 401 </span> <span class="FunctionName">_.keys</span><span class="Keyword">:</span> nativeKeys <span class="Keyword">or</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 402 </span> <span class="Keyword">return</span> _.range <span class="Number">0</span>, obj.length <span class="Keyword">if</span> _.isArray(obj)
|
||||
<span class="line-numbers"> 403 </span> key <span class="Keyword">for</span> key, val <span class="Keyword">of</span> obj
|
||||
<span class="line-numbers"> 404 </span>
|
||||
<span class="line-numbers"> 405 </span>
|
||||
<span class="line-numbers"> 406 </span> <span class="Comment"><span class="Comment">#</span> Retrieve the values of an object's properties.</span>
|
||||
<span class="line-numbers"> 407 </span> <span class="FunctionName">_.values</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 408 </span> _.map obj, _.identity
|
||||
<span class="line-numbers"> 409 </span>
|
||||
<span class="line-numbers"> 410 </span>
|
||||
<span class="line-numbers"> 411 </span> <span class="Comment"><span class="Comment">#</span> Return a sorted list of the function names available in Underscore.</span>
|
||||
<span class="line-numbers"> 412 </span> <span class="FunctionName">_.functions</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 413 </span> _.filter(_.keys(obj), <span class="FunctionArgument">(</span><span class="FunctionArgument">key</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> _.isFunction(obj[key])).sort()
|
||||
<span class="line-numbers"> 414 </span>
|
||||
<span class="line-numbers"> 415 </span>
|
||||
<span class="line-numbers"> 416 </span> <span class="Comment"><span class="Comment">#</span> Extend a given object with all of the properties in a source object.</span>
|
||||
<span class="line-numbers"> 417 </span> <span class="FunctionName">_.extend</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">destination, source</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 418 </span> (destination[key]<span class="Keyword">:</span> val) <span class="Keyword">for</span> key, val <span class="Keyword">of</span> source
|
||||
<span class="line-numbers"> 419 </span> destination
|
||||
<span class="line-numbers"> 420 </span>
|
||||
<span class="line-numbers"> 421 </span>
|
||||
<span class="line-numbers"> 422 </span> <span class="Comment"><span class="Comment">#</span> Create a (shallow-cloned) duplicate of an object.</span>
|
||||
<span class="line-numbers"> 423 </span> <span class="FunctionName">_.clone</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 424 </span> <span class="Keyword">return</span> obj.slice <span class="Number">0</span> <span class="Keyword">if</span> _.isArray obj
|
||||
<span class="line-numbers"> 425 </span> _.extend {}, obj
|
||||
<span class="line-numbers"> 426 </span>
|
||||
<span class="line-numbers"> 427 </span>
|
||||
<span class="line-numbers"> 428 </span> <span class="Comment"><span class="Comment">#</span> Invokes interceptor with the obj, and then returns obj.</span>
|
||||
<span class="line-numbers"> 429 </span> <span class="Comment"><span class="Comment">#</span> The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain.</span>
|
||||
<span class="line-numbers"> 430 </span> <span class="FunctionName">_.tap</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, interceptor</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 431 </span> interceptor obj
|
||||
<span class="line-numbers"> 432 </span> obj
|
||||
<span class="line-numbers"> 433 </span>
|
||||
<span class="line-numbers"> 434 </span>
|
||||
<span class="line-numbers"> 435 </span> <span class="Comment"><span class="Comment">#</span> Perform a deep comparison to check if two objects are equal.</span>
|
||||
<span class="line-numbers"> 436 </span> <span class="FunctionName">_.isEqual</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">a, b</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 437 </span> <span class="Comment"><span class="Comment">#</span> Check object identity.</span>
|
||||
<span class="line-numbers"> 438 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">true</span> <span class="Keyword">if</span> a <span class="Keyword">is</span> b
|
||||
<span class="line-numbers"> 439 </span> <span class="Comment"><span class="Comment">#</span> Different types?</span>
|
||||
<span class="line-numbers"> 440 </span> <span class="FunctionName">atype</span><span class="Keyword">:</span> <span class="Keyword">typeof</span>(a); <span class="FunctionName">btype</span><span class="Keyword">:</span> <span class="Keyword">typeof</span>(b)
|
||||
<span class="line-numbers"> 441 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">false</span> <span class="Keyword">if</span> atype <span class="Keyword">isnt</span> btype
|
||||
<span class="line-numbers"> 442 </span> <span class="Comment"><span class="Comment">#</span> Basic equality test (watch out for coercions).</span>
|
||||
<span class="line-numbers"> 443 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">true</span> <span class="Keyword">if</span> <span class="String"><span class="String">`</span>a == b<span class="String">`</span></span>
|
||||
<span class="line-numbers"> 444 </span> <span class="Comment"><span class="Comment">#</span> One is falsy and the other truthy.</span>
|
||||
<span class="line-numbers"> 445 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">false</span> <span class="Keyword">if</span> (<span class="Keyword">!</span>a <span class="Keyword">and</span> b) <span class="Keyword">or</span> (a <span class="Keyword">and</span> <span class="Keyword">!</span>b)
|
||||
<span class="line-numbers"> 446 </span> <span class="Comment"><span class="Comment">#</span> One of them implements an isEqual()?</span>
|
||||
<span class="line-numbers"> 447 </span> <span class="Keyword">return</span> a.isEqual(b) <span class="Keyword">if</span> a.isEqual
|
||||
<span class="line-numbers"> 448 </span> <span class="Comment"><span class="Comment">#</span> Check dates' integer values.</span>
|
||||
<span class="line-numbers"> 449 </span> <span class="Keyword">return</span> a.getTime() <span class="Keyword">is</span> b.getTime() <span class="Keyword">if</span> _.isDate(a) <span class="Keyword">and</span> _.isDate(b)
|
||||
<span class="line-numbers"> 450 </span> <span class="Comment"><span class="Comment">#</span> Both are NaN?</span>
|
||||
<span class="line-numbers"> 451 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">true</span> <span class="Keyword">if</span> _.isNaN(a) <span class="Keyword">and</span> _.isNaN(b)
|
||||
<span class="line-numbers"> 452 </span> <span class="Comment"><span class="Comment">#</span> Compare regular expressions.</span>
|
||||
<span class="line-numbers"> 453 </span> <span class="Keyword">if</span> _.isRegExp(a) <span class="Keyword">and</span> _.isRegExp(b)
|
||||
<span class="line-numbers"> 454 </span> <span class="Keyword">return</span> a.source <span class="Keyword">is</span> b.source <span class="Keyword">and</span>
|
||||
<span class="line-numbers"> 455 </span> a.global <span class="Keyword">is</span> b.global <span class="Keyword">and</span>
|
||||
<span class="line-numbers"> 456 </span> a.ignoreCase <span class="Keyword">is</span> b.ignoreCase <span class="Keyword">and</span>
|
||||
<span class="line-numbers"> 457 </span> a.multiline <span class="Keyword">is</span> b.multiline
|
||||
<span class="line-numbers"> 458 </span> <span class="Comment"><span class="Comment">#</span> If a is not an object by this point, we can't handle it.</span>
|
||||
<span class="line-numbers"> 459 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">false</span> <span class="Keyword">if</span> atype <span class="Keyword">isnt</span> <span class="String"><span class="String">'</span>object<span class="String">'</span></span>
|
||||
<span class="line-numbers"> 460 </span> <span class="Comment"><span class="Comment">#</span> Check for different array lengths before comparing contents.</span>
|
||||
<span class="line-numbers"> 461 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">false</span> <span class="Keyword">if</span> a.length <span class="Keyword">and</span> (a.length <span class="Keyword">isnt</span> b.length)
|
||||
<span class="line-numbers"> 462 </span> <span class="Comment"><span class="Comment">#</span> Nothing else worked, deep compare the contents.</span>
|
||||
<span class="line-numbers"> 463 </span> <span class="FunctionName">aKeys</span><span class="Keyword">:</span> _.keys(a); <span class="FunctionName">bKeys</span><span class="Keyword">:</span> _.keys(b)
|
||||
<span class="line-numbers"> 464 </span> <span class="Comment"><span class="Comment">#</span> Different object sizes?</span>
|
||||
<span class="line-numbers"> 465 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">false</span> <span class="Keyword">if</span> aKeys.length <span class="Keyword">isnt</span> bKeys.length
|
||||
<span class="line-numbers"> 466 </span> <span class="Comment"><span class="Comment">#</span> Recursive comparison of contents.</span>
|
||||
<span class="line-numbers"> 467 </span> (<span class="Keyword">return</span> <span class="BuiltInConstant">false</span>) <span class="Keyword">for</span> key, val <span class="Keyword">of</span> a <span class="Keyword">when</span> <span class="Keyword">!</span>_.isEqual(val, b[key])
|
||||
<span class="line-numbers"> 468 </span> <span class="BuiltInConstant">true</span>
|
||||
<span class="line-numbers"> 469 </span>
|
||||
<span class="line-numbers"> 470 </span>
|
||||
<span class="line-numbers"> 471 </span> <span class="Comment"><span class="Comment">#</span> Is a given array or object empty?</span>
|
||||
<span class="line-numbers"> 472 </span> <span class="FunctionName">_.isEmpty</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 473 </span> <span class="Keyword">return</span> obj.length <span class="Keyword">is</span> <span class="Number">0</span> <span class="Keyword">if</span> _.isArray obj
|
||||
<span class="line-numbers"> 474 </span> (<span class="Keyword">return</span> <span class="BuiltInConstant">false</span>) <span class="Keyword">for</span> key <span class="Keyword">of</span> obj <span class="Keyword">when</span> hasOwnProperty.call(obj, key)
|
||||
<span class="line-numbers"> 475 </span> <span class="BuiltInConstant">true</span>
|
||||
<span class="line-numbers"> 476 </span>
|
||||
<span class="line-numbers"> 477 </span>
|
||||
<span class="line-numbers"> 478 </span> <span class="Comment"><span class="Comment">#</span> Is a given value a DOM element?</span>
|
||||
<span class="line-numbers"> 479 </span> <span class="FunctionName">_.isElement</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> obj <span class="Keyword">and</span> obj.nodeType <span class="Keyword">is</span> <span class="Number">1</span>
|
||||
<span class="line-numbers"> 480 </span>
|
||||
<span class="line-numbers"> 481 </span>
|
||||
<span class="line-numbers"> 482 </span> <span class="Comment"><span class="Comment">#</span> Is a given value an array?</span>
|
||||
<span class="line-numbers"> 483 </span> <span class="FunctionName">_.isArray</span><span class="Keyword">:</span> nativeIsArray <span class="Keyword">or</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">and</span> obj.concat <span class="Keyword">and</span> obj.unshift)
|
||||
<span class="line-numbers"> 484 </span>
|
||||
<span class="line-numbers"> 485 </span>
|
||||
<span class="line-numbers"> 486 </span> <span class="Comment"><span class="Comment">#</span> Is a given variable an arguments object?</span>
|
||||
<span class="line-numbers"> 487 </span> <span class="FunctionName">_.isArguments</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> obj <span class="Keyword">and</span> _.isNumber(obj.length) <span class="Keyword">and</span> <span class="Keyword">not</span> obj.concat <span class="Keyword">and</span>
|
||||
<span class="line-numbers"> 488 </span> <span class="Keyword">not</span> obj.substr <span class="Keyword">and</span> <span class="Keyword">not</span> obj.apply <span class="Keyword">and</span> <span class="Keyword">not</span> propertyIsEnumerable.call(obj, <span class="String"><span class="String">'</span>length<span class="String">'</span></span>)
|
||||
<span class="line-numbers"> 489 </span>
|
||||
<span class="line-numbers"> 490 </span>
|
||||
<span class="line-numbers"> 491 </span> <span class="Comment"><span class="Comment">#</span> Is the given value a function?</span>
|
||||
<span class="line-numbers"> 492 </span> <span class="FunctionName">_.isFunction</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">and</span> obj.constructor <span class="Keyword">and</span> obj.call <span class="Keyword">and</span> obj.apply)
|
||||
<span class="line-numbers"> 493 </span>
|
||||
<span class="line-numbers"> 494 </span>
|
||||
<span class="line-numbers"> 495 </span> <span class="Comment"><span class="Comment">#</span> Is the given value a string?</span>
|
||||
<span class="line-numbers"> 496 </span> <span class="FunctionName">_.isString</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">is</span> <span class="String"><span class="String">'</span><span class="String">'</span></span> <span class="Keyword">or</span> (obj <span class="Keyword">and</span> obj.charCodeAt <span class="Keyword">and</span> obj.substr))
|
||||
<span class="line-numbers"> 497 </span>
|
||||
<span class="line-numbers"> 498 </span>
|
||||
<span class="line-numbers"> 499 </span> <span class="Comment"><span class="Comment">#</span> Is a given value a number?</span>
|
||||
<span class="line-numbers"> 500 </span> <span class="FunctionName">_.isNumber</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> (obj <span class="Keyword">is</span> <span class="Keyword">+</span>obj) <span class="Keyword">or</span> toString.call(obj) <span class="Keyword">is</span> <span class="String"><span class="String">'</span>[object Number]<span class="String">'</span></span>
|
||||
<span class="line-numbers"> 501 </span>
|
||||
<span class="line-numbers"> 502 </span>
|
||||
<span class="line-numbers"> 503 </span> <span class="Comment"><span class="Comment">#</span> Is a given value a boolean?</span>
|
||||
<span class="line-numbers"> 504 </span> <span class="FunctionName">_.isBoolean</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> obj <span class="Keyword">is</span> <span class="BuiltInConstant">true</span> <span class="Keyword">or</span> obj <span class="Keyword">is</span> <span class="BuiltInConstant">false</span>
|
||||
<span class="line-numbers"> 505 </span>
|
||||
<span class="line-numbers"> 506 </span>
|
||||
<span class="line-numbers"> 507 </span> <span class="Comment"><span class="Comment">#</span> Is a given value a Date?</span>
|
||||
<span class="line-numbers"> 508 </span> <span class="FunctionName">_.isDate</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">and</span> obj.getTimezoneOffset <span class="Keyword">and</span> obj.setUTCFullYear)
|
||||
<span class="line-numbers"> 509 </span>
|
||||
<span class="line-numbers"> 510 </span>
|
||||
<span class="line-numbers"> 511 </span> <span class="Comment"><span class="Comment">#</span> Is the given value a regular expression?</span>
|
||||
<span class="line-numbers"> 512 </span> <span class="FunctionName">_.isRegExp</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">and</span> obj.exec <span class="Keyword">and</span> (obj.ignoreCase <span class="Keyword">or</span> obj.ignoreCase <span class="Keyword">is</span> <span class="BuiltInConstant">false</span>))
|
||||
<span class="line-numbers"> 513 </span>
|
||||
<span class="line-numbers"> 514 </span>
|
||||
<span class="line-numbers"> 515 </span> <span class="Comment"><span class="Comment">#</span> Is the given value NaN -- this one is interesting. NaN != NaN, and</span>
|
||||
<span class="line-numbers"> 516 </span> <span class="Comment"><span class="Comment">#</span> isNaN(undefined) == true, so we make sure it's a number first.</span>
|
||||
<span class="line-numbers"> 517 </span> <span class="FunctionName">_.isNaN</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> _.isNumber(obj) <span class="Keyword">and</span> window.isNaN(obj)
|
||||
<span class="line-numbers"> 518 </span>
|
||||
<span class="line-numbers"> 519 </span>
|
||||
<span class="line-numbers"> 520 </span> <span class="Comment"><span class="Comment">#</span> Is a given value equal to null?</span>
|
||||
<span class="line-numbers"> 521 </span> <span class="FunctionName">_.isNull</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> obj <span class="Keyword">is</span> <span class="BuiltInConstant">null</span>
|
||||
<span class="line-numbers"> 522 </span>
|
||||
<span class="line-numbers"> 523 </span>
|
||||
<span class="line-numbers"> 524 </span> <span class="Comment"><span class="Comment">#</span> Is a given variable undefined?</span>
|
||||
<span class="line-numbers"> 525 </span> <span class="FunctionName">_.isUndefined</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> <span class="Keyword">typeof</span> obj <span class="Keyword">is</span> <span class="String"><span class="String">'</span>undefined<span class="String">'</span></span>
|
||||
<span class="line-numbers"> 526 </span>
|
||||
<span class="line-numbers"> 527 </span>
|
||||
<span class="line-numbers"> 528 </span> <span class="Comment"><span class="Comment">#</span> -------------------------- Utility Functions: --------------------------</span>
|
||||
<span class="line-numbers"> 529 </span>
|
||||
<span class="line-numbers"> 530 </span> <span class="Comment"><span class="Comment">#</span> Run Underscore.js in noConflict mode, returning the '_' variable to its</span>
|
||||
<span class="line-numbers"> 531 </span> <span class="Comment"><span class="Comment">#</span> previous owner. Returns a reference to the Underscore object.</span>
|
||||
<span class="line-numbers"> 532 </span> <span class="FunctionName">_.noConflict</span><span class="Keyword">:</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 533 </span> <span class="FunctionName">root._</span><span class="Keyword">:</span> previousUnderscore
|
||||
<span class="line-numbers"> 534 </span> <span class="Variable">this</span>
|
||||
<span class="line-numbers"> 535 </span>
|
||||
<span class="line-numbers"> 536 </span>
|
||||
<span class="line-numbers"> 537 </span> <span class="Comment"><span class="Comment">#</span> Keep the identity function around for default iterators.</span>
|
||||
<span class="line-numbers"> 538 </span> <span class="FunctionName">_.identity</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">value</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> value
|
||||
<span class="line-numbers"> 539 </span>
|
||||
<span class="line-numbers"> 540 </span>
|
||||
<span class="line-numbers"> 541 </span> <span class="Comment"><span class="Comment">#</span> Run a function n times.</span>
|
||||
<span class="line-numbers"> 542 </span> <span class="FunctionName">_.times</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">n, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 543 </span> iterator.call(context, i) <span class="Keyword">for</span> i <span class="Keyword">in</span> [<span class="Number">0</span>...n]
|
||||
<span class="line-numbers"> 544 </span>
|
||||
<span class="line-numbers"> 545 </span>
|
||||
<span class="line-numbers"> 546 </span> <span class="Comment"><span class="Comment">#</span> Break out of the middle of an iteration.</span>
|
||||
<span class="line-numbers"> 547 </span> <span class="FunctionName">_.breakLoop</span><span class="Keyword">:</span> <span class="Storage">-></span> <span class="Keyword">throw</span> breaker
|
||||
<span class="line-numbers"> 548 </span>
|
||||
<span class="line-numbers"> 549 </span>
|
||||
<span class="line-numbers"> 550 </span> <span class="Comment"><span class="Comment">#</span> Add your own custom functions to the Underscore object, ensuring that</span>
|
||||
<span class="line-numbers"> 551 </span> <span class="Comment"><span class="Comment">#</span> they're correctly added to the OOP wrapper as well.</span>
|
||||
<span class="line-numbers"> 552 </span> <span class="FunctionName">_.mixin</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 553 </span> <span class="Keyword">for</span> name <span class="Keyword">in</span> _.functions(obj)
|
||||
<span class="line-numbers"> 554 </span> addToWrapper name, _[name]<span class="Keyword">:</span> obj[name]
|
||||
<span class="line-numbers"> 555 </span>
|
||||
<span class="line-numbers"> 556 </span>
|
||||
<span class="line-numbers"> 557 </span> <span class="Comment"><span class="Comment">#</span> Generate a unique integer id (unique within the entire client session).</span>
|
||||
<span class="line-numbers"> 558 </span> <span class="Comment"><span class="Comment">#</span> Useful for temporary DOM ids.</span>
|
||||
<span class="line-numbers"> 559 </span> <span class="FunctionName">idCounter</span><span class="Keyword">:</span> <span class="Number">0</span>
|
||||
<span class="line-numbers"> 560 </span> <span class="FunctionName">_.uniqueId</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">prefix</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 561 </span> (prefix <span class="Keyword">or</span> <span class="String"><span class="String">'</span><span class="String">'</span></span>) <span class="Keyword">+</span> idCounter<span class="Keyword">++</span>
|
||||
<span class="line-numbers"> 562 </span>
|
||||
<span class="line-numbers"> 563 </span>
|
||||
<span class="line-numbers"> 564 </span> <span class="Comment"><span class="Comment">#</span> By default, Underscore uses ERB-style template delimiters, change the</span>
|
||||
<span class="line-numbers"> 565 </span> <span class="Comment"><span class="Comment">#</span> following template settings to use alternative delimiters.</span>
|
||||
<span class="line-numbers"> 566 </span> <span class="FunctionName">_.templateSettings</span><span class="Keyword">:</span> {
|
||||
<span class="line-numbers"> 567 </span> <span class="FunctionName">start</span><span class="Keyword">:</span> <span class="String"><span class="String">'</span><%<span class="String">'</span></span>
|
||||
<span class="line-numbers"> 568 </span> <span class="FunctionName">end</span><span class="Keyword">:</span> <span class="String"><span class="String">'</span>%><span class="String">'</span></span>
|
||||
<span class="line-numbers"> 569 </span> <span class="FunctionName">interpolate</span><span class="Keyword">:</span><span class="String"> <span class="String">/</span><%=(.+?)%><span class="String">/</span>g</span>
|
||||
<span class="line-numbers"> 570 </span> }
|
||||
<span class="line-numbers"> 571 </span>
|
||||
<span class="line-numbers"> 572 </span>
|
||||
<span class="line-numbers"> 573 </span> <span class="Comment"><span class="Comment">#</span> JavaScript templating a-la ERB, pilfered from John Resig's</span>
|
||||
<span class="line-numbers"> 574 </span> <span class="Comment"><span class="Comment">#</span> "Secrets of the JavaScript Ninja", page 83.</span>
|
||||
<span class="line-numbers"> 575 </span> <span class="Comment"><span class="Comment">#</span> Single-quote fix from Rick Strahl's version.</span>
|
||||
<span class="line-numbers"> 576 </span> <span class="FunctionName">_.template</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">str, data</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 577 </span> <span class="FunctionName">c</span><span class="Keyword">:</span> _.templateSettings
|
||||
<span class="line-numbers"> 578 </span> <span class="FunctionName">endMatch</span><span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">RegExp</span>(<span class="String"><span class="String">"</span>'(?=[^<span class="String">"</span></span><span class="Keyword">+</span>c.end.substr(<span class="Number">0</span>, <span class="Number">1</span>)<span class="Keyword">+</span><span class="String"><span class="String">"</span>]*<span class="String">"</span></span><span class="Keyword">+</span>escapeRegExp(c.end)<span class="Keyword">+</span><span class="String"><span class="String">"</span>)<span class="String">"</span></span>,<span class="String"><span class="String">"</span>g<span class="String">"</span></span>)
|
||||
<span class="line-numbers"> 579 </span> <span class="FunctionName">fn</span><span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Function</span> <span class="String"><span class="String">'</span>obj<span class="String">'</span></span>,
|
||||
<span class="line-numbers"> 580 </span> <span class="String"><span class="String">'</span>var p=[],print=function(){p.push.apply(p,arguments);};<span class="String">'</span></span> <span class="Keyword">+</span>
|
||||
<span class="line-numbers"> 581 </span> <span class="String"><span class="String">'</span>with(obj){p.push(<span class="UserDefinedConstant">\'</span><span class="String">'</span></span> <span class="Keyword">+</span>
|
||||
<span class="line-numbers"> 582 </span> str.replace(<span class="String"><span class="String">/</span>[<span class="UserDefinedConstant">\r</span><span class="UserDefinedConstant">\t</span><span class="UserDefinedConstant">\n</span>]<span class="String">/</span>g</span>, <span class="String"><span class="String">"</span> <span class="String">"</span></span>)
|
||||
<span class="line-numbers"> 583 </span> .replace(endMatch,<span class="String"><span class="String">"</span><span class="UserDefinedConstant">\t</span><span class="String">"</span></span>)
|
||||
<span class="line-numbers"> 584 </span> .split(<span class="String"><span class="String">"</span>'<span class="String">"</span></span>).join(<span class="String"><span class="String">"</span><span class="UserDefinedConstant">\\</span>'<span class="String">"</span></span>)
|
||||
<span class="line-numbers"> 585 </span> .split(<span class="String"><span class="String">"</span><span class="UserDefinedConstant">\t</span><span class="String">"</span></span>).join(<span class="String"><span class="String">"</span>'<span class="String">"</span></span>)
|
||||
<span class="line-numbers"> 586 </span> .replace(c.interpolate, <span class="String"><span class="String">"</span>',$1,'<span class="String">"</span></span>)
|
||||
<span class="line-numbers"> 587 </span> .split(c.start).join(<span class="String"><span class="String">"</span>');<span class="String">"</span></span>)
|
||||
<span class="line-numbers"> 588 </span> .split(c.end).join(<span class="String"><span class="String">"</span>p.push('<span class="String">"</span></span>) <span class="Keyword">+</span>
|
||||
<span class="line-numbers"> 589 </span> <span class="String"><span class="String">"</span>');}return p.join('');<span class="String">"</span></span>
|
||||
<span class="line-numbers"> 590 </span> <span class="Keyword">if</span> data <span class="Keyword">then</span> fn(data) <span class="Keyword">else</span> fn
|
||||
<span class="line-numbers"> 591 </span>
|
||||
<span class="line-numbers"> 592 </span>
|
||||
<span class="line-numbers"> 593 </span> <span class="Comment"><span class="Comment">#</span> ------------------------------- Aliases ----------------------------------</span>
|
||||
<span class="line-numbers"> 594 </span>
|
||||
<span class="line-numbers"> 595 </span> <span class="FunctionName">_.forEach</span><span class="Keyword">:</span> _.each
|
||||
<span class="line-numbers"> 596 </span> <span class="FunctionName">_.foldl</span><span class="Keyword">:</span> <span class="FunctionName">_.inject</span><span class="Keyword">:</span> _.reduce
|
||||
<span class="line-numbers"> 597 </span> <span class="FunctionName">_.foldr</span><span class="Keyword">:</span> _.reduceRight
|
||||
<span class="line-numbers"> 598 </span> <span class="FunctionName">_.select</span><span class="Keyword">:</span> _.filter
|
||||
<span class="line-numbers"> 599 </span> <span class="FunctionName">_.all</span><span class="Keyword">:</span> _.every
|
||||
<span class="line-numbers"> 600 </span> <span class="FunctionName">_.any</span><span class="Keyword">:</span> _.some
|
||||
<span class="line-numbers"> 601 </span> <span class="FunctionName">_.head</span><span class="Keyword">:</span> _.first
|
||||
<span class="line-numbers"> 602 </span> <span class="FunctionName">_.tail</span><span class="Keyword">:</span> _.rest
|
||||
<span class="line-numbers"> 603 </span> <span class="FunctionName">_.methods</span><span class="Keyword">:</span> _.functions
|
||||
<span class="line-numbers"> 604 </span>
|
||||
<span class="line-numbers"> 605 </span>
|
||||
<span class="line-numbers"> 606 </span> <span class="Comment"><span class="Comment">#</span> ------------------------ Setup the OOP Wrapper: --------------------------</span>
|
||||
<span class="line-numbers"> 607 </span>
|
||||
<span class="line-numbers"> 608 </span> <span class="Comment"><span class="Comment">#</span> If Underscore is called as a function, it returns a wrapped object that</span>
|
||||
<span class="line-numbers"> 609 </span> <span class="Comment"><span class="Comment">#</span> can be used OO-style. This wrapper holds altered versions of all the</span>
|
||||
<span class="line-numbers"> 610 </span> <span class="Comment"><span class="Comment">#</span> underscore functions. Wrapped objects may be chained.</span>
|
||||
<span class="line-numbers"> 611 </span> <span class="FunctionName">wrapper</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 612 </span> <span class="FunctionName">this._wrapped</span><span class="Keyword">:</span> obj
|
||||
<span class="line-numbers"> 613 </span> <span class="Variable">this</span>
|
||||
<span class="line-numbers"> 614 </span>
|
||||
<span class="line-numbers"> 615 </span>
|
||||
<span class="line-numbers"> 616 </span> <span class="Comment"><span class="Comment">#</span> Helper function to continue chaining intermediate results.</span>
|
||||
<span class="line-numbers"> 617 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, chain</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 618 </span> <span class="Keyword">if</span> chain <span class="Keyword">then</span> _(obj).chain() <span class="Keyword">else</span> obj
|
||||
<span class="line-numbers"> 619 </span>
|
||||
<span class="line-numbers"> 620 </span>
|
||||
<span class="line-numbers"> 621 </span> <span class="Comment"><span class="Comment">#</span> A method to easily add functions to the OOP wrapper.</span>
|
||||
<span class="line-numbers"> 622 </span> <span class="FunctionName">addToWrapper</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">name, func</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 623 </span> wrapper.prototype[name]<span class="Keyword">:</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 624 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> _.toArray arguments
|
||||
<span class="line-numbers"> 625 </span> unshift.call args, <span class="Variable">this</span>._wrapped
|
||||
<span class="line-numbers"> 626 </span> result func.apply(_, args), <span class="Variable">this</span>._chain
|
||||
<span class="line-numbers"> 627 </span>
|
||||
<span class="line-numbers"> 628 </span>
|
||||
<span class="line-numbers"> 629 </span> <span class="Comment"><span class="Comment">#</span> Add all of the Underscore functions to the wrapper object.</span>
|
||||
<span class="line-numbers"> 630 </span> _.mixin _
|
||||
<span class="line-numbers"> 631 </span>
|
||||
<span class="line-numbers"> 632 </span>
|
||||
<span class="line-numbers"> 633 </span> <span class="Comment"><span class="Comment">#</span> Add all mutator Array functions to the wrapper.</span>
|
||||
<span class="line-numbers"> 634 </span> _.each [<span class="String"><span class="String">'</span>pop<span class="String">'</span></span>, <span class="String"><span class="String">'</span>push<span class="String">'</span></span>, <span class="String"><span class="String">'</span>reverse<span class="String">'</span></span>, <span class="String"><span class="String">'</span>shift<span class="String">'</span></span>, <span class="String"><span class="String">'</span>sort<span class="String">'</span></span>, <span class="String"><span class="String">'</span>splice<span class="String">'</span></span>, <span class="String"><span class="String">'</span>unshift<span class="String">'</span></span>], <span class="FunctionArgument">(</span><span class="FunctionArgument">name</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 635 </span> <span class="FunctionName">method</span><span class="Keyword">:</span> Array.prototype[name]
|
||||
<span class="line-numbers"> 636 </span> wrapper.prototype[name]<span class="Keyword">:</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 637 </span> method.apply(<span class="Variable">this</span>._wrapped, arguments)
|
||||
<span class="line-numbers"> 638 </span> result(<span class="Variable">this</span>._wrapped, <span class="Variable">this</span>._chain)
|
||||
<span class="line-numbers"> 639 </span>
|
||||
<span class="line-numbers"> 640 </span>
|
||||
<span class="line-numbers"> 641 </span> <span class="Comment"><span class="Comment">#</span> Add all accessor Array functions to the wrapper.</span>
|
||||
<span class="line-numbers"> 642 </span> _.each [<span class="String"><span class="String">'</span>concat<span class="String">'</span></span>, <span class="String"><span class="String">'</span>join<span class="String">'</span></span>, <span class="String"><span class="String">'</span>slice<span class="String">'</span></span>], <span class="FunctionArgument">(</span><span class="FunctionArgument">name</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 643 </span> <span class="FunctionName">method</span><span class="Keyword">:</span> Array.prototype[name]
|
||||
<span class="line-numbers"> 644 </span> wrapper.prototype[name]<span class="Keyword">:</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 645 </span> result(method.apply(<span class="Variable">this</span>._wrapped, arguments), <span class="Variable">this</span>._chain)
|
||||
<span class="line-numbers"> 646 </span>
|
||||
<span class="line-numbers"> 647 </span>
|
||||
<span class="line-numbers"> 648 </span> <span class="Comment"><span class="Comment">#</span> Start chaining a wrapped Underscore object.</span>
|
||||
<span class="line-numbers"> 649 </span> <span class="FunctionName">wrapper::chain</span><span class="Keyword">:</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 650 </span> <span class="FunctionName">this._chain</span><span class="Keyword">:</span> <span class="BuiltInConstant">true</span>
|
||||
<span class="line-numbers"> 651 </span> <span class="Variable">this</span>
|
||||
<span class="line-numbers"> 652 </span>
|
||||
<span class="line-numbers"> 653 </span>
|
||||
<span class="line-numbers"> 654 </span> <span class="Comment"><span class="Comment">#</span> Extracts the result from a wrapped and chained object.</span>
|
||||
<span class="line-numbers"> 655 </span> <span class="FunctionName">wrapper::value</span><span class="Keyword">:</span> <span class="Storage">-></span> <span class="Variable">this</span>._wrapped
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -21,7 +21,7 @@ match_here: (regexp, text) ->
|
||||
|
||||
# Search for a kleene star match at the beginning of the text.
|
||||
match_star: (c, regexp, text) ->
|
||||
while true
|
||||
loop
|
||||
return true if match_here(regexp, text)
|
||||
return false unless text and (text[0] is c or c is '.')
|
||||
text: text.slice(1)
|
||||
|
||||
@@ -94,7 +94,7 @@ while demand > supply
|
||||
|
||||
while supply > demand then buy()
|
||||
|
||||
while true
|
||||
loop
|
||||
break if broken
|
||||
continue if continuing
|
||||
|
||||
|
||||
@@ -14,8 +14,7 @@ print(add(2, 4))
|
||||
|
||||
# loop: 'quaff' print.
|
||||
|
||||
while true
|
||||
print('quaff')
|
||||
loop print 'quaff'
|
||||
|
||||
|
||||
# ('cheese', 'bread', 'mayo') at (1) print
|
||||
|
||||
@@ -1,28 +1,33 @@
|
||||
|
||||
# Underscore.coffee
|
||||
# (c) 2010 Jeremy Ashkenas, DocumentCloud Inc.
|
||||
# Underscore is freely distributable under the terms of the MIT license.
|
||||
# Portions of Underscore are inspired by or borrowed from Prototype.js,
|
||||
# Oliver Steele's Functional, and John Resig's Micro-Templating.
|
||||
# **Underscore.coffee
|
||||
# (c) 2010 Jeremy Ashkenas, DocumentCloud Inc.**
|
||||
# Underscore is freely distributable under the terms of the
|
||||
# [MIT license](http://en.wikipedia.org/wiki/MIT_License).
|
||||
# Portions of Underscore are inspired by or borrowed from
|
||||
# [Prototype.js](http://prototypejs.org/api), Oliver Steele's
|
||||
# [Functional](http://osteele.com), and John Resig's
|
||||
# [Micro-Templating](http://ejohn.com).
|
||||
# For all details and documentation:
|
||||
# http://documentcloud.github.com/underscore/
|
||||
|
||||
|
||||
# ------------------------- Baseline setup ---------------------------------
|
||||
# Baseline setup
|
||||
# --------------
|
||||
|
||||
# Establish the root object, "window" in the browser, or "global" on the server.
|
||||
# Establish the root object, `window` in the browser, or `global` on the server.
|
||||
root: this
|
||||
|
||||
|
||||
# Save the previous value of the "_" variable.
|
||||
# Save the previous value of the `_` variable.
|
||||
previousUnderscore: root._
|
||||
|
||||
|
||||
# Establish the object that gets thrown to break out of a loop iteration.
|
||||
# `StopIteration` is SOP on Mozilla.
|
||||
breaker: if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration
|
||||
|
||||
|
||||
# Quick regexp-escaping function, because JS doesn't have RegExp.escape().
|
||||
# Helper function to escape **RegExp** contents, because JS doesn't have one.
|
||||
escapeRegExp: (string) -> string.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1')
|
||||
|
||||
|
||||
@@ -31,7 +36,7 @@
|
||||
ObjProto: Object.prototype
|
||||
|
||||
|
||||
#Create quick reference variables for speed access to core prototypes.
|
||||
# Create quick reference variables for speed access to core prototypes.
|
||||
slice: ArrayProto.slice
|
||||
unshift: ArrayProto.unshift
|
||||
toString: ObjProto.toString
|
||||
@@ -39,7 +44,7 @@
|
||||
propertyIsEnumerable: ObjProto.propertyIsEnumerable
|
||||
|
||||
|
||||
# All ECMA5 native implementations we hope to use are declared here.
|
||||
# All **ECMA5** native implementations we hope to use are declared here.
|
||||
nativeForEach: ArrayProto.forEach
|
||||
nativeMap: ArrayProto.map
|
||||
nativeReduce: ArrayProto.reduce
|
||||
@@ -57,7 +62,7 @@
|
||||
_: (obj) -> new wrapper(obj)
|
||||
|
||||
|
||||
# Export the Underscore object for CommonJS.
|
||||
# Export the Underscore object for **CommonJS**.
|
||||
if typeof(exports) != 'undefined' then exports._: _
|
||||
|
||||
|
||||
@@ -66,13 +71,14 @@
|
||||
|
||||
|
||||
# Current version.
|
||||
_.VERSION: '0.6.0'
|
||||
_.VERSION: '1.0.2'
|
||||
|
||||
|
||||
# ------------------------ Collection Functions: ---------------------------
|
||||
# Collection Functions
|
||||
# --------------------
|
||||
|
||||
# The cornerstone, an each implementation.
|
||||
# Handles objects implementing forEach, arrays, and raw objects.
|
||||
# The cornerstone, an **each** implementation.
|
||||
# Handles objects implementing **forEach**, arrays, and raw objects.
|
||||
_.each: (obj, iterator, context) ->
|
||||
try
|
||||
if nativeForEach and obj.forEach is nativeForEach
|
||||
@@ -87,7 +93,7 @@
|
||||
|
||||
|
||||
# Return the results of applying the iterator to each element. Use JavaScript
|
||||
# 1.6's version of map, if possible.
|
||||
# 1.6's version of **map**, if possible.
|
||||
_.map: (obj, iterator, context) ->
|
||||
return obj.map(iterator, context) if nativeMap and obj.map is nativeMap
|
||||
results: []
|
||||
@@ -96,8 +102,8 @@
|
||||
results
|
||||
|
||||
|
||||
# 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** 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
|
||||
_.each obj, (value, index, list) ->
|
||||
@@ -105,8 +111,8 @@
|
||||
memo
|
||||
|
||||
|
||||
# The right-associative version of reduce, also known as foldr. Uses
|
||||
# JavaScript 1.8's version of reduceRight, if available.
|
||||
# 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) ->
|
||||
@@ -125,7 +131,7 @@
|
||||
|
||||
|
||||
# Return all the elements that pass a truth test. Use JavaScript 1.6's
|
||||
# filter(), if it exists.
|
||||
# **filter**, if it exists.
|
||||
_.filter: (obj, iterator, context) ->
|
||||
return obj.filter iterator, context if nativeFilter and obj.filter is nativeFilter
|
||||
results: []
|
||||
@@ -143,7 +149,7 @@
|
||||
|
||||
|
||||
# Determine whether all of the elements match a truth test. Delegate to
|
||||
# JavaScript 1.6's every(), if it is present.
|
||||
# JavaScript 1.6's **every**, if it is present.
|
||||
_.every: (obj, iterator, context) ->
|
||||
iterator ||= _.identity
|
||||
return obj.every iterator, context if nativeEvery and obj.every is nativeEvery
|
||||
@@ -154,7 +160,7 @@
|
||||
|
||||
|
||||
# Determine if at least one element in the object matches a truth test. Use
|
||||
# JavaScript 1.6's some(), if it exists.
|
||||
# JavaScript 1.6's **some**, if it exists.
|
||||
_.some: (obj, iterator, context) ->
|
||||
iterator ||= _.identity
|
||||
return obj.some iterator, context if nativeSome and obj.some is nativeSome
|
||||
@@ -165,7 +171,7 @@
|
||||
|
||||
|
||||
# Determine if a given value is included in the array or object,
|
||||
# based on '==='.
|
||||
# based on `===`.
|
||||
_.include: (obj, target) ->
|
||||
return _.indexOf(obj, target) isnt -1 if nativeIndexOf and obj.indexOf is nativeIndexOf
|
||||
for key, val of obj
|
||||
@@ -179,7 +185,7 @@
|
||||
(if method then val[method] else val).apply(val, args) for val in obj
|
||||
|
||||
|
||||
# Convenience version of a common use case of map: fetching a property.
|
||||
# Convenience version of a common use case of **map**: fetching a property.
|
||||
_.pluck: (obj, key) ->
|
||||
_.map(obj, (val) -> val[key])
|
||||
|
||||
@@ -239,19 +245,20 @@
|
||||
_.size: (obj) -> _.toArray(obj).length
|
||||
|
||||
|
||||
# -------------------------- Array Functions: ------------------------------
|
||||
# Array Functions
|
||||
# ---------------
|
||||
|
||||
# Get the first element of an array. Passing "n" will return the first N
|
||||
# values in the array. Aliased as "head". The "guard" check allows it to work
|
||||
# with _.map.
|
||||
# Get the first element of an array. Passing `n` will return the first N
|
||||
# values in the array. Aliased as **head**. The `guard` check allows it to work
|
||||
# with **map**.
|
||||
_.first: (array, n, guard) ->
|
||||
if n and not guard then slice.call(array, 0, n) else array[0]
|
||||
|
||||
|
||||
# Returns everything but the first entry of the array. Aliased as "tail".
|
||||
# Especially useful on the arguments object. Passing an "index" will return
|
||||
# the rest of the values in the array from that index onward. The "guard"
|
||||
# check allows it to work with _.map.
|
||||
# Returns everything but the first entry of the array. Aliased as **tail**.
|
||||
# Especially useful on the arguments object. Passing an `index` will return
|
||||
# the rest of the values in the array from that index onward. The `guard`
|
||||
# check allows it to work with **map**.
|
||||
_.rest: (array, index, guard) ->
|
||||
slice.call(array, if _.isUndefined(index) or guard then 1 else index)
|
||||
|
||||
@@ -306,7 +313,7 @@
|
||||
results
|
||||
|
||||
|
||||
# If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),
|
||||
# If the browser doesn't supply us with **indexOf** (I'm looking at you, MSIE),
|
||||
# we need this function. Return the position of the first occurence of an
|
||||
# item in an array, or -1 if the item is not included in the array.
|
||||
_.indexOf: (array, item) ->
|
||||
@@ -317,7 +324,7 @@
|
||||
-1
|
||||
|
||||
|
||||
# Provide JavaScript 1.6's lastIndexOf, delegating to the native function,
|
||||
# Provide JavaScript 1.6's **lastIndexOf**, delegating to the native function,
|
||||
# if possible.
|
||||
_.lastIndexOf: (array, item) ->
|
||||
return array.lastIndexOf(item) if nativeLastIndexOf and array.lastIndexOf is nativeLastIndexOf
|
||||
@@ -328,8 +335,7 @@
|
||||
|
||||
|
||||
# Generate an integer Array containing an arithmetic progression. A port of
|
||||
# the native Python range() function. See:
|
||||
# http://docs.python.org/library/functions.html#range
|
||||
# [the native Python **range** function](http://docs.python.org/library/functions.html#range).
|
||||
_.range: (start, stop, step) ->
|
||||
a: arguments
|
||||
solo: a.length <= 1
|
||||
@@ -340,17 +346,18 @@
|
||||
return [] if len <= 0
|
||||
range: new Array len
|
||||
idx: 0
|
||||
while true
|
||||
loop
|
||||
return range if (if step > 0 then i - stop else stop - i) >= 0
|
||||
range[idx]: i
|
||||
idx++
|
||||
i+= step
|
||||
|
||||
|
||||
# ----------------------- Function Functions: -----------------------------
|
||||
# Function Functions
|
||||
# ------------------
|
||||
|
||||
# Create a function bound to a given object (assigning 'this', and arguments,
|
||||
# optionally). Binding with arguments is also known as 'curry'.
|
||||
# Create a function bound to a given object (assigning `this`, and arguments,
|
||||
# optionally). Binding with arguments is also known as **curry**.
|
||||
_.bind: (func, obj) ->
|
||||
args: _.rest arguments, 2
|
||||
-> func.apply obj or root, args.concat arguments
|
||||
@@ -395,7 +402,8 @@
|
||||
args[0]
|
||||
|
||||
|
||||
# ------------------------- Object Functions: ----------------------------
|
||||
# Object Functions
|
||||
# ----------------
|
||||
|
||||
# Retrieve the names of an object's properties.
|
||||
_.keys: nativeKeys or (obj) ->
|
||||
@@ -414,9 +422,10 @@
|
||||
|
||||
|
||||
# Extend a given object with all of the properties in a source object.
|
||||
_.extend: (destination, source) ->
|
||||
(destination[key]: val) for key, val of source
|
||||
destination
|
||||
_.extend: (obj) ->
|
||||
for source in _.rest(arguments)
|
||||
(obj[key]: val) for key, val of source
|
||||
obj
|
||||
|
||||
|
||||
# Create a (shallow-cloned) duplicate of an object.
|
||||
@@ -443,7 +452,7 @@
|
||||
return true if `a == b`
|
||||
# One is falsy and the other truthy.
|
||||
return false if (!a and b) or (a and !b)
|
||||
# One of them implements an isEqual()?
|
||||
# One of them implements an `isEqual()`?
|
||||
return a.isEqual(b) if a.isEqual
|
||||
# Check dates' integer values.
|
||||
return a.getTime() is b.getTime() if _.isDate(a) and _.isDate(b)
|
||||
@@ -464,7 +473,7 @@
|
||||
# Different object sizes?
|
||||
return false if aKeys.length isnt bKeys.length
|
||||
# Recursive comparison of contents.
|
||||
(return false) for key, val of a when !_.isEqual(val, b[key])
|
||||
(return false) for key, val of a when !(key in b) or !_.isEqual(val, b[key])
|
||||
true
|
||||
|
||||
|
||||
@@ -480,12 +489,11 @@
|
||||
|
||||
|
||||
# Is a given value an array?
|
||||
_.isArray: nativeIsArray or (obj) -> !!(obj and obj.concat and obj.unshift)
|
||||
_.isArray: nativeIsArray or (obj) -> !!(obj and obj.concat and obj.unshift and not obj.callee)
|
||||
|
||||
|
||||
# Is a given variable an arguments object?
|
||||
_.isArguments: (obj) -> obj and _.isNumber(obj.length) and not obj.concat and
|
||||
not obj.substr and not obj.apply and not propertyIsEnumerable.call(obj, 'length')
|
||||
_.isArguments: (obj) -> obj and obj.callee
|
||||
|
||||
|
||||
# Is the given value a function?
|
||||
@@ -512,8 +520,8 @@
|
||||
_.isRegExp: (obj) -> !!(obj and obj.exec and (obj.ignoreCase or obj.ignoreCase is false))
|
||||
|
||||
|
||||
# Is the given value NaN -- this one is interesting. NaN != NaN, and
|
||||
# isNaN(undefined) == true, so we make sure it's a number first.
|
||||
# Is the given value NaN -- this one is interesting. `NaN != NaN`, and
|
||||
# `isNaN(undefined) == true`, so we make sure it's a number first.
|
||||
_.isNaN: (obj) -> _.isNumber(obj) and window.isNaN(obj)
|
||||
|
||||
|
||||
@@ -525,9 +533,10 @@
|
||||
_.isUndefined: (obj) -> typeof obj is 'undefined'
|
||||
|
||||
|
||||
# -------------------------- Utility Functions: --------------------------
|
||||
# Utility Functions
|
||||
# -----------------
|
||||
|
||||
# Run Underscore.js in noConflict mode, returning the '_' variable to its
|
||||
# Run Underscore.js in noConflict mode, returning the `_` variable to its
|
||||
# previous owner. Returns a reference to the Underscore object.
|
||||
_.noConflict: ->
|
||||
root._: previousUnderscore
|
||||
@@ -538,7 +547,7 @@
|
||||
_.identity: (value) -> value
|
||||
|
||||
|
||||
# Run a function n times.
|
||||
# Run a function `n` times.
|
||||
_.times: (n, iterator, context) ->
|
||||
iterator.call(context, i) for i in [0...n]
|
||||
|
||||
@@ -561,7 +570,7 @@
|
||||
(prefix or '') + idCounter++
|
||||
|
||||
|
||||
# By default, Underscore uses ERB-style template delimiters, change the
|
||||
# By default, Underscore uses **ERB**-style template delimiters, change the
|
||||
# following template settings to use alternative delimiters.
|
||||
_.templateSettings: {
|
||||
start: '<%'
|
||||
@@ -570,9 +579,9 @@
|
||||
}
|
||||
|
||||
|
||||
# JavaScript templating a-la ERB, pilfered from John Resig's
|
||||
# "Secrets of the JavaScript Ninja", page 83.
|
||||
# Single-quote fix from Rick Strahl's version.
|
||||
# JavaScript templating a-la **ERB**, pilfered from John Resig's
|
||||
# *Secrets of the JavaScript Ninja*, page 83.
|
||||
# Single-quote fix from Rick Strahl.
|
||||
_.template: (str, data) ->
|
||||
c: _.templateSettings
|
||||
endMatch: new RegExp("'(?=[^"+c.end.substr(0, 1)+"]*"+escapeRegExp(c.end)+")","g")
|
||||
@@ -590,7 +599,8 @@
|
||||
if data then fn(data) else fn
|
||||
|
||||
|
||||
# ------------------------------- Aliases ----------------------------------
|
||||
# Aliases
|
||||
# -------
|
||||
|
||||
_.forEach: _.each
|
||||
_.foldl: _.inject: _.reduce
|
||||
@@ -603,7 +613,8 @@
|
||||
_.methods: _.functions
|
||||
|
||||
|
||||
# ------------------------ Setup the OOP Wrapper: --------------------------
|
||||
# Setup the OOP Wrapper
|
||||
# ---------------------
|
||||
|
||||
# If Underscore is called as a function, it returns a wrapped object that
|
||||
# can be used OO-style. This wrapper holds altered versions of all the
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
# Contributed by Jason Huggins
|
||||
|
||||
sys: require 'sys'
|
||||
http: require 'http'
|
||||
|
||||
server: http.createServer (req, res) ->
|
||||
res.sendHeader 200, {'Content-Type': 'text/plain'}
|
||||
res.writeHeader 200, {'Content-Type': 'text/plain'}
|
||||
res.write 'Hello, World!'
|
||||
res.close()
|
||||
res.end()
|
||||
|
||||
server.listen 3000
|
||||
|
||||
puts "Server running at http://localhost:3000/"
|
||||
sys.puts "Server running at http://localhost:3000/"
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>comments</string>
|
||||
<key>scope</key>
|
||||
<string>source.coffee</string>
|
||||
<key>settings</key>
|
||||
<dict>
|
||||
<key>shellVariables</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>TM_COMMENT_START</string>
|
||||
<key>value</key>
|
||||
<string># </string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<key>uuid</key>
|
||||
<string>0A92C6F6-4D73-4859-B38C-4CC19CBC191F</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,361 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>CoffeeScript Syntax: version 1</string>
|
||||
<key>fileTypes</key>
|
||||
<array>
|
||||
<string>coffee</string>
|
||||
</array>
|
||||
<key>name</key>
|
||||
<string>CoffeeScript</string>
|
||||
<key>foldingStartMarker</key>
|
||||
<string>^.*[:=] \{[^\}]*$</string>
|
||||
<key>foldingStopMarker</key>
|
||||
<string>\s*\}</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>variable.parameter.function.coffee</string>
|
||||
</dict>
|
||||
<key>2</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>variable.parameter.function.coffee</string>
|
||||
</dict>
|
||||
<key>4</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>variable.parameter.function.coffee</string>
|
||||
</dict>
|
||||
<key>5</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>storage.type.function.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>comment</key>
|
||||
<string>match stuff like: a -> … </string>
|
||||
<key>match</key>
|
||||
<string>(\()([a-zA-Z0-9_?.$]*(,\s*[a-zA-Z0-9_?.$]+)*)(\))\s*((=|-)>)</string>
|
||||
<key>name</key>
|
||||
<string>meta.inline.function.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.operator.new.coffee</string>
|
||||
</dict>
|
||||
<key>2</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>entity.name.type.instance.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>match</key>
|
||||
<string>(new)\s+(\w+(?:\.\w*)?)</string>
|
||||
<key>name</key>
|
||||
<string>meta.class.instance.constructor</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?(e[+\-]?[0-9]+)?))\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.numeric.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(@)([a-zA-Z_$]\w*)?</string>
|
||||
<key>name</key>
|
||||
<string>variable.other.readwrite.instance.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>string.quoted.heredoc.coffee</string>
|
||||
<key>begin</key>
|
||||
<string>("""|''')</string>
|
||||
<key>end</key>
|
||||
<string>("""|''')</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>'</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>'</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>string.quoted.single.coffee</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)</string>
|
||||
<key>name</key>
|
||||
<string>constant.character.escape.coffee</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>"</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>"</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>string.quoted.double.coffee</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)</string>
|
||||
<key>name</key>
|
||||
<string>constant.character.escape.coffee</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>`</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>`</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>string.quoted.script.coffee</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)</string>
|
||||
<key>name</key>
|
||||
<string>constant.character.escape.coffee</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.comment.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>match</key>
|
||||
<string>(#).*$\n?</string>
|
||||
<key>name</key>
|
||||
<string>comment.line.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>(?<=[=(:]|^|return)\s*(/)(?![/*+{}?])</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>(/)[igm]*</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>string.regexp.coffee</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\\.</string>
|
||||
<key>name</key>
|
||||
<string>constant.character.escape.coffee</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(break|by|catch|continue|else|finally|for|in|of|if|return|switch|then|throw|try|unless|when|while)\b</string>
|
||||
<key>name</key>
|
||||
<string>keyword.control.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b([a-zA-Z$_](\w|\$|:|\.)*\s*(?=\:))</string>
|
||||
<key>name</key>
|
||||
<string>variable.assignment.coffee</string>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>entity.name.function.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(true|on|yes)\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.language.boolean.true.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(false|off|no)\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.language.boolean.false.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\bnull\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.language.null.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(super|this|extends|class)\b</string>
|
||||
<key>name</key>
|
||||
<string>variable.language.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(debugger|\\)\b</string>
|
||||
<key>name</key>
|
||||
<string>keyword.other.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(=|-)></string>
|
||||
<key>name</key>
|
||||
<string>storage.type.function.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>!|%|&|\*|\/|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\?|\|\||\:|\*=|(?<!\()/=|%=|\+=|\-=|&=|\^=|\b(instanceof|new|delete|typeof|and|or|is|isnt|not)\b</string>
|
||||
<key>name</key>
|
||||
<string>keyword.operator.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(Infinity|NaN|undefined)\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.language.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\;</string>
|
||||
<key>name</key>
|
||||
<string>punctuation.terminator.statement.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>,[ |\t]*</string>
|
||||
<key>name</key>
|
||||
<string>meta.delimiter.object.comma.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\.</string>
|
||||
<key>name</key>
|
||||
<string>meta.delimiter.method.period.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\{|\}</string>
|
||||
<key>name</key>
|
||||
<string>meta.brace.curly.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\(|\)</string>
|
||||
<key>name</key>
|
||||
<string>meta.brace.round.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\[|\]</string>
|
||||
<key>name</key>
|
||||
<string>meta.brace.square.coffee</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>scopeName</key>
|
||||
<string>source.coffee</string>
|
||||
<key>uuid</key>
|
||||
<string>5B520980-A7D5-4E10-8582-1A4C889A8DE5</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>CoffeeScript</string>
|
||||
<key>uuid</key>
|
||||
<string>A46E4382-F1AC-405B-8F22-65FF470F34D7</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -5,24 +5,3 @@ CoffeeScript compiler. To use it in the browser, include the script after any
|
||||
inline script tags of type "text/coffeescript" on the page. It will compile
|
||||
and evaluate all of the scripts in order.
|
||||
|
||||
|
||||
This folder also includes rough cuts of CoffeeScript syntax highlighters for
|
||||
TextMate and Vim. Improvements to their lexing ability are always welcome.
|
||||
|
||||
To install the TextMate bundle, drop it into:
|
||||
~/Library/Application Support/TextMate/Bundles
|
||||
|
||||
To install the Vim highlighter, copy "coffee.vim" into the "syntax" directory of
|
||||
your vim72, and enable it in either of the following two ways:
|
||||
|
||||
* Manually, by running `:set syntax=coffee`
|
||||
|
||||
* Or automatically, by creating a "filetype.vim" file within "~/.vim", which
|
||||
contains something along these lines:
|
||||
|
||||
if exists("did_load_filetypes")
|
||||
finish
|
||||
end
|
||||
augroup filetypedetect
|
||||
au! BufRead,BufNewFile *.coffee setfiletype coffee
|
||||
augroup END
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,117 +0,0 @@
|
||||
" Vim syntax file
|
||||
" Language: CoffeeScript
|
||||
" Maintainer: Jeff Olson <olson.jeffery@gmail.com>
|
||||
" URL: http://github.com/olsonjeffery
|
||||
" Changes: (jro) initial port from javascript
|
||||
" Last Change: 2006 Jun 19
|
||||
" Adaptation of javascript.vim syntax file (distro'd w/ vim72),
|
||||
" maintained by Claudio Fleiner <claudio@fleiner.com>
|
||||
" with updates from Scott Shattuck (ss) <ss@technicalpursuit.com>
|
||||
|
||||
if !exists("main_syntax")
|
||||
if version < 600
|
||||
syntax clear
|
||||
elseif exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
let main_syntax = 'coffee'
|
||||
endif
|
||||
|
||||
syn case ignore
|
||||
|
||||
syn match coffeeLineComment "#.*" contains=@Spell,CoffeeCommentTodo
|
||||
syn match coffeeSpecial "\\\d\d\d\|\\."
|
||||
syn region coffeeStringD start=+"+ skip=+\\\\\|\\"+ end=+"\|$+ contains=coffeeSpecial,@htmlPreproc
|
||||
syn region coffeeStringS start=+'+ skip=+\\\\\|\\'+ end=+'\|$+ contains=coffeeSpecial,@htmlPreproc
|
||||
|
||||
syn match coffeeSpecialCharacter "'\\.'"
|
||||
syn match coffeeNumber "-\=\<\d\+L\=\>\|0[xX][0-9a-fA-F]\+\>"
|
||||
syn region coffeeRegexpString start=+/[^/*]+me=e-1 skip=+\\\\\|\\/+ end=+/[gi]\{0,2\}\s*$+ end=+/[gi]\{0,2\}\s*[;.,)\]}]+me=e-1 contains=@htmlPreproc oneline
|
||||
|
||||
syn match coffeeFunctionParams "([^)]*)\s*->"
|
||||
syn match coffeeBindFunctionParams "([^)]*)\s*=>"
|
||||
syn match coffeePrototypeAccess "::"
|
||||
syn match coffeeBindFunction "=[1]>[1]"
|
||||
syn match coffeeFunction "->"
|
||||
|
||||
syn keyword coffeeExtends extends
|
||||
syn keyword coffeeConditional if else switch then not
|
||||
syn keyword coffeeRepeat while for in of
|
||||
syn keyword coffeeBranch break continue
|
||||
syn keyword coffeeOperator delete instanceof typeof
|
||||
syn keyword coffeeType Array Boolean Date Function Number Object String RegExp
|
||||
syn keyword coffeeStatement return with
|
||||
syn keyword coffeeBoolean true false
|
||||
syn keyword coffeeNull null undefined
|
||||
syn keyword coffeeIdentifier arguments this var
|
||||
syn keyword coffeeLabel case default
|
||||
syn keyword coffeeException try catch finally throw
|
||||
syn keyword coffeeMessage alert confirm prompt status
|
||||
syn keyword coffeeGlobal self window top parent
|
||||
syn keyword coffeeMember document event location
|
||||
syn keyword coffeeDeprecated escape unescape
|
||||
syn keyword coffeeReserved abstract boolean byte char class const debugger double enum export final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile
|
||||
|
||||
syn sync fromstart
|
||||
syn sync maxlines=100
|
||||
|
||||
if main_syntax == "coffee"
|
||||
syn sync ccomment coffeeComment
|
||||
endif
|
||||
|
||||
" Define the default highlighting.
|
||||
" For version 5.7 and earlier: only when not done already
|
||||
" For version 5.8 and later: only when an item doesn't have highlighting yet
|
||||
if version >= 508 || !exists("did_coffee_syn_inits")
|
||||
if version < 508
|
||||
let did_coffee_syn_inits = 1
|
||||
command -nargs=+ HiLink hi link <args>
|
||||
else
|
||||
command -nargs=+ HiLink hi def link <args>
|
||||
endif
|
||||
HiLink coffeePrototypeAccess Keyword
|
||||
HiLink coffeeExtends Keyword
|
||||
HiLink coffeeLineComment Comment
|
||||
HiLink coffeeSpecial Special
|
||||
HiLink coffeeStringS String
|
||||
HiLink coffeeStringD String
|
||||
HiLink coffeeCharacter Character
|
||||
HiLink coffeeSpecialCharacter coffeeSpecial
|
||||
HiLink coffeeNumber coffeeValue
|
||||
HiLink coffeeConditional Conditional
|
||||
HiLink coffeeRepeat Repeat
|
||||
HiLink coffeeBranch Conditional
|
||||
HiLink coffeeOperator Operator
|
||||
HiLink coffeeType Type
|
||||
HiLink coffeeStatement Statement
|
||||
HiLink coffeeBindFunctionParams Function
|
||||
HiLink coffeeFunctionParams Function
|
||||
HiLink coffeeFunction Function
|
||||
HiLink coffeeBindFunction Function
|
||||
HiLink coffeeBraces Function
|
||||
HiLink coffeeError Error
|
||||
HiLink coffeeScrParenError coffeeError
|
||||
HiLink coffeeNull Keyword
|
||||
HiLink coffeeBoolean Boolean
|
||||
HiLink coffeeRegexpString String
|
||||
|
||||
HiLink coffeeIdentifier Identifier
|
||||
HiLink coffeeLabel Label
|
||||
HiLink coffeeException Exception
|
||||
HiLink coffeeMessage Keyword
|
||||
HiLink coffeeGlobal Keyword
|
||||
HiLink coffeeMember Keyword
|
||||
HiLink coffeeDeprecated Exception
|
||||
HiLink coffeeReserved Keyword
|
||||
HiLink coffeeDebug Debug
|
||||
HiLink coffeeConstant Label
|
||||
|
||||
delcommand HiLink
|
||||
endif
|
||||
|
||||
let b:current_syntax = "coffee"
|
||||
if main_syntax == 'coffee'
|
||||
unlet main_syntax
|
||||
endif
|
||||
|
||||
" vim: ts=8
|
||||
1016
index.html
1016
index.html
File diff suppressed because it is too large
Load Diff
74
lib/cake.js
74
lib/cake.js
@@ -1,86 +1,86 @@
|
||||
(function(){
|
||||
var coffee, fs, no_such_task, oparse, options, optparse, path, print_tasks, switches, tasks;
|
||||
var CoffeeScript, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
// `cake` is a simplified version of Make (Rake, Jake) 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.
|
||||
fs = require('fs');
|
||||
path = require('path');
|
||||
coffee = require('coffee-script');
|
||||
optparse = require('optparse');
|
||||
helpers = require('./helpers').helpers;
|
||||
optparse = require('./optparse');
|
||||
CoffeeScript = require('./coffee-script');
|
||||
tasks = {};
|
||||
options = {};
|
||||
switches = [];
|
||||
oparse = null;
|
||||
// Mixin the top-level Cake functions for Cakefiles to use.
|
||||
process.mixin({
|
||||
// Define a task with a name, a description, and the action itself.
|
||||
task: function task(name, description, action) {
|
||||
return tasks[name] = {
|
||||
helpers.extend(global, {
|
||||
task: function(name, description, action) {
|
||||
var _a;
|
||||
if (!(action)) {
|
||||
_a = [description, action];
|
||||
action = _a[0];
|
||||
description = _a[1];
|
||||
}
|
||||
tasks[name] = {
|
||||
name: name,
|
||||
description: description,
|
||||
action: action
|
||||
};
|
||||
return tasks[name];
|
||||
},
|
||||
// Define an option that the Cakefile accepts.
|
||||
option: function option(letter, flag, description) {
|
||||
option: function(letter, flag, description) {
|
||||
return switches.push([letter, flag, description]);
|
||||
},
|
||||
// Invoke another task in the Cakefile.
|
||||
invoke: function invoke(name) {
|
||||
invoke: function(name) {
|
||||
if (!(tasks[name])) {
|
||||
no_such_task(name);
|
||||
missingTask(name);
|
||||
}
|
||||
return tasks[name].action(options);
|
||||
}
|
||||
});
|
||||
// Running `cake` runs the tasks you pass asynchronously (node-style), or
|
||||
// prints them out, with no arguments.
|
||||
exports.run = function run() {
|
||||
exports.run = function() {
|
||||
return path.exists('Cakefile', function(exists) {
|
||||
var _a, _b, _c, _d, arg, args;
|
||||
if (!(exists)) {
|
||||
throw new Error('Cakefile not found in ' + process.cwd());
|
||||
throw new Error(("Cakefile not found in " + (process.cwd())));
|
||||
}
|
||||
args = process.ARGV.slice(2, process.ARGV.length);
|
||||
eval(coffee.compile(fs.readFileSync('Cakefile')));
|
||||
args = process.argv.slice(2, process.argv.length);
|
||||
CoffeeScript.run(fs.readFileSync('Cakefile').toString(), {
|
||||
source: 'Cakefile'
|
||||
});
|
||||
oparse = new optparse.OptionParser(switches);
|
||||
if (!(args.length)) {
|
||||
return print_tasks();
|
||||
return printTasks();
|
||||
}
|
||||
options = oparse.parse(args);
|
||||
_a = []; _b = options.arguments;
|
||||
for (_c = 0, _d = _b.length; _c < _d; _c++) {
|
||||
arg = _b[_c];
|
||||
_a = []; _c = options.arguments;
|
||||
for (_b = 0, _d = _c.length; _b < _d; _b++) {
|
||||
arg = _c[_b];
|
||||
_a.push(invoke(arg));
|
||||
}
|
||||
return _a;
|
||||
});
|
||||
};
|
||||
// Display the list of Cake tasks.
|
||||
print_tasks = function print_tasks() {
|
||||
var _a, _b, _c, _d, _e, _f, i, name, spaces, task;
|
||||
printTasks = function() {
|
||||
var _a, _b, desc, i, name, spaces, task;
|
||||
puts('');
|
||||
_a = tasks;
|
||||
for (name in _a) { if (__hasProp.call(_a, name)) {
|
||||
task = _a[name];
|
||||
spaces = 20 - name.length;
|
||||
spaces = spaces > 0 ? (function() {
|
||||
_b = []; _e = 0; _f = spaces;
|
||||
for (_d = 0, i = _e; (_e <= _f ? i <= _f : i >= _f); (_e <= _f ? i += 1 : i -= 1), _d++) {
|
||||
_b = [];
|
||||
for (i = 0; i <= spaces; i += 1) {
|
||||
_b.push(' ');
|
||||
}
|
||||
return _b;
|
||||
}).call(this).join('') : '';
|
||||
puts("cake " + name + spaces + ' # ' + task.description);
|
||||
})().join('') : '';
|
||||
desc = task.description ? ("# " + task.description) : '';
|
||||
puts("cake " + name + spaces + " " + desc);
|
||||
}}
|
||||
if (switches.length) {
|
||||
return puts('\n' + oparse.help() + '\n');
|
||||
return puts(oparse.help());
|
||||
}
|
||||
};
|
||||
// Print an error and exit when attempting to all an undefined task.
|
||||
no_such_task = function no_such_task(task) {
|
||||
process.stdio.writeError('No such task: "' + task + '"\n');
|
||||
missingTask = function(task) {
|
||||
puts("No such task: \"" + task + "\"");
|
||||
return process.exit(1);
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,19 +1,47 @@
|
||||
(function(){
|
||||
var lexer, parser, path, process_scripts;
|
||||
// Set up for both the browser and the server.
|
||||
if ((typeof process !== "undefined" && process !== null)) {
|
||||
process.mixin(require('nodes'));
|
||||
var Lexer, compile, helpers, lexer, parser, path, processScripts;
|
||||
if (typeof process !== "undefined" && process !== null) {
|
||||
path = require('path');
|
||||
lexer = new (require('lexer').Lexer)();
|
||||
parser = require('parser').parser;
|
||||
Lexer = require('./lexer').Lexer;
|
||||
parser = require('./parser').parser;
|
||||
helpers = require('./helpers').helpers;
|
||||
helpers.extend(global, require('./nodes'));
|
||||
require.registerExtension ? require.registerExtension('.coffee', function(content) {
|
||||
return compile(content);
|
||||
}) : null;
|
||||
} else {
|
||||
lexer = new Lexer();
|
||||
parser = exports.parser;
|
||||
this.exports = (this.CoffeeScript = {});
|
||||
Lexer = this.Lexer;
|
||||
parser = this.parser;
|
||||
helpers = this.helpers;
|
||||
}
|
||||
// Thin wrapper for Jison compatibility around the real lexer.
|
||||
exports.VERSION = '0.7.0';
|
||||
lexer = new Lexer();
|
||||
exports.compile = (compile = function(code, options) {
|
||||
options = options || {};
|
||||
try {
|
||||
return (parser.parse(lexer.tokenize(code))).compile(options);
|
||||
} catch (err) {
|
||||
if (options.source) {
|
||||
err.message = ("In " + options.source + ", " + err.message);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
exports.tokens = function(code) {
|
||||
return lexer.tokenize(code);
|
||||
};
|
||||
exports.nodes = function(code) {
|
||||
return parser.parse(lexer.tokenize(code));
|
||||
};
|
||||
exports.run = (function(code, options) {
|
||||
var __dirname, __filename;
|
||||
module.filename = (__filename = options.source);
|
||||
__dirname = path.dirname(__filename);
|
||||
return eval(exports.compile(code, options));
|
||||
});
|
||||
parser.lexer = {
|
||||
lex: function lex() {
|
||||
lex: function() {
|
||||
var token;
|
||||
token = this.tokens[this.pos] || [""];
|
||||
this.pos += 1;
|
||||
@@ -21,48 +49,29 @@
|
||||
this.yytext = token[1];
|
||||
return token[0];
|
||||
},
|
||||
setInput: function setInput(tokens) {
|
||||
setInput: function(tokens) {
|
||||
this.tokens = tokens;
|
||||
return this.pos = 0;
|
||||
},
|
||||
upcomingInput: function upcomingInput() {
|
||||
return "";
|
||||
},
|
||||
showPosition: function showPosition() {
|
||||
this.pos = 0;
|
||||
return this.pos;
|
||||
},
|
||||
upcomingInput: function() {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
exports.VERSION = '0.5.4';
|
||||
// Compile CoffeeScript to JavaScript, using the Coffee/Jison compiler.
|
||||
exports.compile = function compile(code, options) {
|
||||
return (parser.parse(lexer.tokenize(code))).compile(options);
|
||||
};
|
||||
// Just the tokens.
|
||||
exports.tokens = function tokens(code) {
|
||||
return lexer.tokenize(code);
|
||||
};
|
||||
// Just the nodes.
|
||||
exports.nodes = function nodes(code) {
|
||||
return parser.parse(lexer.tokenize(code));
|
||||
};
|
||||
// Activate CoffeeScript in the browser by having it compile and eval
|
||||
// all script tags with a content-type of text/coffeescript.
|
||||
if ((typeof document !== "undefined" && document !== null) && document.getElementsByTagName) {
|
||||
process_scripts = function process_scripts() {
|
||||
processScripts = function() {
|
||||
var _a, _b, _c, _d, tag;
|
||||
_a = []; _b = document.getElementsByTagName('script');
|
||||
for (_c = 0, _d = _b.length; _c < _d; _c++) {
|
||||
tag = _b[_c];
|
||||
if (tag.type === 'text/coffeescript') {
|
||||
_a.push(eval(exports.compile(tag.innerHTML)));
|
||||
}
|
||||
_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', process_scripts, false);
|
||||
window.addEventListener('load', processScripts, false);
|
||||
} else if (window.attachEvent) {
|
||||
window.attachEvent('onload', process_scripts);
|
||||
window.attachEvent('onload', processScripts);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
216
lib/command.js
Normal file
216
lib/command.js
Normal file
@@ -0,0 +1,216 @@
|
||||
(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;
|
||||
fs = require('fs');
|
||||
path = require('path');
|
||||
optparse = require('./optparse');
|
||||
CoffeeScript = require('./coffee-script');
|
||||
_a = require('child_process');
|
||||
spawn = _a.spawn;
|
||||
exec = _a.exec;
|
||||
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 = {};
|
||||
sources = [];
|
||||
optionParser = null;
|
||||
exports.run = function() {
|
||||
var flags, separator;
|
||||
parseOptions();
|
||||
if (options.help) {
|
||||
return usage();
|
||||
}
|
||||
if (options.version) {
|
||||
return version();
|
||||
}
|
||||
if (options.interactive) {
|
||||
return require('./repl');
|
||||
}
|
||||
if (options.stdio) {
|
||||
return compileStdio();
|
||||
}
|
||||
if (options.eval) {
|
||||
return compileScript('console', sources[0]);
|
||||
}
|
||||
if (!(sources.length)) {
|
||||
return require('./repl');
|
||||
}
|
||||
separator = sources.indexOf('--');
|
||||
flags = [];
|
||||
if (separator >= 0) {
|
||||
flags = sources.slice((separator + 1), sources.length);
|
||||
sources = sources.slice(0, separator);
|
||||
}
|
||||
process.ARGV = (process.argv = flags);
|
||||
return compileScripts();
|
||||
};
|
||||
compileScripts = function() {
|
||||
var _b, _c, _d, _e;
|
||||
_b = []; _d = sources;
|
||||
for (_c = 0, _e = _d.length; _c < _e; _c++) {
|
||||
(function() {
|
||||
var base, compile;
|
||||
var source = _d[_c];
|
||||
return _b.push((function() {
|
||||
base = source;
|
||||
compile = function(source, topLevel) {
|
||||
return path.exists(source, function(exists) {
|
||||
if (!(exists)) {
|
||||
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)));
|
||||
}
|
||||
return _f;
|
||||
});
|
||||
} else if (topLevel || path.extname(source) === '.coffee') {
|
||||
fs.readFile(source, function(err, code) {
|
||||
return compileScript(source, code.toString(), base);
|
||||
});
|
||||
if (options.watch) {
|
||||
return watch(source, base);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
return compile(source, true);
|
||||
})());
|
||||
})();
|
||||
}
|
||||
return _b;
|
||||
};
|
||||
compileScript = function(source, code, base) {
|
||||
var codeOpts, js, o;
|
||||
o = options;
|
||||
codeOpts = compileOptions(source);
|
||||
try {
|
||||
if (o.tokens) {
|
||||
return printTokens(CoffeeScript.tokens(code));
|
||||
} else if (o.nodes) {
|
||||
return puts(CoffeeScript.nodes(code).toString());
|
||||
} else if (o.run) {
|
||||
return CoffeeScript.run(code, codeOpts);
|
||||
} else {
|
||||
js = CoffeeScript.compile(code, codeOpts);
|
||||
if (o.print) {
|
||||
return print(js);
|
||||
} else if (o.compile) {
|
||||
return writeJs(source, js, base);
|
||||
} else if (o.lint) {
|
||||
return lint(js);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
if (!(o.watch)) {
|
||||
error(err.stack) && process.exit(1);
|
||||
}
|
||||
return puts(err.message);
|
||||
}
|
||||
};
|
||||
compileStdio = function() {
|
||||
var code, stdin;
|
||||
code = '';
|
||||
stdin = process.openStdin();
|
||||
stdin.addListener('data', function(buffer) {
|
||||
if (buffer) {
|
||||
return code += buffer.toString();
|
||||
}
|
||||
});
|
||||
return stdin.addListener('end', function() {
|
||||
return compileScript('stdio', code);
|
||||
});
|
||||
};
|
||||
watch = function(source, base) {
|
||||
return fs.watchFile(source, {
|
||||
persistent: true,
|
||||
interval: 500
|
||||
}, function(curr, prev) {
|
||||
if (curr.mtime.getTime() === prev.mtime.getTime()) {
|
||||
return null;
|
||||
}
|
||||
return fs.readFile(source, function(err, code) {
|
||||
return compileScript(source, code.toString(), base);
|
||||
});
|
||||
});
|
||||
};
|
||||
writeJs = function(source, js, base) {
|
||||
var baseDir, compile, dir, filename, jsPath, srcDir;
|
||||
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;
|
||||
jsPath = path.join(dir, filename);
|
||||
compile = function() {
|
||||
return fs.writeFile(jsPath, js, function(err) {
|
||||
if (options.compile && options.watch) {
|
||||
return puts("Compiled " + source);
|
||||
}
|
||||
});
|
||||
};
|
||||
return path.exists(dir, function(exists) {
|
||||
if (exists) {
|
||||
return compile();
|
||||
} else {
|
||||
return exec(("mkdir -p " + dir), compile);
|
||||
}
|
||||
});
|
||||
};
|
||||
lint = function(js) {
|
||||
var jsl, printIt;
|
||||
printIt = function(buffer) {
|
||||
return print(buffer.toString());
|
||||
};
|
||||
jsl = spawn('jsl', ['-nologo', '-stdin']);
|
||||
jsl.stdout.addListener('data', printIt);
|
||||
jsl.stderr.addListener('data', printIt);
|
||||
jsl.stdin.write(js);
|
||||
return jsl.stdin.end();
|
||||
};
|
||||
printTokens = function(tokens) {
|
||||
var _b, _c, _d, _e, _f, 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 + "]";
|
||||
})());
|
||||
}
|
||||
return _b;
|
||||
})();
|
||||
return puts(strings.join(' '));
|
||||
};
|
||||
parseOptions = function() {
|
||||
var o;
|
||||
optionParser = new optparse.OptionParser(SWITCHES, BANNER);
|
||||
o = (options = optionParser.parse(process.argv));
|
||||
options.run = !(o.compile || o.print || o.lint);
|
||||
options.print = !!(o.print || (o.eval || o.stdio && o.compile));
|
||||
sources = options.arguments.slice(2, options.arguments.length);
|
||||
return sources;
|
||||
};
|
||||
compileOptions = function(source) {
|
||||
var o;
|
||||
o = {
|
||||
source: source
|
||||
};
|
||||
o.noWrap = options['no-wrap'];
|
||||
return o;
|
||||
};
|
||||
usage = function() {
|
||||
puts(optionParser.help());
|
||||
return process.exit(0);
|
||||
};
|
||||
version = function() {
|
||||
puts("CoffeeScript version " + CoffeeScript.VERSION);
|
||||
return process.exit(0);
|
||||
};
|
||||
})();
|
||||
@@ -1,198 +0,0 @@
|
||||
(function(){
|
||||
var BANNER, CoffeeScript, SWITCHES, compile_options, compile_script, compile_scripts, compile_stdio, fs, lint, option_parser, options, optparse, parse_options, path, print_tokens, sources, usage, version, watch_scripts, write_js;
|
||||
fs = require('fs');
|
||||
path = require('path');
|
||||
optparse = require('optparse');
|
||||
CoffeeScript = require('coffee-script');
|
||||
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 = {};
|
||||
sources = [];
|
||||
option_parser = null;
|
||||
// The CommandLine handles all of the functionality of the `coffee` utility.
|
||||
exports.run = function run() {
|
||||
var flags, separator;
|
||||
parse_options();
|
||||
if (options.help) {
|
||||
return usage();
|
||||
}
|
||||
if (options.version) {
|
||||
return version();
|
||||
}
|
||||
if (options.interactive) {
|
||||
return require('repl');
|
||||
}
|
||||
if (options.stdio) {
|
||||
return compile_stdio();
|
||||
}
|
||||
if (options.eval) {
|
||||
return compile_script('unknown', sources[0]);
|
||||
}
|
||||
if (!(sources.length)) {
|
||||
return usage();
|
||||
}
|
||||
separator = sources.indexOf('--');
|
||||
flags = [];
|
||||
if (separator >= 0) {
|
||||
flags = sources.slice((separator + 1), sources.length);
|
||||
sources = sources.slice(0, separator);
|
||||
}
|
||||
process.ARGV = flags;
|
||||
if (options.watch) {
|
||||
watch_scripts();
|
||||
}
|
||||
compile_scripts();
|
||||
return this;
|
||||
};
|
||||
// The "--help" usage message.
|
||||
usage = function usage() {
|
||||
puts('\n' + option_parser.help() + '\n');
|
||||
return process.exit(0);
|
||||
};
|
||||
// The "--version" message.
|
||||
version = function version() {
|
||||
puts("CoffeeScript version " + CoffeeScript.VERSION);
|
||||
return process.exit(0);
|
||||
};
|
||||
// Compiles the source CoffeeScript, returning the desired JavaScript, tokens,
|
||||
// or JSLint results.
|
||||
compile_scripts = function compile_scripts() {
|
||||
var _a, _b, _c, _d, compile, source;
|
||||
compile = function compile(source) {
|
||||
return path.exists(source, function(exists) {
|
||||
if (!(exists)) {
|
||||
throw new Error('File not found: ' + source);
|
||||
}
|
||||
return fs.readFile(source, function(err, code) {
|
||||
return compile_script(source, code);
|
||||
});
|
||||
});
|
||||
};
|
||||
_a = []; _b = sources;
|
||||
for (_c = 0, _d = _b.length; _c < _d; _c++) {
|
||||
source = _b[_c];
|
||||
_a.push(compile(source));
|
||||
}
|
||||
return _a;
|
||||
};
|
||||
// Compile a single source script, containing the given code, according to the
|
||||
// requested options. Both compile_scripts and watch_scripts share this method.
|
||||
compile_script = function compile_script(source, code) {
|
||||
var __dirname, __filename, js, o;
|
||||
o = options;
|
||||
try {
|
||||
if (o.tokens) {
|
||||
return print_tokens(CoffeeScript.tokens(code));
|
||||
} else if (o.nodes) {
|
||||
return puts(CoffeeScript.nodes(code).toString());
|
||||
} else {
|
||||
js = CoffeeScript.compile(code, compile_options());
|
||||
if (o.compile) {
|
||||
return write_js(source, js);
|
||||
} else if (o.lint) {
|
||||
return lint(js);
|
||||
} else if (o.print || o.eval) {
|
||||
return print(js);
|
||||
} else {
|
||||
__filename = source;
|
||||
__dirname = path.dirname(source);
|
||||
return eval(js);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
if (o.watch) {
|
||||
return puts(err.message);
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
};
|
||||
// Listen for and compile scripts over stdio.
|
||||
compile_stdio = function compile_stdio() {
|
||||
var code;
|
||||
code = '';
|
||||
process.stdio.open();
|
||||
process.stdio.addListener('data', function(string) {
|
||||
if (string) {
|
||||
return code += string;
|
||||
}
|
||||
});
|
||||
return process.stdio.addListener('close', function() {
|
||||
return process.stdio.write(CoffeeScript.compile(code, compile_options()));
|
||||
});
|
||||
};
|
||||
// Watch a list of source CoffeeScript files, recompiling them every time the
|
||||
// files are updated.
|
||||
watch_scripts = function watch_scripts() {
|
||||
var _a, _b, _c, _d, source, watch;
|
||||
watch = function watch(source) {
|
||||
return fs.watchFile(source, {
|
||||
persistent: true,
|
||||
interval: 500
|
||||
}, function(curr, prev) {
|
||||
if (curr.mtime.getTime() === prev.mtime.getTime()) {
|
||||
return null;
|
||||
}
|
||||
return fs.readFile(source, function(err, code) {
|
||||
return compile_script(source, code);
|
||||
});
|
||||
});
|
||||
};
|
||||
_a = []; _b = sources;
|
||||
for (_c = 0, _d = _b.length; _c < _d; _c++) {
|
||||
source = _b[_c];
|
||||
_a.push(watch(source));
|
||||
}
|
||||
return _a;
|
||||
};
|
||||
// Write out a JavaScript source file with the compiled code.
|
||||
write_js = function write_js(source, js) {
|
||||
var dir, filename, js_path;
|
||||
filename = path.basename(source, path.extname(source)) + '.js';
|
||||
dir = options.output || path.dirname(source);
|
||||
js_path = path.join(dir, filename);
|
||||
return fs.writeFile(js_path, js);
|
||||
};
|
||||
// Pipe compiled JS through JSLint (requires a working 'jsl' command).
|
||||
lint = function lint(js) {
|
||||
var jsl;
|
||||
jsl = process.createChildProcess('jsl', ['-nologo', '-stdin']);
|
||||
jsl.addListener('output', function(result) {
|
||||
if (result) {
|
||||
return puts(result.replace(/\n/g, ''));
|
||||
}
|
||||
});
|
||||
jsl.addListener('error', function(result) {
|
||||
if (result) {
|
||||
return puts(result);
|
||||
}
|
||||
});
|
||||
jsl.write(js);
|
||||
return jsl.close();
|
||||
};
|
||||
// Pretty-print a token stream.
|
||||
print_tokens = function print_tokens(tokens) {
|
||||
var _a, _b, _c, _d, strings, token;
|
||||
strings = (function() {
|
||||
_a = []; _b = tokens;
|
||||
for (_c = 0, _d = _b.length; _c < _d; _c++) {
|
||||
token = _b[_c];
|
||||
_a.push('[' + token[0] + ' ' + token[1].toString().replace(/\n/, '\\n') + ']');
|
||||
}
|
||||
return _a;
|
||||
}).call(this);
|
||||
return puts(strings.join(' '));
|
||||
};
|
||||
// Use OptionParser for all the options.
|
||||
parse_options = function parse_options() {
|
||||
option_parser = new optparse.OptionParser(SWITCHES, BANNER);
|
||||
options = option_parser.parse(process.ARGV);
|
||||
return sources = options.arguments.slice(2, options.arguments.length);
|
||||
};
|
||||
// The options to pass to the CoffeeScript compiler.
|
||||
compile_options = function compile_options() {
|
||||
return options['no-wrap'] ? {
|
||||
no_wrap: true
|
||||
} : {};
|
||||
};
|
||||
})();
|
||||
894
lib/grammar.js
894
lib/grammar.js
@@ -1,76 +1,64 @@
|
||||
(function(){
|
||||
var Parser, _a, _b, _c, _d, _e, _f, _g, _h, bnf, grammar, name, non_terminal, o, operators, option, part, tokens, unwrap;
|
||||
var Parser, _a, _b, _c, _d, _e, _f, _g, _h, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
Parser = require('jison').Parser;
|
||||
// DSL ===================================================================
|
||||
// Detect functions: [
|
||||
unwrap = /function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/;
|
||||
// Quickie DSL for Jison access.
|
||||
o = function o(pattern_string, func, options) {
|
||||
o = function(patternString, action, options) {
|
||||
var match;
|
||||
if (func) {
|
||||
func = (match = (func + "").match(unwrap)) ? match[1] : '(' + func + '())';
|
||||
return [pattern_string, '$$ = ' + func + ';', options];
|
||||
} else {
|
||||
return [pattern_string, '$$ = $1;', options];
|
||||
if (!(action)) {
|
||||
return [patternString, '$$ = $1;', options];
|
||||
}
|
||||
action = (match = (action + '').match(unwrap)) ? match[1] : ("(" + action + "())");
|
||||
return [patternString, ("$$ = " + action + ";"), options];
|
||||
};
|
||||
// Precedence ===========================================================
|
||||
operators = [["left", '?'], ["nonassoc", 'UMINUS', 'UPLUS', 'NOT', '!', '!!', '~', '++', '--'], ["left", '*', '/', '%'], ["left", '+', '-'], ["left", '<<', '>>', '>>>'], ["left", '&', '|', '^'], ["left", '<=', '<', '>', '>='], ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'], ["right", '==', '!=', 'IS', 'ISNT'], ["left", '&&', '||', 'AND', 'OR'], ["right", '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?='], ["left", '.'], ["right", 'INDENT'], ["left", 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY', 'THROW'], ["right", 'FOR', 'NEW', 'SUPER', 'CLASS'], ["left", 'EXTENDS'], ["right", 'ASSIGN', 'RETURN'], ["right", '->', '=>', 'UNLESS', 'IF', 'ELSE', 'WHILE']];
|
||||
// Grammar ==============================================================
|
||||
grammar = {
|
||||
// All parsing will end in this rule, being the trunk of the AST.
|
||||
Root: [o("", function() {
|
||||
Root: [
|
||||
o("", function() {
|
||||
return new Expressions();
|
||||
}), o("TERMINATOR", function() {
|
||||
return new Expressions();
|
||||
}), o("Expressions", function() {
|
||||
return $1;
|
||||
}), o("Block TERMINATOR", function() {
|
||||
return $1;
|
||||
})
|
||||
}), o("Body"), o("Block TERMINATOR")
|
||||
],
|
||||
// Any list of expressions or method body, seperated by line breaks or semis.
|
||||
Expressions: [o("Expression", function() {
|
||||
Body: [
|
||||
o("Line", function() {
|
||||
return Expressions.wrap([$1]);
|
||||
}), o("Expressions TERMINATOR Expression", function() {
|
||||
}), o("Body TERMINATOR Line", function() {
|
||||
return $1.push($3);
|
||||
}), o("Expressions TERMINATOR", function() {
|
||||
return $1;
|
||||
}), o("Body TERMINATOR")
|
||||
],
|
||||
Line: [o("Expression"), o("Statement")],
|
||||
Statement: [
|
||||
o("Return"), o("Throw"), o("BREAK", function() {
|
||||
return new LiteralNode($1);
|
||||
}), o("CONTINUE", function() {
|
||||
return new LiteralNode($1);
|
||||
})
|
||||
],
|
||||
// All types of expressions in our language. The basic unit of CoffeeScript
|
||||
// is the expression.
|
||||
Expression: [o("Value"), o("Call"), o("Code"), o("Operation"), o("Assign"), o("If"), o("Try"), o("Throw"), o("Return"), o("While"), o("For"), o("Switch"), o("Extends"), o("Class"), o("Splat"), o("Existence"), o("Comment")],
|
||||
// A block of expressions. Note that the Rewriter will convert some postfix
|
||||
// forms into blocks for us, by altering the token stream.
|
||||
Block: [o("INDENT Expressions OUTDENT", function() {
|
||||
Expression: [o("Value"), o("Call"), o("Code"), o("Operation"), o("Assign"), o("If"), o("Try"), o("While"), o("For"), o("Switch"), o("Extends"), o("Class"), o("Splat"), o("Existence")],
|
||||
Block: [
|
||||
o("INDENT Body OUTDENT", function() {
|
||||
return $2;
|
||||
}), o("INDENT OUTDENT", function() {
|
||||
return new Expressions();
|
||||
})
|
||||
],
|
||||
Identifier: [o("IDENTIFIER", function() {
|
||||
return new LiteralNode(yytext);
|
||||
Identifier: [
|
||||
o("IDENTIFIER", function() {
|
||||
return new LiteralNode($1);
|
||||
})
|
||||
],
|
||||
AlphaNumeric: [o("NUMBER", function() {
|
||||
return new LiteralNode(yytext);
|
||||
AlphaNumeric: [
|
||||
o("NUMBER", function() {
|
||||
return new LiteralNode($1);
|
||||
}), o("STRING", function() {
|
||||
return new LiteralNode(yytext);
|
||||
return new LiteralNode($1);
|
||||
})
|
||||
],
|
||||
// All hard-coded values. These can be printed straight to JavaScript.
|
||||
Literal: [o("AlphaNumeric", function() {
|
||||
return $1;
|
||||
}), o("JS", function() {
|
||||
return new LiteralNode(yytext);
|
||||
Literal: [
|
||||
o("AlphaNumeric"), o("JS", function() {
|
||||
return new LiteralNode($1);
|
||||
}), o("REGEX", function() {
|
||||
return new LiteralNode(yytext);
|
||||
}), o("BREAK", function() {
|
||||
return new LiteralNode(yytext);
|
||||
}), o("CONTINUE", function() {
|
||||
return new LiteralNode(yytext);
|
||||
return new LiteralNode($1);
|
||||
}), o("TRUE", function() {
|
||||
return new LiteralNode(true);
|
||||
}), o("FALSE", function() {
|
||||
@@ -85,34 +73,430 @@
|
||||
return new LiteralNode(false);
|
||||
})
|
||||
],
|
||||
// Assignment to a variable (or index).
|
||||
Assign: [o("Value ASSIGN Expression", function() {
|
||||
Assign: [
|
||||
o("Assignable ASSIGN Expression", function() {
|
||||
return new AssignNode($1, $3);
|
||||
})
|
||||
],
|
||||
// Assignment within an object literal (can be quoted).
|
||||
AssignObj: [o("Identifier ASSIGN Expression", function() {
|
||||
AssignObj: [
|
||||
o("Identifier", function() {
|
||||
return new ValueNode($1);
|
||||
}), o("AlphaNumeric"), o("Identifier ASSIGN Expression", function() {
|
||||
return new AssignNode(new ValueNode($1), $3, 'object');
|
||||
}), o("AlphaNumeric ASSIGN Expression", function() {
|
||||
return new AssignNode(new ValueNode($1), $3, 'object');
|
||||
}), o("Comment")
|
||||
})
|
||||
],
|
||||
// A return statement.
|
||||
Return: [o("RETURN Expression", function() {
|
||||
Return: [
|
||||
o("RETURN Expression", function() {
|
||||
return new ReturnNode($2);
|
||||
}), o("RETURN", function() {
|
||||
return new ReturnNode(new ValueNode(new LiteralNode('null')));
|
||||
})
|
||||
],
|
||||
// A comment.
|
||||
Comment: [o("COMMENT", function() {
|
||||
return new CommentNode(yytext);
|
||||
Existence: [
|
||||
o("Expression ?", function() {
|
||||
return new ExistenceNode($1);
|
||||
})
|
||||
],
|
||||
// Arithmetic and logical operators
|
||||
// For Ruby's Operator precedence, see: [
|
||||
// https://www.cs.auckland.ac.nz/references/ruby/ProgrammingRuby/language.html
|
||||
Operation: [o("! Expression", function() {
|
||||
Code: [
|
||||
o("PARAM_START ParamList PARAM_END FuncGlyph Block", function() {
|
||||
return new CodeNode($2, $5, $4);
|
||||
}), o("FuncGlyph Block", function() {
|
||||
return new CodeNode([], $2, $1);
|
||||
})
|
||||
],
|
||||
FuncGlyph: [
|
||||
o("->", function() {
|
||||
return 'func';
|
||||
}), o("=>", function() {
|
||||
return 'boundfunc';
|
||||
})
|
||||
],
|
||||
OptComma: [o(''), o(',')],
|
||||
ParamList: [
|
||||
o("", function() {
|
||||
return [];
|
||||
}), o("Param", function() {
|
||||
return [$1];
|
||||
}), o("ParamList , Param", function() {
|
||||
return $1.concat([$3]);
|
||||
})
|
||||
],
|
||||
Param: [
|
||||
o("PARAM", function() {
|
||||
return new LiteralNode($1);
|
||||
}), o("Param . . .", function() {
|
||||
return new SplatNode($1);
|
||||
})
|
||||
],
|
||||
Splat: [
|
||||
o("Expression . . .", function() {
|
||||
return new SplatNode($1);
|
||||
})
|
||||
],
|
||||
SimpleAssignable: [
|
||||
o("Identifier", function() {
|
||||
return new ValueNode($1);
|
||||
}), o("Value Accessor", function() {
|
||||
return $1.push($2);
|
||||
}), o("Invocation Accessor", function() {
|
||||
return new ValueNode($1, [$2]);
|
||||
}), o("ThisProperty")
|
||||
],
|
||||
Assignable: [
|
||||
o("SimpleAssignable"), o("Array", function() {
|
||||
return new ValueNode($1);
|
||||
}), o("Object", function() {
|
||||
return new ValueNode($1);
|
||||
})
|
||||
],
|
||||
Value: [
|
||||
o("Assignable"), o("Literal", function() {
|
||||
return new ValueNode($1);
|
||||
}), o("Parenthetical", function() {
|
||||
return new ValueNode($1);
|
||||
}), o("Range", function() {
|
||||
return new ValueNode($1);
|
||||
}), o("This"), o("NULL", function() {
|
||||
return new ValueNode(new LiteralNode('null'));
|
||||
})
|
||||
],
|
||||
Accessor: [
|
||||
o("PROPERTY_ACCESS Identifier", function() {
|
||||
return new AccessorNode($2);
|
||||
}), o("PROTOTYPE_ACCESS Identifier", function() {
|
||||
return new AccessorNode($2, 'prototype');
|
||||
}), o("::", function() {
|
||||
return new AccessorNode(new LiteralNode('prototype'));
|
||||
}), o("SOAK_ACCESS Identifier", function() {
|
||||
return new AccessorNode($2, 'soak');
|
||||
}), o("Index"), o("Slice", function() {
|
||||
return new SliceNode($1);
|
||||
})
|
||||
],
|
||||
Index: [
|
||||
o("INDEX_START Expression INDEX_END", function() {
|
||||
return new IndexNode($2);
|
||||
}), o("INDEX_SOAK Index", function() {
|
||||
$2.soakNode = true;
|
||||
return $2;
|
||||
}), o("INDEX_PROTO Index", function() {
|
||||
$2.proto = true;
|
||||
return $2;
|
||||
})
|
||||
],
|
||||
Object: [
|
||||
o("{ AssignList OptComma }", function() {
|
||||
return new ObjectNode($2);
|
||||
})
|
||||
],
|
||||
AssignList: [
|
||||
o("", function() {
|
||||
return [];
|
||||
}), o("AssignObj", function() {
|
||||
return [$1];
|
||||
}), o("AssignList , AssignObj", function() {
|
||||
return $1.concat([$3]);
|
||||
}), o("AssignList OptComma TERMINATOR AssignObj", function() {
|
||||
return $1.concat([$4]);
|
||||
}), o("AssignList OptComma INDENT AssignList OptComma OUTDENT", function() {
|
||||
return $1.concat($4);
|
||||
})
|
||||
],
|
||||
Class: [
|
||||
o("CLASS SimpleAssignable", function() {
|
||||
return new ClassNode($2);
|
||||
}), o("CLASS SimpleAssignable EXTENDS Value", function() {
|
||||
return new ClassNode($2, $4);
|
||||
}), o("CLASS SimpleAssignable INDENT ClassBody OUTDENT", function() {
|
||||
return new ClassNode($2, null, $4);
|
||||
}), o("CLASS SimpleAssignable EXTENDS Value INDENT ClassBody OUTDENT", function() {
|
||||
return new ClassNode($2, $4, $6);
|
||||
})
|
||||
],
|
||||
ClassAssign: [
|
||||
o("AssignObj", function() {
|
||||
return $1;
|
||||
}), o("ThisProperty ASSIGN Expression", function() {
|
||||
return new AssignNode(new ValueNode($1), $3, 'this');
|
||||
})
|
||||
],
|
||||
ClassBody: [
|
||||
o("", function() {
|
||||
return [];
|
||||
}), o("ClassAssign", function() {
|
||||
return [$1];
|
||||
}), o("ClassBody TERMINATOR ClassAssign", function() {
|
||||
return $1.concat($3);
|
||||
})
|
||||
],
|
||||
Call: [
|
||||
o("Invocation"), o("NEW Invocation", function() {
|
||||
return $2.newInstance();
|
||||
}), o("Super")
|
||||
],
|
||||
Extends: [
|
||||
o("SimpleAssignable EXTENDS Value", function() {
|
||||
return new ExtendsNode($1, $3);
|
||||
})
|
||||
],
|
||||
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 Arguments", function() {
|
||||
return new CallNode('super', $2);
|
||||
})
|
||||
],
|
||||
This: [
|
||||
o("THIS", function() {
|
||||
return new ValueNode(new LiteralNode('this'));
|
||||
}), o("@", function() {
|
||||
return new ValueNode(new LiteralNode('this'));
|
||||
})
|
||||
],
|
||||
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);
|
||||
})
|
||||
],
|
||||
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);
|
||||
})
|
||||
],
|
||||
Array: [
|
||||
o("[ ArgList OptComma ]", function() {
|
||||
return new ArrayNode($2);
|
||||
})
|
||||
],
|
||||
ArgList: [
|
||||
o("", function() {
|
||||
return [];
|
||||
}), o("Expression", function() {
|
||||
return [$1];
|
||||
}), o("ArgList , Expression", function() {
|
||||
return $1.concat([$3]);
|
||||
}), o("ArgList OptComma TERMINATOR Expression", function() {
|
||||
return $1.concat([$4]);
|
||||
}), o("ArgList OptComma INDENT ArgList OptComma OUTDENT", function() {
|
||||
return $1.concat($4);
|
||||
})
|
||||
],
|
||||
SimpleArgs: [
|
||||
o("Expression"), o("SimpleArgs , Expression", function() {
|
||||
if ($1 instanceof Array) {
|
||||
return $1.concat([$3]);
|
||||
} else {
|
||||
return [$1].concat([$3]);
|
||||
}
|
||||
})
|
||||
],
|
||||
Try: [
|
||||
o("TRY Block Catch", function() {
|
||||
return new TryNode($2, $3[0], $3[1]);
|
||||
}), o("TRY Block FINALLY Block", function() {
|
||||
return new TryNode($2, null, null, $4);
|
||||
}), o("TRY Block Catch FINALLY Block", function() {
|
||||
return new TryNode($2, $3[0], $3[1], $5);
|
||||
})
|
||||
],
|
||||
Catch: [
|
||||
o("CATCH Identifier Block", function() {
|
||||
return [$2, $3];
|
||||
})
|
||||
],
|
||||
Throw: [
|
||||
o("THROW Expression", function() {
|
||||
return new ThrowNode($2);
|
||||
})
|
||||
],
|
||||
Parenthetical: [
|
||||
o("( Line )", function() {
|
||||
return new ParentheticalNode($2);
|
||||
})
|
||||
],
|
||||
WhileSource: [
|
||||
o("WHILE Expression", function() {
|
||||
return new WhileNode($2);
|
||||
}), o("WHILE Expression WHEN Expression", function() {
|
||||
return new WhileNode($2, {
|
||||
guard: $4
|
||||
});
|
||||
}), o("UNTIL Expression", function() {
|
||||
return new WhileNode($2, {
|
||||
invert: true
|
||||
});
|
||||
}), o("UNTIL Expression WHEN Expression", function() {
|
||||
return new WhileNode($2, {
|
||||
invert: true,
|
||||
guard: $4
|
||||
});
|
||||
})
|
||||
],
|
||||
While: [
|
||||
o("WhileSource Block", function() {
|
||||
return $1.addBody($2);
|
||||
}), o("Statement WhileSource", function() {
|
||||
return $2.addBody(Expressions.wrap([$1]));
|
||||
}), o("Expression WhileSource", function() {
|
||||
return $2.addBody(Expressions.wrap([$1]));
|
||||
}), o("Loop", function() {
|
||||
return $1;
|
||||
})
|
||||
],
|
||||
Loop: [
|
||||
o("LOOP Block", function() {
|
||||
return new WhileNode(new LiteralNode('true')).addBody($2);
|
||||
}), o("LOOP Expression", function() {
|
||||
return new WhileNode(new LiteralNode('true')).addBody(Expressions.wrap([$2]));
|
||||
})
|
||||
],
|
||||
For: [
|
||||
o("Statement FOR ForVariables ForSource", function() {
|
||||
return new ForNode($1, $4, $3[0], $3[1]);
|
||||
}), o("Expression FOR ForVariables ForSource", function() {
|
||||
return new ForNode($1, $4, $3[0], $3[1]);
|
||||
}), o("FOR ForVariables ForSource Block", function() {
|
||||
return new ForNode($4, $3, $2[0], $2[1]);
|
||||
})
|
||||
],
|
||||
ForValue: [
|
||||
o("Identifier"), o("Array", function() {
|
||||
return new ValueNode($1);
|
||||
}), o("Object", function() {
|
||||
return new ValueNode($1);
|
||||
})
|
||||
],
|
||||
ForVariables: [
|
||||
o("ForValue", function() {
|
||||
return [$1];
|
||||
}), o("ForValue , ForValue", function() {
|
||||
return [$1, $3];
|
||||
})
|
||||
],
|
||||
ForSource: [
|
||||
o("IN Expression", function() {
|
||||
return {
|
||||
source: $2
|
||||
};
|
||||
}), o("OF Expression", function() {
|
||||
return {
|
||||
source: $2,
|
||||
object: true
|
||||
};
|
||||
}), o("IN Expression WHEN Expression", function() {
|
||||
return {
|
||||
source: $2,
|
||||
guard: $4
|
||||
};
|
||||
}), o("OF Expression WHEN Expression", function() {
|
||||
return {
|
||||
source: $2,
|
||||
guard: $4,
|
||||
object: true
|
||||
};
|
||||
}), o("IN Expression BY Expression", function() {
|
||||
return {
|
||||
source: $2,
|
||||
step: $4
|
||||
};
|
||||
}), o("IN Expression WHEN Expression BY Expression", function() {
|
||||
return {
|
||||
source: $2,
|
||||
guard: $4,
|
||||
step: $6
|
||||
};
|
||||
}), o("IN Expression BY Expression WHEN Expression", function() {
|
||||
return {
|
||||
source: $2,
|
||||
step: $4,
|
||||
guard: $6
|
||||
};
|
||||
})
|
||||
],
|
||||
Switch: [
|
||||
o("SWITCH Expression INDENT Whens OUTDENT", function() {
|
||||
return $4.switchesOver($2);
|
||||
}), o("SWITCH Expression INDENT Whens ELSE Block OUTDENT", function() {
|
||||
return $4.switchesOver($2).addElse($6, true);
|
||||
}), o("SWITCH INDENT Whens OUTDENT", function() {
|
||||
return $3;
|
||||
}), o("SWITCH INDENT Whens ELSE Block OUTDENT", function() {
|
||||
return $3.addElse($5, true);
|
||||
})
|
||||
],
|
||||
Whens: [
|
||||
o("When"), o("Whens When", function() {
|
||||
return $1.addElse($2);
|
||||
})
|
||||
],
|
||||
When: [
|
||||
o("LEADING_WHEN SimpleArgs Block", function() {
|
||||
return new IfNode($2, $3, {
|
||||
statement: true
|
||||
});
|
||||
}), o("LEADING_WHEN SimpleArgs Block TERMINATOR", function() {
|
||||
return new IfNode($2, $3, {
|
||||
statement: true
|
||||
});
|
||||
})
|
||||
],
|
||||
IfBlock: [
|
||||
o("IF Expression Block", function() {
|
||||
return new IfNode($2, $3);
|
||||
}), o("UNLESS Expression Block", function() {
|
||||
return new IfNode($2, $3, {
|
||||
invert: true
|
||||
});
|
||||
}), o("IfBlock ELSE IF Expression Block", function() {
|
||||
return $1.addElse((new IfNode($4, $5)).forceStatement());
|
||||
}), o("IfBlock ELSE Block", function() {
|
||||
return $1.addElse($3);
|
||||
})
|
||||
],
|
||||
If: [
|
||||
o("IfBlock"), o("Statement IF Expression", function() {
|
||||
return new IfNode($3, Expressions.wrap([$1]), {
|
||||
statement: true
|
||||
});
|
||||
}), o("Expression IF Expression", function() {
|
||||
return new IfNode($3, Expressions.wrap([$1]), {
|
||||
statement: true
|
||||
});
|
||||
}), o("Statement UNLESS Expression", function() {
|
||||
return new IfNode($3, Expressions.wrap([$1]), {
|
||||
statement: true,
|
||||
invert: true
|
||||
});
|
||||
}), o("Expression UNLESS Expression", function() {
|
||||
return new IfNode($3, Expressions.wrap([$1]), {
|
||||
statement: true,
|
||||
invert: true
|
||||
});
|
||||
})
|
||||
],
|
||||
Operation: [
|
||||
o("! Expression", function() {
|
||||
return new OpNode('!', $2);
|
||||
}), o("!! Expression", function() {
|
||||
return new OpNode('!!', $2);
|
||||
@@ -124,8 +508,6 @@
|
||||
return new OpNode('+', $2);
|
||||
}), {
|
||||
prec: 'UPLUS'
|
||||
}), o("NOT Expression", function() {
|
||||
return new OpNode('not', $2);
|
||||
}), o("~ Expression", function() {
|
||||
return new OpNode('~', $2);
|
||||
}), o("-- Expression", function() {
|
||||
@@ -174,18 +556,10 @@
|
||||
return new OpNode('==', $1, $3);
|
||||
}), o("Expression != Expression", function() {
|
||||
return new OpNode('!=', $1, $3);
|
||||
}), o("Expression IS Expression", function() {
|
||||
return new OpNode('is', $1, $3);
|
||||
}), o("Expression ISNT Expression", function() {
|
||||
return new OpNode('isnt', $1, $3);
|
||||
}), o("Expression && Expression", function() {
|
||||
return new OpNode('&&', $1, $3);
|
||||
}), o("Expression || Expression", function() {
|
||||
return new OpNode('||', $1, $3);
|
||||
}), o("Expression AND Expression", function() {
|
||||
return new OpNode('and', $1, $3);
|
||||
}), o("Expression OR Expression", function() {
|
||||
return new OpNode('or', $1, $3);
|
||||
}), o("Expression ? Expression", function() {
|
||||
return new OpNode('?', $1, $3);
|
||||
}), o("Expression -= Expression", function() {
|
||||
@@ -207,374 +581,46 @@
|
||||
}), o("Expression INSTANCEOF Expression", function() {
|
||||
return new OpNode('instanceof', $1, $3);
|
||||
}), o("Expression IN Expression", function() {
|
||||
return new InNode($1, $3);
|
||||
}), o("Expression OF Expression", function() {
|
||||
return new OpNode('in', $1, $3);
|
||||
})
|
||||
],
|
||||
// The existence operator.
|
||||
Existence: [o("Expression ?", function() {
|
||||
return new ExistenceNode($1);
|
||||
})
|
||||
],
|
||||
// Function definition.
|
||||
Code: [o("PARAM_START ParamList PARAM_END FuncGlyph Block", function() {
|
||||
return new CodeNode($2, $5, $4);
|
||||
}), o("FuncGlyph Block", function() {
|
||||
return new CodeNode([], $2, $1);
|
||||
})
|
||||
],
|
||||
// The symbols to signify functions, and bound functions.
|
||||
FuncGlyph: [o("->", function() {
|
||||
return 'func';
|
||||
}), o("=>", function() {
|
||||
return 'boundfunc';
|
||||
})
|
||||
],
|
||||
// The parameters to a function definition.
|
||||
ParamList: [o("", function() {
|
||||
return [];
|
||||
}), o("Param", function() {
|
||||
return [$1];
|
||||
}), o("ParamList , Param", function() {
|
||||
return $1.concat([$3]);
|
||||
})
|
||||
],
|
||||
// A Parameter (or ParamSplat) in a function definition.
|
||||
Param: [o("PARAM", function() {
|
||||
return new LiteralNode(yytext);
|
||||
}), o("Param . . .", function() {
|
||||
return new SplatNode($1);
|
||||
})
|
||||
],
|
||||
// A regular splat.
|
||||
Splat: [o("Expression . . .", function() {
|
||||
return new SplatNode($1);
|
||||
})
|
||||
],
|
||||
// Expressions that can be treated as values.
|
||||
Value: [o("Identifier", function() {
|
||||
return new ValueNode($1);
|
||||
}), o("Literal", function() {
|
||||
return new ValueNode($1);
|
||||
}), o("Array", function() {
|
||||
return new ValueNode($1);
|
||||
}), o("Object", function() {
|
||||
return new ValueNode($1);
|
||||
}), o("Parenthetical", function() {
|
||||
return new ValueNode($1);
|
||||
}), o("Range", function() {
|
||||
return new ValueNode($1);
|
||||
}), o("This", function() {
|
||||
return $1;
|
||||
}), o("Value Accessor", function() {
|
||||
return $1.push($2);
|
||||
}), o("Invocation Accessor", function() {
|
||||
return new ValueNode($1, [$2]);
|
||||
})
|
||||
],
|
||||
// Accessing into an object or array, through dot or index notation.
|
||||
Accessor: [o("PROPERTY_ACCESS Identifier", function() {
|
||||
return new AccessorNode($2);
|
||||
}), o("PROTOTYPE_ACCESS Identifier", function() {
|
||||
return new AccessorNode($2, 'prototype');
|
||||
}), o("SOAK_ACCESS Identifier", function() {
|
||||
return new AccessorNode($2, 'soak');
|
||||
}), o("Index"), o("Slice", function() {
|
||||
return new SliceNode($1);
|
||||
})
|
||||
],
|
||||
// Indexing into an object or array.
|
||||
Index: [o("INDEX_START Expression INDEX_END", function() {
|
||||
return new IndexNode($2);
|
||||
}), o("SOAKED_INDEX_START Expression SOAKED_INDEX_END", function() {
|
||||
return new IndexNode($2, 'soak');
|
||||
})
|
||||
],
|
||||
// An object literal.
|
||||
Object: [o("{ AssignList }", function() {
|
||||
return new ObjectNode($2);
|
||||
}), o("{ IndentedAssignList }", function() {
|
||||
return new ObjectNode($2);
|
||||
})
|
||||
],
|
||||
// A class literal.
|
||||
Class: [o("CLASS Value", function() {
|
||||
return new ClassNode($2);
|
||||
}), o("CLASS Value EXTENDS Value", function() {
|
||||
return new ClassNode($2, $4);
|
||||
}), o("CLASS Value IndentedAssignList", function() {
|
||||
return new ClassNode($2, null, $3);
|
||||
}), o("CLASS Value EXTENDS Value IndentedAssignList", function() {
|
||||
return new ClassNode($2, $4, $5);
|
||||
})
|
||||
],
|
||||
// Assignment within an object literal (comma or newline separated).
|
||||
AssignList: [o("", function() {
|
||||
return [];
|
||||
}), o("AssignObj", function() {
|
||||
return [$1];
|
||||
}), o("AssignList , AssignObj", function() {
|
||||
return $1.concat([$3]);
|
||||
}), o("AssignList TERMINATOR AssignObj", function() {
|
||||
return $1.concat([$3]);
|
||||
}), o("AssignList , TERMINATOR AssignObj", function() {
|
||||
return $1.concat([$4]);
|
||||
})
|
||||
],
|
||||
// A list of assignments in a block indentation.
|
||||
IndentedAssignList: [o("INDENT AssignList OUTDENT", function() {
|
||||
return $2;
|
||||
})
|
||||
],
|
||||
// All flavors of function call (instantiation, super, and regular).
|
||||
Call: [o("Invocation", function() {
|
||||
return $1;
|
||||
}), o("NEW Invocation", function() {
|
||||
return $2.new_instance();
|
||||
}), o("Super", function() {
|
||||
return $1;
|
||||
})
|
||||
],
|
||||
// Extending an object's prototype.
|
||||
Extends: [o("Value EXTENDS Value", function() {
|
||||
return new ExtendsNode($1, $3);
|
||||
})
|
||||
],
|
||||
// A generic function invocation.
|
||||
Invocation: [o("Value Arguments", function() {
|
||||
return new CallNode($1, $2);
|
||||
}), o("Invocation Arguments", function() {
|
||||
return new CallNode($1, $2);
|
||||
})
|
||||
],
|
||||
// The list of arguments to a function invocation.
|
||||
Arguments: [o("CALL_START ArgList CALL_END", function() {
|
||||
return $2;
|
||||
})
|
||||
],
|
||||
// Calling super.
|
||||
Super: [o("SUPER CALL_START ArgList CALL_END", function() {
|
||||
return new CallNode('super', $3);
|
||||
})
|
||||
],
|
||||
// This references, either naked or to a property.
|
||||
This: [o("@", function() {
|
||||
return new ValueNode(new LiteralNode('this'));
|
||||
}), o("@ Identifier", function() {
|
||||
return new ValueNode(new LiteralNode('this'), [new AccessorNode($2)]);
|
||||
})
|
||||
],
|
||||
// The range literal.
|
||||
Range: [o("[ Expression . . Expression ]", function() {
|
||||
return new RangeNode($2, $5);
|
||||
}), o("[ Expression . . . Expression ]", function() {
|
||||
return new RangeNode($2, $6, true);
|
||||
})
|
||||
],
|
||||
// The slice literal.
|
||||
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);
|
||||
})
|
||||
],
|
||||
// The array literal.
|
||||
Array: [o("[ ArgList ]", function() {
|
||||
return new ArrayNode($2);
|
||||
})
|
||||
],
|
||||
// A list of arguments to a method call, or as the contents of an array.
|
||||
ArgList: [o("", function() {
|
||||
return [];
|
||||
}), o("Expression", function() {
|
||||
return [$1];
|
||||
}), o("INDENT Expression", function() {
|
||||
return [$2];
|
||||
}), o("ArgList , Expression", function() {
|
||||
return $1.concat([$3]);
|
||||
}), o("ArgList TERMINATOR Expression", function() {
|
||||
return $1.concat([$3]);
|
||||
}), o("ArgList , TERMINATOR Expression", function() {
|
||||
return $1.concat([$4]);
|
||||
}), o("ArgList , INDENT Expression", function() {
|
||||
return $1.concat([$4]);
|
||||
}), o("ArgList OUTDENT", function() {
|
||||
return $1;
|
||||
})
|
||||
],
|
||||
// Just simple, comma-separated, required arguments (no fancy syntax).
|
||||
SimpleArgs: [o("Expression", function() {
|
||||
return $1;
|
||||
}), o("SimpleArgs , Expression", function() {
|
||||
return $1 instanceof Array ? $1.concat([$3]) : [$1].concat([$3]);
|
||||
})
|
||||
],
|
||||
// Try/catch/finally exception handling blocks.
|
||||
Try: [o("TRY Block Catch", function() {
|
||||
return new TryNode($2, $3[0], $3[1]);
|
||||
}), o("TRY Block FINALLY Block", function() {
|
||||
return new TryNode($2, null, null, $4);
|
||||
}), o("TRY Block Catch FINALLY Block", function() {
|
||||
return new TryNode($2, $3[0], $3[1], $5);
|
||||
})
|
||||
],
|
||||
// A catch clause.
|
||||
Catch: [o("CATCH Identifier Block", function() {
|
||||
return [$2, $3];
|
||||
})
|
||||
],
|
||||
// Throw an exception.
|
||||
Throw: [o("THROW Expression", function() {
|
||||
return new ThrowNode($2);
|
||||
})
|
||||
],
|
||||
// Parenthetical expressions.
|
||||
Parenthetical: [o("( Expression )", function() {
|
||||
return new ParentheticalNode($2);
|
||||
})
|
||||
],
|
||||
// The condition for a while loop.
|
||||
WhileSource: [o("WHILE Expression", function() {
|
||||
return new WhileNode($2);
|
||||
}), o("WHILE Expression WHEN Expression", function() {
|
||||
return new WhileNode($2, {
|
||||
filter: $4
|
||||
});
|
||||
})
|
||||
],
|
||||
// The while loop. (there is no do..while).
|
||||
While: [o("WhileSource Block", function() {
|
||||
return $1.add_body($2);
|
||||
}), o("Expression WhileSource", function() {
|
||||
return $2.add_body($1);
|
||||
})
|
||||
],
|
||||
// Array comprehensions, including guard and current index.
|
||||
// Looks a little confusing, check nodes.rb for the arguments to ForNode.
|
||||
For: [o("Expression FOR ForVariables ForSource", function() {
|
||||
return new ForNode($1, $4, $3[0], $3[1]);
|
||||
}), o("FOR ForVariables ForSource Block", function() {
|
||||
return new ForNode($4, $3, $2[0], $2[1]);
|
||||
})
|
||||
],
|
||||
// An array comprehension has variables for the current element and index.
|
||||
ForVariables: [o("Identifier", function() {
|
||||
return [$1];
|
||||
}), o("Identifier , Identifier", function() {
|
||||
return [$1, $3];
|
||||
})
|
||||
],
|
||||
// The source of the array comprehension can optionally be filtered.
|
||||
ForSource: [o("IN Expression", function() {
|
||||
return {
|
||||
source: $2
|
||||
};
|
||||
}), o("OF Expression", function() {
|
||||
return {
|
||||
source: $2,
|
||||
object: true
|
||||
};
|
||||
}), o("ForSource WHEN Expression", function() {
|
||||
$1.filter = $3;
|
||||
return $1;
|
||||
}), o("ForSource BY Expression", function() {
|
||||
$1.step = $3;
|
||||
return $1;
|
||||
})
|
||||
],
|
||||
// Switch/When blocks.
|
||||
Switch: [o("SWITCH Expression INDENT Whens OUTDENT", function() {
|
||||
return $4.rewrite_condition($2);
|
||||
}), o("SWITCH Expression INDENT Whens ELSE Block OUTDENT", function() {
|
||||
return $4.rewrite_condition($2).add_else($6, true);
|
||||
})
|
||||
],
|
||||
// The inner list of whens.
|
||||
Whens: [o("When", function() {
|
||||
return $1;
|
||||
}), o("Whens When", function() {
|
||||
return $1.push($2);
|
||||
})
|
||||
],
|
||||
// An individual when.
|
||||
When: [o("LEADING_WHEN SimpleArgs Block", function() {
|
||||
return new IfNode($2, $3, null, {
|
||||
statement: true
|
||||
});
|
||||
}), o("LEADING_WHEN SimpleArgs Block TERMINATOR", function() {
|
||||
return new IfNode($2, $3, null, {
|
||||
statement: true
|
||||
});
|
||||
}), o("Comment TERMINATOR When", function() {
|
||||
$3.comment = $1;
|
||||
return $3;
|
||||
})
|
||||
],
|
||||
// The most basic form of "if".
|
||||
IfStart: [o("IF Expression Block", function() {
|
||||
return new IfNode($2, $3);
|
||||
}), o("IfStart ElsIfs", function() {
|
||||
return $1.add_else($2);
|
||||
})
|
||||
],
|
||||
IfBlock: [o("IfStart", function() {
|
||||
return $1;
|
||||
}), o("IfStart ELSE Block", function() {
|
||||
return $1.add_else($3);
|
||||
})
|
||||
],
|
||||
// Multiple elsifs can be chained together.
|
||||
ElsIfs: [o("ELSE IF Expression Block", function() {
|
||||
return (new IfNode($3, $4)).force_statement();
|
||||
}), o("ElsIfs ElsIf", function() {
|
||||
return $1.add_else($2);
|
||||
})
|
||||
],
|
||||
// The full complement of if blocks, including postfix one-liner ifs and unlesses.
|
||||
If: [o("IfBlock", function() {
|
||||
return $1;
|
||||
}), o("Expression IF Expression", function() {
|
||||
return new IfNode($3, Expressions.wrap([$1]), null, {
|
||||
statement: true
|
||||
});
|
||||
}), o("Expression UNLESS Expression", function() {
|
||||
return new IfNode($3, Expressions.wrap([$1]), null, {
|
||||
statement: true,
|
||||
invert: true
|
||||
});
|
||||
}), 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)));
|
||||
})
|
||||
]
|
||||
};
|
||||
// Helpers ==============================================================
|
||||
// Make the Jison parser.
|
||||
bnf = {};
|
||||
operators = [["left", '?'], ["nonassoc", 'UMINUS', 'UPLUS', '!', '!!', '~', '++', '--'], ["left", '*', '/', '%'], ["left", '+', '-'], ["left", '<<', '>>', '>>>'], ["left", '&', '|', '^'], ["left", '<=', '<', '>', '>='], ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'], ["left", '==', '!='], ["left", '&&', '||'], ["right", '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?='], ["left", '.'], ["right", 'INDENT'], ["left", 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY', 'THROW'], ["right", 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'NEW', 'SUPER', 'CLASS'], ["left", 'EXTENDS'], ["right", 'ASSIGN', 'RETURN'], ["right", '->', '=>', 'UNLESS', 'IF', 'ELSE']];
|
||||
tokens = [];
|
||||
_a = grammar;
|
||||
for (name in _a) { if (__hasProp.call(_a, name)) {
|
||||
non_terminal = _a[name];
|
||||
bnf[name] = (function() {
|
||||
_b = []; _c = non_terminal;
|
||||
for (_d = 0, _e = _c.length; _d < _e; _d++) {
|
||||
option = _c[_d];
|
||||
alternatives = _a[name];
|
||||
grammar[name] = (function() {
|
||||
_b = []; _d = alternatives;
|
||||
for (_c = 0, _e = _d.length; _c < _e; _c++) {
|
||||
alt = _d[_c];
|
||||
_b.push((function() {
|
||||
_f = option[0].split(" ");
|
||||
for (_g = 0, _h = _f.length; _g < _h; _g++) {
|
||||
part = _f[_g];
|
||||
!grammar[part] ? tokens.push(part) : null;
|
||||
_g = alt[0].split(' ');
|
||||
for (_f = 0, _h = _g.length; _f < _h; _f++) {
|
||||
token = _g[_f];
|
||||
if (!(grammar[token])) {
|
||||
tokens.push(token);
|
||||
}
|
||||
}
|
||||
name === "Root" ? (option[1] = "return " + option[1]) : null;
|
||||
return option;
|
||||
}).call(this));
|
||||
if (name === 'Root') {
|
||||
alt[1] = ("return " + (alt[1]));
|
||||
}
|
||||
return alt;
|
||||
})());
|
||||
}
|
||||
return _b;
|
||||
}).call(this);
|
||||
})();
|
||||
}}
|
||||
tokens = tokens.join(" ");
|
||||
exports.parser = new Parser({
|
||||
tokens: tokens,
|
||||
bnf: bnf,
|
||||
tokens: tokens.join(' '),
|
||||
bnf: grammar,
|
||||
operators: operators.reverse(),
|
||||
startSymbol: 'Root'
|
||||
}, {
|
||||
debug: false
|
||||
});
|
||||
})();
|
||||
|
||||
89
lib/helpers.js
Normal file
89
lib/helpers.js
Normal file
@@ -0,0 +1,89 @@
|
||||
(function(){
|
||||
var compact, count, del, extend, flatten, helpers, include, indexOf, merge, starts;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
if (!(typeof process !== "undefined" && process !== null)) {
|
||||
this.exports = this;
|
||||
}
|
||||
helpers = (exports.helpers = {});
|
||||
helpers.indexOf = (indexOf = function(array, item, from) {
|
||||
var _a, _b, index, other;
|
||||
if (array.indexOf) {
|
||||
return array.indexOf(item, from);
|
||||
}
|
||||
_a = array;
|
||||
for (index = 0, _b = _a.length; index < _b; index++) {
|
||||
other = _a[index];
|
||||
if (other === item && (!from || (from <= index))) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
});
|
||||
helpers.include = (include = function(list, value) {
|
||||
return indexOf(list, value) >= 0;
|
||||
});
|
||||
helpers.starts = (starts = function(string, literal, start) {
|
||||
return string.substring(start, (start || 0) + 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;
|
||||
}
|
||||
return _a;
|
||||
});
|
||||
helpers.count = (count = function(string, letter) {
|
||||
var num, pos;
|
||||
num = 0;
|
||||
pos = indexOf(string, letter);
|
||||
while (pos !== -1) {
|
||||
num += 1;
|
||||
pos = indexOf(string, letter, pos + 1);
|
||||
}
|
||||
return num;
|
||||
});
|
||||
helpers.merge = (merge = function(options, overrides) {
|
||||
var _a, _b, fresh, key, val;
|
||||
fresh = {};
|
||||
_a = options;
|
||||
for (key in _a) { if (__hasProp.call(_a, key)) {
|
||||
val = _a[key];
|
||||
(fresh[key] = val);
|
||||
}}
|
||||
if (overrides) {
|
||||
_b = overrides;
|
||||
for (key in _b) { if (__hasProp.call(_b, key)) {
|
||||
val = _b[key];
|
||||
(fresh[key] = val);
|
||||
}}
|
||||
}
|
||||
return fresh;
|
||||
});
|
||||
helpers.extend = (extend = function(object, properties) {
|
||||
var _a, _b, key, val;
|
||||
_a = []; _b = properties;
|
||||
for (key in _b) { if (__hasProp.call(_b, key)) {
|
||||
val = _b[key];
|
||||
_a.push(object[key] = val);
|
||||
}}
|
||||
return _a;
|
||||
});
|
||||
helpers.flatten = (flatten = function(array) {
|
||||
var _a, _b, _c, 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);
|
||||
}
|
||||
return memo;
|
||||
});
|
||||
helpers.del = (del = function(obj, key) {
|
||||
var val;
|
||||
val = obj[key];
|
||||
delete obj[key];
|
||||
return val;
|
||||
});
|
||||
})();
|
||||
9
lib/index.js
Normal file
9
lib/index.js
Normal file
@@ -0,0 +1,9 @@
|
||||
(function(){
|
||||
var _a, key, val;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
_a = require('./coffee-script');
|
||||
for (key in _a) { if (__hasProp.call(_a, key)) {
|
||||
val = _a[key];
|
||||
(exports[key] = val);
|
||||
}}
|
||||
})();
|
||||
706
lib/lexer.js
706
lib/lexer.js
@@ -1,275 +1,265 @@
|
||||
(function(){
|
||||
var ACCESSORS, ASSIGNMENT, BEFORE_WHEN, CALLABLE, CODE, COFFEE_KEYWORDS, COMMENT, COMMENT_CLEANER, HEREDOC, HEREDOC_INDENT, IDENTIFIER, JS, JS_CLEANER, JS_FORBIDDEN, JS_KEYWORDS, KEYWORDS, LAST_DENT, LAST_DENTS, Lexer, MULTILINER, MULTI_DENT, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, RESERVED, Rewriter, STRING, STRING_NEWLINES, WHITESPACE, compact, count, include;
|
||||
// The CoffeeScript Lexer. Uses a series of token-matching regexes to attempt
|
||||
// matches against the beginning of the source code. When a match is found,
|
||||
// a token is produced, we consume the match, and start again. Tokens are in the
|
||||
// form:
|
||||
// [tag, value, line_number]
|
||||
// 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 ((typeof process !== "undefined" && process !== null)) {
|
||||
Rewriter = require('./rewriter').Rewriter;
|
||||
var ASSIGNED, ASSIGNMENT, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_KEYWORDS, COMMENT, CONVERSIONS, HALF_ASSIGNMENTS, 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 __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;
|
||||
}
|
||||
// Constants
|
||||
// ---------
|
||||
// Keywords that CoffeeScript shares in common with JavaScript.
|
||||
JS_KEYWORDS = ["if", "else", "true", "false", "new", "return", "try", "catch", "finally", "throw", "break", "continue", "for", "in", "while", "delete", "instanceof", "typeof", "switch", "super", "extends", "class"];
|
||||
// CoffeeScript-only keywords, which we're more relaxed about allowing. They can't
|
||||
// be used standalone, but you can reference them as an attached property.
|
||||
COFFEE_KEYWORDS = ["then", "unless", "yes", "no", "on", "off", "and", "or", "is", "isnt", "not", "of", "by", "where", "when"];
|
||||
// The combined list of keywords is the superset that gets passed verbatim to
|
||||
// the parser.
|
||||
KEYWORDS = JS_KEYWORDS.concat(COFFEE_KEYWORDS);
|
||||
// The list of keywords that are reserved by JavaScript, but not used, or are
|
||||
// used by CoffeeScript internally. We throw an error when these are encountered,
|
||||
// to avoid having a JavaScript error at runtime.
|
||||
RESERVED = ["case", "default", "do", "function", "var", "void", "with", "const", "let", "debugger", "enum", "export", "import", "native", "__extends", "__hasProp"];
|
||||
// The superset of both JavaScript keywords and reserved words, none of which may
|
||||
// be used as identifiers or properties.
|
||||
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED);
|
||||
// Token matching regexes.
|
||||
IDENTIFIER = /^([a-zA-Z$_](\w|\$)*)/;
|
||||
NUMBER = /^(\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?(e[+\-]?[0-9]+)?)))\b/i;
|
||||
STRING = /^(""|''|"([\s\S]*?)([^\\]|\\\\)"|'([\s\S]*?)([^\\]|\\\\)')/;
|
||||
HEREDOC = /^("{6}|'{6}|"{3}\n?([\s\S]*?)\n?([ \t]*)"{3}|'{3}\n?([\s\S]*?)\n?([ \t]*)'{3})/;
|
||||
JS = /^(``|`([\s\S]*?)([^\\]|\\\\)`)/;
|
||||
OPERATOR = /^([+\*&|\/\-%=<>:!?]+)/;
|
||||
WHITESPACE = /^([ \t]+)/;
|
||||
COMMENT = /^(((\n?[ \t]*)?#[^\n]*)+)/;
|
||||
CODE = /^((-|=)>)/;
|
||||
REGEX = /^(\/(\S.*?)?([^\\]|\\\\)\/[imgy]{0,4})/;
|
||||
MULTI_DENT = /^((\n([ \t]*))+)(\.)?/;
|
||||
LAST_DENTS = /\n([ \t]*)/g;
|
||||
LAST_DENT = /\n([ \t]*)/;
|
||||
ASSIGNMENT = /^(:|=)$/;
|
||||
// Token cleaning regexes.
|
||||
JS_CLEANER = /(^`|`$)/g;
|
||||
MULTILINER = /\n/g;
|
||||
STRING_NEWLINES = /\n[ \t]*/g;
|
||||
COMMENT_CLEANER = /(^[ \t]*#|\n[ \t]*$)/mg;
|
||||
NO_NEWLINE = /^([+\*&|\/\-%=<>:!.\\][<>=&|]*|and|or|is|isnt|not|delete|typeof|instanceof)$/;
|
||||
HEREDOC_INDENT = /^[ \t]+/mg;
|
||||
// Tokens which a regular expression will never immediately follow, but which
|
||||
// a division operator might.
|
||||
// See: http://www.mozilla.org/js/language/js20-2002-04/rationale/syntax.html#regular-expressions
|
||||
// Our list is shorter, due to sans-parentheses method calls.
|
||||
NOT_REGEX = ['NUMBER', 'REGEX', '++', '--', 'FALSE', 'NULL', 'TRUE'];
|
||||
// Tokens which could legitimately be invoked or indexed. A opening
|
||||
// parentheses or bracket following these tokens will be recorded as the start
|
||||
// of a function invocation or indexing operation.
|
||||
CALLABLE = ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING', '@'];
|
||||
// Tokens that indicate an access -- keywords immediately following will be
|
||||
// treated as identifiers.
|
||||
ACCESSORS = ['PROPERTY_ACCESS', 'PROTOTYPE_ACCESS', 'SOAK_ACCESS', '@'];
|
||||
// Tokens that, when immediately preceding a `WHEN`, indicate that the `WHEN`
|
||||
// occurs at the start of a line. We disambiguate these from trailing whens to
|
||||
// avoid an ambiguity in the grammar.
|
||||
BEFORE_WHEN = ['INDENT', 'OUTDENT', 'TERMINATOR'];
|
||||
// The Lexer Class
|
||||
// ---------------
|
||||
// The Lexer class reads a stream of CoffeeScript and divvys it up into tagged
|
||||
// tokens. A minor bit of the ambiguity in the grammar has been avoided by
|
||||
// pushing some extra smarts into the Lexer.
|
||||
_c = helpers;
|
||||
include = _c.include;
|
||||
count = _c.count;
|
||||
starts = _c.starts;
|
||||
compact = _c.compact;
|
||||
exports.Lexer = (function() {
|
||||
Lexer = function Lexer() { };
|
||||
// Scan by attempting to match tokens one at a time. Slow and steady.
|
||||
Lexer.prototype.tokenize = function tokenize(code) {
|
||||
Lexer = function() { };
|
||||
Lexer.prototype.tokenize = function(code, options) {
|
||||
var o;
|
||||
code = code.replace(/(\r|\s+$)/g, '');
|
||||
o = options || {};
|
||||
this.code = code;
|
||||
// The remainder of the source code.
|
||||
this.i = 0;
|
||||
// Current character position we're parsing.
|
||||
this.line = 0;
|
||||
// The current line.
|
||||
this.line = o.line || 0;
|
||||
this.indent = 0;
|
||||
// The current indent level.
|
||||
this.outdebt = 0;
|
||||
this.indents = [];
|
||||
// The stack of all indent levels we are currently within.
|
||||
this.tokens = [];
|
||||
// Collection of all parsed tokens in the form ['TOKEN_TYPE', value, line]
|
||||
while (this.i < this.code.length) {
|
||||
this.chunk = this.code.slice(this.i);
|
||||
this.extract_next_token();
|
||||
this.extractNextToken();
|
||||
}
|
||||
this.closeIndentation();
|
||||
if (o.rewrite === false) {
|
||||
return this.tokens;
|
||||
}
|
||||
this.close_indentation();
|
||||
return (new Rewriter()).rewrite(this.tokens);
|
||||
};
|
||||
// At every position, run through this list of attempted matches,
|
||||
// short-circuiting if any of them succeed.
|
||||
Lexer.prototype.extract_next_token = function extract_next_token() {
|
||||
if (this.identifier_token()) {
|
||||
Lexer.prototype.extractNextToken = function() {
|
||||
if (this.identifierToken()) {
|
||||
return null;
|
||||
}
|
||||
if (this.number_token()) {
|
||||
if (this.commentToken()) {
|
||||
return null;
|
||||
}
|
||||
if (this.heredoc_token()) {
|
||||
if (this.whitespaceToken()) {
|
||||
return null;
|
||||
}
|
||||
if (this.string_token()) {
|
||||
if (this.lineToken()) {
|
||||
return null;
|
||||
}
|
||||
if (this.js_token()) {
|
||||
if (this.heredocToken()) {
|
||||
return null;
|
||||
}
|
||||
if (this.regex_token()) {
|
||||
if (this.stringToken()) {
|
||||
return null;
|
||||
}
|
||||
if (this.comment_token()) {
|
||||
if (this.numberToken()) {
|
||||
return null;
|
||||
}
|
||||
if (this.line_token()) {
|
||||
if (this.regexToken()) {
|
||||
return null;
|
||||
}
|
||||
if (this.whitespace_token()) {
|
||||
if (this.jsToken()) {
|
||||
return null;
|
||||
}
|
||||
return this.literal_token();
|
||||
return this.literalToken();
|
||||
};
|
||||
// Tokenizers
|
||||
// ----------
|
||||
// Matches identifying literals: variables, keywords, method names, etc.
|
||||
Lexer.prototype.identifier_token = function identifier_token() {
|
||||
var id, tag;
|
||||
if (!((id = this.match(IDENTIFIER, 1)))) {
|
||||
Lexer.prototype.identifierToken = function() {
|
||||
var close_index, forcedIdentifier, id, tag;
|
||||
if (!(id = this.match(IDENTIFIER, 1))) {
|
||||
return false;
|
||||
}
|
||||
this.name_access_type();
|
||||
this.i += id.length;
|
||||
forcedIdentifier = this.tagAccessor() || this.match(ASSIGNED, 1);
|
||||
tag = 'IDENTIFIER';
|
||||
if (include(KEYWORDS, id) && !(include(ACCESSORS, this.tag(0)) && !this.prev().spaced)) {
|
||||
if (include(JS_KEYWORDS, id) || (!forcedIdentifier && include(COFFEE_KEYWORDS, id))) {
|
||||
tag = id.toUpperCase();
|
||||
}
|
||||
if (include(RESERVED, id)) {
|
||||
this.identifier_error(id);
|
||||
}
|
||||
if (tag === 'WHEN' && include(BEFORE_WHEN, this.tag())) {
|
||||
if (tag === 'WHEN' && include(LINE_BREAK, this.tag())) {
|
||||
tag = 'LEADING_WHEN';
|
||||
}
|
||||
if (include(JS_FORBIDDEN, id)) {
|
||||
if (forcedIdentifier) {
|
||||
tag = 'STRING';
|
||||
id = ("'" + id + "'");
|
||||
if (forcedIdentifier === 'accessor') {
|
||||
close_index = true;
|
||||
if (this.tag() !== '@') {
|
||||
this.tokens.pop();
|
||||
}
|
||||
this.token('INDEX_START', '[');
|
||||
}
|
||||
} else if (include(RESERVED, id)) {
|
||||
this.identifierError(id);
|
||||
}
|
||||
}
|
||||
if (!(forcedIdentifier)) {
|
||||
if (include(COFFEE_ALIASES, id)) {
|
||||
tag = (id = CONVERSIONS[id]);
|
||||
}
|
||||
if (this.prev() && this.prev()[0] === 'ASSIGN' && include(HALF_ASSIGNMENTS, tag)) {
|
||||
return this.tagHalfAssignment(tag);
|
||||
}
|
||||
}
|
||||
this.token(tag, id);
|
||||
this.i += id.length;
|
||||
if (close_index) {
|
||||
this.token(']', ']');
|
||||
}
|
||||
return true;
|
||||
};
|
||||
// Matches numbers, including decimals, hex, and exponential notation.
|
||||
Lexer.prototype.number_token = function number_token() {
|
||||
Lexer.prototype.numberToken = function() {
|
||||
var number;
|
||||
if (!((number = this.match(NUMBER, 1)))) {
|
||||
if (!(number = this.match(NUMBER, 1))) {
|
||||
return false;
|
||||
}
|
||||
if (this.tag() === '.' && starts(number, '.')) {
|
||||
return false;
|
||||
}
|
||||
this.token('NUMBER', number);
|
||||
this.i += number.length;
|
||||
this.token('NUMBER', number);
|
||||
return true;
|
||||
};
|
||||
// Matches strings, including multi-line strings.
|
||||
Lexer.prototype.string_token = function string_token() {
|
||||
var escaped, string;
|
||||
if (!((string = this.match(STRING, 1)))) {
|
||||
Lexer.prototype.stringToken = function() {
|
||||
var string;
|
||||
if (!(starts(this.chunk, '"') || starts(this.chunk, "'"))) {
|
||||
return false;
|
||||
}
|
||||
escaped = string.replace(STRING_NEWLINES, " \\\n");
|
||||
this.token('STRING', escaped);
|
||||
if (!(string = this.balancedToken(['"', '"'], ['${', '}']) || this.balancedToken(["'", "'"]))) {
|
||||
return false;
|
||||
}
|
||||
this.interpolateString(string.replace(STRING_NEWLINES, " \\\n"));
|
||||
this.line += count(string, "\n");
|
||||
this.i += string.length;
|
||||
return true;
|
||||
};
|
||||
// Matches heredocs, adjusting indentation to the correct level.
|
||||
Lexer.prototype.heredoc_token = function heredoc_token() {
|
||||
var doc, match;
|
||||
if (!((match = this.chunk.match(HEREDOC)))) {
|
||||
Lexer.prototype.heredocToken = function() {
|
||||
var doc, match, quote;
|
||||
if (!(match = this.chunk.match(HEREDOC))) {
|
||||
return false;
|
||||
}
|
||||
doc = this.sanitize_heredoc(match[2] || match[4]);
|
||||
this.token('STRING', '"' + doc + '"');
|
||||
quote = match[1].substr(0, 1);
|
||||
doc = this.sanitizeHeredoc(match[2] || match[4], {
|
||||
quote: quote
|
||||
});
|
||||
this.interpolateString("" + quote + doc + quote);
|
||||
this.line += count(match[1], "\n");
|
||||
this.i += match[1].length;
|
||||
return true;
|
||||
};
|
||||
// Matches interpolated JavaScript.
|
||||
Lexer.prototype.js_token = function js_token() {
|
||||
Lexer.prototype.commentToken = function() {
|
||||
var match;
|
||||
if (!(match = this.chunk.match(COMMENT))) {
|
||||
return false;
|
||||
}
|
||||
this.line += count(match[1], "\n");
|
||||
this.i += match[1].length;
|
||||
return true;
|
||||
};
|
||||
Lexer.prototype.jsToken = function() {
|
||||
var script;
|
||||
if (!((script = this.match(JS, 1)))) {
|
||||
if (!(starts(this.chunk, '`'))) {
|
||||
return false;
|
||||
}
|
||||
if (!(script = this.balancedToken(['`', '`']))) {
|
||||
return false;
|
||||
}
|
||||
this.token('JS', script.replace(JS_CLEANER, ''));
|
||||
this.i += script.length;
|
||||
return true;
|
||||
};
|
||||
// Matches regular expression literals.
|
||||
Lexer.prototype.regex_token = function regex_token() {
|
||||
var regex;
|
||||
if (!((regex = this.match(REGEX, 1)))) {
|
||||
Lexer.prototype.regexToken = function() {
|
||||
var end, flags, regex, str;
|
||||
if (!(this.chunk.match(REGEX_START))) {
|
||||
return false;
|
||||
}
|
||||
if (include(NOT_REGEX, this.tag())) {
|
||||
return false;
|
||||
}
|
||||
this.token('REGEX', regex);
|
||||
if (!(regex = this.balancedToken(['/', '/']))) {
|
||||
return false;
|
||||
}
|
||||
if (!(end = this.chunk.substr(regex.length).match(REGEX_END))) {
|
||||
return false;
|
||||
}
|
||||
if (end[2]) {
|
||||
regex += (flags = end[2]);
|
||||
}
|
||||
if (regex.match(REGEX_INTERPOLATION)) {
|
||||
str = regex.substring(1).split('/')[0];
|
||||
str = str.replace(REGEX_ESCAPE, function(escaped) {
|
||||
return '\\' + escaped;
|
||||
});
|
||||
this.tokens = this.tokens.concat([['(', '('], ['NEW', 'new'], ['IDENTIFIER', 'RegExp'], ['CALL_START', '(']]);
|
||||
this.interpolateString(("\"" + str + "\""), true);
|
||||
this.tokens = this.tokens.concat([[',', ','], ['STRING', ("\"" + flags + "\"")], [')', ')'], [')', ')']]);
|
||||
} else {
|
||||
this.token('REGEX', regex);
|
||||
}
|
||||
this.i += regex.length;
|
||||
return true;
|
||||
};
|
||||
// Matches and conumes comments.
|
||||
Lexer.prototype.comment_token = function comment_token() {
|
||||
var comment, lines;
|
||||
if (!((comment = this.match(COMMENT, 1)))) {
|
||||
return false;
|
||||
}
|
||||
this.line += (comment.match(MULTILINER) || []).length;
|
||||
lines = comment.replace(COMMENT_CLEANER, '').split(MULTILINER);
|
||||
this.token('COMMENT', compact(lines));
|
||||
this.token('TERMINATOR', "\n");
|
||||
this.i += comment.length;
|
||||
return true;
|
||||
Lexer.prototype.balancedToken = function() {
|
||||
var delimited;
|
||||
var _d = arguments.length, _e = _d >= 1;
|
||||
delimited = __slice.call(arguments, 0, _d - 0);
|
||||
return this.balancedString(this.chunk, delimited);
|
||||
};
|
||||
// Matches newlines, indents, and outdents, and determines which is which.
|
||||
Lexer.prototype.line_token = function line_token() {
|
||||
var diff, indent, next_character, no_newlines, prev, size;
|
||||
if (!((indent = this.match(MULTI_DENT, 1)))) {
|
||||
Lexer.prototype.lineToken = function() {
|
||||
var diff, indent, nextCharacter, noNewlines, prev, size;
|
||||
if (!(indent = this.match(MULTI_DENT, 1))) {
|
||||
return false;
|
||||
}
|
||||
this.line += indent.match(MULTILINER).length;
|
||||
this.line += count(indent, "\n");
|
||||
this.i += indent.length;
|
||||
prev = this.prev(2);
|
||||
size = indent.match(LAST_DENTS).reverse()[0].match(LAST_DENT)[1].length;
|
||||
next_character = this.chunk.match(MULTI_DENT)[4];
|
||||
no_newlines = next_character === '.' || (this.value() && this.value().match(NO_NEWLINE) && prev && (prev[0] !== '.') && !this.value().match(CODE));
|
||||
nextCharacter = this.match(NEXT_CHARACTER, 1);
|
||||
noNewlines = nextCharacter === '.' || nextCharacter === ',' || this.unfinished();
|
||||
if (size === this.indent) {
|
||||
if (no_newlines) {
|
||||
return this.suppress_newlines(indent);
|
||||
if (noNewlines) {
|
||||
return this.suppressNewlines();
|
||||
}
|
||||
return this.newline_token(indent);
|
||||
return this.newlineToken(indent);
|
||||
} else if (size > this.indent) {
|
||||
if (no_newlines) {
|
||||
return this.suppress_newlines(indent);
|
||||
if (noNewlines) {
|
||||
return this.suppressNewlines();
|
||||
}
|
||||
diff = size - this.indent;
|
||||
this.token('INDENT', diff);
|
||||
this.indents.push(diff);
|
||||
} else {
|
||||
this.outdent_token(this.indent - size, no_newlines);
|
||||
this.outdentToken(this.indent - size, noNewlines);
|
||||
}
|
||||
this.indent = size;
|
||||
return true;
|
||||
};
|
||||
// Record an outdent token or tokens, if we happen to be moving back inwards
|
||||
// past multiple recorded indents.
|
||||
Lexer.prototype.outdent_token = function outdent_token(move_out, no_newlines) {
|
||||
var last_indent;
|
||||
while (move_out > 0 && this.indents.length) {
|
||||
last_indent = this.indents.pop();
|
||||
this.token('OUTDENT', last_indent);
|
||||
move_out -= last_indent;
|
||||
Lexer.prototype.outdentToken = function(moveOut, noNewlines) {
|
||||
var lastIndent;
|
||||
if (moveOut > -this.outdebt) {
|
||||
while (moveOut > 0 && this.indents.length) {
|
||||
lastIndent = this.indents.pop();
|
||||
this.token('OUTDENT', lastIndent);
|
||||
moveOut -= lastIndent;
|
||||
}
|
||||
} else {
|
||||
this.outdebt += moveOut;
|
||||
}
|
||||
if (!(this.tag() === 'TERMINATOR' || no_newlines)) {
|
||||
if (!(noNewlines)) {
|
||||
this.outdebt = moveOut;
|
||||
}
|
||||
if (!(this.tag() === 'TERMINATOR' || noNewlines)) {
|
||||
this.token('TERMINATOR', "\n");
|
||||
}
|
||||
return true;
|
||||
};
|
||||
// Matches and consumes non-meaningful whitespace. Tag the previous token
|
||||
// as being "spaced", because there are some cases where it makes a difference.
|
||||
Lexer.prototype.whitespace_token = function whitespace_token() {
|
||||
Lexer.prototype.whitespaceToken = function() {
|
||||
var prev, space;
|
||||
if (!((space = this.match(WHITESPACE, 1)))) {
|
||||
if (!(space = this.match(WHITESPACE, 1))) {
|
||||
return false;
|
||||
}
|
||||
prev = this.prev();
|
||||
@@ -279,90 +269,99 @@
|
||||
this.i += space.length;
|
||||
return true;
|
||||
};
|
||||
// Generate a newline token. Multiple newlines get merged together.
|
||||
Lexer.prototype.newline_token = function newline_token(newlines) {
|
||||
Lexer.prototype.newlineToken = function(newlines) {
|
||||
if (!(this.tag() === 'TERMINATOR')) {
|
||||
this.token('TERMINATOR', "\n");
|
||||
}
|
||||
return true;
|
||||
};
|
||||
// Use a `\` at a line-ending to suppress the newline.
|
||||
// The slash is removed here once its job is done.
|
||||
Lexer.prototype.suppress_newlines = function suppress_newlines(newlines) {
|
||||
Lexer.prototype.suppressNewlines = function() {
|
||||
if (this.value() === "\\") {
|
||||
this.tokens.pop();
|
||||
}
|
||||
return true;
|
||||
};
|
||||
// We treat all other single characters as a token. Eg.: `( ) , . !`
|
||||
// Multi-character operators are also literal tokens, so that Jison can assign
|
||||
// the proper order of operations.
|
||||
Lexer.prototype.literal_token = function literal_token() {
|
||||
var match, not_spaced, tag, value;
|
||||
Lexer.prototype.literalToken = function() {
|
||||
var match, prevSpaced, space, tag, value;
|
||||
match = this.chunk.match(OPERATOR);
|
||||
value = match && match[1];
|
||||
space = match && match[2];
|
||||
if (value && value.match(CODE)) {
|
||||
this.tag_parameters();
|
||||
this.tagParameters();
|
||||
}
|
||||
value = value || this.chunk.substr(0, 1);
|
||||
not_spaced = !this.prev() || !this.prev().spaced;
|
||||
prevSpaced = this.prev() && this.prev().spaced;
|
||||
tag = value;
|
||||
if (value.match(ASSIGNMENT)) {
|
||||
tag = 'ASSIGN';
|
||||
if (include(JS_FORBIDDEN, this.value)) {
|
||||
this.assignment_error();
|
||||
this.assignmentError();
|
||||
}
|
||||
} else if (value === ';') {
|
||||
tag = 'TERMINATOR';
|
||||
} else if (value === '[' && this.tag() === '?' && not_spaced) {
|
||||
tag = 'SOAKED_INDEX_START';
|
||||
this.soaked_index = true;
|
||||
this.tokens.pop();
|
||||
} else if (value === ']' && this.soaked_index) {
|
||||
tag = 'SOAKED_INDEX_END';
|
||||
this.soaked_index = false;
|
||||
} else if (include(CALLABLE, this.tag()) && not_spaced) {
|
||||
} else if (include(CALLABLE, this.tag()) && !prevSpaced) {
|
||||
if (value === '(') {
|
||||
tag = 'CALL_START';
|
||||
}
|
||||
if (value === '[') {
|
||||
} else if (value === '[') {
|
||||
tag = 'INDEX_START';
|
||||
if (this.tag() === '?') {
|
||||
this.tag(1, 'INDEX_SOAK');
|
||||
}
|
||||
if (this.tag() === '::') {
|
||||
this.tag(1, 'INDEX_PROTO');
|
||||
}
|
||||
}
|
||||
}
|
||||
this.i += value.length;
|
||||
if (space && prevSpaced && this.prev()[0] === 'ASSIGN' && include(HALF_ASSIGNMENTS, tag)) {
|
||||
return this.tagHalfAssignment(tag);
|
||||
}
|
||||
this.token(tag, value);
|
||||
this.i += value.length;
|
||||
return true;
|
||||
};
|
||||
// Token Manipulators
|
||||
// ------------------
|
||||
// As we consume a new `IDENTIFIER`, look at the previous token to determine
|
||||
// if it's a special kind of accessor.
|
||||
Lexer.prototype.name_access_type = function name_access_type() {
|
||||
if (this.value() === '::') {
|
||||
this.tag(1, 'PROTOTYPE_ACCESS');
|
||||
Lexer.prototype.tagAccessor = function() {
|
||||
var accessor, prev;
|
||||
if ((!(prev = this.prev())) || (prev && prev.spaced)) {
|
||||
return false;
|
||||
}
|
||||
if (this.value() === '.' && !(this.value(2) === '.')) {
|
||||
if (this.tag(2) === '?') {
|
||||
this.tag(1, 'SOAK_ACCESS');
|
||||
return this.tokens.splice(-2, 1);
|
||||
accessor = (function() {
|
||||
if (prev[1] === '::') {
|
||||
return this.tag(1, 'PROTOTYPE_ACCESS');
|
||||
} else if (prev[1] === '.' && !(this.value(2) === '.')) {
|
||||
if (this.tag(2) === '?') {
|
||||
this.tag(1, 'SOAK_ACCESS');
|
||||
return this.tokens.splice(-2, 1);
|
||||
} else {
|
||||
return this.tag(1, 'PROPERTY_ACCESS');
|
||||
}
|
||||
} else {
|
||||
return this.tag(1, 'PROPERTY_ACCESS');
|
||||
return prev[0] === '@';
|
||||
}
|
||||
}).call(this);
|
||||
if (accessor) {
|
||||
return 'accessor';
|
||||
} else {
|
||||
return 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;
|
||||
}
|
||||
}
|
||||
return doc.replace(new RegExp("^" + indent, 'gm'), '').replace(MULTILINER, "\\n").replace(new RegExp(options.quote, 'g'), ("\\" + options.quote));
|
||||
};
|
||||
// Sanitize a heredoc by escaping double quotes and erasing all external
|
||||
// indentation on the left-hand side.
|
||||
Lexer.prototype.sanitize_heredoc = function sanitize_heredoc(doc) {
|
||||
var indent;
|
||||
indent = (doc.match(HEREDOC_INDENT) || ['']).sort()[0];
|
||||
return doc.replace(new RegExp("^" + indent, 'gm'), '').replace(MULTILINER, "\\n").replace(/"/g, '\\"');
|
||||
Lexer.prototype.tagHalfAssignment = function(tag) {
|
||||
var last;
|
||||
last = this.tokens.pop();
|
||||
this.tokens.push([("" + tag + "="), ("" + tag + "="), last[2]]);
|
||||
return true;
|
||||
};
|
||||
// A source of ambiguity in our grammar was parameter lists in function
|
||||
// definitions (as opposed to argument lists in function calls). Tag
|
||||
// parameter identifiers in order to avoid this. Also, parameter lists can
|
||||
// make use of splats.
|
||||
Lexer.prototype.tag_parameters = function tag_parameters() {
|
||||
var _a, i, tok;
|
||||
Lexer.prototype.tagParameters = function() {
|
||||
var _d, i, tok;
|
||||
if (this.tag() !== ')') {
|
||||
return null;
|
||||
}
|
||||
@@ -373,100 +372,241 @@
|
||||
if (!tok) {
|
||||
return null;
|
||||
}
|
||||
if ((_a = tok[0]) === 'IDENTIFIER') {
|
||||
if ((_d = tok[0]) === 'IDENTIFIER') {
|
||||
tok[0] = 'PARAM';
|
||||
} else if (_a === ')') {
|
||||
} else if (_d === ')') {
|
||||
tok[0] = 'PARAM_END';
|
||||
} else if (_a === '(') {
|
||||
return (tok[0] = 'PARAM_START');
|
||||
} else if (_d === '(' || _d === 'CALL_START') {
|
||||
tok[0] = 'PARAM_START';
|
||||
return tok[0];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
// Close up all remaining open blocks at the end of the file.
|
||||
Lexer.prototype.close_indentation = function close_indentation() {
|
||||
return this.outdent_token(this.indent);
|
||||
Lexer.prototype.closeIndentation = function() {
|
||||
return this.outdentToken(this.indent);
|
||||
};
|
||||
// Error for when you try to use a forbidden word in JavaScript as
|
||||
// an identifier.
|
||||
Lexer.prototype.identifier_error = function identifier_error(word) {
|
||||
throw new Error('SyntaxError: Reserved word "' + word + '" on line ' + this.line);
|
||||
Lexer.prototype.identifierError = function(word) {
|
||||
throw new Error(("SyntaxError: Reserved word \"" + word + "\" on line " + (this.line + 1)));
|
||||
};
|
||||
// Error for when you try to assign to a reserved word in JavaScript,
|
||||
// like "function" or "default".
|
||||
Lexer.prototype.assignment_error = function assignment_error() {
|
||||
throw new Error('SyntaxError: Reserved word "' + this.value() + '" on line ' + this.line + ' can\'t be assigned');
|
||||
Lexer.prototype.assignmentError = function() {
|
||||
throw new Error(("SyntaxError: Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned"));
|
||||
};
|
||||
// Helpers
|
||||
// -------
|
||||
// Add a token to the results, taking note of the line number.
|
||||
Lexer.prototype.token = function token(tag, value) {
|
||||
Lexer.prototype.balancedString = function(str, delimited, options) {
|
||||
var _d, _e, _f, _g, close, i, levels, open, pair, slash;
|
||||
options = options || {};
|
||||
slash = delimited[0][0] === '/';
|
||||
levels = [];
|
||||
i = 0;
|
||||
while (i < str.length) {
|
||||
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];
|
||||
if (levels.length && starts(str, close, i) && levels[levels.length - 1] === pair) {
|
||||
levels.pop();
|
||||
i += close.length - 1;
|
||||
if (!(levels.length)) {
|
||||
i += 1;
|
||||
}
|
||||
break;
|
||||
} else if (starts(str, open, i)) {
|
||||
levels.push(pair);
|
||||
i += open.length - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!levels.length || slash && starts(str, '\n', i)) {
|
||||
break;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
if (levels.length) {
|
||||
if (slash) {
|
||||
return false;
|
||||
}
|
||||
throw new Error(("SyntaxError: Unterminated " + (levels.pop()[0]) + " starting on line " + (this.line + 1)));
|
||||
}
|
||||
if (!i) {
|
||||
return false;
|
||||
} else {
|
||||
return str.substring(0, i);
|
||||
}
|
||||
};
|
||||
Lexer.prototype.interpolateString = function(str, escapeQuotes) {
|
||||
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;
|
||||
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];
|
||||
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)));
|
||||
}
|
||||
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)]);
|
||||
}
|
||||
inner = expr.substring(2, expr.length - 1);
|
||||
if (inner.length) {
|
||||
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;
|
||||
}
|
||||
nested.pop();
|
||||
tokens.push(['TOKENS', nested]);
|
||||
} else {
|
||||
tokens.push(['STRING', ("" + quote + quote)]);
|
||||
}
|
||||
i += expr.length - 1;
|
||||
pi = i + 1;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
if (pi < i && pi < str.length - 1) {
|
||||
tokens.push(['STRING', ("" + quote + (str.substring(pi, i)) + quote)]);
|
||||
}
|
||||
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];
|
||||
if (tag === 'TOKENS') {
|
||||
this.tokens = this.tokens.concat(value);
|
||||
} else if (tag === 'STRING' && escapeQuotes) {
|
||||
escaped = value.substring(1, value.length - 1).replace(/"/g, '\\"');
|
||||
this.token(tag, ("\"" + escaped + "\""));
|
||||
} else {
|
||||
this.token(tag, value);
|
||||
}
|
||||
if (i < tokens.length - 1) {
|
||||
this.token('+', '+');
|
||||
}
|
||||
}
|
||||
if (interpolated) {
|
||||
this.token(')', ')');
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
};
|
||||
Lexer.prototype.token = function(tag, value) {
|
||||
return this.tokens.push([tag, value, this.line]);
|
||||
};
|
||||
// Peek at a tag in the current token stream.
|
||||
Lexer.prototype.tag = function tag(index, tag) {
|
||||
Lexer.prototype.tag = function(index, newTag) {
|
||||
var tok;
|
||||
if (!((tok = this.prev(index)))) {
|
||||
if (!(tok = this.prev(index))) {
|
||||
return null;
|
||||
}
|
||||
if ((typeof tag !== "undefined" && tag !== null)) {
|
||||
return (tok[0] = tag);
|
||||
if (typeof newTag !== "undefined" && newTag !== null) {
|
||||
tok[0] = newTag;
|
||||
return tok[0];
|
||||
}
|
||||
return tok[0];
|
||||
};
|
||||
// Peek at a value in the current token stream.
|
||||
Lexer.prototype.value = function value(index, val) {
|
||||
Lexer.prototype.value = function(index, val) {
|
||||
var tok;
|
||||
if (!((tok = this.prev(index)))) {
|
||||
if (!(tok = this.prev(index))) {
|
||||
return null;
|
||||
}
|
||||
if ((typeof val !== "undefined" && val !== null)) {
|
||||
return (tok[1] = val);
|
||||
if (typeof val !== "undefined" && val !== null) {
|
||||
tok[1] = val;
|
||||
return tok[1];
|
||||
}
|
||||
return tok[1];
|
||||
};
|
||||
// Peek at a previous token, entire.
|
||||
Lexer.prototype.prev = function prev(index) {
|
||||
Lexer.prototype.prev = function(index) {
|
||||
return this.tokens[this.tokens.length - (index || 1)];
|
||||
};
|
||||
// Attempt to match a string against the current chunk, returning the indexed
|
||||
// match if successful, and `false` otherwise.
|
||||
Lexer.prototype.match = function match(regex, index) {
|
||||
Lexer.prototype.match = function(regex, index) {
|
||||
var m;
|
||||
if (!((m = this.chunk.match(regex)))) {
|
||||
if (!(m = this.chunk.match(regex))) {
|
||||
return false;
|
||||
}
|
||||
return m ? m[index] : false;
|
||||
if (m) {
|
||||
return m[index];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
Lexer.prototype.unfinished = function() {
|
||||
var prev;
|
||||
prev = this.prev(2);
|
||||
return this.value() && this.value().match && this.value().match(NO_NEWLINE) && prev && (prev[0] !== '.') && !this.value().match(CODE);
|
||||
};
|
||||
return Lexer;
|
||||
}).call(this);
|
||||
// Utility Functions
|
||||
// -----------------
|
||||
// Does a list include a value?
|
||||
include = function include(list, value) {
|
||||
return list.indexOf(value) >= 0;
|
||||
};
|
||||
// Trim out all falsy values from an array.
|
||||
compact = function compact(array) {
|
||||
var _a, _b, _c, _d, item;
|
||||
_a = []; _b = array;
|
||||
for (_c = 0, _d = _b.length; _c < _d; _c++) {
|
||||
item = _b[_c];
|
||||
if (item) {
|
||||
_a.push(item);
|
||||
}
|
||||
}
|
||||
return _a;
|
||||
};
|
||||
// Count the number of occurences of a character in a string.
|
||||
count = function count(string, letter) {
|
||||
var num, pos;
|
||||
num = 0;
|
||||
pos = string.indexOf(letter);
|
||||
while (pos !== -1) {
|
||||
num += 1;
|
||||
pos = string.indexOf(letter, pos + 1);
|
||||
}
|
||||
return num;
|
||||
})();
|
||||
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"];
|
||||
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"];
|
||||
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]*)/;
|
||||
WHITESPACE = /^([ \t]+)/;
|
||||
COMMENT = /^(\s*#{3}(?!#)[ \t]*\n+([\s\S]*?)[ \t]*\n+[ \t]*#{3}|(\s*#[^\n]*)+)/;
|
||||
CODE = /^((-|=)>)/;
|
||||
MULTI_DENT = /^((\n([ \t]*))+)(\.)?/;
|
||||
LAST_DENTS = /\n([ \t]*)/g;
|
||||
LAST_DENT = /\n([ \t]*)/;
|
||||
ASSIGNMENT = /^[:=]$/;
|
||||
REGEX_START = /^\/[^\/ ]/;
|
||||
REGEX_INTERPOLATION = /([^\\]\$[a-zA-Z_@]|[^\\]\$\{.*[^\\]\})/;
|
||||
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 = /^([a-zA-Z\$_]\w*[ \t]*?[:=])/;
|
||||
NEXT_CHARACTER = /^\s*(\S)/;
|
||||
NOT_REGEX = ['NUMBER', 'REGEX', '++', '--', 'FALSE', 'NULL', 'TRUE', ']'];
|
||||
CALLABLE = ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING', '@', 'THIS', '?', '::'];
|
||||
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];
|
||||
HALF_ASSIGNMENTS = ['-', '+', '/', '*', '%', '||', '&&', '?'];
|
||||
CONVERSIONS = {
|
||||
'and': '&&',
|
||||
'or': '||',
|
||||
'is': '==',
|
||||
'isnt': '!=',
|
||||
'not': '!'
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
(function(){
|
||||
var coffee, factories, file, loader, os, puts;
|
||||
// The Narwhal-compatibility wrapper for CoffeeScript.
|
||||
// Require external dependencies.
|
||||
os = require('os');
|
||||
file = require('file');
|
||||
coffee = require('./coffee-script');
|
||||
// Alias print to "puts", for Node.js compatibility:
|
||||
puts = print;
|
||||
// Compile a string of CoffeeScript into JavaScript.
|
||||
exports.compile = function compile(source) {
|
||||
return coffee.compile(source);
|
||||
};
|
||||
// Compile a given CoffeeScript file into JavaScript.
|
||||
exports.compileFile = function compileFile(path) {
|
||||
return coffee.compile(file.read(path));
|
||||
};
|
||||
// Make a factory for the CoffeeScript environment.
|
||||
exports.makeNarwhalFactory = function makeNarwhalFactory(path) {
|
||||
var code, factoryText;
|
||||
code = exports.compileFile(path);
|
||||
factoryText = "function(require,exports,module,system,print){" + code + "/**/\n}";
|
||||
if (system.engine === "rhino") {
|
||||
return Packages.org.mozilla.javascript.Context.getCurrentContext().compileFunction(global, factoryText, path, 0, null);
|
||||
} else {
|
||||
// eval requires parentheses, but parentheses break compileFunction.
|
||||
return eval("(" + factoryText + ")");
|
||||
}
|
||||
};
|
||||
// The Narwhal loader for '.coffee' files.
|
||||
factories = {};
|
||||
loader = {};
|
||||
// Reload the coffee-script environment from source.
|
||||
loader.reload = function reload(topId, path) {
|
||||
return factories[topId] = function() {
|
||||
return exports.makeNarwhalFactory(path);
|
||||
};
|
||||
};
|
||||
// Ensure that the coffee-script environment is loaded.
|
||||
loader.load = function load(topId, path) {
|
||||
return factories[topId] = factories[topId] || this.reload(topId, path);
|
||||
};
|
||||
require.loader.loaders.unshift([".coffee", loader]);
|
||||
})();
|
||||
2182
lib/nodes.js
2182
lib/nodes.js
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user