mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-01-14 01:07:55 -05:00
Compare commits
474 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af53c230a1 | ||
|
|
ac9d0e17e4 | ||
|
|
5e498ca395 | ||
|
|
5c3acfefeb | ||
|
|
9b63e806dd | ||
|
|
bd842241a6 | ||
|
|
3815f0a132 | ||
|
|
d43b50b1ca | ||
|
|
14c2a16833 | ||
|
|
5ae9c5d947 | ||
|
|
2402f9774a | ||
|
|
3d3fe0df34 | ||
|
|
a320e1e535 | ||
|
|
8f0a7774f9 | ||
|
|
7f8b56eadd | ||
|
|
385d93e332 | ||
|
|
9ed804d9b1 | ||
|
|
03cfe23493 | ||
|
|
a97c23a4bd | ||
|
|
e1a2e11de4 | ||
|
|
5e49df8ed4 | ||
|
|
fa1ffa66d3 | ||
|
|
1aa57bf24f | ||
|
|
31dd0b75af | ||
|
|
46ecfd3c1a | ||
|
|
c31bc6deb7 | ||
|
|
fe45f1bf35 | ||
|
|
fc7f4ed904 | ||
|
|
33553839e2 | ||
|
|
1818e74f42 | ||
|
|
d72daca7bd | ||
|
|
c37202ecb9 | ||
|
|
1f5b19b81c | ||
|
|
8a98cb380e | ||
|
|
de5e2c60ae | ||
|
|
b31cc70235 | ||
|
|
78891a0ccc | ||
|
|
0b1d4d374a | ||
|
|
ac398998a2 | ||
|
|
21d69e3e6e | ||
|
|
33140259b8 | ||
|
|
723907464a | ||
|
|
bf4d91dd38 | ||
|
|
64fe56a9e1 | ||
|
|
a106fb451b | ||
|
|
b1300bdd79 | ||
|
|
be9707f8d2 | ||
|
|
702071553f | ||
|
|
47bd05e9a0 | ||
|
|
537c5f4b70 | ||
|
|
041033a51a | ||
|
|
2e191dc0e7 | ||
|
|
4a52814a79 | ||
|
|
69d80e2ded | ||
|
|
d84cd9466e | ||
|
|
627b921bca | ||
|
|
955afe0c9f | ||
|
|
316d5e5e77 | ||
|
|
1f051e6e14 | ||
|
|
f67da27d2f | ||
|
|
923739ebb4 | ||
|
|
97bc9f4730 | ||
|
|
bbbf612f29 | ||
|
|
d11fa573e6 | ||
|
|
6becd8fb13 | ||
|
|
a1ba0a89f8 | ||
|
|
a9aa52dc6a | ||
|
|
9595b30d6f | ||
|
|
f672e0cdb5 | ||
|
|
66bbef4ce0 | ||
|
|
dfe91d1766 | ||
|
|
cdde576182 | ||
|
|
82aeb70380 | ||
|
|
69ef1abdf6 | ||
|
|
cc6f0451e7 | ||
|
|
2c20ac6aa9 | ||
|
|
f8c751b3a4 | ||
|
|
547a271cee | ||
|
|
cd2444e546 | ||
|
|
6f1fb0352c | ||
|
|
4bf2c6b2e9 | ||
|
|
025b0be31b | ||
|
|
27551b23f3 | ||
|
|
ba08a21d21 | ||
|
|
48d625816c | ||
|
|
cee4f4ab6e | ||
|
|
de29613d91 | ||
|
|
9e3d43193d | ||
|
|
847ab4d18e | ||
|
|
183e124077 | ||
|
|
3142b237f5 | ||
|
|
969e45a599 | ||
|
|
df6c497ab0 | ||
|
|
12625cc00c | ||
|
|
bb94e02fad | ||
|
|
25126e2f99 | ||
|
|
d5d772d55e | ||
|
|
bdcd77d8e6 | ||
|
|
b9ebcbf555 | ||
|
|
c407a0bf19 | ||
|
|
7c77a5d3c8 | ||
|
|
ce2bf36aae | ||
|
|
3284f6af18 | ||
|
|
52b0f76eb2 | ||
|
|
e46b129c4f | ||
|
|
35787ef79b | ||
|
|
f029695db8 | ||
|
|
0ba628159f | ||
|
|
158d37215a | ||
|
|
7ad25c90fa | ||
|
|
b06a326c7d | ||
|
|
25bdde85a9 | ||
|
|
d8905e2f87 | ||
|
|
b4e13b294d | ||
|
|
4fb3a312b0 | ||
|
|
82fadea1ed | ||
|
|
bb194dc6c6 | ||
|
|
9167b3aca1 | ||
|
|
76a25dc797 | ||
|
|
97de09c8f1 | ||
|
|
7595cb689a | ||
|
|
2b86470665 | ||
|
|
78423e9a14 | ||
|
|
ec59a626f2 | ||
|
|
1b14c035e7 | ||
|
|
ba34f8d389 | ||
|
|
b74e73058c | ||
|
|
c29597b3bc | ||
|
|
7c53d8c120 | ||
|
|
5d7a83468a | ||
|
|
a396837fa4 | ||
|
|
1fa3da68ba | ||
|
|
219726a9c5 | ||
|
|
81c0964e48 | ||
|
|
c9388ce767 | ||
|
|
2a56f0cdf7 | ||
|
|
ace4837365 | ||
|
|
6417cf4d1b | ||
|
|
1731f7d321 | ||
|
|
8d39c1cc79 | ||
|
|
bc7e0cf09a | ||
|
|
7c29ea4d38 | ||
|
|
6c6c8bd454 | ||
|
|
81f780f1fb | ||
|
|
6838bae36e | ||
|
|
972a5299d5 | ||
|
|
b8149812cd | ||
|
|
01d4e87f57 | ||
|
|
f938a213fe | ||
|
|
df54c63b1b | ||
|
|
1810d9f318 | ||
|
|
29b9c3bb29 | ||
|
|
da2298988a | ||
|
|
f31ff7774a | ||
|
|
c6fafa1bc9 | ||
|
|
e8a8209a2b | ||
|
|
fa82859814 | ||
|
|
55e1386503 | ||
|
|
dc9565f54a | ||
|
|
c264bf04cc | ||
|
|
5c66e552d7 | ||
|
|
c4ebe352a4 | ||
|
|
79492aab36 | ||
|
|
e3454ed7fb | ||
|
|
8dcbe54e55 | ||
|
|
dac24a3d8a | ||
|
|
5c8eef2ab5 | ||
|
|
66c751be11 | ||
|
|
7792a3a6e3 | ||
|
|
e57a5de33e | ||
|
|
ed705403ad | ||
|
|
fa899ab810 | ||
|
|
fdcd99dfef | ||
|
|
d5ddd0f783 | ||
|
|
848d10594b | ||
|
|
caf3da2f66 | ||
|
|
f1b286469a | ||
|
|
46065199cd | ||
|
|
879fe3976d | ||
|
|
c1309e12f7 | ||
|
|
6bcc798a76 | ||
|
|
3e95d7f2d0 | ||
|
|
c3159e48c8 | ||
|
|
34be878257 | ||
|
|
87257ea6b3 | ||
|
|
8bc6001d27 | ||
|
|
e433098eb2 | ||
|
|
afdcdcfd54 | ||
|
|
4fc9a345bb | ||
|
|
c06487c13b | ||
|
|
7a80661ad5 | ||
|
|
2fb527a63f | ||
|
|
99394e1011 | ||
|
|
3b1a566117 | ||
|
|
d58da49cee | ||
|
|
0fada5109a | ||
|
|
46ff7705ee | ||
|
|
eabcb2c8b0 | ||
|
|
ea60dfa44d | ||
|
|
53a82da3f3 | ||
|
|
b03bea14fa | ||
|
|
2f13fae6f0 | ||
|
|
a92af02ae8 | ||
|
|
4043124135 | ||
|
|
7b66e22bc6 | ||
|
|
5542e00b80 | ||
|
|
f3a1f46679 | ||
|
|
08673261b1 | ||
|
|
60c9b94656 | ||
|
|
f0e17fc20f | ||
|
|
de511e0348 | ||
|
|
ed8d94f69c | ||
|
|
1b3af684cb | ||
|
|
53fe10e4ad | ||
|
|
b4e1e54cf7 | ||
|
|
22db7ae85a | ||
|
|
6a88ce7d1e | ||
|
|
7e32c32057 | ||
|
|
c5737764b5 | ||
|
|
ddd6e9a48b | ||
|
|
d6fbfa55b6 | ||
|
|
abb11c80d1 | ||
|
|
ef0cb46b9b | ||
|
|
209a0f5a79 | ||
|
|
44e1ccec7e | ||
|
|
7c1f4b38f4 | ||
|
|
b9cfb5a7d8 | ||
|
|
1c8411f628 | ||
|
|
de9970412a | ||
|
|
a0e3a8b420 | ||
|
|
bc2ca1ef73 | ||
|
|
9a955859fd | ||
|
|
ecfe49adca | ||
|
|
7a75b2b8d0 | ||
|
|
127653b7d4 | ||
|
|
b7f2681007 | ||
|
|
12d6461bbe | ||
|
|
28a1101b91 | ||
|
|
8248601b72 | ||
|
|
2e78508016 | ||
|
|
d9120b8365 | ||
|
|
eb8e20c3ef | ||
|
|
cb0003d894 | ||
|
|
7becf808c7 | ||
|
|
13f8348568 | ||
|
|
d6e2ae292e | ||
|
|
e42f96b76d | ||
|
|
40a9196c7f | ||
|
|
0ca255b7b8 | ||
|
|
8ade4f1077 | ||
|
|
d74c909930 | ||
|
|
c0dac45fe1 | ||
|
|
eb5c4057a1 | ||
|
|
a080bd40fb | ||
|
|
b7b92eddbd | ||
|
|
e0ec397046 | ||
|
|
34e517de09 | ||
|
|
f40ba672db | ||
|
|
8ac440fd52 | ||
|
|
c3a8a4f81f | ||
|
|
7c56da26f6 | ||
|
|
97cd2dbc41 | ||
|
|
8affc297fc | ||
|
|
6d69812046 | ||
|
|
de8d16f5e7 | ||
|
|
b4712c6a93 | ||
|
|
3fc4f10248 | ||
|
|
ec55335092 | ||
|
|
af51300887 | ||
|
|
233cd27d70 | ||
|
|
c1f7db8275 | ||
|
|
0bf488ea49 | ||
|
|
bf8e0aa1ea | ||
|
|
4372138fdd | ||
|
|
8b179fb391 | ||
|
|
0b7cfba94a | ||
|
|
f43ec97e30 | ||
|
|
7521068ba3 | ||
|
|
a2ef66f197 | ||
|
|
3a694d7dfa | ||
|
|
cad108eca0 | ||
|
|
66eb186a74 | ||
|
|
6e1e77d46d | ||
|
|
e207c983c1 | ||
|
|
9a23511965 | ||
|
|
df7ab264ab | ||
|
|
9e1d418d7a | ||
|
|
ee9311c025 | ||
|
|
2ec4c38433 | ||
|
|
b6310d0365 | ||
|
|
77670b0f3e | ||
|
|
fd1fa7d551 | ||
|
|
0c5726d3ab | ||
|
|
5816de39ba | ||
|
|
80677a9d2b | ||
|
|
8d952c245f | ||
|
|
6d33a2e1a0 | ||
|
|
ff05575b78 | ||
|
|
16e297ab61 | ||
|
|
447ce82721 | ||
|
|
86e4d79ffb | ||
|
|
11342ef97b | ||
|
|
48c17e2c3d | ||
|
|
36a69864e3 | ||
|
|
64b0e50609 | ||
|
|
806df9bc1e | ||
|
|
f98c613ecc | ||
|
|
642fcbbbfe | ||
|
|
58bb6725e4 | ||
|
|
3484ca5e64 | ||
|
|
0b1b7c36d2 | ||
|
|
8eb04cd80b | ||
|
|
8dfec65034 | ||
|
|
4a0e8139ea | ||
|
|
c8059a752f | ||
|
|
62a331a3dc | ||
|
|
90e0ce97e4 | ||
|
|
3b3c069c3b | ||
|
|
46b34d4b43 | ||
|
|
080ed2e8dd | ||
|
|
0c4cb309b0 | ||
|
|
8d5f800e2f | ||
|
|
e2a205ab22 | ||
|
|
21a499c726 | ||
|
|
e5f3750de2 | ||
|
|
4944fba3f7 | ||
|
|
65d21766b7 | ||
|
|
2a0521fba6 | ||
|
|
97cd7cc1c9 | ||
|
|
d3f60599e8 | ||
|
|
8728706237 | ||
|
|
c6c527e830 | ||
|
|
fc0a169a9a | ||
|
|
5b7366583d | ||
|
|
01e03ae2d8 | ||
|
|
8a1deee8d8 | ||
|
|
2e06316e31 | ||
|
|
6870af36b7 | ||
|
|
0f1dbffa40 | ||
|
|
cfb9cb6fe9 | ||
|
|
9de0d886eb | ||
|
|
5c24b80367 | ||
|
|
a477880edc | ||
|
|
00f5f54b77 | ||
|
|
1018c51359 | ||
|
|
8d8c345216 | ||
|
|
dd25ac03e4 | ||
|
|
3ff194dd61 | ||
|
|
215979c9e0 | ||
|
|
6d3acdcd2f | ||
|
|
9abe614ea8 | ||
|
|
36c171d78e | ||
|
|
c75c4421a7 | ||
|
|
55998f7481 | ||
|
|
d5acd7f338 | ||
|
|
d3cc05bdfc | ||
|
|
07ccd91022 | ||
|
|
edd0b661f3 | ||
|
|
4b0fabd7cb | ||
|
|
55e794dbe5 | ||
|
|
988dedd08d | ||
|
|
f66564273c | ||
|
|
dfc602159e | ||
|
|
9fde794858 | ||
|
|
ed1ddbce50 | ||
|
|
cda95afd3e | ||
|
|
0e40feb9af | ||
|
|
846306f85e | ||
|
|
a0aa090f2c | ||
|
|
460b5d6edb | ||
|
|
b9805f3f80 | ||
|
|
0069c4901f | ||
|
|
93b118bfa2 | ||
|
|
7c6bc95a84 | ||
|
|
ee8a1a3b68 | ||
|
|
5bca978444 | ||
|
|
347409e354 | ||
|
|
c284f3f226 | ||
|
|
cdd3c13ce9 | ||
|
|
f6dbaa7c31 | ||
|
|
a4553c970c | ||
|
|
38b6a43e26 | ||
|
|
121009dec4 | ||
|
|
510fb59e29 | ||
|
|
e4b3e838e2 | ||
|
|
4b70a16cf9 | ||
|
|
af0ee70ea3 | ||
|
|
ad39150565 | ||
|
|
686ef9e7f4 | ||
|
|
fac615108c | ||
|
|
ddfe89d916 | ||
|
|
b0948f81dd | ||
|
|
00f9e244f2 | ||
|
|
eb55f2d8f4 | ||
|
|
b50315d8a0 | ||
|
|
85286b8ca5 | ||
|
|
74944da211 | ||
|
|
c9a0a33fa2 | ||
|
|
b12be3188f | ||
|
|
26a28abcb5 | ||
|
|
5f1314cd66 | ||
|
|
0ad9d4bf16 | ||
|
|
621e5648e3 | ||
|
|
f0728fcf8f | ||
|
|
63ab886e9f | ||
|
|
7b4f1b165d | ||
|
|
8855eede5f | ||
|
|
69d49e137a | ||
|
|
94e17e0d88 | ||
|
|
5debc3c903 | ||
|
|
0ce332edca | ||
|
|
b122406683 | ||
|
|
35dc56d785 | ||
|
|
6cb13f4c44 | ||
|
|
26d5c99570 | ||
|
|
24836ccf6d | ||
|
|
7d22a011ab | ||
|
|
e9e5ae119f | ||
|
|
2c92904109 | ||
|
|
2fb6d0beb9 | ||
|
|
b9c17cab3c | ||
|
|
d2c3b79617 | ||
|
|
03b8222c9e | ||
|
|
57e109ff11 | ||
|
|
30614c5721 | ||
|
|
55521a2f4c | ||
|
|
8762e37e58 | ||
|
|
fba69f5651 | ||
|
|
bde1c6282e | ||
|
|
a24451b6d3 | ||
|
|
d0b8cded6b | ||
|
|
1e25c9da30 | ||
|
|
fe78e65b16 | ||
|
|
9e1d1f57f0 | ||
|
|
73acfa18a3 | ||
|
|
266d97f8f5 | ||
|
|
a70753e6d3 | ||
|
|
97dbb7bb49 | ||
|
|
79945ad473 | ||
|
|
1d7a3b4d0f | ||
|
|
5bf8b422f8 | ||
|
|
9633816d7a | ||
|
|
cc8708493e | ||
|
|
51b25fb3d8 | ||
|
|
b41a69da2d | ||
|
|
1ce92d1aeb | ||
|
|
496978abdd | ||
|
|
424bb17224 | ||
|
|
6d6a5f609a | ||
|
|
a296957771 | ||
|
|
fbe84e376c | ||
|
|
d30aa6d621 | ||
|
|
966063db0c | ||
|
|
13717e2e65 | ||
|
|
7aaaac42bc | ||
|
|
65930224ee | ||
|
|
97d1eedd5a | ||
|
|
11544f2717 | ||
|
|
590bd3dec9 | ||
|
|
74501f643c | ||
|
|
cebfe394ad | ||
|
|
2e037dcb93 | ||
|
|
8a41ee95c7 | ||
|
|
3564f51fb5 | ||
|
|
df641261d6 | ||
|
|
f3486499ac | ||
|
|
a768f167cf | ||
|
|
03a8340a85 | ||
|
|
036197fac3 | ||
|
|
b8d60a9cf1 | ||
|
|
b02ac3a733 | ||
|
|
70a5402509 | ||
|
|
f2c0ea7fa4 | ||
|
|
216ad777de |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,6 +1,7 @@
|
||||
raw
|
||||
presentation
|
||||
test.coffee
|
||||
test.litcoffee
|
||||
parser.output
|
||||
test/fixtures/underscore
|
||||
test/*.js
|
||||
|
||||
9
CONTRIBUTING.md
Normal file
9
CONTRIBUTING.md
Normal file
@@ -0,0 +1,9 @@
|
||||
## How to contribute to CoffeeScript
|
||||
|
||||
* Before you open a ticket or send a pull request, [search](https://github.com/jashkenas/coffee-script/issues) for previous discussions about the same feature or issue. Add to the earlier ticket if you find one.
|
||||
|
||||
* Before sending a pull request for a feature, be sure to have [tests](https://github.com/jashkenas/coffee-script/tree/master/test).
|
||||
|
||||
* Use the same coding style as the rest of the [codebase](https://github.com/jashkenas/coffee-script/tree/master/src). If you're just getting started with CoffeeScript, there's a nice [style guide](https://github.com/polarmobile/coffeescript-style-guide).
|
||||
|
||||
* In your pull request, do not add documentation to `index.html` or re-build the minified `coffee-script.js` file. We'll do those things before cutting a new release.
|
||||
88
Cakefile
88
Cakefile
@@ -5,16 +5,12 @@ CoffeeScript = require './lib/coffee-script'
|
||||
{spawn, exec} = require 'child_process'
|
||||
|
||||
# ANSI Terminal Colors.
|
||||
enableColors = no
|
||||
unless process.platform is 'win32'
|
||||
enableColors = not process.env.NODE_DISABLE_COLORS
|
||||
|
||||
bold = red = green = reset = ''
|
||||
if enableColors
|
||||
bold = '\033[0;1m'
|
||||
red = '\033[0;31m'
|
||||
green = '\033[0;32m'
|
||||
reset = '\033[0m'
|
||||
unless process.env.NODE_DISABLE_COLORS
|
||||
bold = '\x1B[0;1m'
|
||||
red = '\x1B[0;31m'
|
||||
green = '\x1B[0;32m'
|
||||
reset = '\x1B[0m'
|
||||
|
||||
# Built file header.
|
||||
header = """
|
||||
@@ -27,14 +23,9 @@ header = """
|
||||
*/
|
||||
"""
|
||||
|
||||
sources = [
|
||||
'coffee-script', 'grammar', 'helpers'
|
||||
'lexer', 'nodes', 'rewriter', 'scope'
|
||||
].map (filename) -> "src/#{filename}.coffee"
|
||||
|
||||
# Run a CoffeeScript through our node/coffee interpreter.
|
||||
run = (args, cb) ->
|
||||
proc = spawn 'bin/coffee', args
|
||||
proc = spawn 'node', ['bin/coffee'].concat(args)
|
||||
proc.stderr.on 'data', (buffer) -> console.log buffer.toString()
|
||||
proc.on 'exit', (status) ->
|
||||
process.exit(1) if status != 0
|
||||
@@ -68,7 +59,7 @@ task 'install', 'install CoffeeScript into /usr/local (or --prefix)', (options)
|
||||
|
||||
task 'build', 'build the CoffeeScript language from source', build = (cb) ->
|
||||
files = fs.readdirSync 'src'
|
||||
files = ('src/' + file for file in files when file.match(/\.coffee$/))
|
||||
files = ('src/' + file for file in files when file.match(/\.(lit)?coffee$/))
|
||||
run ['-c', '-o', 'lib/coffee-script'].concat(files), cb
|
||||
|
||||
|
||||
@@ -76,7 +67,11 @@ task 'build:full', 'rebuild the source twice, and run the tests', ->
|
||||
build ->
|
||||
build ->
|
||||
csPath = './lib/coffee-script'
|
||||
delete require.cache[require.resolve csPath]
|
||||
csDir = path.dirname require.resolve csPath
|
||||
|
||||
for mod of require.cache when csDir is mod[0 ... csDir.length]
|
||||
delete require.cache[mod]
|
||||
|
||||
unless runTests require csPath
|
||||
process.exit 1
|
||||
|
||||
@@ -104,15 +99,22 @@ task 'build:browser', 'rebuild the merged script for inclusion in the browser',
|
||||
};
|
||||
"""
|
||||
code = """
|
||||
this.CoffeeScript = function() {
|
||||
function require(path){ return require[path]; }
|
||||
#{code}
|
||||
return require['./coffee-script']
|
||||
}()
|
||||
(function(root) {
|
||||
var CoffeeScript = function() {
|
||||
function require(path){ return require[path]; }
|
||||
#{code}
|
||||
return require['./coffee-script'];
|
||||
}();
|
||||
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(function() { return CoffeeScript; });
|
||||
} else {
|
||||
root.CoffeeScript = CoffeeScript;
|
||||
}
|
||||
}(this));
|
||||
"""
|
||||
unless process.env.MINIFY is 'false'
|
||||
{parser, uglify} = require 'uglify-js'
|
||||
code = uglify.gen_code uglify.ast_squeeze uglify.ast_mangle parser.parse code
|
||||
{code} = require('uglify-js').minify code, fromString: true
|
||||
fs.writeFileSync 'extras/coffee-script.js', header + '\n' + code
|
||||
console.log "built ... running browser tests:"
|
||||
invoke 'test:browser'
|
||||
@@ -134,25 +136,25 @@ task 'doc:underscore', 'rebuild the Underscore.coffee documentation page', ->
|
||||
|
||||
task 'bench', 'quick benchmark of compilation time', ->
|
||||
{Rewriter} = require './lib/coffee-script/rewriter'
|
||||
co = sources.map((name) -> fs.readFileSync name).join '\n'
|
||||
sources = ['coffee-script', 'grammar', 'helpers', 'lexer', 'nodes', 'rewriter']
|
||||
coffee = sources.map((name) -> fs.readFileSync "src/#{name}.coffee").join '\n'
|
||||
litcoffee = fs.readFileSync("src/scope.litcoffee").toString()
|
||||
fmt = (ms) -> " #{bold}#{ " #{ms}".slice -4 }#{reset} ms"
|
||||
total = 0
|
||||
now = Date.now()
|
||||
time = -> total += ms = -(now - now = Date.now()); fmt ms
|
||||
tokens = CoffeeScript.tokens co, rewrite: false
|
||||
tokens = CoffeeScript.tokens coffee, rewrite: no
|
||||
littokens = CoffeeScript.tokens litcoffee, rewrite: no, literate: yes
|
||||
tokens = tokens.concat(littokens)
|
||||
console.log "Lex #{time()} (#{tokens.length} tokens)"
|
||||
tokens = new Rewriter().rewrite tokens
|
||||
console.log "Rewrite#{time()} (#{tokens.length} tokens)"
|
||||
nodes = CoffeeScript.nodes tokens
|
||||
console.log "Parse #{time()}"
|
||||
js = nodes.compile bare: true
|
||||
js = nodes.compile bare: yes
|
||||
console.log "Compile#{time()} (#{js.length} chars)"
|
||||
console.log "total #{ fmt total }"
|
||||
|
||||
task 'loc', 'count the lines of source code in the CoffeeScript compiler', ->
|
||||
exec "cat #{ sources.join(' ') } | grep -v '^\\( *#\\|\\s*$\\)' | wc -l | tr -s ' '", (err, stdout) ->
|
||||
console.log stdout.trim()
|
||||
|
||||
|
||||
# Run the CoffeeScript test suite.
|
||||
runTests = (CoffeeScript) ->
|
||||
@@ -165,6 +167,7 @@ runTests = (CoffeeScript) ->
|
||||
|
||||
# Convenience aliases.
|
||||
global.CoffeeScript = CoffeeScript
|
||||
global.Repl = require './lib/coffee-script/repl'
|
||||
|
||||
# Our test helper function for delimiting different test cases.
|
||||
global.test = (description, fn) ->
|
||||
@@ -173,9 +176,11 @@ runTests = (CoffeeScript) ->
|
||||
fn.call(fn)
|
||||
++passedTests
|
||||
catch e
|
||||
e.description = description if description?
|
||||
e.source = fn.toString() if fn.toString?
|
||||
failures.push filename: currentFile, error: e
|
||||
failures.push
|
||||
filename: currentFile
|
||||
error: e
|
||||
description: description if description?
|
||||
source: fn.toString() if fn.toString?
|
||||
|
||||
# See http://wiki.ecmascript.org/doku.php?id=harmony:egal
|
||||
egal = (a, b) ->
|
||||
@@ -192,8 +197,8 @@ runTests = (CoffeeScript) ->
|
||||
return no for el, idx in a when not arrayEgal el, b[idx]
|
||||
yes
|
||||
|
||||
global.eq = (a, b, msg) -> ok egal(a, b), msg
|
||||
global.arrayEq = (a, b, msg) -> ok arrayEgal(a,b), msg
|
||||
global.eq = (a, b, msg) -> ok egal(a, b), msg ? "Expected #{a} to equal #{b}"
|
||||
global.arrayEq = (a, b, msg) -> ok arrayEgal(a,b), msg ? "Expected #{a} to deep equal #{b}"
|
||||
|
||||
# When all the tests have run, collect and print errors.
|
||||
# If a stacktrace is available, output the compiled function source.
|
||||
@@ -203,25 +208,26 @@ runTests = (CoffeeScript) ->
|
||||
return log(message, green) unless failures.length
|
||||
log "failed #{failures.length} and #{message}", red
|
||||
for fail in failures
|
||||
{error, filename} = fail
|
||||
{error, filename, description, source} = fail
|
||||
jsFilename = filename.replace(/\.coffee$/,'.js')
|
||||
match = error.stack?.match(new RegExp(fail.file+":(\\d+):(\\d+)"))
|
||||
match = error.stack?.match(/on line (\d+):/) unless match
|
||||
[match, line, col] = match if match
|
||||
console.log ''
|
||||
log " #{error.description}", red if error.description
|
||||
log " #{description}", red if description
|
||||
log " #{error.stack}", red
|
||||
log " #{jsFilename}: line #{line ? 'unknown'}, column #{col ? 'unknown'}", red
|
||||
console.log " #{error.source}" if error.source
|
||||
console.log " #{source}" if source
|
||||
return
|
||||
|
||||
# Run every test in the `test` folder, recording failures.
|
||||
files = fs.readdirSync 'test'
|
||||
for file in files when file.match /\.coffee$/i
|
||||
for file in files when file.match /\.(lit)?coffee$/i
|
||||
literate = path.extname(file) is '.litcoffee'
|
||||
currentFile = filename = path.join 'test', file
|
||||
code = fs.readFileSync filename
|
||||
try
|
||||
CoffeeScript.run code.toString(), {filename}
|
||||
CoffeeScript.run code.toString(), {filename, literate}
|
||||
catch error
|
||||
failures.push {filename, error}
|
||||
return !failures.length
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2011 Jeremy Ashkenas
|
||||
Copyright (c) 2009-2012 Jeremy Ashkenas
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
||||
1
Rakefile
1
Rakefile
@@ -49,6 +49,7 @@ task :gem do
|
||||
s.authors = ['Jeremy Ashkenas']
|
||||
s.email = 'jashkenas@gmail.com'
|
||||
s.rubyforge_project = 'coffee-script-source'
|
||||
s.license = "MIT"
|
||||
end
|
||||
|
||||
file = File.open("coffee-script-source.gem", "w")
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Eat lunch.
|
||||
eat food for food in ['toast', 'cheese', 'wine']
|
||||
|
||||
# Fine dining
|
||||
courses = ['salad', 'entree', 'dessert']
|
||||
menu course + 1, dish for dish, course in courses
|
||||
# Fine five course dining.
|
||||
courses = ['greens', 'caviar', 'truffles', 'roast', 'cake']
|
||||
menu i + 1, dish for dish, i in courses
|
||||
|
||||
# Health conscious meal
|
||||
# Health conscious meal.
|
||||
foods = ['broccoli', 'spinach', 'chocolate']
|
||||
eat food for food in foods when food isnt 'chocolate'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
###
|
||||
CoffeeScript Compiler v1.1.3
|
||||
CoffeeScript Compiler v1.5.0
|
||||
Released under the MIT License
|
||||
###
|
||||
|
||||
|
||||
@@ -8,6 +8,5 @@ else
|
||||
|
||||
date = if friday then sue else jill
|
||||
|
||||
options or= defaults
|
||||
|
||||
|
||||
|
||||
@@ -3,3 +3,4 @@ hi = `function() {
|
||||
}`
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
solipsism = true if mind? and not world?
|
||||
|
||||
speed ?= 75
|
||||
speed = 0
|
||||
speed ?= 15
|
||||
|
||||
footprints = yeti ? "bear"
|
||||
|
||||
@@ -8,3 +9,5 @@ footprints = yeti ? "bear"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
html = '''
|
||||
html = """
|
||||
<strong>
|
||||
cup of coffeescript
|
||||
</strong>
|
||||
'''
|
||||
|
||||
|
||||
"""
|
||||
|
||||
|
||||
@@ -4,3 +4,6 @@ quote = "A picture is a fact. -- #{ author }"
|
||||
sentence = "#{ 22 / 7 } is a decent approximation of π"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,3 +5,5 @@ weatherReport = (location) ->
|
||||
[city, temp, forecast] = weatherReport "Berkeley, CA"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -11,3 +11,4 @@ futurists =
|
||||
{poet: {name, address: [street, city]}} = futurists
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,3 +4,6 @@ theSwitch = 0
|
||||
[theBait, theSwitch] = [theSwitch, theBait]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,3 +5,5 @@ tag = "<impossible>"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
|
||||
copy = numbers[0...numbers.length]
|
||||
start = numbers[0..2]
|
||||
|
||||
middle = copy[3..6]
|
||||
middle = numbers[3...6]
|
||||
|
||||
end = numbers[6..]
|
||||
|
||||
copy = numbers[..]
|
||||
|
||||
@@ -3,3 +3,5 @@ numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
numbers[3..6] = [-3, -4, -5, -6]
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,36 +1,40 @@
|
||||
<!DOCTYPE html> <html> <head> <title>browser.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> browser.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> <p>Override exported methods for non-Node.js engines.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s1">'./coffee-script'</span>
|
||||
<span class="nv">CoffeeScript.require = </span><span class="nx">require</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>Use standard JavaScript <code>eval</code> to eval code.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.eval = </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nb">eval</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Running code does not provide access to this scope.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.run = </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nv">options = </span><span class="p">{})</span> <span class="o">-></span>
|
||||
<!DOCTYPE html> <html> <head> <title>browser.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> browser.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> <p>Override exported methods for non-Node.js engines.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s">'./coffee-script'</span>
|
||||
<span class="nv">CoffeeScript.require = </span><span class="nx">require</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>Use standard JavaScript <code>eval</code> to eval code.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.eval = </span><span class="nf">(code, options = {}) -></span>
|
||||
<span class="nx">options</span><span class="p">.</span><span class="nx">bare</span> <span class="o">?=</span> <span class="kc">on</span>
|
||||
<span class="nb">eval</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Running code does not provide access to this scope.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.run = </span><span class="nf">(code, options = {}) -></span>
|
||||
<span class="nv">options.bare = </span><span class="kc">on</span>
|
||||
<span class="nb">Function</span><span class="p">(</span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)()</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>If we're not in a browser environment, we're finished with the public API.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">return</span> <span class="nx">unless</span> <span class="nb">window</span><span class="o">?</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Load a remote script from the current domain via XHR.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.load = </span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">xhr = </span><span class="k">new</span> <span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">ActiveXObject</span> <span class="o">or</span> <span class="nx">XMLHttpRequest</span><span class="p">)(</span><span class="s1">'Microsoft.XMLHTTP'</span><span class="p">)</span>
|
||||
<span class="nx">xhr</span><span class="p">.</span><span class="nx">open</span> <span class="s1">'GET'</span><span class="p">,</span> <span class="nx">url</span><span class="p">,</span> <span class="kc">true</span>
|
||||
<span class="nx">xhr</span><span class="p">.</span><span class="nx">overrideMimeType</span> <span class="s1">'text/plain'</span> <span class="k">if</span> <span class="s1">'overrideMimeType'</span> <span class="k">of</span> <span class="nx">xhr</span>
|
||||
<span class="nv">xhr.onreadystatechange = </span><span class="o">-></span>
|
||||
<span class="nb">Function</span><span class="p">(</span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)()</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>If we're not in a browser environment, we're finished with the public API.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">return</span> <span class="k">unless</span> <span class="nb">window</span><span class="o">?</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Load a remote script from the current domain via XHR.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.load = </span><span class="nf">(url, callback) -></span>
|
||||
<span class="nv">xhr = </span><span class="k">if</span> <span class="nb">window</span><span class="p">.</span><span class="nx">ActiveXObject</span>
|
||||
<span class="k">new</span> <span class="nb">window</span><span class="p">.</span><span class="nx">ActiveXObject</span><span class="p">(</span><span class="s">'Microsoft.XMLHTTP'</span><span class="p">)</span>
|
||||
<span class="k">else</span>
|
||||
<span class="k">new</span> <span class="nx">XMLHttpRequest</span><span class="p">()</span>
|
||||
<span class="nx">xhr</span><span class="p">.</span><span class="nx">open</span> <span class="s">'GET'</span><span class="p">,</span> <span class="nx">url</span><span class="p">,</span> <span class="kc">true</span>
|
||||
<span class="nx">xhr</span><span class="p">.</span><span class="nx">overrideMimeType</span> <span class="s">'text/plain'</span> <span class="k">if</span> <span class="s">'overrideMimeType'</span> <span class="k">of</span> <span class="nx">xhr</span>
|
||||
<span class="nv">xhr.onreadystatechange = </span><span class="nf">-></span>
|
||||
<span class="k">if</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">readyState</span> <span class="o">is</span> <span class="mi">4</span>
|
||||
<span class="k">if</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">status</span> <span class="k">in</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">200</span><span class="p">]</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">responseText</span>
|
||||
<span class="k">else</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"Could not load #{url}"</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">"Could not load </span><span class="si">#{</span><span class="nx">url</span><span class="si">}</span><span class="s">"</span>
|
||||
<span class="nx">callback</span><span class="p">()</span> <span class="k">if</span> <span class="nx">callback</span>
|
||||
<span class="nx">xhr</span><span class="p">.</span><span class="nx">send</span> <span class="kc">null</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Activate CoffeeScript in the browser by having it compile and evaluate
|
||||
all script tags with a content-type of <code>text/coffeescript</code>.
|
||||
This happens on page load.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">runScripts = </span><span class="o">-></span>
|
||||
<span class="nv">scripts = </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span> <span class="s1">'script'</span>
|
||||
<span class="nv">coffees = </span><span class="p">(</span><span class="nx">s</span> <span class="k">for</span> <span class="nx">s</span> <span class="k">in</span> <span class="nx">scripts</span> <span class="k">when</span> <span class="nx">s</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s1">'text/coffeescript'</span><span class="p">)</span>
|
||||
This happens on page load.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">runScripts = </span><span class="nf">-></span>
|
||||
<span class="nv">scripts = </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span> <span class="s">'script'</span>
|
||||
<span class="nv">coffees = </span><span class="p">(</span><span class="nx">s</span> <span class="k">for</span> <span class="nx">s</span> <span class="k">in</span> <span class="nx">scripts</span> <span class="k">when</span> <span class="nx">s</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s">'text/coffeescript'</span><span class="p">)</span>
|
||||
<span class="nv">index = </span><span class="mi">0</span>
|
||||
<span class="nv">length = </span><span class="nx">coffees</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nx">do</span> <span class="nv">execute = </span><span class="o">-></span>
|
||||
<span class="nx">do</span> <span class="nv">execute = </span><span class="nf">-></span>
|
||||
<span class="nv">script = </span><span class="nx">coffees</span><span class="p">[</span><span class="nx">index</span><span class="o">++</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="nx">script</span><span class="o">?</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s1">'text/coffeescript'</span>
|
||||
<span class="k">if</span> <span class="nx">script</span><span class="o">?</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s">'text/coffeescript'</span>
|
||||
<span class="k">if</span> <span class="nx">script</span><span class="p">.</span><span class="nx">src</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">load</span> <span class="nx">script</span><span class="p">.</span><span class="nx">src</span><span class="p">,</span> <span class="nx">execute</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">script</span><span class="p">.</span><span class="nx">innerHTML</span>
|
||||
<span class="nx">execute</span><span class="p">()</span>
|
||||
<span class="kc">null</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Listen for window load, both in browsers and in IE.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span>
|
||||
<span class="nx">addEventListener</span> <span class="s1">'DOMContentLoaded'</span><span class="p">,</span> <span class="nx">runScripts</span><span class="p">,</span> <span class="kc">no</span>
|
||||
<span class="nx">addEventListener</span> <span class="s">'DOMContentLoaded'</span><span class="p">,</span> <span class="nx">runScripts</span><span class="p">,</span> <span class="kc">no</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">attachEvent</span> <span class="s1">'onload'</span><span class="p">,</span> <span class="nx">runScripts</span>
|
||||
<span class="nx">attachEvent</span> <span class="s">'onload'</span><span class="p">,</span> <span class="nx">runScripts</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -1,49 +1,59 @@
|
||||
<!DOCTYPE html> <html> <head> <title>cake.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> cake.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> <p><code>cake</code> is a simplified version of <a href="http://www.gnu.org/software/make/">Make</a>
|
||||
<!DOCTYPE html> <html> <head> <title>cake.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </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="pilwrap"> <a class="pilcrow" 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="pilwrap"> <a class="pilcrow" 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="s1">'./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="pilwrap"> <a class="pilcrow" 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>
|
||||
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="pilwrap"> <a class="pilcrow" 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="s">'fs'</span>
|
||||
<span class="nv">path = </span><span class="nx">require</span> <span class="s">'path'</span>
|
||||
<span class="nv">helpers = </span><span class="nx">require</span> <span class="s">'./helpers'</span>
|
||||
<span class="nv">optparse = </span><span class="nx">require</span> <span class="s">'./optparse'</span>
|
||||
<span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s">'./coffee-script'</span>
|
||||
|
||||
<span class="nv">existsSync = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">existsSync</span> <span class="o">or</span> <span class="nx">path</span><span class="p">.</span><span class="nx">existsSync</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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="pilwrap"> <a class="pilcrow" 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></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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="nx">task</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> <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>
|
||||
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="nf">(name, description, action) -></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="k">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="pilwrap"> <a class="pilcrow" 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="nx">option</span><span class="o">:</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="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Invoke another task in the current Cakefile.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">invoke</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">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>
|
||||
as the first argument to the action.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">option: </span><span class="nf">(letter, flag, description) -></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="pilwrap"> <a class="pilcrow" 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="nf">(name) -></span>
|
||||
<span class="nx">missingTask</span> <span class="nx">name</span> <span class="k">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></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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. Keep a reference to the
|
||||
original directory name, when running Cake tasks from subdirectories. </p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run = </span><span class="o">-></span>
|
||||
<span class="nv">global.__originalDirname = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span> <span class="s1">'.'</span>
|
||||
If no tasks are passed, print the help screen. Keep a reference to the
|
||||
original directory name, when running Cake tasks from subdirectories.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run = </span><span class="nf">-></span>
|
||||
<span class="nv">global.__originalDirname = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span> <span class="s">'.'</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">chdir</span> <span class="nx">cakefileDirectory</span> <span class="nx">__originalDirname</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="nx">slice</span> <span class="mi">2</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="nx">filename</span><span class="o">:</span> <span class="s1">'Cakefile'</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">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="s">'Cakefile'</span><span class="p">).</span><span class="nx">toString</span><span class="p">(),</span> <span class="nv">filename: </span><span class="s">'Cakefile'</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="pilwrap"> <a class="pilcrow" 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">console</span><span class="p">.</span><span class="nx">log</span> <span class="s1">''</span>
|
||||
<span class="k">return</span> <span class="nx">printTasks</span><span class="p">()</span> <span class="k">unless</span> <span class="nx">args</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="k">try</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="k">catch</span> <span class="nx">e</span>
|
||||
<span class="k">return</span> <span class="nx">fatalError</span> <span class="s">"</span><span class="si">#{</span><span class="nx">e</span><span class="si">}</span><span class="s">"</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="pilwrap"> <a class="pilcrow" 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="nf">-></span>
|
||||
<span class="nv">relative = </span><span class="nx">path</span><span class="p">.</span><span class="nx">relative</span> <span class="o">or</span> <span class="nx">path</span><span class="p">.</span><span class="nx">resolve</span>
|
||||
<span class="nv">cakefilePath = </span><span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">relative</span><span class="p">(</span><span class="nx">__originalDirname</span><span class="p">,</span> <span class="nx">process</span><span class="p">.</span><span class="nx">cwd</span><span class="p">()),</span> <span class="s">'Cakefile'</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s">"</span><span class="si">#{</span><span class="nx">cakefilePath</span><span class="si">}</span><span class="s"> defines the following tasks:\n"</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="nb">Array</span><span class="p">(</span><span class="nx">spaces</span> <span class="o">+</span> <span class="mi">1</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s1">' '</span><span class="p">)</span> <span class="k">else</span> <span class="s1">''</span>
|
||||
<span class="nv">desc = </span><span class="k">if</span> <span class="nx">task</span><span class="p">.</span><span class="nx">description</span> <span class="k">then</span> <span class="s2">"# #{task.description}"</span> <span class="k">else</span> <span class="s1">''</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s2">"cake #{name}#{spaces} #{desc}"</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</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="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Print an error and exit when attempting to call 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">console</span><span class="p">.</span><span class="nx">log</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> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>When <code>cake</code> is invoked, search in the current and all parent directories
|
||||
to find the relevant Cakefile.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">cakefileDirectory = </span><span class="p">(</span><span class="nx">dir</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="nx">dir</span> <span class="k">if</span> <span class="nx">path</span><span class="p">.</span><span class="nx">existsSync</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="s1">'Cakefile'</span>
|
||||
<span class="nv">parent = </span><span class="nx">path</span><span class="p">.</span><span class="nx">normalize</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="s1">'..'</span>
|
||||
<span class="k">return</span> <span class="nx">cakefileDirectory</span> <span class="nx">parent</span> <span class="nx">unless</span> <span class="nx">parent</span> <span class="o">is</span> <span class="nx">dir</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"Cakefile not found in #{process.cwd()}"</span>
|
||||
<span class="nv">spaces = </span><span class="k">if</span> <span class="nx">spaces</span> <span class="o">></span> <span class="mi">0</span> <span class="k">then</span> <span class="nb">Array</span><span class="p">(</span><span class="nx">spaces</span> <span class="o">+</span> <span class="mi">1</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s">' '</span><span class="p">)</span> <span class="k">else</span> <span class="s">''</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="s">"</span><span class="err">#</span><span class="s"> </span><span class="si">#{</span><span class="nx">task</span><span class="p">.</span><span class="nx">description</span><span class="si">}</span><span class="s">"</span> <span class="k">else</span> <span class="s">''</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s">"cake </span><span class="si">#{</span><span class="nx">name</span><span class="si">}#{</span><span class="nx">spaces</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">desc</span><span class="si">}</span><span class="s">"</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</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="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Print an error and exit when attempting to use an invalid task/option.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">fatalError = </span><span class="nf">(message) -></span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span> <span class="nx">message</span> <span class="o">+</span> <span class="s">'\n'</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s">'To see a list of all tasks/options, run "cake"'</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span>
|
||||
|
||||
<span class="nv">missingTask = </span><span class="nf">(task) -></span> <span class="nx">fatalError</span> <span class="s">"No such task: </span><span class="si">#{</span><span class="nx">task</span><span class="si">}</span><span class="s">"</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>When <code>cake</code> is invoked, search in the current and all parent directories
|
||||
to find the relevant Cakefile.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">cakefileDirectory = </span><span class="nf">(dir) -></span>
|
||||
<span class="k">return</span> <span class="nx">dir</span> <span class="k">if</span> <span class="nx">existsSync</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="s">'Cakefile'</span>
|
||||
<span class="nv">parent = </span><span class="nx">path</span><span class="p">.</span><span class="nx">normalize</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="s">'..'</span>
|
||||
<span class="k">return</span> <span class="nx">cakefileDirectory</span> <span class="nx">parent</span> <span class="k">unless</span> <span class="nx">parent</span> <span class="o">is</span> <span class="nx">dir</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">"Cakefile not found in </span><span class="si">#{</span><span class="nx">process</span><span class="p">.</span><span class="nx">cwd</span><span class="p">()</span><span class="si">}</span><span class="s">"</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -1,40 +1,46 @@
|
||||
<!DOCTYPE html> <html> <head> <title>coffee-script.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> coffee-script.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> <p>CoffeeScript can be used both on the server, as a command-line compiler based
|
||||
<!DOCTYPE html> <html> <head> <title>coffee-script.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </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="pilwrap"> <a class="pilcrow" 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 tokenizing, 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><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="p">{</span><span class="nx">Lexer</span><span class="p">,</span><span class="nx">RESERVED</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'./lexer'</span>
|
||||
<span class="p">{</span><span class="nx">parser</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'./parser'</span>
|
||||
<span class="nv">vm = </span><span class="nx">require</span> <span class="s1">'vm'</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>TODO: Remove registerExtension when fully deprecated.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span>
|
||||
<span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span><span class="p">[</span><span class="s1">'.coffee'</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="nx">module</span><span class="p">,</span> <span class="nx">filename</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">content = </span><span class="nx">compile</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="nx">filename</span><span class="p">,</span> <span class="s1">'utf8'</span><span class="p">),</span> <span class="p">{</span><span class="nx">filename</span><span class="p">}</span>
|
||||
<span class="nx">module</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">content</span><span class="p">,</span> <span class="nx">filename</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">require</span><span class="p">.</span><span class="nx">registerExtension</span>
|
||||
<span class="nx">require</span><span class="p">.</span><span class="nx">registerExtension</span> <span class="s1">'.coffee'</span><span class="p">,</span> <span class="p">(</span><span class="nx">content</span><span class="p">)</span> <span class="o">-></span> <span class="nx">compile</span> <span class="nx">content</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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">'1.1.3'</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Words that cannot be used as identifiers in CoffeeScript code</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.RESERVED = </span><span class="nx">RESERVED</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Expose helpers for testing.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.helpers = </span><span class="nx">require</span> <span class="s1">'./helpers'</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</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="nv">options = </span><span class="p">{})</span> <span class="o">-></span>
|
||||
execute all scripts present in <code>text/coffeescript</code> tags.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">fs = </span><span class="nx">require</span> <span class="s">'fs'</span>
|
||||
<span class="nv">path = </span><span class="nx">require</span> <span class="s">'path'</span>
|
||||
<span class="p">{</span><span class="nx">Lexer</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">'./lexer'</span>
|
||||
<span class="p">{</span><span class="nx">parser</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">'./parser'</span>
|
||||
<span class="nv">vm = </span><span class="nx">require</span> <span class="s">'vm'</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>The file extensions that are considered to be CoffeeScript.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">extensions = </span><span class="p">[</span><span class="s">'.coffee'</span><span class="p">,</span> <span class="s">'.litcoffee'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Load and run a CoffeeScript file for Node, stripping any <code>BOM</code>s.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">loadFile = </span><span class="nf">(module, filename) -></span>
|
||||
<span class="nv">raw = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span> <span class="nx">filename</span><span class="p">,</span> <span class="s">'utf8'</span>
|
||||
<span class="nv">stripped = </span><span class="k">if</span> <span class="nx">raw</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">is</span> <span class="mh">0xFEFF</span> <span class="k">then</span> <span class="nx">raw</span><span class="p">.</span><span class="nx">substring</span> <span class="mi">1</span> <span class="k">else</span> <span class="nx">raw</span>
|
||||
<span class="nx">module</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">compile</span><span class="p">(</span><span class="nx">stripped</span><span class="p">,</span> <span class="p">{</span><span class="nx">filename</span><span class="p">}),</span> <span class="nx">filename</span>
|
||||
|
||||
<span class="k">if</span> <span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span>
|
||||
<span class="k">for</span> <span class="nx">ext</span> <span class="k">in</span> <span class="nx">extensions</span>
|
||||
<span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span><span class="p">[</span><span class="nx">ext</span><span class="p">]</span> <span class="o">=</span> <span class="nx">loadFile</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</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="s">'1.5.0'</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Expose helpers for testing.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.helpers = </span><span class="nx">require</span> <span class="s">'./helpers'</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</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="nf">(code, options = {}) -></span>
|
||||
<span class="p">{</span><span class="nx">merge</span><span class="p">}</span> <span class="o">=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">helpers</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="nv">js = </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="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)).</span><span class="nx">compile</span> <span class="nx">options</span>
|
||||
<span class="k">return</span> <span class="nx">js</span> <span class="k">unless</span> <span class="nx">options</span><span class="p">.</span><span class="nx">header</span>
|
||||
<span class="k">catch</span> <span class="nx">err</span>
|
||||
<span class="nv">err.message = </span><span class="s2">"In #{options.filename}, #{err.message}"</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span>
|
||||
<span class="k">throw</span> <span class="nx">err</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</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="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">err.message = </span><span class="s">"In </span><span class="si">#{</span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span><span class="si">}</span><span class="s">, </span><span class="si">#{</span><span class="nx">err</span><span class="p">.</span><span class="nx">message</span><span class="si">}</span><span class="s">"</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span>
|
||||
<span class="k">throw</span> <span class="nx">err</span>
|
||||
<span class="nv">header = </span><span class="s">"Generated by CoffeeScript </span><span class="si">#{</span><span class="nx">@VERSION</span><span class="si">}</span><span class="s">"</span>
|
||||
<span class="s">"// </span><span class="si">#{</span><span class="nx">header</span><span class="si">}</span><span class="s">\n</span><span class="si">#{</span><span class="nx">js</span><span class="si">}</span><span class="s">"</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</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="nf">(code, options) -></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">options</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Parse a string of CoffeeScript code or an array of lexed tokens, 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">source</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="k">typeof</span> <span class="nx">source</span> <span class="o">is</span> <span class="s1">'string'</span>
|
||||
or traverse it by using <code>.traverseChildren()</code> with a callback.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.nodes = </span><span class="nf">(source, options) -></span>
|
||||
<span class="k">if</span> <span class="k">typeof</span> <span class="nx">source</span> <span class="o">is</span> <span class="s">'string'</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">source</span><span class="p">,</span> <span class="nx">options</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">source</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</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>
|
||||
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="nf">(code, options = {}) -></span>
|
||||
<span class="nv">mainModule = </span><span class="nx">require</span><span class="p">.</span><span class="nx">main</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Set the filename.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">mainModule.filename = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span>
|
||||
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span> <span class="k">then</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span> <span class="k">else</span> <span class="s1">'.'</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Clear the module cache.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">mainModule</span><span class="p">.</span><span class="nx">moduleCache</span> <span class="o">and=</span> <span class="p">{}</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Assign paths for node_modules loading</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">mainModule.paths = </span><span class="nx">require</span><span class="p">(</span><span class="s1">'module'</span><span class="p">).</span><span class="nx">_nodeModulePaths</span> <span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Compile.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">mainModule</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span> <span class="o">isnt</span> <span class="s1">'.coffee'</span> <span class="o">or</span> <span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span>
|
||||
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span> <span class="k">then</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span> <span class="k">else</span> <span class="s">'.'</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Clear the module cache.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">mainModule</span><span class="p">.</span><span class="nx">moduleCache</span> <span class="o">and=</span> <span class="p">{}</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Assign paths for node_modules loading</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">mainModule.paths = </span><span class="nx">require</span><span class="p">(</span><span class="s">'module'</span><span class="p">).</span><span class="nx">_nodeModulePaths</span> <span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Compile.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</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">mainModule</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span> <span class="o">not</span> <span class="k">in</span> <span class="nx">extensions</span><span class="p">)</span> <span class="o">or</span> <span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span>
|
||||
<span class="nx">mainModule</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">compile</span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">),</span> <span class="nx">mainModule</span><span class="p">.</span><span class="nx">filename</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">mainModule</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">mainModule</span><span class="p">.</span><span class="nx">filename</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Compile and evaluate a string of CoffeeScript (in a Node.js-like environment).
|
||||
The CoffeeScript REPL uses this to run the input.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.eval = </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nv">options = </span><span class="p">{})</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="nx">unless</span> <span class="nv">code = </span><span class="nx">code</span><span class="p">.</span><span class="nx">trim</span><span class="p">()</span>
|
||||
The CoffeeScript REPL uses this to run the input.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.eval = </span><span class="nf">(code, options = {}) -></span>
|
||||
<span class="k">return</span> <span class="k">unless</span> <span class="nv">code = </span><span class="nx">code</span><span class="p">.</span><span class="nx">trim</span><span class="p">()</span>
|
||||
<span class="nv">Script = </span><span class="nx">vm</span><span class="p">.</span><span class="nx">Script</span>
|
||||
<span class="k">if</span> <span class="nx">Script</span>
|
||||
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</span><span class="o">?</span>
|
||||
@@ -42,20 +48,20 @@ The CoffeeScript REPL uses this to run the input.</p> </td>
|
||||
<span class="nv">sandbox = </span><span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">sandbox = </span><span class="nx">Script</span><span class="p">.</span><span class="nx">createContext</span><span class="p">()</span>
|
||||
<span class="nx">sandbox</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">v</span> <span class="k">for</span> <span class="nx">own</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</span>
|
||||
<span class="nx">sandbox</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">v</span> <span class="k">for</span> <span class="k">own</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sandbox</span>
|
||||
<span class="nv">sandbox.global = sandbox.root = sandbox.GLOBAL = </span><span class="nx">sandbox</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">sandbox = </span><span class="nx">global</span>
|
||||
<span class="nv">sandbox.__filename = </span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span> <span class="o">||</span> <span class="s1">'eval'</span>
|
||||
<span class="nv">sandbox.__dirname = </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">__filename</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>define module/require only if they chose not to specify their own</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">unless</span> <span class="nx">sandbox</span> <span class="o">isnt</span> <span class="nx">global</span> <span class="o">or</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">module</span> <span class="o">or</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">require</span>
|
||||
<span class="nv">Module = </span><span class="nx">require</span> <span class="s1">'module'</span>
|
||||
<span class="nv">sandbox.module = _module = </span><span class="k">new</span> <span class="nx">Module</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">modulename</span> <span class="o">||</span> <span class="s1">'eval'</span><span class="p">)</span>
|
||||
<span class="nv">sandbox.require = _require = </span><span class="p">(</span><span class="nx">path</span><span class="p">)</span> <span class="o">-></span> <span class="nx">Module</span><span class="p">.</span><span class="nx">_load</span> <span class="nx">path</span><span class="p">,</span> <span class="nx">_module</span><span class="p">,</span> <span class="kc">true</span>
|
||||
<span class="nv">sandbox.__filename = </span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span> <span class="o">||</span> <span class="s">'eval'</span>
|
||||
<span class="nv">sandbox.__dirname = </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">__filename</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>define module/require only if they chose not to specify their own</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">unless</span> <span class="nx">sandbox</span> <span class="o">isnt</span> <span class="nx">global</span> <span class="o">or</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">module</span> <span class="o">or</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">require</span>
|
||||
<span class="nv">Module = </span><span class="nx">require</span> <span class="s">'module'</span>
|
||||
<span class="nv">sandbox.module = _module = </span><span class="k">new</span> <span class="nx">Module</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">modulename</span> <span class="o">||</span> <span class="s">'eval'</span><span class="p">)</span>
|
||||
<span class="nv">sandbox.require = _require = </span><span class="nf">(path) -></span> <span class="nx">Module</span><span class="p">.</span><span class="nx">_load</span> <span class="nx">path</span><span class="p">,</span> <span class="nx">_module</span><span class="p">,</span> <span class="kc">true</span>
|
||||
<span class="nv">_module.filename = </span><span class="nx">sandbox</span><span class="p">.</span><span class="nx">__filename</span>
|
||||
<span class="nx">_require</span><span class="p">[</span><span class="nx">r</span><span class="p">]</span> <span class="o">=</span> <span class="nx">require</span><span class="p">[</span><span class="nx">r</span><span class="p">]</span> <span class="k">for</span> <span class="nx">r</span> <span class="k">in</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertyNames</span> <span class="nx">require</span> <span class="k">when</span> <span class="nx">r</span> <span class="o">isnt</span> <span class="s1">'paths'</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>use the same hack node currently uses for their own REPL</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">_require.paths = _module.paths = </span><span class="nx">Module</span><span class="p">.</span><span class="nx">_nodeModulePaths</span> <span class="nx">process</span><span class="p">.</span><span class="nx">cwd</span><span class="p">()</span>
|
||||
<span class="nv">_require.resolve = </span><span class="p">(</span><span class="nx">request</span><span class="p">)</span> <span class="o">-></span> <span class="nx">Module</span><span class="p">.</span><span class="nx">_resolveFilename</span> <span class="nx">request</span><span class="p">,</span> <span class="nx">_module</span>
|
||||
<span class="nx">_require</span><span class="p">[</span><span class="nx">r</span><span class="p">]</span> <span class="o">=</span> <span class="nx">require</span><span class="p">[</span><span class="nx">r</span><span class="p">]</span> <span class="k">for</span> <span class="nx">r</span> <span class="k">in</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertyNames</span> <span class="nx">require</span> <span class="k">when</span> <span class="nx">r</span> <span class="o">isnt</span> <span class="s">'paths'</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>use the same hack node currently uses for their own REPL</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">_require.paths = _module.paths = </span><span class="nx">Module</span><span class="p">.</span><span class="nx">_nodeModulePaths</span> <span class="nx">process</span><span class="p">.</span><span class="nx">cwd</span><span class="p">()</span>
|
||||
<span class="nv">_require.resolve = </span><span class="nf">(request) -></span> <span class="nx">Module</span><span class="p">.</span><span class="nx">_resolveFilename</span> <span class="nx">request</span><span class="p">,</span> <span class="nx">_module</span>
|
||||
<span class="nv">o = </span><span class="p">{}</span>
|
||||
<span class="nx">o</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">v</span> <span class="k">for</span> <span class="nx">own</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">options</span>
|
||||
<span class="nx">o</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">v</span> <span class="k">for</span> <span class="k">own</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">options</span>
|
||||
<span class="nv">o.bare = </span><span class="kc">on</span> <span class="c1"># ensure return value</span>
|
||||
<span class="nv">js = </span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">o</span>
|
||||
<span class="k">if</span> <span class="nx">sandbox</span> <span class="o">is</span> <span class="nx">global</span>
|
||||
@@ -64,14 +70,20 @@ The CoffeeScript REPL uses this to run the input.</p> </td>
|
||||
<span class="nx">vm</span><span class="p">.</span><span class="nx">runInContext</span> <span class="nx">js</span><span class="p">,</span> <span class="nx">sandbox</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>Instantiate a Lexer for our use here.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lexer = </span><span class="k">new</span> <span class="nx">Lexer</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <p>The real Lexer produces a generic stream of tokens. This object provides a
|
||||
thin wrapper around it, compatible with the Jison API. We can then pass it
|
||||
directly as a "Jison lexer".</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">parser.lexer =</span>
|
||||
<span class="nx">lex</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="p">[</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">@yytext</span><span class="p">,</span> <span class="nx">@yylineno</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">@pos</span><span class="o">++</span><span class="p">]</span> <span class="o">or</span> <span class="p">[</span><span class="s1">''</span><span class="p">]</span>
|
||||
<span class="nx">tag</span>
|
||||
<span class="nx">setInput</span><span class="o">:</span> <span class="p">(</span><span class="nx">@tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="vi">@pos = </span><span class="mi">0</span>
|
||||
<span class="nx">upcomingInput</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="s2">""</span>
|
||||
<span class="nv">lex: </span><span class="nf">-></span>
|
||||
<span class="nv">token = </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">@pos</span><span class="o">++</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="nx">token</span>
|
||||
<span class="p">[</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">@yytext</span><span class="p">,</span> <span class="nx">@yylloc</span><span class="p">]</span> <span class="o">=</span> <span class="nx">token</span>
|
||||
<span class="vi">@yylineno = </span><span class="nx">@yylloc</span><span class="p">.</span><span class="nx">first_line</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">tag = </span><span class="s">''</span>
|
||||
|
||||
<span class="nv">parser.yy = </span><span class="nx">require</span> <span class="s1">'./nodes'</span>
|
||||
<span class="nx">tag</span>
|
||||
<span class="nv">setInput: </span><span class="nf">(@tokens) -></span>
|
||||
<span class="vi">@pos = </span><span class="mi">0</span>
|
||||
<span class="nv">upcomingInput: </span><span class="nf">-></span>
|
||||
<span class="s">""</span>
|
||||
|
||||
<span class="nv">parser.yy = </span><span class="nx">require</span> <span class="s">'./nodes'</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -1,198 +1,263 @@
|
||||
<!DOCTYPE html> <html> <head> <title>command.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> command.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> <p>The <code>coffee</code> utility. Handles command-line compilation of CoffeeScript
|
||||
<!DOCTYPE html> <html> <head> <title>command.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </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="pilwrap"> <a class="pilcrow" 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/">JavaScript Lint</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="pilwrap"> <a class="pilcrow" 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="s1">'./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>
|
||||
<span class="p">{</span><span class="nx">spawn</span><span class="p">,</span> <span class="nx">exec</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'child_process'</span>
|
||||
<span class="p">{</span><span class="nx">EventEmitter</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'events'</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Allow CoffeeScript to emit Node.js events.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">helpers</span><span class="p">.</span><span class="nx">extend</span> <span class="nx">CoffeeScript</span><span class="p">,</span> <span class="k">new</span> <span class="nx">EventEmitter</span>
|
||||
interactive REPL.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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="s">'fs'</span>
|
||||
<span class="nv">path = </span><span class="nx">require</span> <span class="s">'path'</span>
|
||||
<span class="nv">helpers = </span><span class="nx">require</span> <span class="s">'./helpers'</span>
|
||||
<span class="nv">optparse = </span><span class="nx">require</span> <span class="s">'./optparse'</span>
|
||||
<span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s">'./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="s">'child_process'</span>
|
||||
<span class="p">{</span><span class="nx">EventEmitter</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">'events'</span>
|
||||
|
||||
<span class="nv">printLine = </span><span class="p">(</span><span class="nx">line</span><span class="p">)</span> <span class="o">-></span> <span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="nx">line</span> <span class="o">+</span> <span class="s1">'\n'</span>
|
||||
<span class="nv">printWarn = </span><span class="p">(</span><span class="nx">line</span><span class="p">)</span> <span class="o">-></span> <span class="nx">process</span><span class="p">.</span><span class="nx">stderr</span><span class="p">.</span><span class="nx">write</span> <span class="nx">line</span> <span class="o">+</span> <span class="s1">'\n'</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>The help banner that is printed when <code>coffee</code> is called without arguments.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BANNER = </span><span class="s1">'''</span>
|
||||
<span class="s1"> Usage: coffee [options] path/to/script.coffee</span>
|
||||
<span class="nv">exists = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">exists</span> <span class="o">or</span> <span class="nx">path</span><span class="p">.</span><span class="nx">exists</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Allow CoffeeScript to emit Node.js events.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">helpers</span><span class="p">.</span><span class="nx">extend</span> <span class="nx">CoffeeScript</span><span class="p">,</span> <span class="k">new</span> <span class="nx">EventEmitter</span>
|
||||
|
||||
<span class="s1"> If called without options, `coffee` will run your script.</span>
|
||||
<span class="s1"> '''</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>The list of all the valid option flags that <code>coffee</code> knows how to handle.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">SWITCHES = </span><span class="p">[</span>
|
||||
<span class="p">[</span><span class="s1">'-b'</span><span class="p">,</span> <span class="s1">'--bare'</span><span class="p">,</span> <span class="s1">'compile without a top-level function wrapper'</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">'-e'</span><span class="p">,</span> <span class="s1">'--eval'</span><span class="p">,</span> <span class="s1">'pass a string from the command line as input'</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><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">'-j'</span><span class="p">,</span> <span class="s1">'--join [FILE]'</span><span class="p">,</span> <span class="s1">'concatenate the source CoffeeScript before compiling'</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 JavaScript Lint'</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 out the parse tree that the parser produces'</span><span class="p">]</span>
|
||||
<span class="p">[</span> <span class="s1">'--nodejs [ARGS]'</span><span class="p">,</span> <span class="s1">'pass options directly to the "node" binary'</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 output directory for compiled JavaScript'</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 out the compiled JavaScript'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-r'</span><span class="p">,</span> <span class="s1">'--require [FILE*]'</span><span class="p">,</span> <span class="s1">'require a library before executing your script'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-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">'-t'</span><span class="p">,</span> <span class="s1">'--tokens'</span><span class="p">,</span> <span class="s1">'print out the tokens that the lexer/rewriter produce'</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 the version number'</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 rerun commands'</span><span class="p">]</span>
|
||||
<span class="nv">printLine = </span><span class="nf">(line) -></span> <span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="nx">line</span> <span class="o">+</span> <span class="s">'\n'</span>
|
||||
<span class="nv">printWarn = </span><span class="nf">(line) -></span> <span class="nx">process</span><span class="p">.</span><span class="nx">stderr</span><span class="p">.</span><span class="nx">write</span> <span class="nx">line</span> <span class="o">+</span> <span class="s">'\n'</span>
|
||||
|
||||
<span class="nv">hidden = </span><span class="nf">(file) -></span> <span class="o">/^</span><span class="err">\</span><span class="p">.</span><span class="o">|~</span><span class="nx">$</span><span class="o">/</span><span class="p">.</span><span class="nx">test</span> <span class="nx">file</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>The help banner that is printed when <code>coffee</code> is called without arguments.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BANNER = </span><span class="s">'''</span>
|
||||
<span class="s"> Usage: coffee [options] path/to/script.coffee -- [args]</span>
|
||||
|
||||
<span class="s"> If called without options, `coffee` will run your script.</span>
|
||||
<span class="s">'''</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>The list of all the valid option flags that <code>coffee</code> knows how to handle.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">SWITCHES = </span><span class="p">[</span>
|
||||
<span class="p">[</span><span class="s">'-b'</span><span class="p">,</span> <span class="s">'--bare'</span><span class="p">,</span> <span class="s">'compile without a top-level function wrapper'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-c'</span><span class="p">,</span> <span class="s">'--compile'</span><span class="p">,</span> <span class="s">'compile to JavaScript and save as .js files'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-e'</span><span class="p">,</span> <span class="s">'--eval'</span><span class="p">,</span> <span class="s">'pass a string from the command line as input'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-h'</span><span class="p">,</span> <span class="s">'--help'</span><span class="p">,</span> <span class="s">'display this help message'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-i'</span><span class="p">,</span> <span class="s">'--interactive'</span><span class="p">,</span> <span class="s">'run an interactive CoffeeScript REPL'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-j'</span><span class="p">,</span> <span class="s">'--join [FILE]'</span><span class="p">,</span> <span class="s">'concatenate the source CoffeeScript before compiling'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-l'</span><span class="p">,</span> <span class="s">'--lint'</span><span class="p">,</span> <span class="s">'pipe the compiled JavaScript through JavaScript Lint'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-n'</span><span class="p">,</span> <span class="s">'--nodes'</span><span class="p">,</span> <span class="s">'print out the parse tree that the parser produces'</span><span class="p">]</span>
|
||||
<span class="p">[</span> <span class="s">'--nodejs [ARGS]'</span><span class="p">,</span> <span class="s">'pass options directly to the "node" binary'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-o'</span><span class="p">,</span> <span class="s">'--output [DIR]'</span><span class="p">,</span> <span class="s">'set the output directory for compiled JavaScript'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-p'</span><span class="p">,</span> <span class="s">'--print'</span><span class="p">,</span> <span class="s">'print out the compiled JavaScript'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-s'</span><span class="p">,</span> <span class="s">'--stdio'</span><span class="p">,</span> <span class="s">'listen for and compile scripts over stdio'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-t'</span><span class="p">,</span> <span class="s">'--tokens'</span><span class="p">,</span> <span class="s">'print out the tokens that the lexer/rewriter produce'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-v'</span><span class="p">,</span> <span class="s">'--version'</span><span class="p">,</span> <span class="s">'display the version number'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'-w'</span><span class="p">,</span> <span class="s">'--watch'</span><span class="p">,</span> <span class="s">'watch scripts for changes and rerun commands'</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Top-level objects shared by all the functions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">opts = </span><span class="p">{}</span>
|
||||
<span class="nv">sources = </span><span class="p">[]</span>
|
||||
<span class="nv">contents = </span><span class="p">[]</span>
|
||||
<span class="nv">optionParser = </span><span class="kc">null</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Run <code>coffee</code> by parsing passed options and determining what action to take.
|
||||
<span class="nv">sourceCode = </span><span class="p">[]</span>
|
||||
<span class="nv">notSources = </span><span class="p">{}</span>
|
||||
<span class="nv">watchers = </span><span class="p">{}</span>
|
||||
<span class="nv">optionParser = </span><span class="kc">null</span>
|
||||
<span class="nv">coffee_exts = </span><span class="p">[</span><span class="s">'.coffee'</span><span class="p">,</span> <span class="s">'.litcoffee'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>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>
|
||||
<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="nf">-></span>
|
||||
<span class="nx">parseOptions</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="nx">forkNode</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">nodejs</span>
|
||||
<span class="k">return</span> <span class="nx">usage</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">help</span>
|
||||
<span class="k">return</span> <span class="nx">version</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">version</span>
|
||||
<span class="nx">loadRequires</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">require</span>
|
||||
<span class="k">return</span> <span class="nx">require</span> <span class="s1">'./repl'</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">interactive</span>
|
||||
<span class="k">return</span> <span class="nx">require</span><span class="p">(</span><span class="s">'./repl'</span><span class="p">).</span><span class="nx">start</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">interactive</span>
|
||||
<span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span> <span class="o">and</span> <span class="o">!</span><span class="nx">fs</span><span class="p">.</span><span class="nx">watch</span>
|
||||
<span class="k">return</span> <span class="nx">printWarn</span> <span class="s">"The --watch feature depends on Node v0.6.0+. You are running </span><span class="si">#{</span><span class="nx">process</span><span class="p">.</span><span class="nx">version</span><span class="si">}</span><span class="s">."</span>
|
||||
<span class="k">return</span> <span class="nx">compileStdio</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">stdio</span>
|
||||
<span class="k">return</span> <span class="nx">compileScript</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">sources</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nb">eval</span>
|
||||
<span class="k">return</span> <span class="nx">require</span> <span class="s1">'./repl'</span> <span class="nx">unless</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">run</span>
|
||||
<span class="nv">opts.literals = </span><span class="nx">sources</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="mi">1</span><span class="p">).</span><span class="nx">concat</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">literals</span>
|
||||
<span class="nv">process.argv = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">).</span><span class="nx">concat</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">literals</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'coffee'</span>
|
||||
<span class="nv">process.execPath = </span><span class="nx">require</span><span class="p">.</span><span class="nx">main</span><span class="p">.</span><span class="nx">filename</span>
|
||||
<span class="nx">compileScripts</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>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="nv">unprocessed = </span><span class="p">[]</span>
|
||||
<span class="nv">remaining_files = </span><span class="o">-></span>
|
||||
<span class="nv">total = </span><span class="mi">0</span>
|
||||
<span class="nx">total</span> <span class="o">+=</span> <span class="nx">x</span> <span class="k">for</span> <span class="nx">x</span> <span class="k">in</span> <span class="nx">unprocessed</span>
|
||||
<span class="nx">total</span>
|
||||
<span class="nv">trackUnprocessedFiles = </span><span class="p">(</span><span class="nx">sourceIndex</span><span class="p">,</span> <span class="nx">fileCount</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">unprocessed</span><span class="p">[</span><span class="nx">sourceIndex</span><span class="p">]</span> <span class="o">?=</span> <span class="mi">0</span>
|
||||
<span class="nx">unprocessed</span><span class="p">[</span><span class="nx">sourceIndex</span><span class="p">]</span> <span class="o">+=</span> <span class="nx">fileCount</span>
|
||||
<span class="nv">trackCompleteFiles = </span><span class="p">(</span><span class="nx">sourceIndex</span><span class="p">,</span> <span class="nx">fileCount</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">unprocessed</span><span class="p">[</span><span class="nx">sourceIndex</span><span class="p">]</span> <span class="o">-=</span> <span class="nx">fileCount</span>
|
||||
<span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span>
|
||||
<span class="k">if</span> <span class="nx">helpers</span><span class="p">.</span><span class="nx">compact</span><span class="p">(</span><span class="nx">contents</span><span class="p">).</span><span class="nx">length</span> <span class="o">></span> <span class="mi">0</span> <span class="o">and</span> <span class="nx">remaining_files</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span>
|
||||
<span class="nx">compileJoin</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="nx">require</span><span class="p">(</span><span class="s">'./repl'</span><span class="p">).</span><span class="nx">start</span><span class="p">()</span> <span class="k">unless</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">literals = </span><span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">run</span> <span class="k">then</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">splice</span> <span class="mi">1</span> <span class="k">else</span> <span class="p">[]</span>
|
||||
<span class="nv">process.argv = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">..</span><span class="mi">1</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">literals</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s">'coffee'</span>
|
||||
<span class="k">for</span> <span class="nx">source</span> <span class="k">in</span> <span class="nx">sources</span>
|
||||
<span class="nx">trackUnprocessedFiles</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">source</span><span class="p">),</span> <span class="mi">1</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">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="nv">compile = </span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">sourceIndex</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">if</span> <span class="nx">topLevel</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">exists</span> <span class="o">and</span> <span class="nx">source</span><span class="p">[</span><span class="o">-</span><span class="mi">7</span><span class="p">..]</span> <span class="o">isnt</span> <span class="s1">'.coffee'</span>
|
||||
<span class="k">return</span> <span class="nx">compile</span> <span class="s2">"#{source}.coffee"</span><span class="p">,</span> <span class="nx">sourceIndex</span><span class="p">,</span> <span class="nx">topLevel</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="k">if</span> <span class="nx">topLevel</span> <span class="o">and</span> <span class="o">not</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">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</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">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
|
||||
<span class="nx">trackUnprocessedFiles</span> <span class="nx">sourceIndex</span><span class="p">,</span> <span class="nx">files</span><span class="p">.</span><span class="nx">length</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="nx">sourceIndex</span>
|
||||
<span class="nx">trackCompleteFiles</span> <span class="nx">sourceIndex</span><span class="p">,</span> <span class="mi">1</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="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
|
||||
<span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span>
|
||||
<span class="nx">contents</span><span class="p">[</span><span class="nx">sourceIndex</span><span class="p">]</span> <span class="o">=</span> <span class="nx">helpers</span><span class="p">.</span><span class="nx">compact</span><span class="p">([</span><span class="nx">contents</span><span class="p">[</span><span class="nx">sourceIndex</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">join</span><span class="p">(</span><span class="s1">'\n'</span><span class="p">)</span>
|
||||
<span class="k">else</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">trackCompleteFiles</span> <span class="nx">sourceIndex</span><span class="p">,</span> <span class="mi">1</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">opts</span><span class="p">.</span><span class="nx">watch</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">trackCompleteFiles</span> <span class="nx">sourceIndex</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="nx">compile</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">source</span><span class="p">),</span> <span class="kc">true</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Compile a single source script, containing the given code, according to the
|
||||
<span class="nx">compilePath</span> <span class="nx">source</span><span class="p">,</span> <span class="kc">yes</span><span class="p">,</span> <span class="nx">path</span><span class="p">.</span><span class="nx">normalize</span> <span class="nx">source</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Compile a path, which could be a script or a directory. If a directory
|
||||
is passed, recursively compile all '.coffee' and '.litcoffee' extension source
|
||||
files in it and all subdirectories.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compilePath = </span><span class="nf">(source, topLevel, base) -></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="nf">(err, stats) -></span>
|
||||
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">code</span> <span class="o">isnt</span> <span class="s">'ENOENT'</span>
|
||||
<span class="k">if</span> <span class="nx">err</span><span class="o">?</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s">'ENOENT'</span>
|
||||
<span class="k">if</span> <span class="nx">topLevel</span> <span class="o">and</span> <span class="nx">source</span> <span class="o">and</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">not</span> <span class="k">in</span> <span class="nx">coffee_exts</span>
|
||||
<span class="nv">source = </span><span class="nx">sources</span><span class="p">[</span><span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">source</span><span class="p">)]</span> <span class="o">=</span> <span class="s">"</span><span class="si">#{</span><span class="nx">source</span><span class="si">}</span><span class="s">.coffee"</span>
|
||||
<span class="k">return</span> <span class="nx">compilePath</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">topLevel</span><span class="p">,</span> <span class="nx">base</span>
|
||||
<span class="k">if</span> <span class="nx">topLevel</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span> <span class="s">"File not found: </span><span class="si">#{</span><span class="nx">source</span><span class="si">}</span><span class="s">"</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span>
|
||||
<span class="k">return</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="o">and</span> <span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">isnt</span> <span class="s">'node_modules'</span>
|
||||
<span class="nx">watchDir</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">readdir</span> <span class="nx">source</span><span class="p">,</span> <span class="nf">(err, files) -></span>
|
||||
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">code</span> <span class="o">isnt</span> <span class="s">'ENOENT'</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">err</span><span class="o">?</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s">'ENOENT'</span>
|
||||
<span class="nv">index = </span><span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span> <span class="nx">source</span>
|
||||
<span class="nv">files = </span><span class="nx">files</span><span class="p">.</span><span class="nx">filter</span> <span class="nf">(file) -></span> <span class="o">not</span> <span class="nx">hidden</span> <span class="nx">file</span>
|
||||
<span class="nx">sources</span><span class="p">[</span><span class="nx">index</span><span class="p">..</span><span class="nx">index</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">file</span> <span class="k">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">files</span><span class="p">)</span>
|
||||
<span class="nx">sourceCode</span><span class="p">[</span><span class="nx">index</span><span class="p">..</span><span class="nx">index</span><span class="p">]</span> <span class="o">=</span> <span class="nx">files</span><span class="p">.</span><span class="nx">map</span> <span class="nf">-></span> <span class="kc">null</span>
|
||||
<span class="nx">files</span><span class="p">.</span><span class="nx">forEach</span> <span class="nf">(file) -></span>
|
||||
<span class="nx">compilePath</span> <span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">file</span><span class="p">),</span> <span class="kc">no</span><span class="p">,</span> <span class="nx">base</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="k">in</span> <span class="nx">coffee_exts</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">opts</span><span class="p">.</span><span class="nx">watch</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="nf">(err, code) -></span>
|
||||
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">code</span> <span class="o">isnt</span> <span class="s">'ENOENT'</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">err</span><span class="o">?</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s">'ENOENT'</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="k">else</span>
|
||||
<span class="nx">notSources</span><span class="p">[</span><span class="nx">source</span><span class="p">]</span> <span class="o">=</span> <span class="kc">yes</span>
|
||||
<span class="nx">removeSource</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Compile a single source script, containing the given code, according to the
|
||||
requested options. If evaluating the script directly sets <code>__filename</code>,
|
||||
<code>__dirname</code> and <code>module.filename</code> to be correct relative to the script's path.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileScript = </span><span class="p">(</span><span class="nx">file</span><span class="p">,</span> <span class="nx">input</span><span class="p">,</span> <span class="nx">base</span><span class="p">)</span> <span class="o">-></span>
|
||||
<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="nf">(file, input, base) -></span>
|
||||
<span class="nv">o = </span><span class="nx">opts</span>
|
||||
<span class="nv">options = </span><span class="nx">compileOptions</span> <span class="nx">file</span>
|
||||
<span class="k">try</span>
|
||||
<span class="nv">t = task = </span><span class="p">{</span><span class="nx">file</span><span class="p">,</span> <span class="nx">input</span><span class="p">,</span> <span class="nx">options</span><span class="p">}</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s1">'compile'</span><span class="p">,</span> <span class="nx">task</span>
|
||||
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">tokens</span> <span class="k">then</span> <span class="nx">printTokens</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">tokens</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">nodes</span> <span class="k">then</span> <span class="nx">printLine</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">nodes</span><span class="p">(</span><span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">).</span><span class="nx">toString</span><span class="p">().</span><span class="nx">trim</span><span class="p">()</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s">'compile'</span><span class="p">,</span> <span class="nx">task</span>
|
||||
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">tokens</span> <span class="k">then</span> <span class="nx">printTokens</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">tokens</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">options</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">printLine</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">nodes</span><span class="p">(</span><span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">options</span><span class="p">).</span><span class="nx">toString</span><span class="p">().</span><span class="nx">trim</span><span class="p">()</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">run</span> <span class="k">then</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">options</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">join</span> <span class="o">and</span> <span class="nx">t</span><span class="p">.</span><span class="nx">file</span> <span class="o">isnt</span> <span class="nx">o</span><span class="p">.</span><span class="nx">join</span>
|
||||
<span class="nx">sourceCode</span><span class="p">[</span><span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">t</span><span class="p">.</span><span class="nx">file</span><span class="p">)]</span> <span class="o">=</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span>
|
||||
<span class="nx">compileJoin</span><span class="p">()</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">t.output = </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">options</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s1">'success'</span><span class="p">,</span> <span class="nx">task</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s">'success'</span><span class="p">,</span> <span class="nx">task</span>
|
||||
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="k">then</span> <span class="nx">printLine</span> <span class="nx">t</span><span class="p">.</span><span class="nx">output</span><span class="p">.</span><span class="nx">trim</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">compile</span> <span class="k">then</span> <span class="nx">writeJs</span> <span class="nx">t</span><span class="p">.</span><span class="nx">file</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">output</span><span class="p">,</span> <span class="nx">base</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">lint</span> <span class="k">then</span> <span class="nx">lint</span> <span class="nx">t</span><span class="p">.</span><span class="nx">file</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">output</span>
|
||||
<span class="k">catch</span> <span class="nx">err</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s1">'failure'</span><span class="p">,</span> <span class="nx">err</span><span class="p">,</span> <span class="nx">task</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">listeners</span><span class="p">(</span><span class="s1">'failure'</span><span class="p">).</span><span class="nx">length</span>
|
||||
<span class="k">return</span> <span class="nx">printLine</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">watch</span>
|
||||
<span class="nx">printWarn</span> <span class="nx">err</span> <span class="k">instanceof</span> <span class="nb">Error</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">stack</span> <span class="o">or</span> <span class="s2">"ERROR: #{err}"</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s">'failure'</span><span class="p">,</span> <span class="nx">err</span><span class="p">,</span> <span class="nx">task</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">listeners</span><span class="p">(</span><span class="s">'failure'</span><span class="p">).</span><span class="nx">length</span>
|
||||
<span class="k">return</span> <span class="nx">printLine</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span> <span class="o">+</span> <span class="s">'\x07'</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">watch</span>
|
||||
<span class="nx">printWarn</span> <span class="nx">err</span> <span class="k">instanceof</span> <span class="nb">Error</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">stack</span> <span class="o">or</span> <span class="s">"ERROR: </span><span class="si">#{</span><span class="nx">err</span><span class="si">}</span><span class="s">"</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</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>
|
||||
and write them back to <strong>stdout</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileStdio = </span><span class="nf">-></span>
|
||||
<span class="nv">code = </span><span class="s">''</span>
|
||||
<span class="nv">stdin = </span><span class="nx">process</span><span class="p">.</span><span class="nx">openStdin</span><span class="p">()</span>
|
||||
<span class="nx">stdin</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'data'</span><span class="p">,</span> <span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">on</span> <span class="s">'data'</span><span class="p">,</span> <span class="nf">(buffer) -></span>
|
||||
<span class="nx">code</span> <span class="o">+=</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span> <span class="k">if</span> <span class="nx">buffer</span>
|
||||
<span class="nx">stdin</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'end'</span><span class="p">,</span> <span class="o">-></span>
|
||||
<span class="nx">compileScript</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">code</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>After all of the source files are done being read, concatenate and compile
|
||||
them together.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileJoin = </span><span class="o">-></span>
|
||||
<span class="nv">code = </span><span class="nx">contents</span><span class="p">.</span><span class="nx">join</span> <span class="s1">'\n'</span>
|
||||
<span class="nx">compileScript</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span><span class="p">,</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Load files that are to-be-required before compilation occurs.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">loadRequires = </span><span class="o">-></span>
|
||||
<span class="nv">realFilename = </span><span class="nx">module</span><span class="p">.</span><span class="nx">filename</span>
|
||||
<span class="nv">module.filename = </span><span class="s1">'.'</span>
|
||||
<span class="nx">require</span> <span class="nx">req</span> <span class="k">for</span> <span class="nx">req</span> <span class="k">in</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">require</span>
|
||||
<span class="nv">module.filename = </span><span class="nx">realFilename</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Watch a source CoffeeScript file using <code>fs.watch</code>, recompiling it every
|
||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">on</span> <span class="s">'end'</span><span class="p">,</span> <span class="nf">-></span>
|
||||
<span class="nx">compileScript</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">code</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>If all of the source files are done being read, concatenate and compile
|
||||
them together.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">joinTimeout = </span><span class="kc">null</span>
|
||||
<span class="nv">compileJoin = </span><span class="nf">-></span>
|
||||
<span class="k">return</span> <span class="k">unless</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span>
|
||||
<span class="k">unless</span> <span class="nx">sourceCode</span><span class="p">.</span><span class="nx">some</span><span class="p">(</span><span class="nf">(code) -></span> <span class="nx">code</span> <span class="o">is</span> <span class="kc">null</span><span class="p">)</span>
|
||||
<span class="nx">clearTimeout</span> <span class="nx">joinTimeout</span>
|
||||
<span class="nv">joinTimeout = </span><span class="nx">wait</span> <span class="mi">100</span><span class="p">,</span> <span class="nf">-></span>
|
||||
<span class="nx">compileScript</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span><span class="p">,</span> <span class="nx">sourceCode</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s">'\n'</span><span class="p">),</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Watch a source CoffeeScript file using <code>fs.watch</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">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">prevStats</span><span class="p">)</span><span class="o">-></span>
|
||||
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">event</span> <span class="o">is</span> <span class="s1">'change'</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">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">stats</span><span class="p">.</span><span class="nx">size</span> <span class="o">is</span> <span class="nx">prevStats</span><span class="p">.</span><span class="nx">size</span> <span class="o">and</span>
|
||||
<span class="nx">stats</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">prevStats</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="nv">prevStats = </span><span class="nx">stats</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">code</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
|
||||
<span class="nx">compileScript</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">code</span><span class="p">.</span><span class="nx">toString</span><span class="p">(),</span> <span class="nx">base</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</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>
|
||||
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="nf">(source, base) -></span>
|
||||
|
||||
<span class="nv">prevStats = </span><span class="kc">null</span>
|
||||
<span class="nv">compileTimeout = </span><span class="kc">null</span>
|
||||
|
||||
<span class="nv">watchErr = </span><span class="nf">(e) -></span>
|
||||
<span class="k">if</span> <span class="nx">e</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s">'ENOENT'</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">is</span> <span class="o">-</span><span class="mi">1</span>
|
||||
<span class="k">try</span>
|
||||
<span class="nx">rewatch</span><span class="p">()</span>
|
||||
<span class="nx">compile</span><span class="p">()</span>
|
||||
<span class="k">catch</span> <span class="nx">e</span>
|
||||
<span class="nx">removeSource</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span><span class="p">,</span> <span class="kc">yes</span>
|
||||
<span class="nx">compileJoin</span><span class="p">()</span>
|
||||
<span class="k">else</span> <span class="k">throw</span> <span class="nx">e</span>
|
||||
|
||||
<span class="nv">compile = </span><span class="nf">-></span>
|
||||
<span class="nx">clearTimeout</span> <span class="nx">compileTimeout</span>
|
||||
<span class="nv">compileTimeout = </span><span class="nx">wait</span> <span class="mi">25</span><span class="p">,</span> <span class="nf">-></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="nf">(err, stats) -></span>
|
||||
<span class="k">return</span> <span class="nx">watchErr</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
|
||||
<span class="k">return</span> <span class="nx">rewatch</span><span class="p">()</span> <span class="k">if</span> <span class="nx">prevStats</span> <span class="o">and</span> <span class="nx">stats</span><span class="p">.</span><span class="nx">size</span> <span class="o">is</span> <span class="nx">prevStats</span><span class="p">.</span><span class="nx">size</span> <span class="o">and</span>
|
||||
<span class="nx">stats</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">prevStats</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="nv">prevStats = </span><span class="nx">stats</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="nf">(err, code) -></span>
|
||||
<span class="k">return</span> <span class="nx">watchErr</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
|
||||
<span class="nx">compileScript</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">code</span><span class="p">.</span><span class="nx">toString</span><span class="p">(),</span> <span class="nx">base</span><span class="p">)</span>
|
||||
<span class="nx">rewatch</span><span class="p">()</span>
|
||||
|
||||
<span class="k">try</span>
|
||||
<span class="nv">watcher = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">compile</span>
|
||||
<span class="k">catch</span> <span class="nx">e</span>
|
||||
<span class="nx">watchErr</span> <span class="nx">e</span>
|
||||
|
||||
<span class="nv">rewatch = </span><span class="nf">-></span>
|
||||
<span class="nx">watcher</span><span class="o">?</span><span class="p">.</span><span class="nx">close</span><span class="p">()</span>
|
||||
<span class="nv">watcher = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">compile</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Watch a directory of files for new additions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">watchDir = </span><span class="nf">(source, base) -></span>
|
||||
<span class="nv">readdirTimeout = </span><span class="kc">null</span>
|
||||
<span class="k">try</span>
|
||||
<span class="nv">watcher = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="nf">-></span>
|
||||
<span class="nx">clearTimeout</span> <span class="nx">readdirTimeout</span>
|
||||
<span class="nv">readdirTimeout = </span><span class="nx">wait</span> <span class="mi">25</span><span class="p">,</span> <span class="nf">-></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="nf">(err, files) -></span>
|
||||
<span class="k">if</span> <span class="nx">err</span>
|
||||
<span class="k">throw</span> <span class="nx">err</span> <span class="k">unless</span> <span class="nx">err</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s">'ENOENT'</span>
|
||||
<span class="nx">watcher</span><span class="p">.</span><span class="nx">close</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="nx">unwatchDir</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span>
|
||||
<span class="k">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">files</span> <span class="k">when</span> <span class="o">not</span> <span class="nx">hidden</span><span class="p">(</span><span class="nx">file</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">notSources</span><span class="p">[</span><span class="nx">file</span><span class="p">]</span>
|
||||
<span class="nv">file = </span><span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">file</span>
|
||||
<span class="k">continue</span> <span class="k">if</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">some</span> <span class="nf">(s) -></span> <span class="nx">s</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">file</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span>
|
||||
<span class="nx">sources</span><span class="p">.</span><span class="nx">push</span> <span class="nx">file</span>
|
||||
<span class="nx">sourceCode</span><span class="p">.</span><span class="nx">push</span> <span class="kc">null</span>
|
||||
<span class="nx">compilePath</span> <span class="nx">file</span><span class="p">,</span> <span class="kc">no</span><span class="p">,</span> <span class="nx">base</span>
|
||||
<span class="k">catch</span> <span class="nx">e</span>
|
||||
<span class="k">throw</span> <span class="nx">e</span> <span class="k">unless</span> <span class="nx">e</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s">'ENOENT'</span>
|
||||
|
||||
<span class="nv">unwatchDir = </span><span class="nf">(source, base) -></span>
|
||||
<span class="nv">prevSources = </span><span class="nx">sources</span><span class="p">[..]</span>
|
||||
<span class="nv">toRemove = </span><span class="p">(</span><span class="nx">file</span> <span class="k">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">sources</span> <span class="k">when</span> <span class="nx">file</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">)</span>
|
||||
<span class="nx">removeSource</span> <span class="nx">file</span><span class="p">,</span> <span class="nx">base</span><span class="p">,</span> <span class="kc">yes</span> <span class="k">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">toRemove</span>
|
||||
<span class="k">return</span> <span class="k">unless</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">some</span> <span class="nf">(s, i) -></span> <span class="nx">prevSources</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">isnt</span> <span class="nx">s</span>
|
||||
<span class="nx">compileJoin</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Remove a file from our source list, and source code cache. Optionally remove
|
||||
the compiled JS version as well.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">removeSource = </span><span class="nf">(source, base, removeJs) -></span>
|
||||
<span class="nv">index = </span><span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span> <span class="nx">source</span>
|
||||
<span class="nx">sources</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">index</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="nx">sourceCode</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">index</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="k">if</span> <span class="nx">removeJs</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">join</span>
|
||||
<span class="nv">jsPath = </span><span class="nx">outputPath</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span>
|
||||
<span class="nx">exists</span> <span class="nx">jsPath</span><span class="p">,</span> <span class="nf">(itExists) -></span>
|
||||
<span class="k">if</span> <span class="nx">itExists</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">unlink</span> <span class="nx">jsPath</span><span class="p">,</span> <span class="nf">(err) -></span>
|
||||
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">code</span> <span class="o">isnt</span> <span class="s">'ENOENT'</span>
|
||||
<span class="nx">timeLog</span> <span class="s">"removed </span><span class="si">#{</span><span class="nx">source</span><span class="si">}</span><span class="s">"</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>Get the corresponding output JavaScript path for a source file.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">outputPath = </span><span class="nf">(source, base) -></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="s">'.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="k">if</span> <span class="nx">base</span> <span class="o">is</span> <span class="s1">'.'</span> <span class="k">then</span> <span class="nx">srcDir</span> <span class="k">else</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">baseDir = </span><span class="k">if</span> <span class="nx">base</span> <span class="o">is</span> <span class="s">'.'</span> <span class="k">then</span> <span class="nx">srcDir</span> <span class="k">else</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">opts</span><span class="p">.</span><span class="nx">output</span> <span class="k">then</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">output</span><span class="p">,</span> <span class="nx">baseDir</span> <span class="k">else</span> <span class="nx">srcDir</span>
|
||||
<span class="nv">jsPath = </span><span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">dir</span><span class="p">,</span> <span class="nx">filename</span>
|
||||
<span class="nv">compile = </span><span class="o">-></span>
|
||||
<span class="nv">js = </span><span class="s1">' '</span> <span class="k">if</span> <span class="nx">js</span><span class="p">.</span><span class="nx">length</span> <span class="o"><=</span> <span class="mi">0</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">writeFile</span> <span class="nx">jsPath</span><span class="p">,</span> <span class="nx">js</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">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></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</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="nf">(source, js, base) -></span>
|
||||
<span class="nv">jsPath = </span><span class="nx">outputPath</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span>
|
||||
<span class="nv">jsDir = </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">jsPath</span>
|
||||
<span class="nv">compile = </span><span class="nf">-></span>
|
||||
<span class="nv">js = </span><span class="s">' '</span> <span class="k">if</span> <span class="nx">js</span><span class="p">.</span><span class="nx">length</span> <span class="o"><=</span> <span class="mi">0</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">writeFile</span> <span class="nx">jsPath</span><span class="p">,</span> <span class="nx">js</span><span class="p">,</span> <span class="nf">(err) -></span>
|
||||
<span class="k">if</span> <span class="nx">err</span>
|
||||
<span class="nx">printLine</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">compile</span> <span class="o">and</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s2">"#{(new Date).toLocaleTimeString()} - compiled #{source}"</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-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</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">file</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">printLine</span> <span class="nx">file</span> <span class="o">+</span> <span class="s1">':\t'</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="nx">trim</span><span class="p">()</span>
|
||||
<span class="nv">conf = </span><span class="nx">__dirname</span> <span class="o">+</span> <span class="s1">'/../../extras/jsl.conf'</span>
|
||||
<span class="nv">jsl = </span><span class="nx">spawn</span> <span class="s1">'jsl'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'-nologo'</span><span class="p">,</span> <span class="s1">'-stdin'</span><span class="p">,</span> <span class="s1">'-conf'</span><span class="p">,</span> <span class="nx">conf</span><span class="p">]</span>
|
||||
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'data'</span><span class="p">,</span> <span class="nx">printIt</span>
|
||||
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stderr</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'data'</span><span class="p">,</span> <span class="nx">printIt</span>
|
||||
<span class="nx">timeLog</span> <span class="s">"compiled </span><span class="si">#{</span><span class="nx">source</span><span class="si">}</span><span class="s">"</span>
|
||||
<span class="nx">exists</span> <span class="nx">jsDir</span><span class="p">,</span> <span class="nf">(itExists) -></span>
|
||||
<span class="k">if</span> <span class="nx">itExists</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="s">"mkdir -p </span><span class="si">#{</span><span class="nx">jsDir</span><span class="si">}</span><span class="s">"</span><span class="p">,</span> <span class="nx">compile</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>Convenience for cleaner setTimeouts.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">wait = </span><span class="nf">(milliseconds, func) -></span> <span class="nx">setTimeout</span> <span class="nx">func</span><span class="p">,</span> <span class="nx">milliseconds</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <p>When watching scripts, it's useful to log changes with the timestamp.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">timeLog = </span><span class="nf">(message) -></span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s">"</span><span class="si">#{</span><span class="p">(</span><span class="k">new</span> <span class="nb">Date</span><span class="p">).</span><span class="nx">toLocaleTimeString</span><span class="p">()</span><span class="si">}</span><span class="s"> - </span><span class="si">#{</span><span class="nx">message</span><span class="si">}</span><span class="s">"</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</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="nf">(file, js) -></span>
|
||||
<span class="nv">printIt = </span><span class="nf">(buffer) -></span> <span class="nx">printLine</span> <span class="nx">file</span> <span class="o">+</span> <span class="s">':\t'</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="nx">trim</span><span class="p">()</span>
|
||||
<span class="nv">conf = </span><span class="nx">__dirname</span> <span class="o">+</span> <span class="s">'/../../extras/jsl.conf'</span>
|
||||
<span class="nv">jsl = </span><span class="nx">spawn</span> <span class="s">'jsl'</span><span class="p">,</span> <span class="p">[</span><span class="s">'-nologo'</span><span class="p">,</span> <span class="s">'-stdin'</span><span class="p">,</span> <span class="s">'-conf'</span><span class="p">,</span> <span class="nx">conf</span><span class="p">]</span>
|
||||
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">on</span> <span class="s">'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">on</span> <span class="s">'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-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>Pretty-print a stream of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">printTokens = </span><span class="p">(</span><span class="nx">tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdin</span><span class="p">.</span><span class="nx">end</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</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="nf">(tokens) -></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">printLine</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-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</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">tag = </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nv">value = </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="s">'\\n'</span><span class="p">)</span>
|
||||
<span class="nv">locationData = </span><span class="nx">helpers</span><span class="p">.</span><span class="nx">locationDataToString</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="s">"[</span><span class="si">#{</span><span class="nx">tag</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">value</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">locationData</span><span class="si">}</span><span class="s">]"</span>
|
||||
<span class="nx">printLine</span> <span class="nx">strings</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s">' '</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">¶</a> </div> <p>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="nf">-></span>
|
||||
<span class="nv">optionParser = </span><span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">SWITCHES</span><span class="p">,</span> <span class="nx">BANNER</span>
|
||||
<span class="nv">o = opts = </span><span class="nx">optionParser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">.</span><span class="nx">slice</span> <span class="mi">2</span>
|
||||
<span class="nv">o = opts = </span><span class="nx">optionParser</span><span class="p">.</span><span class="nx">parse</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">o</span><span class="p">.</span><span class="nx">compile</span> <span class="o">or=</span> <span class="o">!!</span><span class="nx">o</span><span class="p">.</span><span class="nx">output</span>
|
||||
<span class="nv">o.run = </span><span class="o">not</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">lint</span><span class="p">)</span>
|
||||
<span class="nv">o.print = </span><span class="o">!!</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nb">eval</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">stdio</span> <span class="o">and</span> <span class="nx">o</span><span class="p">.</span><span class="nx">compile</span><span class="p">))</span>
|
||||
<span class="nv">sources = </span><span class="nx">o</span><span class="p">.</span><span class="nx">arguments</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <p>The compile-time options to pass to the CoffeeScript compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileOptions = </span><span class="p">(</span><span class="nx">filename</span><span class="p">)</span> <span class="o">-></span> <span class="p">{</span><span class="nx">filename</span><span class="p">,</span> <span class="nx">bare</span><span class="o">:</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">bare</span><span class="p">}</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</a> </div> <p>Start up a new Node.js instance with the arguments in <code>--nodejs</code> passed to
|
||||
the <code>node</code> binary, preserving the other options.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">forkNode = </span><span class="o">-></span>
|
||||
<span class="nv">sources = </span><span class="nx">o</span><span class="p">.</span><span class="nx">arguments</span>
|
||||
<span class="nx">sourceCode</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="kc">null</span> <span class="k">for</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">sources</span>
|
||||
<span class="k">return</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">¶</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="nf">(filename) -></span>
|
||||
<span class="nv">literate = </span><span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">filename</span><span class="p">)</span> <span class="o">is</span> <span class="s">'.litcoffee'</span>
|
||||
<span class="p">{</span><span class="nx">filename</span><span class="p">,</span> <span class="nx">literate</span><span class="p">,</span> <span class="nv">bare: </span><span class="nx">opts</span><span class="p">.</span><span class="nx">bare</span><span class="p">,</span> <span class="nv">header: </span><span class="nx">opts</span><span class="p">.</span><span class="nx">compile</span><span class="p">}</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">¶</a> </div> <p>Start up a new Node.js instance with the arguments in <code>--nodejs</code> passed to
|
||||
the <code>node</code> binary, preserving the other options.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">forkNode = </span><span class="nf">-></span>
|
||||
<span class="nv">nodeArgs = </span><span class="nx">opts</span><span class="p">.</span><span class="nx">nodejs</span><span class="p">.</span><span class="nx">split</span> <span class="sr">/\s+/</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">1</span><span class="p">..]</span>
|
||||
<span class="nx">args</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">args</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">'--nodejs'</span><span class="p">),</span> <span class="mi">2</span>
|
||||
<span class="nx">args</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">args</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s">'--nodejs'</span><span class="p">),</span> <span class="mi">2</span>
|
||||
<span class="nx">spawn</span> <span class="nx">process</span><span class="p">.</span><span class="nx">execPath</span><span class="p">,</span> <span class="nx">nodeArgs</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">args</span><span class="p">),</span>
|
||||
<span class="nx">cwd</span><span class="o">:</span> <span class="nx">process</span><span class="p">.</span><span class="nx">cwd</span><span class="p">()</span>
|
||||
<span class="nx">env</span><span class="o">:</span> <span class="nx">process</span><span class="p">.</span><span class="nx">env</span>
|
||||
<span class="nx">customFds</span><span class="o">:</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</a> </div> <p>Print the <code>--help</code> usage message and exit. Deprecated switches are not
|
||||
shown.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">usage = </span><span class="o">-></span>
|
||||
<span class="nx">printLine</span> <span class="p">(</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="p">).</span><span class="nx">help</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">¶</a> </div> <p>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">printLine</span> <span class="s2">"CoffeeScript version #{CoffeeScript.VERSION}"</span>
|
||||
<span class="nv">cwd: </span> <span class="nx">process</span><span class="p">.</span><span class="nx">cwd</span><span class="p">()</span>
|
||||
<span class="nv">env: </span> <span class="nx">process</span><span class="p">.</span><span class="nx">env</span>
|
||||
<span class="nv">customFds: </span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">¶</a> </div> <p>Print the <code>--help</code> usage message and exit. Deprecated switches are not
|
||||
shown.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">usage = </span><span class="nf">-></span>
|
||||
<span class="nx">printLine</span> <span class="p">(</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="p">).</span><span class="nx">help</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">¶</a> </div> <p>Print the <code>--version</code> message and exit.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">version = </span><span class="nf">-></span>
|
||||
<span class="nx">printLine</span> <span class="s">"CoffeeScript version </span><span class="si">#{</span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">VERSION</span><span class="si">}</span><span class="s">"</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -21,6 +21,12 @@ h1, h2, h3, h4, h5, h6 {
|
||||
h1 {
|
||||
margin-top: 40px;
|
||||
}
|
||||
hr {
|
||||
border: 0 none;
|
||||
border-top: 1px solid #e5e5ee;
|
||||
height: 1px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
#container {
|
||||
position: relative;
|
||||
}
|
||||
@@ -115,7 +121,7 @@ table td {
|
||||
}
|
||||
pre, tt, code {
|
||||
font-size: 12px; line-height: 18px;
|
||||
font-family: Monaco, Consolas, "Lucida Console", monospace;
|
||||
font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace;
|
||||
margin: 0; padding: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html> <html> <head> <title>grammar.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> grammar.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> <p>The CoffeeScript parser is generated by <a href="http://github.com/zaach/jison">Jison</a>
|
||||
<!DOCTYPE html> <html> <head> <title>grammar.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </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="pilwrap"> <a class="pilcrow" 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>
|
||||
@@ -12,19 +12,30 @@ reduces into the <a href="http://en.wikipedia.org/wiki/Terminal_and_nonterminal_
|
||||
(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="pilwrap"> <a class="pilcrow" 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="p">{</span><span class="nx">Parser</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'jison'</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Since we're going to be wrapped in a function by Jison in any case, if our
|
||||
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="pilwrap"> <a class="pilcrow" 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="p">{</span><span class="nx">Parser</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">'jison'</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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="pilwrap"> <a class="pilcrow" 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="pilwrap"> <a class="pilcrow" 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="nv">patternString = </span><span class="nx">patternString</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\s{2,}/g</span><span class="p">,</span> <span class="s1">' '</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="nx">unwrap</span><span class="p">.</span><span class="nx">exec</span> <span class="nx">action</span> <span class="k">then</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">else</span> <span class="s2">"(#{action}())"</span>
|
||||
<span class="nv">action = </span><span class="nx">action</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\bnew /g</span><span class="p">,</span> <span class="s1">'$&yy.'</span>
|
||||
<span class="nv">action = </span><span class="nx">action</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\b(?:Block\.wrap|extend)\b/g</span><span class="p">,</span> <span class="s1">'yy.$&'</span>
|
||||
<span class="p">[</span><span class="nx">patternString</span><span class="p">,</span> <span class="s2">"$$ = #{action};"</span><span class="p">,</span> <span class="nx">options</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>In all of the rules that follow, you'll see the name of the nonterminal as
|
||||
previous nonterminal.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">o = </span><span class="nf">(patternString, action, options) -></span>
|
||||
<span class="nv">patternString = </span><span class="nx">patternString</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\s{2,}/g</span><span class="p">,</span> <span class="s">' '</span>
|
||||
<span class="nv">patternCount = </span><span class="nx">patternString</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s">' '</span><span class="p">).</span><span class="nx">length</span>
|
||||
<span class="k">return</span> <span class="p">[</span><span class="nx">patternString</span><span class="p">,</span> <span class="s">'$$ = $1;'</span><span class="p">,</span> <span class="nx">options</span><span class="p">]</span> <span class="k">unless</span> <span class="nx">action</span>
|
||||
<span class="nv">action = </span><span class="k">if</span> <span class="nv">match = </span><span class="nx">unwrap</span><span class="p">.</span><span class="nx">exec</span> <span class="nx">action</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="s">"(</span><span class="si">#{</span><span class="nx">action</span><span class="si">}</span><span class="s">())"</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>All runtime functions we need are defined on "yy"</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">action = </span><span class="nx">action</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\bnew /g</span><span class="p">,</span> <span class="s">'$&yy.'</span>
|
||||
<span class="nv">action = </span><span class="nx">action</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\b(?:Block\.wrap|extend)\b/g</span><span class="p">,</span> <span class="s">'yy.$&'</span>
|
||||
<span class="nv">action = </span><span class="nx">action</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\b(Op|Value\.(create|wrap))\b/g</span><span class="p">,</span> <span class="s">'yy.$&'</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Returns a function which adds location data to the first parameter passed
|
||||
in, and returns the parameter. If the parameter is not a node, it will
|
||||
just be passed through unaffected.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">addLocationDataFn = </span><span class="nf">(first, last) -></span>
|
||||
<span class="k">if</span> <span class="o">not</span> <span class="nx">last</span>
|
||||
<span class="s">"yy.addLocationDataFn(@</span><span class="si">#{</span><span class="nx">first</span><span class="si">}</span><span class="s">)"</span>
|
||||
<span class="k">else</span>
|
||||
<span class="s">"yy.addLocationDataFn(@</span><span class="si">#{</span><span class="nx">first</span><span class="si">}</span><span class="s">, @</span><span class="si">#{</span><span class="nx">last</span><span class="si">}</span><span class="s">)"</span>
|
||||
|
||||
<span class="nv">action = </span><span class="nx">action</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/LOC\(([0-9]*)\)/g</span><span class="p">,</span> <span class="nx">addLocationDataFn</span><span class="p">(</span><span class="s">'$1'</span><span class="p">)</span>
|
||||
<span class="nv">action = </span><span class="nx">action</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/LOC\(([0-9]*),\s*([0-9]*)\)/g</span><span class="p">,</span> <span class="nx">addLocationDataFn</span><span class="p">(</span><span class="s">'$1'</span><span class="p">,</span> <span class="s">'$2'</span><span class="p">)</span>
|
||||
|
||||
<span class="p">[</span><span class="nx">patternString</span><span class="p">,</span> <span class="s">"$$ = </span><span class="si">#{</span><span class="nx">addLocationDataFn</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nx">patternCount</span><span class="p">)</span><span class="si">}</span><span class="s">(</span><span class="si">#{</span><span class="nx">action</span><span class="si">}</span><span class="s">);"</span><span class="p">,</span> <span class="nx">options</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <h2>Grammatical Rules</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</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>
|
||||
@@ -34,328 +45,336 @@ their numeric position, so in this rule:</p>
|
||||
|
||||
<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></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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="nx">Root</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">''</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Block</span>
|
||||
<span class="nx">o</span> <span class="s1">'Body'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Block TERMINATOR'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Any list of statements and expressions, separated by line breaks or semicolons.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Body</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Line'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">Block</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="s1">'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="s1">'Body TERMINATOR'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Block and statements, which make up a line in a body.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Line</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Statement'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Pure statements which cannot be expressions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Statement</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Return'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Throw'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Comment'</span>
|
||||
<span class="nx">o</span> <span class="s1">'STATEMENT'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>All the different types of expressions in our language. The basic unit of
|
||||
<code>Expression</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">grammar =</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</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="s">''</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Block</span>
|
||||
<span class="nx">o</span> <span class="s">'Body'</span>
|
||||
<span class="nx">o</span> <span class="s">'Block TERMINATOR'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Any list of statements and expressions, separated 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="s">'Line'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Block</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="s">'Body TERMINATOR Line'</span><span class="p">,</span> <span class="nf">-></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="s">'Body TERMINATOR'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Block 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="s">'Expression'</span>
|
||||
<span class="nx">o</span> <span class="s">'Statement'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>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="s">'Return'</span>
|
||||
<span class="nx">o</span> <span class="s">'Comment'</span>
|
||||
<span class="nx">o</span> <span class="s">'STATEMENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>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. Blocks serve as the building blocks of many other rules, making
|
||||
them somewhat circular.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Expression</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Value'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Invocation'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Code'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Operation'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Assign'</span>
|
||||
<span class="nx">o</span> <span class="s1">'If'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Try'</span>
|
||||
<span class="nx">o</span> <span class="s1">'While'</span>
|
||||
<span class="nx">o</span> <span class="s1">'For'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Switch'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Class'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>An indented block of expressions. Note that the <a href="rewriter.html">Rewriter</a>
|
||||
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="s">'Value'</span>
|
||||
<span class="nx">o</span> <span class="s">'Invocation'</span>
|
||||
<span class="nx">o</span> <span class="s">'Code'</span>
|
||||
<span class="nx">o</span> <span class="s">'Operation'</span>
|
||||
<span class="nx">o</span> <span class="s">'Assign'</span>
|
||||
<span class="nx">o</span> <span class="s">'If'</span>
|
||||
<span class="nx">o</span> <span class="s">'Try'</span>
|
||||
<span class="nx">o</span> <span class="s">'While'</span>
|
||||
<span class="nx">o</span> <span class="s">'For'</span>
|
||||
<span class="nx">o</span> <span class="s">'Switch'</span>
|
||||
<span class="nx">o</span> <span class="s">'Class'</span>
|
||||
<span class="nx">o</span> <span class="s">'Throw'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>An indented block of expressions. Note that the <a href="rewriter.html">Rewriter</a>
|
||||
will convert some postfix forms into blocks for us, by adjusting the
|
||||
token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Block</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'INDENT OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Block</span>
|
||||
<span class="nx">o</span> <span class="s1">'INDENT Body OUTDENT'</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-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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="nx">Identifier</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>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="nx">AlphaNumeric</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'NUMBER'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'STRING'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>All of our immediate values. Generally these can be passed straight
|
||||
through and printed to JavaScript.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Literal</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'AlphaNumeric'</span>
|
||||
<span class="nx">o</span> <span class="s1">'JS'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'REGEX'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'BOOL'</span><span class="p">,</span> <span class="o">-></span>
|
||||
<span class="nv">val = </span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="nv">val.isUndefined = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">$1</span> <span class="o">is</span> <span class="s1">'undefined'</span>
|
||||
<span class="nx">val</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>Assignment of a variable, property, or index to a value.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Assign</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Assignable = Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'Assignable = INDENT Expression OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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="nx">AssignObj</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'ObjAssignable'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'ObjAssignable : Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="k">new</span> <span class="nx">Value</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="s1">'ObjAssignable :</span>
|
||||
<span class="s1"> INDENT Expression OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">$1</span><span class="p">),</span> <span class="nx">$4</span><span class="p">,</span> <span class="s1">'object'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Comment'</span>
|
||||
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="s">'INDENT OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Block</span>
|
||||
<span class="nx">o</span> <span class="s">'INDENT Body OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</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="s">'IDENTIFIER'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>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="s">'NUMBER'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'STRING'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <p>All of our immediate values. Generally these can 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="s">'AlphaNumeric'</span>
|
||||
<span class="nx">o</span> <span class="s">'JS'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'REGEX'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'DEBUGGER'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Literal</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'UNDEFINED'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Undefined</span>
|
||||
<span class="nx">o</span> <span class="s">'NULL'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Null</span>
|
||||
<span class="nx">o</span> <span class="s">'BOOL'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Bool</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</a> </div> <p>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="s">'Assignable = Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'Assignable = TERMINATOR Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s">'Assignable = INDENT Expression OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</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="s">'ObjAssignable'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'ObjAssignable : Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">LOC</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">wrap</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="s">'object'</span>
|
||||
<span class="nx">o</span> <span class="s">'ObjAssignable :</span>
|
||||
<span class="s"> INDENT Expression OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">LOC</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">wrap</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="s">'object'</span>
|
||||
<span class="nx">o</span> <span class="s">'Comment'</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nx">ObjAssignable</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Identifier'</span>
|
||||
<span class="nx">o</span> <span class="s1">'AlphaNumeric'</span>
|
||||
<span class="nx">o</span> <span class="s1">'ThisProperty'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</a> </div> <p>A return statement from a function body.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Return</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'RETURN Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Return</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'RETURN'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Return</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</a> </div> <p>A block comment.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Comment</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'HERECOMMENT'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Comment</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">¶</a> </div> <p>The <strong>Code</strong> node is the function literal. It's defined by an indented block
|
||||
<span class="nv">ObjAssignable: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Identifier'</span>
|
||||
<span class="nx">o</span> <span class="s">'AlphaNumeric'</span>
|
||||
<span class="nx">o</span> <span class="s">'ThisProperty'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">¶</a> </div> <p>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="s">'RETURN Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Return</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'RETURN'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Return</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">¶</a> </div> <p>A block comment.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Comment: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'HERECOMMENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Comment</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">¶</a> </div> <p>The <strong>Code</strong> node is the function literal. It's defined by an indented block
|
||||
of <strong>Block</strong> preceded by a function arrow, with an optional parameter
|
||||
list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Code</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'PARAM_START ParamList PARAM_END FuncGlyph Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Code</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="s1">'FuncGlyph Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Code</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="pilwrap"> <a class="pilcrow" 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="nx">FuncGlyph</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'->'</span><span class="p">,</span> <span class="o">-></span> <span class="s1">'func'</span>
|
||||
<span class="nx">o</span> <span class="s1">'=>'</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="pilwrap"> <a class="pilcrow" href="#section-23">¶</a> </div> <p>An optional, trailing comma.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">OptComma</span><span class="o">:</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="pilwrap"> <a class="pilcrow" 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="nx">ParamList</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">''</span><span class="p">,</span> <span class="o">-></span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s1">'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="s1">'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="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">¶</a> </div> <p>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="nx">Param</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'ParamVar'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Param</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'ParamVar ...'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Param</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">on</span>
|
||||
<span class="nx">o</span> <span class="s1">'ParamVar = Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Param</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-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">¶</a> </div> <p>Function Parameters</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ParamVar</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Identifier'</span>
|
||||
<span class="nx">o</span> <span class="s1">'ThisProperty'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Array'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Object'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">¶</a> </div> <p>A splat that occurs outside of a parameter list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Splat</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression ...'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Splat</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">¶</a> </div> <p>Variables and properties that can be assigned to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">SimpleAssignable</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Identifier'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'Value Accessor'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">add</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'Invocation Accessor'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</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="s1">'ThisProperty'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-29">¶</a> </div> <p>Everything that can be assigned to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Assignable</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'SimpleAssignable'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Array'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'Object'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-30">¶</a> </div> <p>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="nx">Value</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Assignable'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Literal'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'Parenthetical'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'Range'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'This'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-31">¶</a> </div> <p>The 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="nx">Accessor</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'. Identifier'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Access</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'?. Identifier'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Access</span> <span class="nx">$2</span><span class="p">,</span> <span class="s1">'soak'</span>
|
||||
<span class="nx">o</span> <span class="s1">':: Identifier'</span><span class="p">,</span> <span class="o">-></span> <span class="p">[(</span><span class="k">new</span> <span class="nx">Access</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s1">'prototype'</span><span class="p">),</span> <span class="k">new</span> <span class="nx">Access</span> <span class="nx">$2</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s1">'::'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Access</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s1">'prototype'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Index'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-32">¶</a> </div> <p>Indexing into an object or array using bracket notation.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Index</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'INDEX_START IndexValue INDEX_END'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'INDEX_SOAK Index'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">extend</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">soak</span> <span class="o">:</span> <span class="kc">yes</span>
|
||||
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="s">'PARAM_START ParamList PARAM_END FuncGlyph Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Code</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="s">'FuncGlyph Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Code</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-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">¶</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="s">'->'</span><span class="p">,</span> <span class="nf">-></span> <span class="s">'func'</span>
|
||||
<span class="nx">o</span> <span class="s">'=>'</span><span class="p">,</span> <span class="nf">-></span> <span class="s">'boundfunc'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">¶</a> </div> <p>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="s">''</span>
|
||||
<span class="nx">o</span> <span class="s">','</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">¶</a> </div> <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="s">''</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s">'Param'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s">'ParamList , Param'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'ParamList OptComma TERMINATOR Param'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s">'ParamList OptComma INDENT ParamList OptComma OUTDENT'</span><span class="p">,</span> <span class="nf">-></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-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">¶</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="s">'ParamVar'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Param</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'ParamVar ...'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Param</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">on</span>
|
||||
<span class="nx">o</span> <span class="s">'ParamVar = Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Param</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-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">¶</a> </div> <p>Function Parameters</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ParamVar: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Identifier'</span>
|
||||
<span class="nx">o</span> <span class="s">'ThisProperty'</span>
|
||||
<span class="nx">o</span> <span class="s">'Array'</span>
|
||||
<span class="nx">o</span> <span class="s">'Object'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-29">¶</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="s">'Expression ...'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Splat</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-30">¶</a> </div> <p>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="s">'Identifier'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'Value Accessor'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">add</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'Invocation Accessor'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">$1</span><span class="p">,</span> <span class="p">[].</span><span class="nx">concat</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'ThisProperty'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-31">¶</a> </div> <p>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="s">'SimpleAssignable'</span>
|
||||
<span class="nx">o</span> <span class="s">'Array'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'Object'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-32">¶</a> </div> <p>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="s">'Assignable'</span>
|
||||
<span class="nx">o</span> <span class="s">'Literal'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'Parenthetical'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'Range'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'This'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-33">¶</a> </div> <p>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="s">'. Identifier'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Access</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'?. Identifier'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Access</span> <span class="nx">$2</span><span class="p">,</span> <span class="s">'soak'</span>
|
||||
<span class="nx">o</span> <span class="s">':: Identifier'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[</span><span class="nx">LOC</span><span class="p">(</span><span class="mi">1</span><span class="p">)(</span><span class="k">new</span> <span class="nx">Access</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">'prototype'</span><span class="p">),</span> <span class="nx">LOC</span><span class="p">(</span><span class="mi">2</span><span class="p">)(</span><span class="k">new</span> <span class="nx">Access</span> <span class="nx">$2</span><span class="p">)]</span>
|
||||
<span class="nx">o</span> <span class="s">'::'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Access</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">'prototype'</span>
|
||||
<span class="nx">o</span> <span class="s">'Index'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-34">¶</a> </div> <p>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="s">'INDEX_START IndexValue INDEX_END'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'INDEX_SOAK Index'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">extend</span> <span class="nx">$2</span><span class="p">,</span> <span class="nv">soak : </span><span class="kc">yes</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nx">IndexValue</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Index</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'Slice'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Slice</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-33">¶</a> </div> <p>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="s1">'{ AssignList OptComma }'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Obj</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">generated</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-34">¶</a> </div> <p>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="nx">AssignList</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">''</span><span class="p">,</span> <span class="o">-></span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s1">'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="s1">'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="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'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="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s1">'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-35"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-35">¶</a> </div> <p>Class definitions have optional bodies of prototype property assignments,
|
||||
and optional references to the superclass.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Class</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'CLASS'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Class</span>
|
||||
<span class="nx">o</span> <span class="s1">'CLASS Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'CLASS EXTENDS Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'CLASS EXTENDS Expression Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s1">'CLASS SimpleAssignable'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'CLASS SimpleAssignable Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'CLASS SimpleAssignable EXTENDS Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s1">'CLASS SimpleAssignable EXTENDS Expression Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$5</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-36">¶</a> </div> <p>Ordinary function invocation, or a chained series of calls.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Invocation</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Value OptFuncExist Arguments'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Call</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'Invocation OptFuncExist Arguments'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Call</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'SUPER'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Call</span> <span class="s1">'super'</span><span class="p">,</span> <span class="p">[</span><span class="k">new</span> <span class="nx">Splat</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s1">'arguments'</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s1">'SUPER Arguments'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Call</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-37"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-37">¶</a> </div> <p>An optional existence check on a function.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">OptFuncExist</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">''</span><span class="p">,</span> <span class="o">-></span> <span class="kc">no</span>
|
||||
<span class="nx">o</span> <span class="s1">'FUNC_EXIST'</span><span class="p">,</span> <span class="o">-></span> <span class="kc">yes</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-38">¶</a> </div> <p>The list of arguments to a function call.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Arguments</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'CALL_START CALL_END'</span><span class="p">,</span> <span class="o">-></span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s1">'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-39"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-39">¶</a> </div> <p>A reference to the <em>this</em> current object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">This</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'THIS'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s1">'this'</span>
|
||||
<span class="nx">o</span> <span class="s1">'@'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s1">'this'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-40">¶</a> </div> <p>A reference to a property on <em>this</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ThisProperty</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'@ Identifier'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="k">new</span> <span class="nx">Literal</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">Access</span><span class="p">(</span><span class="nx">$2</span><span class="p">)],</span> <span class="s1">'this'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-41">¶</a> </div> <p>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="s1">'[ ]'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Arr</span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s1">'[ ArgList OptComma ]'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Arr</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-42">¶</a> </div> <p>Inclusive and exclusive range dots.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">RangeDots</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'..'</span><span class="p">,</span> <span class="o">-></span> <span class="s1">'inclusive'</span>
|
||||
<span class="nx">o</span> <span class="s1">'...'</span><span class="p">,</span> <span class="o">-></span> <span class="s1">'exclusive'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-43">¶</a> </div> <p>The CoffeeScript range literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Range</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'[ Expression RangeDots Expression ]'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Range</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-44">¶</a> </div> <p>Array slice literals.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Slice</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression RangeDots Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Range</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression RangeDots'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Range</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'RangeDots Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Range</span> <span class="kc">null</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-45"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-45">¶</a> </div> <p>The <strong>ArgList</strong> is both the list of objects passed into a function call,
|
||||
<span class="nv">IndexValue: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Index</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'Slice'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Slice</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-35">¶</a> </div> <p>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="s">'{ AssignList OptComma }'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Obj</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">generated</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-36">¶</a> </div> <p>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="s">''</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s">'AssignObj'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s">'AssignList , AssignObj'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'AssignList OptComma TERMINATOR AssignObj'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s">'AssignList OptComma INDENT AssignList OptComma OUTDENT'</span><span class="p">,</span> <span class="nf">-></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-37"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-37">¶</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="s">'CLASS'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Class</span>
|
||||
<span class="nx">o</span> <span class="s">'CLASS Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'CLASS EXTENDS Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'CLASS EXTENDS Expression Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s">'CLASS SimpleAssignable'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'CLASS SimpleAssignable Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'CLASS SimpleAssignable EXTENDS Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s">'CLASS SimpleAssignable EXTENDS Expression Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Class</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$5</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-38">¶</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="s">'Value OptFuncExist Arguments'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Call</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'Invocation OptFuncExist Arguments'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Call</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'SUPER'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Call</span> <span class="s">'super'</span><span class="p">,</span> <span class="p">[</span><span class="k">new</span> <span class="nx">Splat</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">'arguments'</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s">'SUPER Arguments'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Call</span> <span class="s">'super'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-39"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-39">¶</a> </div> <p>An optional existence check on a function.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">OptFuncExist: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">''</span><span class="p">,</span> <span class="nf">-></span> <span class="kc">no</span>
|
||||
<span class="nx">o</span> <span class="s">'FUNC_EXIST'</span><span class="p">,</span> <span class="nf">-></span> <span class="kc">yes</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-40">¶</a> </div> <p>The 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="s">'CALL_START CALL_END'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s">'CALL_START ArgList OptComma CALL_END'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-41">¶</a> </div> <p>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="s">'THIS'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">'this'</span>
|
||||
<span class="nx">o</span> <span class="s">'@'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">'this'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-42">¶</a> </div> <p>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="s">'@ Identifier'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">LOC</span><span class="p">(</span><span class="mi">1</span><span class="p">)(</span><span class="k">new</span> <span class="nx">Literal</span><span class="p">(</span><span class="s">'this'</span><span class="p">)),</span> <span class="p">[</span><span class="nx">LOC</span><span class="p">(</span><span class="mi">2</span><span class="p">)(</span><span class="k">new</span> <span class="nx">Access</span><span class="p">(</span><span class="nx">$2</span><span class="p">))],</span> <span class="s">'this'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-43">¶</a> </div> <p>The 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="s">'[ ]'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Arr</span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s">'[ ArgList OptComma ]'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Arr</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-44">¶</a> </div> <p>Inclusive and exclusive range dots.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">RangeDots: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'..'</span><span class="p">,</span> <span class="nf">-></span> <span class="s">'inclusive'</span>
|
||||
<span class="nx">o</span> <span class="s">'...'</span><span class="p">,</span> <span class="nf">-></span> <span class="s">'exclusive'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-45"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-45">¶</a> </div> <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="s">'[ Expression RangeDots Expression ]'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Range</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-46"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-46">¶</a> </div> <p>Array slice literals.</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="s">'Expression RangeDots Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Range</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression RangeDots'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Range</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'RangeDots Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Range</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'RangeDots'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Range</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-47">¶</a> </div> <p>The <strong>ArgList</strong> is both the list of objects passed into a function call,
|
||||
as well as the contents of an array literal
|
||||
(i.e. comma-separated expressions). Newlines work as well.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ArgList</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Arg'</span><span class="p">,</span> <span class="o">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s1">'ArgList , Arg'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'ArgList OptComma TERMINATOR Arg'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s1">'INDENT ArgList OptComma OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'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-46"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-46">¶</a> </div> <p>Valid arguments are Blocks or Splats.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Arg</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Splat'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-47">¶</a> </div> <p>Just simple, comma-separated, required arguments (no fancy syntax). We need
|
||||
(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="s">'Arg'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s">'ArgList , Arg'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'ArgList OptComma TERMINATOR Arg'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s">'INDENT ArgList OptComma OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'ArgList OptComma INDENT ArgList OptComma OUTDENT'</span><span class="p">,</span> <span class="nf">-></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="pilwrap"> <a class="pilcrow" href="#section-48">¶</a> </div> <p>Valid arguments are Blocks or Splats.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Arg: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression'</span>
|
||||
<span class="nx">o</span> <span class="s">'Splat'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-49">¶</a> </div> <p>Just simple, comma-separated, required arguments (no fancy syntax). We need
|
||||
this to be separate from the <strong>ArgList</strong> for use in <strong>Switch</strong> blocks, where
|
||||
having the newlines wouldn't make sense.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">SimpleArgs</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression'</span>
|
||||
<span class="nx">o</span> <span class="s1">'SimpleArgs , Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="p">[].</span><span class="nx">concat</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-48"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-48">¶</a> </div> <p>The variants of <em>try/catch/finally</em> exception handling blocks.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Try</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'TRY Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Try</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'TRY Block Catch'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Try</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="s1">'TRY Block FINALLY Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Try</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="s1">'TRY Block Catch FINALLY Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Try</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-49"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-49">¶</a> </div> <p>A catch clause names its error and runs a block of code.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Catch</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'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-50"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-50">¶</a> </div> <p>Throw an exception object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Throw</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'THROW Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Throw</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-51">¶</a> </div> <p>Parenthetical expressions. Note that the <strong>Parenthetical</strong> is a <strong>Value</strong>,
|
||||
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="s">'Expression'</span>
|
||||
<span class="nx">o</span> <span class="s">'SimpleArgs , Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[].</span><span class="nx">concat</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-50"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-50">¶</a> </div> <p>The variants of <em>try/catch/finally</em> exception handling blocks.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Try: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'TRY Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Try</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'TRY Block Catch'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Try</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="s">'TRY Block FINALLY Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Try</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="s">'TRY Block Catch FINALLY Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Try</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="nx">$5</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-51">¶</a> </div> <p>A catch clause names its error and runs a block of code.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Catch: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'CATCH Identifier Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[</span><span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s">'CATCH Object Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[</span><span class="nx">LOC</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="nx">wrap</span><span class="p">(</span><span class="nx">$2</span><span class="p">)),</span> <span class="nx">$3</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-52">¶</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="s">'THROW Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Throw</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-53"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-53">¶</a> </div> <p>Parenthetical expressions. Note that the <strong>Parenthetical</strong> is a <strong>Value</strong>,
|
||||
not an <strong>Expression</strong>, so if you need to use an expression in a place
|
||||
where only values are accepted, wrapping it in parentheses will always do
|
||||
the trick.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Parenthetical</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'( Body )'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Parens</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'( INDENT Body OUTDENT )'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Parens</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-52">¶</a> </div> <p>The condition portion of a while loop.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">WhileSource</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'WHILE Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">While</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'WHILE Expression WHEN Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">While</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s1">'UNTIL Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">While</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">invert</span><span class="o">:</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s1">'UNTIL Expression WHEN Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">While</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">invert</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$4</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-53"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-53">¶</a> </div> <p>The while loop can either be normal, with a block of expressions to execute,
|
||||
or postfix, with a single expression. There is no do..while.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">While</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'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="s1">'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">Block</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="s1">'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">Block</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="s1">'Loop'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span>
|
||||
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="s">'( Body )'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Parens</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'( INDENT Body OUTDENT )'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Parens</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-54">¶</a> </div> <p>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="s">'WHILE Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">While</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'WHILE Expression WHEN Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">While</span> <span class="nx">$2</span><span class="p">,</span> <span class="nv">guard: </span><span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s">'UNTIL Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">While</span> <span class="nx">$2</span><span class="p">,</span> <span class="nv">invert: </span><span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s">'UNTIL Expression WHEN Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">While</span> <span class="nx">$2</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></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-55">¶</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="s">'WhileSource Block'</span><span class="p">,</span> <span class="nf">-></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="s">'Statement WhileSource'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$2</span><span class="p">.</span><span class="nx">addBody</span> <span class="nx">LOC</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="nx">Block</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="s">'Expression WhileSource'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$2</span><span class="p">.</span><span class="nx">addBody</span> <span class="nx">LOC</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="nx">Block</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="s">'Loop'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nx">Loop</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'LOOP Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">While</span><span class="p">(</span><span class="k">new</span> <span class="nx">Literal</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="s1">'LOOP Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">While</span><span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span> <span class="s1">'true'</span><span class="p">).</span><span class="nx">addBody</span> <span class="nx">Block</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-54"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-54">¶</a> </div> <p>Array, object, and range comprehensions, at the most generic level.
|
||||
<span class="nv">Loop: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'LOOP Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">While</span><span class="p">(</span><span class="nx">LOC</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">'true'</span><span class="p">).</span><span class="nx">addBody</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'LOOP Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">While</span><span class="p">(</span><span class="nx">LOC</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">'true'</span><span class="p">).</span><span class="nx">addBody</span> <span class="nx">LOC</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="nx">Block</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$2</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-56">¶</a> </div> <p>Array, object, and range comprehensions, at the most generic level.
|
||||
Comprehensions can either be normal, with a block of expressions to execute,
|
||||
or postfix, with a single expression.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">For</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Statement ForBody'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">For</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression ForBody'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">For</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'ForBody Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">For</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span>
|
||||
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="s">'Statement ForBody'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">For</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression ForBody'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">For</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'ForBody Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">For</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nx">ForBody</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'FOR Range'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">$2</span><span class="p">)</span>
|
||||
<span class="nx">o</span> <span class="s1">'ForStart ForSource'</span><span class="p">,</span> <span class="o">-></span> <span class="nv">$2.own = </span><span class="nx">$1</span><span class="p">.</span><span class="nx">own</span><span class="p">;</span> <span class="nv">$2.name = </span><span class="nx">$1</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> <span class="nv">$2.index = </span><span class="nx">$1</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> <span class="nx">$2</span>
|
||||
<span class="nv">ForBody: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'FOR Range'</span><span class="p">,</span> <span class="nf">-></span> <span class="nv">source: </span><span class="nx">LOC</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="nx">wrap</span><span class="p">(</span><span class="nx">$2</span><span class="p">)</span>
|
||||
<span class="nx">o</span> <span class="s">'ForStart ForSource'</span><span class="p">,</span> <span class="nf">-></span> <span class="nv">$2.own = </span><span class="nx">$1</span><span class="p">.</span><span class="nx">own</span><span class="p">;</span> <span class="nv">$2.name = </span><span class="nx">$1</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> <span class="nv">$2.index = </span><span class="nx">$1</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nx">ForStart</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'FOR ForVariables'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'FOR OWN ForVariables'</span><span class="p">,</span> <span class="o">-></span> <span class="nv">$3.own = </span><span class="kc">yes</span><span class="p">;</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-55">¶</a> </div> <p>An array of all accepted values for a variable inside the loop.
|
||||
This enables support for pattern matching.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ForValue</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Identifier'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Array'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'Object'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-56">¶</a> </div> <p>An array or range comprehension has variables for the current element
|
||||
<span class="nv">ForStart: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'FOR ForVariables'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'FOR OWN ForVariables'</span><span class="p">,</span> <span class="nf">-></span> <span class="nv">$3.own = </span><span class="kc">yes</span><span class="p">;</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-57"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-57">¶</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="s">'Identifier'</span>
|
||||
<span class="nx">o</span> <span class="s">'ThisProperty'</span>
|
||||
<span class="nx">o</span> <span class="s">'Array'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'Object'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-58"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-58">¶</a> </div> <p>An array or range comprehension has variables for the current element
|
||||
and (optional) reference to the current index. Or, <em>key, value</em>, in the case
|
||||
of object comprehensions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ForVariables</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'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="s1">'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-57"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-57">¶</a> </div> <p>The source of a comprehension is an array or object with an optional guard
|
||||
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="s">'ForValue'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s">'ForValue , ForValue'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-59"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-59">¶</a> </div> <p>The source of a comprehension is an array or object with an optional guard
|
||||
clause. If it's an array comprehension, you can also choose to step through
|
||||
in fixed-size increments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ForSource</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'FORIN Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'FOROF Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">object</span><span class="o">:</span> <span class="kc">yes</span>
|
||||
<span class="nx">o</span> <span class="s1">'FORIN Expression WHEN Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s1">'FOROF Expression WHEN Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">object</span><span class="o">:</span> <span class="kc">yes</span>
|
||||
<span class="nx">o</span> <span class="s1">'FORIN Expression BY Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">step</span><span class="o">:</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s1">'FORIN Expression WHEN Expression BY Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">step</span><span class="o">:</span> <span class="nx">$6</span>
|
||||
<span class="nx">o</span> <span class="s1">'FORIN Expression BY Expression WHEN Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">step</span><span class="o">:</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$6</span>
|
||||
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="s">'FORIN Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="nv">source: </span><span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'FOROF Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">object: </span><span class="kc">yes</span>
|
||||
<span class="nx">o</span> <span class="s">'FORIN Expression WHEN Expression'</span><span class="p">,</span> <span class="nf">-></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="nx">o</span> <span class="s">'FOROF Expression WHEN Expression'</span><span class="p">,</span> <span class="nf">-></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">yes</span>
|
||||
<span class="nx">o</span> <span class="s">'FORIN Expression BY Expression'</span><span class="p">,</span> <span class="nf">-></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="nx">o</span> <span class="s">'FORIN Expression WHEN Expression BY Expression'</span><span class="p">,</span> <span class="nf">-></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="nx">o</span> <span class="s">'FORIN Expression BY Expression WHEN Expression'</span><span class="p">,</span> <span class="nf">-></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="nx">Switch</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'SWITCH Expression INDENT Whens OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Switch</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s1">'SWITCH Expression INDENT Whens ELSE Block OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Switch</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$6</span>
|
||||
<span class="nx">o</span> <span class="s1">'SWITCH INDENT Whens OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Switch</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'SWITCH INDENT Whens ELSE Block OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Switch</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$5</span>
|
||||
<span class="nv">Switch: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'SWITCH Expression INDENT Whens OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Switch</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s">'SWITCH Expression INDENT Whens ELSE Block OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Switch</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$6</span>
|
||||
<span class="nx">o</span> <span class="s">'SWITCH INDENT Whens OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Switch</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'SWITCH INDENT Whens ELSE Block OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Switch</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$5</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nx">Whens</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'When'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Whens When'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-58"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-58">¶</a> </div> <p>An individual <strong>When</strong> clause, with action.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">When</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'LEADING_WHEN SimpleArgs Block'</span><span class="p">,</span> <span class="o">-></span> <span class="p">[[</span><span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]]</span>
|
||||
<span class="nx">o</span> <span class="s1">'LEADING_WHEN SimpleArgs Block TERMINATOR'</span><span class="p">,</span> <span class="o">-></span> <span class="p">[[</span><span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-59"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-59">¶</a> </div> <p>The most basic form of <em>if</em> is a condition and an action. The following
|
||||
<span class="nv">Whens: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s">'When'</span>
|
||||
<span class="nx">o</span> <span class="s">'Whens When'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-60"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-60">¶</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="s">'LEADING_WHEN SimpleArgs Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="p">[[</span><span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]]</span>
|
||||
<span class="nx">o</span> <span class="s">'LEADING_WHEN SimpleArgs Block TERMINATOR'</span><span class="p">,</span> <span class="nf">-></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-61"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-61">¶</a> </div> <p>The most basic form of <em>if</em> is a condition and an action. The following
|
||||
if-related rules are broken up along these lines in order to avoid
|
||||
ambiguity.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">IfBlock</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'IF Expression Block'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s1">'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="k">new</span> <span class="nx">If</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$5</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-60"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-60">¶</a> </div> <p>The full complement of <em>if</em> expressions, including postfix one-liner
|
||||
<em>if</em> and <em>unless</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">If</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'IfBlock'</span>
|
||||
<span class="nx">o</span> <span class="s1">'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="nx">o</span> <span class="s1">'Statement POST_IF Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">Block</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">type</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">statement</span><span class="o">:</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression POST_IF Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">Block</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">type</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">statement</span><span class="o">:</span> <span class="kc">true</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-61"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-61">¶</a> </div> <p>Arithmetic and logical operators, working on one or more operands.
|
||||
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="s">'IF Expression Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nv">type: </span><span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'IfBlock ELSE IF Expression Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">addElse</span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$5</span><span class="p">,</span> <span class="nv">type: </span><span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-62"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-62">¶</a> </div> <p>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="s">'IfBlock'</span>
|
||||
<span class="nx">o</span> <span class="s">'IfBlock ELSE Block'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">addElse</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'Statement POST_IF Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">LOC</span><span class="p">(</span><span class="mi">1</span><span class="p">)(</span><span class="nx">Block</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="nv">type: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">statement: </span><span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression POST_IF Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">LOC</span><span class="p">(</span><span class="mi">1</span><span class="p">)(</span><span class="nx">Block</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="nv">type: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">statement: </span><span class="kc">true</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-63"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-63">¶</a> </div> <p>Arithmetic and logical operators, working on one or more operands.
|
||||
Here they are grouped by order of precedence. The actual precedence rules
|
||||
are defined at the bottom of the page. It would be shorter if we could
|
||||
combine most of these rules into a single generic <em>Operand OpSymbol Operand</em>
|
||||
-type rule, but in order to make the precedence binding possible, separate
|
||||
rules are necessary.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Operation</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'UNARY Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="nx">$1</span> <span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'- Expression'</span><span class="p">,</span> <span class="p">(</span><span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="s1">'-'</span><span class="p">,</span> <span class="nx">$2</span><span class="p">),</span> <span class="nx">prec</span><span class="o">:</span> <span class="s1">'UNARY'</span>
|
||||
<span class="nx">o</span> <span class="s1">'+ Expression'</span><span class="p">,</span> <span class="p">(</span><span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="s1">'+'</span><span class="p">,</span> <span class="nx">$2</span><span class="p">),</span> <span class="nx">prec</span><span class="o">:</span> <span class="s1">'UNARY'</span>
|
||||
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="s">'UNARY Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="nx">$1</span> <span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'- Expression'</span><span class="p">,</span> <span class="p">(</span><span class="nf">-></span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="s">'-'</span><span class="p">,</span> <span class="nx">$2</span><span class="p">),</span> <span class="nv">prec: </span><span class="s">'UNARY'</span>
|
||||
<span class="nx">o</span> <span class="s">'+ Expression'</span><span class="p">,</span> <span class="p">(</span><span class="nf">-></span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="s">'+'</span><span class="p">,</span> <span class="nx">$2</span><span class="p">),</span> <span class="nv">prec: </span><span class="s">'UNARY'</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s1">'-- SimpleAssignable'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="s1">'--'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'++ SimpleAssignable'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="s1">'++'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'SimpleAssignable --'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</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="s1">'SimpleAssignable ++'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</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></pre></div> </td> </tr> <tr id="section-62"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-62">¶</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="nx">o</span> <span class="s1">'Expression ?'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Existence</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s">'-- SimpleAssignable'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="s">'--'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'++ SimpleAssignable'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="s">'++'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'SimpleAssignable --'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="s">'--'</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="s">'SimpleAssignable ++'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="s">'++'</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></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-64">¶</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="nx">o</span> <span class="s">'Expression ?'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Existence</span> <span class="nx">$1</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s1">'Expression + Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</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="s1">'Expression - Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</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="s">'Expression + Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="s">'+'</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="s">'Expression - Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="s">'-'</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="s1">'Expression MATH Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression SHIFT Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression COMPARE Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression LOGIC Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Op</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'Expression RELATION Expression'</span><span class="p">,</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">$2</span><span class="p">.</span><span class="nx">charAt</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">new</span> <span class="nx">Op</span><span class="p">(</span><span class="nx">$2</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">1</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="nx">invert</span><span class="p">()</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression MATH Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression SHIFT Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression COMPARE Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression LOGIC Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s">'Expression RELATION Expression'</span><span class="p">,</span> <span class="nf">-></span>
|
||||
<span class="k">if</span> <span class="nx">$2</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">is</span> <span class="s">'!'</span>
|
||||
<span class="nx">Op</span><span class="p">.</span><span class="nx">create</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="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">).</span><span class="nx">invert</span><span class="p">()</span>
|
||||
<span class="k">else</span>
|
||||
<span class="k">new</span> <span class="nx">Op</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s1">'SimpleAssignable COMPOUND_ASSIGN</span>
|
||||
<span class="s1"> Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'SimpleAssignable COMPOUND_ASSIGN</span>
|
||||
<span class="s1"> INDENT Expression OUTDENT'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'SimpleAssignable EXTENDS Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Extends</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-63"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-63">¶</a> </div> <h2>Precedence</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-64">¶</a> </div> <p>Operators at the top of this list have higher precedence than the ones lower
|
||||
<span class="nx">o</span> <span class="s">'SimpleAssignable COMPOUND_ASSIGN</span>
|
||||
<span class="s"> Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'SimpleAssignable COMPOUND_ASSIGN</span>
|
||||
<span class="s"> INDENT Expression OUTDENT'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'SimpleAssignable COMPOUND_ASSIGN TERMINATOR</span>
|
||||
<span class="s"> Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s">'SimpleAssignable EXTENDS Expression'</span><span class="p">,</span> <span class="nf">-></span> <span class="k">new</span> <span class="nx">Extends</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-65"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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="pilwrap"> <a class="pilcrow" 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)
|
||||
@@ -365,38 +384,38 @@ down. Following these rules is what makes <code>2 + 3 * 4</code> parse as:</p>
|
||||
|
||||
<pre><code>(2 + 3) * 4
|
||||
</code></pre> </td> <td class="code"> <div class="highlight"><pre><span class="nv">operators = </span><span class="p">[</span>
|
||||
<span class="p">[</span><span class="s1">'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="s1">'left'</span><span class="p">,</span> <span class="s1">'CALL_START'</span><span class="p">,</span> <span class="s1">'CALL_END'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'nonassoc'</span><span class="p">,</span> <span class="s1">'++'</span><span class="p">,</span> <span class="s1">'--'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'left'</span><span class="p">,</span> <span class="s1">'?'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'right'</span><span class="p">,</span> <span class="s1">'UNARY'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'left'</span><span class="p">,</span> <span class="s1">'MATH'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'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="s1">'left'</span><span class="p">,</span> <span class="s1">'SHIFT'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'left'</span><span class="p">,</span> <span class="s1">'RELATION'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'left'</span><span class="p">,</span> <span class="s1">'COMPARE'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'left'</span><span class="p">,</span> <span class="s1">'LOGIC'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'nonassoc'</span><span class="p">,</span> <span class="s1">'INDENT'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'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">'COMPOUND_ASSIGN'</span><span class="p">,</span> <span class="s1">'RETURN'</span><span class="p">,</span> <span class="s1">'THROW'</span><span class="p">,</span> <span class="s1">'EXTENDS'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'right'</span><span class="p">,</span> <span class="s1">'FORIN'</span><span class="p">,</span> <span class="s1">'FOROF'</span><span class="p">,</span> <span class="s1">'BY'</span><span class="p">,</span> <span class="s1">'WHEN'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'right'</span><span class="p">,</span> <span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">,</span> <span class="s1">'FOR'</span><span class="p">,</span> <span class="s1">'DO'</span><span class="p">,</span> <span class="s1">'WHILE'</span><span class="p">,</span> <span class="s1">'UNTIL'</span><span class="p">,</span> <span class="s1">'LOOP'</span><span class="p">,</span> <span class="s1">'SUPER'</span><span class="p">,</span> <span class="s1">'CLASS'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'right'</span><span class="p">,</span> <span class="s1">'POST_IF'</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-65"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-65">¶</a> </div> <h2>Wrapping Up</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-66"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-66">¶</a> </div> <p>Finally, now that we have our <strong>grammar</strong> and our <strong>operators</strong>, we can create
|
||||
<span class="p">[</span><span class="s">'left'</span><span class="p">,</span> <span class="s">'.'</span><span class="p">,</span> <span class="s">'?.'</span><span class="p">,</span> <span class="s">'::'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'left'</span><span class="p">,</span> <span class="s">'CALL_START'</span><span class="p">,</span> <span class="s">'CALL_END'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'nonassoc'</span><span class="p">,</span> <span class="s">'++'</span><span class="p">,</span> <span class="s">'--'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'left'</span><span class="p">,</span> <span class="s">'?'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'right'</span><span class="p">,</span> <span class="s">'UNARY'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'left'</span><span class="p">,</span> <span class="s">'MATH'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'left'</span><span class="p">,</span> <span class="s">'+'</span><span class="p">,</span> <span class="s">'-'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'left'</span><span class="p">,</span> <span class="s">'SHIFT'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'left'</span><span class="p">,</span> <span class="s">'RELATION'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'left'</span><span class="p">,</span> <span class="s">'COMPARE'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'left'</span><span class="p">,</span> <span class="s">'LOGIC'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'nonassoc'</span><span class="p">,</span> <span class="s">'INDENT'</span><span class="p">,</span> <span class="s">'OUTDENT'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'right'</span><span class="p">,</span> <span class="s">'='</span><span class="p">,</span> <span class="s">':'</span><span class="p">,</span> <span class="s">'COMPOUND_ASSIGN'</span><span class="p">,</span> <span class="s">'RETURN'</span><span class="p">,</span> <span class="s">'THROW'</span><span class="p">,</span> <span class="s">'EXTENDS'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'right'</span><span class="p">,</span> <span class="s">'FORIN'</span><span class="p">,</span> <span class="s">'FOROF'</span><span class="p">,</span> <span class="s">'BY'</span><span class="p">,</span> <span class="s">'WHEN'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'right'</span><span class="p">,</span> <span class="s">'IF'</span><span class="p">,</span> <span class="s">'ELSE'</span><span class="p">,</span> <span class="s">'FOR'</span><span class="p">,</span> <span class="s">'WHILE'</span><span class="p">,</span> <span class="s">'UNTIL'</span><span class="p">,</span> <span class="s">'LOOP'</span><span class="p">,</span> <span class="s">'SUPER'</span><span class="p">,</span> <span class="s">'CLASS'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'right'</span><span class="p">,</span> <span class="s">'POST_IF'</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-67"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-67">¶</a> </div> <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="pilwrap"> <a class="pilcrow" href="#section-68">¶</a> </div> <p>Finally, now that 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-67"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-67">¶</a> </div> <p>Initialize the <strong>Parser</strong> with our list of terminal <strong>tokens</strong>, our <strong>grammar</strong>
|
||||
<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="s">' '</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="nx">token</span> <span class="k">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="s">"return </span><span class="si">#{</span><span class="nx">alt</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="si">}</span><span class="s">"</span> <span class="k">if</span> <span class="nx">name</span> <span class="o">is</span> <span class="s">'Root'</span>
|
||||
<span class="nx">alt</span></pre></div> </td> </tr> <tr id="section-69"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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="nx">tokens</span> <span class="o">:</span> <span class="nx">tokens</span><span class="p">.</span><span class="nx">join</span> <span class="s1">' '</span>
|
||||
<span class="nx">bnf</span> <span class="o">:</span> <span class="nx">grammar</span>
|
||||
<span class="nx">operators</span> <span class="o">:</span> <span class="nx">operators</span><span class="p">.</span><span class="nx">reverse</span><span class="p">()</span>
|
||||
<span class="nx">startSymbol</span> <span class="o">:</span> <span class="s1">'Root'</span>
|
||||
<span class="nv">tokens : </span><span class="nx">tokens</span><span class="p">.</span><span class="nx">join</span> <span class="s">' '</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="s">'Root'</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -1,21 +1,21 @@
|
||||
<!DOCTYPE html> <html> <head> <title>helpers.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> helpers.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> <p>This file contains the common helper functions that we'd like to share among
|
||||
<!DOCTYPE html> <html> <head> <title>helpers.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </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="pilwrap"> <a class="pilcrow" 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="pilwrap"> <a class="pilcrow" href="#section-2">¶</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">exports.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">literal</span> <span class="o">is</span> <span class="nx">string</span><span class="p">.</span><span class="nx">substr</span> <span class="nx">start</span><span class="p">,</span> <span class="nx">literal</span><span class="p">.</span><span class="nx">length</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Peek at the end of a given string to see if it matches a sequence.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ends = </span><span class="p">(</span><span class="nx">string</span><span class="p">,</span> <span class="nx">literal</span><span class="p">,</span> <span class="nx">back</span><span class="p">)</span> <span class="o">-></span>
|
||||
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="pilwrap"> <a class="pilcrow" href="#section-2">¶</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">exports.starts = </span><span class="nf">(string, literal, start) -></span>
|
||||
<span class="nx">literal</span> <span class="o">is</span> <span class="nx">string</span><span class="p">.</span><span class="nx">substr</span> <span class="nx">start</span><span class="p">,</span> <span class="nx">literal</span><span class="p">.</span><span class="nx">length</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Peek at the end of a given string to see if it matches a sequence.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ends = </span><span class="nf">(string, literal, back) -></span>
|
||||
<span class="nv">len = </span><span class="nx">literal</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nx">literal</span> <span class="o">is</span> <span class="nx">string</span><span class="p">.</span><span class="nx">substr</span> <span class="nx">string</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="nx">len</span> <span class="o">-</span> <span class="p">(</span><span class="nx">back</span> <span class="o">or</span> <span class="mi">0</span><span class="p">),</span> <span class="nx">len</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Trim out all falsy values from an array.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.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-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Count the number of occurrences of a string in a string.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.count = </span><span class="p">(</span><span class="nx">string</span><span class="p">,</span> <span class="nx">substr</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">literal</span> <span class="o">is</span> <span class="nx">string</span><span class="p">.</span><span class="nx">substr</span> <span class="nx">string</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="nx">len</span> <span class="o">-</span> <span class="p">(</span><span class="nx">back</span> <span class="o">or</span> <span class="mi">0</span><span class="p">),</span> <span class="nx">len</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Trim out all falsy values from an array.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.compact = </span><span class="nf">(array) -></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-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Count the number of occurrences of a string in a string.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.count = </span><span class="nf">(string, substr) -></span>
|
||||
<span class="nv">num = pos = </span><span class="mi">0</span>
|
||||
<span class="k">return</span> <span class="mi">1</span><span class="o">/</span><span class="mi">0</span> <span class="nx">unless</span> <span class="nx">substr</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="k">return</span> <span class="mi">1</span><span class="o">/</span><span class="mi">0</span> <span class="k">unless</span> <span class="nx">substr</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nx">num</span><span class="o">++</span> <span class="k">while</span> <span class="nv">pos = </span><span class="mi">1</span> <span class="o">+</span> <span class="nx">string</span><span class="p">.</span><span class="nx">indexOf</span> <span class="nx">substr</span><span class="p">,</span> <span class="nx">pos</span>
|
||||
<span class="nx">num</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Merge objects, returning a fresh copy with attributes from both sides.
|
||||
Used every time <code>Base#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">exports.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="nx">extend</span> <span class="p">(</span><span class="nx">extend</span> <span class="p">{},</span> <span class="nx">options</span><span class="p">),</span> <span class="nx">overrides</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Extend a source object with the properties of another object (shallow copy).</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">extend = exports.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>
|
||||
options hash to propagate down the tree without polluting other branches.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.merge = </span><span class="nf">(options, overrides) -></span>
|
||||
<span class="nx">extend</span> <span class="p">(</span><span class="nx">extend</span> <span class="p">{},</span> <span class="nx">options</span><span class="p">),</span> <span class="nx">overrides</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Extend a source object with the properties of another object (shallow copy).</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">extend = exports.extend = </span><span class="nf">(object, properties) -></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>
|
||||
<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="nx">object</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Return a 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">exports.flatten = flatten = </span><span class="p">(</span><span class="nx">array</span><span class="p">)</span> <span class="o">-></span>
|
||||
Handy for getting a list of <code>children</code> from the nodes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.flatten = flatten = </span><span class="nf">(array) -></span>
|
||||
<span class="nv">flattened = </span><span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="nx">element</span> <span class="k">in</span> <span class="nx">array</span>
|
||||
<span class="k">if</span> <span class="nx">element</span> <span class="k">instanceof</span> <span class="nb">Array</span>
|
||||
@@ -23,9 +23,34 @@ Handy for getting a list of <code>children</code> from the nodes.</p>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">flattened</span><span class="p">.</span><span class="nx">push</span> <span class="nx">element</span>
|
||||
<span class="nx">flattened</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</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">exports.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>
|
||||
looking for a particular method in an options hash.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.del = </span><span class="nf">(obj, key) -></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> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Gets the last item of an array(-like) object.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.last = </span><span class="p">(</span><span class="nx">array</span><span class="p">,</span> <span class="nx">back</span><span class="p">)</span> <span class="o">-></span> <span class="nx">array</span><span class="p">[</span><span class="nx">array</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="p">(</span><span class="nx">back</span> <span class="o">or</span> <span class="mi">0</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nx">val</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Gets the last item of an array(-like) object.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.last = </span><span class="nf">(array, back) -></span> <span class="nx">array</span><span class="p">[</span><span class="nx">array</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="p">(</span><span class="nx">back</span> <span class="o">or</span> <span class="mi">0</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Typical Array::some</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.some = </span><span class="nb">Array</span><span class="o">::</span><span class="nx">some</span> <span class="o">?</span> <span class="nf">(fn) -></span>
|
||||
<span class="k">return</span> <span class="kc">true</span> <span class="k">for</span> <span class="nx">e</span> <span class="k">in</span> <span class="k">this</span> <span class="k">when</span> <span class="nx">fn</span> <span class="nx">e</span>
|
||||
<span class="kc">false</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Merge two jison-style location data objects together.
|
||||
If <code>last</code> is not provided, this will simply return <code>first</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">buildLocationData = </span><span class="nf">(first, last) -></span>
|
||||
<span class="k">if</span> <span class="o">not</span> <span class="nx">last</span>
|
||||
<span class="nx">first</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">first_line: </span><span class="nx">first</span><span class="p">.</span><span class="nx">first_line</span>
|
||||
<span class="nv">first_column: </span><span class="nx">first</span><span class="p">.</span><span class="nx">first_column</span>
|
||||
<span class="nv">last_line: </span><span class="nx">last</span><span class="p">.</span><span class="nx">last_line</span>
|
||||
<span class="nv">last_column: </span><span class="nx">last</span><span class="p">.</span><span class="nx">last_column</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>This returns a function which takes an object as a parameter, and if that object is an AST node,
|
||||
updates that object's locationData. The object is returned either way.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.addLocationDataFn = </span><span class="nf">(first, last) -></span>
|
||||
<span class="nf">(obj) -></span>
|
||||
<span class="k">if</span> <span class="p">((</span><span class="k">typeof</span> <span class="nx">obj</span><span class="p">)</span> <span class="o">is</span> <span class="s">'object'</span><span class="p">)</span> <span class="o">and</span> <span class="p">(</span><span class="o">!!</span><span class="nx">obj</span><span class="p">[</span><span class="s">'updateLocationDataIfMissing'</span><span class="p">])</span>
|
||||
<span class="nx">obj</span><span class="p">.</span><span class="nx">updateLocationDataIfMissing</span> <span class="nx">buildLocationData</span><span class="p">(</span><span class="nx">first</span><span class="p">,</span> <span class="nx">last</span><span class="p">)</span>
|
||||
|
||||
<span class="k">return</span> <span class="nx">obj</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Convert jison location data to a string.
|
||||
<code>obj</code> can be a token, or a locationData.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.locationDataToString = </span><span class="nf">(obj) -></span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="s">"2"</span> <span class="k">of</span> <span class="nx">obj</span><span class="p">)</span> <span class="o">and</span> <span class="p">(</span><span class="s">"first_line"</span> <span class="k">of</span> <span class="nx">obj</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span> <span class="k">then</span> <span class="nv">locationData = </span><span class="nx">obj</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="s">"first_line"</span> <span class="k">of</span> <span class="nx">obj</span> <span class="k">then</span> <span class="nv">locationData = </span><span class="nx">obj</span>
|
||||
|
||||
<span class="k">if</span> <span class="nx">locationData</span>
|
||||
<span class="s">"</span><span class="si">#{</span><span class="nx">locationData</span><span class="p">.</span><span class="nx">first_line</span> <span class="o">+</span> <span class="mi">1</span><span class="si">}</span><span class="s">:</span><span class="si">#{</span><span class="nx">locationData</span><span class="p">.</span><span class="nx">first_column</span> <span class="o">+</span> <span class="mi">1</span><span class="si">}</span><span class="s">-"</span> <span class="o">+</span>
|
||||
<span class="s">"</span><span class="si">#{</span><span class="nx">locationData</span><span class="p">.</span><span class="nx">last_line</span> <span class="o">+</span> <span class="mi">1</span><span class="si">}</span><span class="s">:</span><span class="si">#{</span><span class="nx">locationData</span><span class="p">.</span><span class="nx">last_column</span> <span class="o">+</span> <span class="mi">1</span><span class="si">}</span><span class="s">"</span>
|
||||
<span class="k">else</span>
|
||||
<span class="s">"No location data"</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -1,3 +1,3 @@
|
||||
<!DOCTYPE html> <html> <head> <title>index.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> index.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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="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="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">require</span> <span class="s1">'./coffee-script'</span>
|
||||
<!DOCTYPE html> <html> <head> <title>index.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </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="pilwrap"> <a class="pilcrow" 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="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="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="s">'./coffee-script'</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html> <html> <head> <title>optparse.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> optparse.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> <p>A simple <strong>OptionParser</strong> class to parse option flags from the command-line.
|
||||
<!DOCTYPE html> <html> <head> <title>optparse.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </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="pilwrap"> <a class="pilcrow" 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
|
||||
@@ -6,74 +6,80 @@ options = parser.parse process.argv
|
||||
</code></pre>
|
||||
|
||||
<p>The first non-option is considered to be the start of the file (and file
|
||||
option) list, and all subsequent arguments are left unparsed.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.OptionParser = </span><span class="nx">class</span> <span class="nx">OptionParser</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>Initialize with a list of valid options, in the form:</p>
|
||||
option) list, and all subsequent arguments are left unparsed.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.OptionParser = </span><span class="k">class</span> <span class="nx">OptionParser</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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="nx">constructor</span><span class="o">:</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>
|
||||
<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="nf">(rules, @banner) -></span>
|
||||
<span class="vi">@rules = </span><span class="nx">buildRules</span> <span class="nx">rules</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Parse the list of arguments, populating an <code>options</code> object with all of the
|
||||
specified options, and return it. <code>options.arguments</code> will be an array
|
||||
containing the remaining non-option arguments. <code>options.literals</code> will be
|
||||
an array of options that are meant to be passed through directly to the
|
||||
executing script. 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="nx">parse</span><span class="o">:</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="nx">arguments</span><span class="o">:</span> <span class="p">[],</span> <span class="nx">literals</span><span class="o">:</span> <span class="p">[]</span>
|
||||
specified options, and return it. Options after the first non-option
|
||||
argument are treated as arguments. <code>options.arguments</code> will be an array
|
||||
containing the remaining 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="nf">(args) -></span>
|
||||
<span class="nv">options = arguments: </span><span class="p">[]</span>
|
||||
<span class="nv">skippingArgument = </span><span class="kc">no</span>
|
||||
<span class="nv">originalArgs = </span><span class="nx">args</span>
|
||||
<span class="nv">args = </span><span class="nx">normalizeArguments</span> <span class="nx">args</span>
|
||||
<span class="k">for</span> <span class="nx">arg</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">args</span>
|
||||
<span class="k">if</span> <span class="nx">arg</span> <span class="o">is</span> <span class="s1">'--'</span>
|
||||
<span class="nv">pos = </span><span class="nx">originalArgs</span><span class="p">.</span><span class="nx">indexOf</span> <span class="s1">'--'</span>
|
||||
<span class="nv">options.arguments = </span><span class="p">[</span><span class="nx">originalArgs</span><span class="p">[</span><span class="mi">1</span> <span class="o">+</span> <span class="nx">pos</span><span class="p">]]</span>
|
||||
<span class="nv">options.literals = </span><span class="nx">originalArgs</span><span class="p">[(</span><span class="mi">2</span> <span class="o">+</span> <span class="nx">pos</span><span class="p">)..]</span>
|
||||
<span class="k">if</span> <span class="nx">skippingArgument</span>
|
||||
<span class="nv">skippingArgument = </span><span class="kc">no</span>
|
||||
<span class="k">continue</span>
|
||||
<span class="k">if</span> <span class="nx">arg</span> <span class="o">is</span> <span class="s">'--'</span>
|
||||
<span class="nv">pos = </span><span class="nx">originalArgs</span><span class="p">.</span><span class="nx">indexOf</span> <span class="s">'--'</span>
|
||||
<span class="nv">options.arguments = </span><span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">originalArgs</span><span class="p">[(</span><span class="nx">pos</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)..]</span>
|
||||
<span class="k">break</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="nv">value = </span><span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">hasArgument</span> <span class="k">then</span> <span class="nx">args</span><span class="p">[</span><span class="nx">i</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">]</span> <span class="k">else</span> <span class="kc">true</span>
|
||||
<span class="nx">options</span><span class="p">[</span><span class="nx">rule</span><span class="p">.</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">isList</span> <span class="k">then</span> <span class="p">(</span><span class="nx">options</span><span class="p">[</span><span class="nx">rule</span><span class="p">.</span><span class="nx">name</span><span class="p">]</span> <span class="o">or</span> <span class="p">[]).</span><span class="nx">concat</span> <span class="nx">value</span> <span class="k">else</span> <span class="nx">value</span>
|
||||
<span class="nv">matchedRule = </span><span class="kc">yes</span>
|
||||
<span class="k">break</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"unrecognized option: #{arg}"</span> <span class="k">if</span> <span class="nx">isOption</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">matchedRule</span>
|
||||
<span class="k">if</span> <span class="o">not</span> <span class="nx">isOption</span>
|
||||
<span class="nv">options.arguments = </span><span class="nx">originalArgs</span><span class="p">[(</span><span class="nx">originalArgs</span><span class="p">.</span><span class="nx">indexOf</span> <span class="nx">arg</span><span class="p">)..]</span>
|
||||
<span class="k">break</span>
|
||||
<span class="nx">options</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Return the help text for this <strong>OptionParser</strong>, listing and describing all
|
||||
of the valid options, for <code>--help</code> and such.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">help</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nv">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></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>the CS option parser is a little odd; options after the first
|
||||
non-option argument are treated as non-option arguments themselves</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">seenNonOptionArg = </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="o">></span> <span class="mi">0</span>
|
||||
<span class="k">unless</span> <span class="nx">seenNonOptionArg</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="nv">value = </span><span class="kc">true</span>
|
||||
<span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">hasArgument</span>
|
||||
<span class="nv">skippingArgument = </span><span class="kc">yes</span>
|
||||
<span class="nv">value = </span><span class="nx">args</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nx">options</span><span class="p">[</span><span class="nx">rule</span><span class="p">.</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">isList</span> <span class="k">then</span> <span class="p">(</span><span class="nx">options</span><span class="p">[</span><span class="nx">rule</span><span class="p">.</span><span class="nx">name</span><span class="p">]</span> <span class="o">or</span> <span class="p">[]).</span><span class="nx">concat</span> <span class="nx">value</span> <span class="k">else</span> <span class="nx">value</span>
|
||||
<span class="nv">matchedRule = </span><span class="kc">yes</span>
|
||||
<span class="k">break</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">"unrecognized option: </span><span class="si">#{</span><span class="nx">arg</span><span class="si">}</span><span class="s">"</span> <span class="k">if</span> <span class="nx">isOption</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">matchedRule</span>
|
||||
<span class="k">if</span> <span class="nx">seenNonOptionArg</span> <span class="o">or</span> <span class="o">not</span> <span class="nx">isOption</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">options</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</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="nf">-></span>
|
||||
<span class="nv">lines = </span><span class="p">[]</span>
|
||||
<span class="nx">lines</span><span class="p">.</span><span class="nx">unshift</span> <span class="s2">"#{@banner}\n"</span> <span class="k">if</span> <span class="nx">@banner</span>
|
||||
<span class="nx">lines</span><span class="p">.</span><span class="nx">unshift</span> <span class="s">"</span><span class="si">#{</span><span class="nx">@banner</span><span class="si">}</span><span class="s">\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="nb">Array</span><span class="p">(</span><span class="nx">spaces</span> <span class="o">+</span> <span class="mi">1</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s1">' '</span><span class="p">)</span> <span class="k">else</span> <span class="s1">''</span>
|
||||
<span class="nv">letPart = </span><span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">shortFlag</span> <span class="k">then</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">shortFlag</span> <span class="o">+</span> <span class="s1">', '</span> <span class="k">else</span> <span class="s1">' '</span>
|
||||
<span class="nx">lines</span><span class="p">.</span><span class="nx">push</span> <span class="s1">' '</span> <span class="o">+</span> <span class="nx">letPart</span> <span class="o">+</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">longFlag</span> <span class="o">+</span> <span class="nx">spaces</span> <span class="o">+</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">description</span>
|
||||
<span class="s2">"\n#{ lines.join('\n') }\n"</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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="pilwrap"> <a class="pilcrow" 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">spaces = </span><span class="k">if</span> <span class="nx">spaces</span> <span class="o">></span> <span class="mi">0</span> <span class="k">then</span> <span class="nb">Array</span><span class="p">(</span><span class="nx">spaces</span> <span class="o">+</span> <span class="mi">1</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s">' '</span><span class="p">)</span> <span class="k">else</span> <span class="s">''</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="s">', '</span> <span class="k">else</span> <span class="s">' '</span>
|
||||
<span class="nx">lines</span><span class="p">.</span><span class="nx">push</span> <span class="s">' '</span> <span class="o">+</span> <span class="nx">letPart</span> <span class="o">+</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">longFlag</span> <span class="o">+</span> <span class="nx">spaces</span> <span class="o">+</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">description</span>
|
||||
<span class="s">"\n</span><span class="si">#{</span> <span class="nx">lines</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s">'\n'</span><span class="p">)</span> <span class="si">}</span><span class="s">\n"</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <h2>Helpers</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</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">/\[(\w+(\*?))\]/</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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="nv">OPTIONAL = </span><span class="sr">/\[(\w+(\*?))\]/</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</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="nf">(rules) -></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="pilwrap"> <a class="pilcrow" 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="nv">options = </span><span class="p">{})</span> <span class="o">-></span>
|
||||
<span class="nx">buildRule</span> <span class="nx">tuple</span><span class="p">...</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>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="nf">(shortFlag, longFlag, description, options = {}) -></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="nx">name</span><span class="o">:</span> <span class="nx">longFlag</span><span class="p">.</span><span class="nx">substr</span> <span class="mi">2</span>
|
||||
<span class="nx">shortFlag</span><span class="o">:</span> <span class="nx">shortFlag</span>
|
||||
<span class="nx">longFlag</span><span class="o">:</span> <span class="nx">longFlag</span>
|
||||
<span class="nx">description</span><span class="o">:</span> <span class="nx">description</span>
|
||||
<span class="nx">hasArgument</span><span class="o">:</span> <span class="o">!!</span><span class="p">(</span><span class="nx">match</span> <span class="o">and</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
|
||||
<span class="nx">isList</span><span class="o">:</span> <span class="o">!!</span><span class="p">(</span><span class="nx">match</span> <span class="o">and</span> <span class="nx">match</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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">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="nv">isList: </span> <span class="o">!!</span><span class="p">(</span><span class="nx">match</span> <span class="o">and</span> <span class="nx">match</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</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="nf">(args) -></span>
|
||||
<span class="nv">args = </span><span class="nx">args</span><span class="p">[..]</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="nx">result</span><span class="p">.</span><span class="nx">push</span> <span class="s">'-'</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="s">''</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>
|
||||
|
||||
@@ -1,83 +1,57 @@
|
||||
<!DOCTYPE html> <html> <head> <title>repl.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> repl.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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>
|
||||
<!DOCTYPE html> <html> <head> <title>repl.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </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="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> </td> <td class="code"> <div class="highlight"><pre><span class="nv">vm = </span><span class="nx">require</span> <span class="s">'vm'</span>
|
||||
<span class="nv">nodeREPL = </span><span class="nx">require</span> <span class="s">'repl'</span>
|
||||
<span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s">'./coffee-script'</span>
|
||||
<span class="p">{</span><span class="nx">merge</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">'./helpers'</span>
|
||||
|
||||
<pre><code>coffee> console.log "#{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="pilwrap"> <a class="pilcrow" 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">readline = </span><span class="nx">require</span> <span class="s1">'readline'</span>
|
||||
<span class="p">{</span><span class="nx">inspect</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'util'</span>
|
||||
<span class="p">{</span><span class="nx">Script</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'vm'</span>
|
||||
<span class="nv">Module = </span><span class="nx">require</span> <span class="s1">'module'</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>REPL Setup</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Config</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">REPL_PROMPT = </span><span class="s1">'coffee> '</span>
|
||||
<span class="nv">REPL_PROMPT_CONTINUATION = </span><span class="s1">'......> '</span>
|
||||
<span class="nv">enableColours = </span><span class="kc">no</span>
|
||||
<span class="nx">unless</span> <span class="nx">process</span><span class="p">.</span><span class="nx">platform</span> <span class="o">is</span> <span class="s1">'win32'</span>
|
||||
<span class="nv">enableColours = </span><span class="o">not</span> <span class="nx">process</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">NODE_DISABLE_COLORS</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Start by opening up <code>stdin</code> and <code>stdout</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">stdin = </span><span class="nx">process</span><span class="p">.</span><span class="nx">openStdin</span><span class="p">()</span>
|
||||
<span class="nv">stdout = </span><span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Log an error.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">error = </span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="p">(</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="o">+</span> <span class="s1">'\n'</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>The current backlog of multi-line code.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">backlog = </span><span class="s1">''</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</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">if</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="nx">trim</span><span class="p">()</span> <span class="o">and</span> <span class="o">!</span><span class="nx">backlog</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span>
|
||||
<span class="nv">replDefaults =</span>
|
||||
<span class="nv">prompt: </span><span class="s">'coffee> '</span><span class="p">,</span>
|
||||
<span class="nb">eval</span><span class="o">:</span> <span class="nf">(input, context, filename, cb) -></span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>XXX: multiline hack</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">input = </span><span class="nx">input</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\uFF00/g</span><span class="p">,</span> <span class="s">'\n'</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>strip single-line comments</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">input = </span><span class="nx">input</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/(^|[\r\n]+)(\s*)##?(?:[^#\r\n][^\r\n]*|)($|[\r\n])/</span><span class="p">,</span> <span class="s">'$1$2$3'</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>empty command</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">return</span> <span class="nx">cb</span> <span class="kc">null</span> <span class="k">if</span> <span class="sr">/^\s*$/</span><span class="p">.</span><span class="nx">test</span> <span class="nx">input</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>TODO: fix #1829: pass in-scope vars and avoid accidentally shadowing them by omitting those declarations</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">try</span>
|
||||
<span class="nv">js = </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="s">"_=(</span><span class="si">#{</span><span class="nx">input</span><span class="si">}</span><span class="s">\n)"</span><span class="p">,</span> <span class="p">{</span><span class="nx">filename</span><span class="p">,</span> <span class="nv">bare: </span><span class="kc">yes</span><span class="p">}</span>
|
||||
<span class="k">catch</span> <span class="nx">err</span>
|
||||
<span class="nx">cb</span> <span class="nx">err</span>
|
||||
<span class="nx">cb</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">vm</span><span class="p">.</span><span class="nx">runInContext</span><span class="p">(</span><span class="nx">js</span><span class="p">,</span> <span class="nx">context</span><span class="p">,</span> <span class="nx">filename</span><span class="p">)</span>
|
||||
|
||||
<span class="nv">addMultilineHandler = </span><span class="nf">(repl) -></span>
|
||||
<span class="p">{</span><span class="nx">rli</span><span class="p">,</span> <span class="nx">inputStream</span><span class="p">,</span> <span class="nx">outputStream</span><span class="p">}</span> <span class="o">=</span> <span class="nx">repl</span>
|
||||
|
||||
<span class="nv">multiline =</span>
|
||||
<span class="nv">enabled: </span><span class="kc">off</span>
|
||||
<span class="nv">initialPrompt: </span><span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/^[^> ]*/</span><span class="p">,</span> <span class="nf">(x) -></span> <span class="nx">x</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/./g</span><span class="p">,</span> <span class="s">'-'</span><span class="p">)</span>
|
||||
<span class="nv">prompt: </span><span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/^[^> ]*>?/</span><span class="p">,</span> <span class="nf">(x) -></span> <span class="nx">x</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/./g</span><span class="p">,</span> <span class="s">'.'</span><span class="p">)</span>
|
||||
<span class="nv">buffer: </span><span class="s">''</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Proxy node's line listener</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">nodeLineListener = </span><span class="nx">rli</span><span class="p">.</span><span class="nx">listeners</span><span class="p">(</span><span class="s">'line'</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nx">rli</span><span class="p">.</span><span class="nx">removeListener</span> <span class="s">'line'</span><span class="p">,</span> <span class="nx">nodeLineListener</span>
|
||||
<span class="nx">rli</span><span class="p">.</span><span class="nx">on</span> <span class="s">'line'</span><span class="p">,</span> <span class="nf">(cmd) -></span>
|
||||
<span class="k">if</span> <span class="nx">multiline</span><span class="p">.</span><span class="nx">enabled</span>
|
||||
<span class="nx">multiline</span><span class="p">.</span><span class="nx">buffer</span> <span class="o">+=</span> <span class="s">"</span><span class="si">#{</span><span class="nx">cmd</span><span class="si">}</span><span class="s">\n"</span>
|
||||
<span class="nx">rli</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="nx">multiline</span><span class="p">.</span><span class="nx">prompt</span>
|
||||
<span class="nx">rli</span><span class="p">.</span><span class="nx">prompt</span> <span class="kc">true</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">nodeLineListener</span> <span class="nx">cmd</span>
|
||||
<span class="k">return</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Handle Ctrl-v</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">inputStream</span><span class="p">.</span><span class="nx">on</span> <span class="s">'keypress'</span><span class="p">,</span> <span class="nf">(char, key) -></span>
|
||||
<span class="k">return</span> <span class="k">unless</span> <span class="nx">key</span> <span class="o">and</span> <span class="nx">key</span><span class="p">.</span><span class="nx">ctrl</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">key</span><span class="p">.</span><span class="nx">meta</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">key</span><span class="p">.</span><span class="nx">shift</span> <span class="o">and</span> <span class="nx">key</span><span class="p">.</span><span class="nx">name</span> <span class="o">is</span> <span class="s">'v'</span>
|
||||
<span class="k">if</span> <span class="nx">multiline</span><span class="p">.</span><span class="nx">enabled</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>allow arbitrarily switching between modes any time before multiple lines are entered</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">unless</span> <span class="nx">multiline</span><span class="p">.</span><span class="nx">buffer</span><span class="p">.</span><span class="nx">match</span> <span class="sr">/\n/</span>
|
||||
<span class="nv">multiline.enabled = </span><span class="o">not</span> <span class="nx">multiline</span><span class="p">.</span><span class="nx">enabled</span>
|
||||
<span class="nx">rli</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span>
|
||||
<span class="nx">rli</span><span class="p">.</span><span class="nx">prompt</span> <span class="kc">true</span>
|
||||
<span class="k">return</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>no-op unless the current line is empty</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">return</span> <span class="k">if</span> <span class="nx">rli</span><span class="p">.</span><span class="nx">line</span><span class="o">?</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">rli</span><span class="p">.</span><span class="nx">line</span><span class="p">.</span><span class="nx">match</span> <span class="sr">/^\s*$/</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>eval, print, loop</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">multiline.enabled = </span><span class="o">not</span> <span class="nx">multiline</span><span class="p">.</span><span class="nx">enabled</span>
|
||||
<span class="nv">rli.line = </span><span class="s">''</span>
|
||||
<span class="nv">rli.cursor = </span><span class="mi">0</span>
|
||||
<span class="nx">rli</span><span class="p">.</span><span class="nx">output</span><span class="p">.</span><span class="nx">cursorTo</span> <span class="mi">0</span>
|
||||
<span class="nx">rli</span><span class="p">.</span><span class="nx">output</span><span class="p">.</span><span class="nx">clearLine</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>XXX: multiline hack</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">multiline.buffer = </span><span class="nx">multiline</span><span class="p">.</span><span class="nx">buffer</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\n/g</span><span class="p">,</span> <span class="s">'\uFF00'</span>
|
||||
<span class="nx">rli</span><span class="p">.</span><span class="nx">emit</span> <span class="s">'line'</span><span class="p">,</span> <span class="nx">multiline</span><span class="p">.</span><span class="nx">buffer</span>
|
||||
<span class="nv">multiline.buffer = </span><span class="s">''</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">multiline.enabled = </span><span class="o">not</span> <span class="nx">multiline</span><span class="p">.</span><span class="nx">enabled</span>
|
||||
<span class="nx">rli</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="nx">multiline</span><span class="p">.</span><span class="nx">initialPrompt</span>
|
||||
<span class="nx">rli</span><span class="p">.</span><span class="nx">prompt</span> <span class="kc">true</span>
|
||||
<span class="k">return</span>
|
||||
<span class="nv">code = </span><span class="nx">backlog</span> <span class="o">+=</span> <span class="nx">buffer</span>
|
||||
<span class="k">if</span> <span class="nx">code</span><span class="p">[</span><span class="nx">code</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="s1">'\\'</span>
|
||||
<span class="nv">backlog = </span><span class="s2">"#{backlog[...-1]}\n"</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="nx">REPL_PROMPT_CONTINUATION</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span>
|
||||
<span class="k">return</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="nx">REPL_PROMPT</span>
|
||||
<span class="nv">backlog = </span><span class="s1">''</span>
|
||||
<span class="k">try</span>
|
||||
<span class="nv">_ = </span><span class="nx">global</span><span class="p">.</span><span class="nx">_</span>
|
||||
<span class="nv">returnValue = </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nb">eval</span> <span class="s2">"_=(#{code}\n)"</span><span class="p">,</span> <span class="p">{</span>
|
||||
<span class="nx">filename</span><span class="o">:</span> <span class="s1">'repl'</span>
|
||||
<span class="nx">modulename</span><span class="o">:</span> <span class="s1">'repl'</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">if</span> <span class="nx">returnValue</span> <span class="o">is</span> <span class="kc">undefined</span>
|
||||
<span class="nv">global._ = </span><span class="nx">_</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="nx">inspect</span><span class="p">(</span><span class="nx">returnValue</span><span class="p">,</span> <span class="kc">no</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">enableColours</span><span class="p">)</span> <span class="o">+</span> <span class="s1">'\n'</span>
|
||||
<span class="k">catch</span> <span class="nx">err</span>
|
||||
<span class="nx">error</span> <span class="nx">err</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-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <h1>Autocompletion</h1> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Regexes to match complete-able bits of text.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">ACCESSOR = </span><span class="sr">/\s*([\w\.]+)(?:\.(\w*))$/</span>
|
||||
<span class="nv">SIMPLEVAR = </span><span class="sr">/\s*(\w*)$/i</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Returns a list of completions, and the completed text.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">autocomplete = </span><span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">completeAttribute</span><span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="o">or</span> <span class="nx">completeVariable</span><span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="o">or</span> <span class="p">[[],</span> <span class="nx">text</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Attempt to autocomplete a chained dotted attribute: <code>one.two.three</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">completeAttribute = </span><span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nv">match = </span><span class="nx">text</span><span class="p">.</span><span class="nx">match</span> <span class="nx">ACCESSOR</span>
|
||||
<span class="p">[</span><span class="nx">all</span><span class="p">,</span> <span class="nx">obj</span><span class="p">,</span> <span class="nx">prefix</span><span class="p">]</span> <span class="o">=</span> <span class="nx">match</span>
|
||||
<span class="k">try</span>
|
||||
<span class="nv">val = </span><span class="nx">Script</span><span class="p">.</span><span class="nx">runInThisContext</span> <span class="nx">obj</span>
|
||||
<span class="k">catch</span> <span class="nx">error</span>
|
||||
<span class="k">return</span>
|
||||
<span class="nv">completions = </span><span class="nx">getCompletions</span> <span class="nx">prefix</span><span class="p">,</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertyNames</span> <span class="nx">val</span>
|
||||
<span class="p">[</span><span class="nx">completions</span><span class="p">,</span> <span class="nx">prefix</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Attempt to autocomplete an in-scope free variable: <code>one</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">completeVariable = </span><span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">free = </span><span class="p">(</span><span class="nx">text</span><span class="p">.</span><span class="nx">match</span> <span class="nx">SIMPLEVAR</span><span class="p">)</span><span class="o">?</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="nx">free</span><span class="o">?</span>
|
||||
<span class="nv">vars = </span><span class="nx">Script</span><span class="p">.</span><span class="nx">runInThisContext</span> <span class="s1">'Object.getOwnPropertyNames(this)'</span>
|
||||
<span class="nv">keywords = </span><span class="p">(</span><span class="nx">r</span> <span class="k">for</span> <span class="nx">r</span> <span class="k">in</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">RESERVED</span> <span class="k">when</span> <span class="nx">r</span><span class="p">[</span><span class="mi">0</span><span class="p">..</span><span class="mi">1</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'__'</span><span class="p">)</span>
|
||||
<span class="nv">possibilities = </span><span class="nx">vars</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">keywords</span>
|
||||
<span class="nv">completions = </span><span class="nx">getCompletions</span> <span class="nx">free</span><span class="p">,</span> <span class="nx">possibilities</span>
|
||||
<span class="p">[</span><span class="nx">completions</span><span class="p">,</span> <span class="nx">free</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Return elements of candidates for which <code>prefix</code> is a prefix.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">getCompletions = </span><span class="p">(</span><span class="nx">prefix</span><span class="p">,</span> <span class="nx">candidates</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="p">(</span><span class="nx">el</span> <span class="k">for</span> <span class="nx">el</span> <span class="k">in</span> <span class="nx">candidates</span> <span class="k">when</span> <span class="nx">el</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">prefix</span><span class="p">)</span> <span class="o">is</span> <span class="mi">0</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>Make sure that uncaught exceptions don't kill the REPL.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">process</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'uncaughtException'</span><span class="p">,</span> <span class="nx">error</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>Create the REPL by listening to <strong>stdin</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nx">readline</span><span class="p">.</span><span class="nx">createInterface</span><span class="p">.</span><span class="nx">length</span> <span class="o"><</span> <span class="mi">3</span>
|
||||
<span class="nv">repl = </span><span class="nx">readline</span><span class="p">.</span><span class="nx">createInterface</span> <span class="nx">stdin</span><span class="p">,</span> <span class="nx">autocomplete</span>
|
||||
<span class="nx">stdin</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'data'</span><span class="p">,</span> <span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-></span> <span class="nx">repl</span><span class="p">.</span><span class="nx">write</span> <span class="nx">buffer</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">repl = </span><span class="nx">readline</span><span class="p">.</span><span class="nx">createInterface</span> <span class="nx">stdin</span><span class="p">,</span> <span class="nx">stdout</span><span class="p">,</span> <span class="nx">autocomplete</span>
|
||||
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'attemptClose'</span><span class="p">,</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">backlog</span>
|
||||
<span class="nv">backlog = </span><span class="s1">''</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="s1">'\n'</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="nx">REPL_PROMPT</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">close</span><span class="p">()</span>
|
||||
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'close'</span><span class="p">,</span> <span class="o">-></span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="s1">'\n'</span>
|
||||
<span class="nx">stdin</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="kc">on</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">setPrompt</span> <span class="nx">REPL_PROMPT</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span>
|
||||
<span class="nv">module.exports =</span>
|
||||
<span class="nv">start: </span><span class="nf">(opts = {}) -></span>
|
||||
<span class="nv">opts = </span><span class="nx">merge</span> <span class="nx">replDefaults</span><span class="p">,</span> <span class="nx">opts</span>
|
||||
<span class="nv">repl = </span><span class="nx">nodeREPL</span><span class="p">.</span><span class="nx">start</span> <span class="nx">opts</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">on</span> <span class="s">'exit'</span><span class="p">,</span> <span class="nf">-></span> <span class="nx">repl</span><span class="p">.</span><span class="nx">outputStream</span><span class="p">.</span><span class="nx">write</span> <span class="s">'\n'</span>
|
||||
<span class="nx">addMultilineHandler</span> <span class="nx">repl</span>
|
||||
<span class="nx">repl</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -1,15 +1,15 @@
|
||||
<!DOCTYPE html> <html> <head> <title>rewriter.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> rewriter.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> <p>The CoffeeScript language has a good deal of optional syntax, implicit syntax,
|
||||
<!DOCTYPE html> <html> <head> <title>rewriter.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </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="pilwrap"> <a class="pilcrow" 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, 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="pilwrap"> <a class="pilcrow" href="#section-2">¶</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="nx">class</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">Rewriter</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Helpful snippet for debugging:
|
||||
its internal array of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">class</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">Rewriter</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Helpful snippet for debugging:
|
||||
console.log (t[0] + '/' + t[1] for t in @tokens).join ' '</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</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="nx">rewrite</span><span class="o">:</span> <span class="p">(</span><span class="nx">@tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
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="nf">(@tokens) -></span>
|
||||
<span class="nx">@removeLeadingNewlines</span><span class="p">()</span>
|
||||
<span class="nx">@removeMidExpressionNewlines</span><span class="p">()</span>
|
||||
<span class="nx">@closeOpenCalls</span><span class="p">()</span>
|
||||
@@ -18,17 +18,18 @@ corrected before implicit parentheses can be wrapped around blocks of code.</p>
|
||||
<span class="nx">@tagPostfixConditionals</span><span class="p">()</span>
|
||||
<span class="nx">@addImplicitBraces</span><span class="p">()</span>
|
||||
<span class="nx">@addImplicitParentheses</span><span class="p">()</span>
|
||||
<span class="nx">@addLocationDataToGeneratedTokens</span><span class="p">()</span>
|
||||
<span class="nx">@tokens</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</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="nx">scanTokens</span><span class="o">:</span> <span class="p">(</span><span class="nx">block</span><span class="p">)</span> <span class="o">-></span>
|
||||
our feet.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">scanTokens: </span><span class="nf">(block) -></span>
|
||||
<span class="p">{</span><span class="nx">tokens</span><span class="p">}</span> <span class="o">=</span> <span class="k">this</span>
|
||||
<span class="nv">i = </span><span class="mi">0</span>
|
||||
<span class="nx">i</span> <span class="o">+=</span> <span class="nx">block</span><span class="p">.</span><span class="nx">call</span> <span class="k">this</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">tokens</span> <span class="k">while</span> <span class="nv">token = </span><span class="nx">tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>
|
||||
<span class="kc">true</span>
|
||||
|
||||
<span class="nx">detectEnd</span><span class="o">:</span> <span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">detectEnd: </span><span class="nf">(i, condition, action) -></span>
|
||||
<span class="p">{</span><span class="nx">tokens</span><span class="p">}</span> <span class="o">=</span> <span class="k">this</span>
|
||||
<span class="nv">levels = </span><span class="mi">0</span>
|
||||
<span class="k">while</span> <span class="nv">token = </span><span class="nx">tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>
|
||||
@@ -40,159 +41,223 @@ our feet.</p> </td> <td class="code"> <div
|
||||
<span class="nx">levels</span> <span class="o">-=</span> <span class="mi">1</span>
|
||||
<span class="nx">i</span> <span class="o">+=</span> <span class="mi">1</span>
|
||||
<span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Leading newlines would introduce an ambiguity in the grammar, so we
|
||||
dispatch them here.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">removeLeadingNewlines</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="k">break</span> <span class="k">for</span> <span class="p">[</span><span class="nx">tag</span><span class="p">],</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">@tokens</span> <span class="k">when</span> <span class="nx">tag</span> <span class="o">isnt</span> <span class="s1">'TERMINATOR'</span>
|
||||
dispatch them here.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">removeLeadingNewlines: </span><span class="nf">-></span>
|
||||
<span class="k">break</span> <span class="k">for</span> <span class="p">[</span><span class="nx">tag</span><span class="p">],</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">@tokens</span> <span class="k">when</span> <span class="nx">tag</span> <span class="o">isnt</span> <span class="s">'TERMINATOR'</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">i</span> <span class="k">if</span> <span class="nx">i</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Some blocks occur in the middle of expressions -- when we're expecting
|
||||
this, remove their trailing newlines.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">removeMidExpressionNewlines</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</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="o">-></span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="k">in</span> <span class="nx">EXPRESSION_CLOSE</span>
|
||||
this, remove their trailing newlines.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">removeMidExpressionNewlines: </span><span class="nf">-></span>
|
||||
<span class="nx">@scanTokens</span> <span class="nf">(token, i, tokens) -></span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="k">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="s">'TERMINATOR'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="k">in</span> <span class="nx">EXPRESSION_CLOSE</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="mi">0</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>The lexer has tagged the opening parenthesis of a method call. Match it with
|
||||
its paired close. We have the mis-nested outdent case included here for
|
||||
calls that close on the same line, just before their outdent.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">closeOpenCalls</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s1">')'</span><span class="p">,</span> <span class="s1">'CALL_END'</span><span class="p">]</span> <span class="o">or</span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'OUTDENT'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s1">')'</span>
|
||||
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@tokens</span><span class="p">[</span><span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'OUTDENT'</span> <span class="k">then</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">else</span> <span class="nx">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'CALL_END'</span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span> <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'CALL_START'</span>
|
||||
calls that close on the same line, just before their outdent.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">closeOpenCalls: </span><span class="nf">-></span>
|
||||
|
||||
<span class="nv">condition = </span><span class="nf">(token, i) -></span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s">')'</span><span class="p">,</span> <span class="s">'CALL_END'</span><span class="p">]</span> <span class="o">or</span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">'OUTDENT'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s">')'</span>
|
||||
|
||||
<span class="nv">action = </span><span class="nf">(token, i) -></span>
|
||||
<span class="nx">@tokens</span><span class="p">[</span><span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">'OUTDENT'</span> <span class="k">then</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">else</span> <span class="nx">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s">'CALL_END'</span>
|
||||
|
||||
<span class="nx">@scanTokens</span> <span class="nf">(token, i) -></span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span> <span class="k">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="s">'CALL_START'</span>
|
||||
<span class="mi">1</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>The lexer has tagged the opening parenthesis of an indexing operation call.
|
||||
Match it with its paired close.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">closeOpenIndexes</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s1">']'</span><span class="p">,</span> <span class="s1">'INDEX_END'</span><span class="p">]</span>
|
||||
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'INDEX_END'</span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span> <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'INDEX_START'</span>
|
||||
Match it with its paired close.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">closeOpenIndexes: </span><span class="nf">-></span>
|
||||
|
||||
<span class="nv">condition = </span><span class="nf">(token, i) -></span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s">']'</span><span class="p">,</span> <span class="s">'INDEX_END'</span><span class="p">]</span>
|
||||
|
||||
<span class="nv">action = </span><span class="nf">(token, i) -></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="s">'INDEX_END'</span>
|
||||
|
||||
<span class="nx">@scanTokens</span> <span class="nf">(token, i) -></span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span> <span class="k">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="s">'INDEX_START'</span>
|
||||
<span class="mi">1</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Object literals may be written with implicit braces, for simple cases.
|
||||
Insert the missing braces here, so that the parser doesn't have to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">addImplicitBraces</span><span class="o">:</span> <span class="o">-></span>
|
||||
Insert the missing braces here, so that the parser doesn't have to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">addImplicitBraces: </span><span class="nf">-></span>
|
||||
|
||||
<span class="nv">stack = </span><span class="p">[]</span>
|
||||
<span class="nv">start = </span><span class="kc">null</span>
|
||||
<span class="nv">startsLine = </span><span class="kc">null</span>
|
||||
<span class="nv">sameLine = </span><span class="kc">yes</span>
|
||||
<span class="nv">startIndent = </span><span class="mi">0</span>
|
||||
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">startIndex = </span><span class="mi">0</span>
|
||||
|
||||
<span class="nv">condition = </span><span class="nf">(token, i) -></span>
|
||||
<span class="p">[</span><span class="nx">one</span><span class="p">,</span> <span class="nx">two</span><span class="p">,</span> <span class="nx">three</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span> <span class="p">..</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">3</span><span class="p">]</span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="k">if</span> <span class="s1">'HERECOMMENT'</span> <span class="o">is</span> <span class="nx">one</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="k">return</span> <span class="kc">no</span> <span class="k">if</span> <span class="s">'HERECOMMENT'</span> <span class="o">is</span> <span class="nx">one</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="nx">tag</span><span class="p">]</span> <span class="o">=</span> <span class="nx">token</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">]</span> <span class="o">and</span>
|
||||
<span class="o">not</span> <span class="p">(</span><span class="nx">two</span><span class="o">?</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">or</span> <span class="nx">one</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="s1">'@'</span> <span class="o">and</span> <span class="nx">three</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="s1">':'</span><span class="p">))</span> <span class="o">or</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="nx">one</span> <span class="o">and</span>
|
||||
<span class="nx">one</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">not</span> <span class="k">in</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">'@'</span><span class="p">,</span> <span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">])</span>
|
||||
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">tok = </span><span class="p">[</span><span class="s1">'}'</span><span class="p">,</span> <span class="s1">'}'</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="nv">tok.generated = </span><span class="kc">yes</span>
|
||||
<span class="nv">sameLine = </span><span class="kc">no</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">LINEBREAKS</span>
|
||||
<span class="k">return</span> <span class="p">(</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s">'TERMINATOR'</span><span class="p">,</span> <span class="s">'OUTDENT'</span><span class="p">]</span> <span class="o">or</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="k">in</span> <span class="nx">IMPLICIT_END</span> <span class="o">and</span> <span class="nx">sameLine</span> <span class="o">and</span> <span class="o">not</span> <span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="nx">startIndex</span> <span class="o">is</span> <span class="mi">1</span><span class="p">)))</span> <span class="o">and</span>
|
||||
<span class="p">((</span><span class="o">!</span><span class="nx">startsLine</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">isnt</span> <span class="s">','</span><span class="p">)</span> <span class="o">or</span>
|
||||
<span class="o">not</span> <span class="p">(</span><span class="nx">two</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="s">':'</span> <span class="o">or</span> <span class="nx">one</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="s">'@'</span> <span class="o">and</span> <span class="nx">three</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="s">':'</span><span class="p">)))</span> <span class="o">or</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="o">is</span> <span class="s">','</span> <span class="o">and</span> <span class="nx">one</span> <span class="o">and</span>
|
||||
<span class="nx">one</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">not</span> <span class="k">in</span> <span class="p">[</span><span class="s">'IDENTIFIER'</span><span class="p">,</span> <span class="s">'NUMBER'</span><span class="p">,</span> <span class="s">'STRING'</span><span class="p">,</span> <span class="s">'@'</span><span class="p">,</span> <span class="s">'TERMINATOR'</span><span class="p">,</span> <span class="s">'OUTDENT'</span><span class="p">]</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
<span class="nv">action = </span><span class="nf">(token, i) -></span>
|
||||
<span class="nv">tok = </span><span class="nx">@generate</span> <span class="s">'}'</span><span class="p">,</span> <span class="s">'}'</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">tok</span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
|
||||
<span class="nx">@scanTokens</span> <span class="nf">(token, i, tokens) -></span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nv">tag = </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="k">in</span> <span class="nx">EXPRESSION_START</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="p">[(</span><span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'INDENT'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'{'</span> <span class="k">then</span> <span class="s1">'{'</span> <span class="k">else</span> <span class="nx">tag</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="p">[(</span><span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">'INDENT'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s">'{'</span> <span class="k">then</span> <span class="s">'{'</span> <span class="k">else</span> <span class="nx">tag</span><span class="p">),</span> <span class="nx">i</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="k">in</span> <span class="nx">EXPRESSION_END</span>
|
||||
<span class="nv">start = </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> <span class="nx">unless</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="nv">ago = </span><span class="nx">@tag</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s1">':'</span> <span class="o">or</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="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'{'</span><span class="p">)</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">'{'</span><span class="p">]</span>
|
||||
<span class="nv">idx = </span> <span class="k">if</span> <span class="nx">ago</span> <span class="o">is</span> <span class="s1">'@'</span> <span class="k">then</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span> <span class="k">else</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nx">idx</span> <span class="o">-=</span> <span class="mi">2</span> <span class="k">while</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">idx</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'HERECOMMENT'</span>
|
||||
<span class="nv">value = </span><span class="k">new</span> <span class="nb">String</span><span class="p">(</span><span class="s1">'{'</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="k">unless</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">':'</span> <span class="o">and</span>
|
||||
<span class="p">((</span><span class="nv">ago = </span><span class="nx">@tag</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s">':'</span> <span class="o">or</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="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s">'{'</span><span class="p">)</span>
|
||||
<span class="nv">sameLine = </span><span class="kc">yes</span>
|
||||
<span class="nv">startIndex = </span><span class="nx">i</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="p">[</span><span class="s">'{'</span><span class="p">]</span>
|
||||
<span class="nv">idx = </span> <span class="k">if</span> <span class="nx">ago</span> <span class="o">is</span> <span class="s">'@'</span> <span class="k">then</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span> <span class="k">else</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nx">idx</span> <span class="o">-=</span> <span class="mi">2</span> <span class="k">while</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">idx</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s">'HERECOMMENT'</span>
|
||||
<span class="nv">prevTag = </span><span class="nx">@tag</span><span class="p">(</span><span class="nx">idx</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
|
||||
<span class="nv">startsLine = </span><span class="o">not</span> <span class="nx">prevTag</span> <span class="o">or</span> <span class="p">(</span><span class="nx">prevTag</span> <span class="k">in</span> <span class="nx">LINEBREAKS</span><span class="p">)</span>
|
||||
<span class="nv">value = </span><span class="k">new</span> <span class="nb">String</span><span class="p">(</span><span class="s">'{'</span><span class="p">)</span>
|
||||
<span class="nv">value.generated = </span><span class="kc">yes</span>
|
||||
<span class="nv">tok = </span><span class="p">[</span><span class="s1">'{'</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="nv">tok.generated = </span><span class="kc">yes</span>
|
||||
<span class="nv">tok = </span><span class="nx">@generate</span> <span class="s">'{'</span><span class="p">,</span> <span class="nx">value</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">idx</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">tok</span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
|
||||
<span class="mi">2</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Methods may be optionally called without parentheses, for simple cases.
|
||||
Insert the implicit parentheses here, so that the parser doesn't have to
|
||||
deal with them.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">addImplicitParentheses</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nv">noCall = </span><span class="kc">no</span>
|
||||
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span> <span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">'CALL_END'</span><span class="p">,</span> <span class="s1">')'</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
deal with them.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">addImplicitParentheses: </span><span class="nf">-></span>
|
||||
|
||||
<span class="nv">noCall = seenSingle = seenControl = </span><span class="kc">no</span>
|
||||
<span class="nv">callIndex = </span><span class="kc">null</span>
|
||||
|
||||
<span class="nv">condition = </span><span class="nf">(token, i) -></span>
|
||||
<span class="p">[</span><span class="nx">tag</span><span class="p">]</span> <span class="o">=</span> <span class="nx">token</span>
|
||||
<span class="k">return</span> <span class="kc">yes</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">seenSingle</span> <span class="o">and</span> <span class="nx">token</span><span class="p">.</span><span class="nx">fromThen</span>
|
||||
<span class="nv">seenSingle = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s">'IF'</span><span class="p">,</span> <span class="s">'ELSE'</span><span class="p">,</span> <span class="s">'CATCH'</span><span class="p">,</span> <span class="s">'->'</span><span class="p">,</span> <span class="s">'=>'</span><span class="p">,</span> <span class="s">'CLASS'</span><span class="p">]</span>
|
||||
<span class="nv">seenControl = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s">'IF'</span><span class="p">,</span> <span class="s">'ELSE'</span><span class="p">,</span> <span class="s">'SWITCH'</span><span class="p">,</span> <span class="s">'TRY'</span><span class="p">,</span> <span class="s">'='</span><span class="p">]</span>
|
||||
<span class="k">return</span> <span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s">'.'</span><span class="p">,</span> <span class="s">'?.'</span><span class="p">,</span> <span class="s">'::'</span><span class="p">]</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s">'OUTDENT'</span>
|
||||
<span class="o">not</span> <span class="nx">token</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">isnt</span> <span class="s">','</span> <span class="o">and</span> <span class="p">(</span><span class="nx">tag</span> <span class="k">in</span> <span class="nx">IMPLICIT_END</span> <span class="o">or</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="o">is</span> <span class="s">'INDENT'</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">seenControl</span><span class="p">))</span> <span class="o">and</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="o">isnt</span> <span class="s">'INDENT'</span> <span class="o">or</span>
|
||||
<span class="p">(</span><span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">not</span> <span class="k">in</span> <span class="p">[</span><span class="s">'CLASS'</span><span class="p">,</span> <span class="s">'EXTENDS'</span><span class="p">]</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">not</span> <span class="k">in</span> <span class="nx">IMPLICIT_BLOCK</span> <span class="o">and</span>
|
||||
<span class="o">not</span> <span class="p">(</span><span class="nx">callIndex</span> <span class="o">is</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span> <span class="o">and</span> <span class="p">(</span><span class="nv">post = </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="o">and</span> <span class="nx">post</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">post</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">'{'</span><span class="p">)))</span>
|
||||
|
||||
<span class="nv">action = </span><span class="nf">(token, i) -></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">@generate</span> <span class="s">'CALL_END'</span><span class="p">,</span> <span class="s">')'</span>
|
||||
|
||||
<span class="nx">@scanTokens</span> <span class="nf">(token, i, tokens) -></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">noCall = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'CLASS'</span><span class="p">,</span> <span class="s1">'IF'</span><span class="p">]</span>
|
||||
<span class="nv">noCall = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s">'CLASS'</span><span class="p">,</span> <span class="s">'IF'</span><span class="p">,</span> <span class="s">'FOR'</span><span class="p">,</span> <span class="s">'WHILE'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">current</span><span class="p">,</span> <span class="nx">next</span><span class="p">]</span> <span class="o">=</span> <span class="nx">tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span> <span class="p">..</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nv">callObject = </span><span class="o">not</span> <span class="nx">noCall</span> <span class="o">and</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'INDENT'</span> <span class="o">and</span>
|
||||
<span class="nx">next</span> <span class="o">and</span> <span class="nx">next</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'{'</span> <span class="o">and</span>
|
||||
<span class="nv">callObject = </span><span class="o">not</span> <span class="nx">noCall</span> <span class="o">and</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">'INDENT'</span> <span class="o">and</span>
|
||||
<span class="nx">next</span> <span class="o">and</span> <span class="nx">next</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">'{'</span> <span class="o">and</span>
|
||||
<span class="nx">prev</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="nx">IMPLICIT_FUNC</span>
|
||||
<span class="nv">seenSingle = </span><span class="kc">no</span>
|
||||
<span class="nv">seenControl = </span><span class="kc">no</span>
|
||||
<span class="nv">noCall = </span><span class="kc">no</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">LINEBREAKS</span>
|
||||
<span class="nv">token.call = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">prev</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">prev</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">and</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'?'</span>
|
||||
<span class="nv">token.call = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">prev</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">prev</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">and</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">'?'</span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">token</span><span class="p">.</span><span class="nx">fromThen</span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">callObject</span> <span class="o">or</span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="k">unless</span> <span class="nx">callObject</span> <span class="o">or</span>
|
||||
<span class="nx">prev</span><span class="o">?</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">and</span> <span class="p">(</span><span class="nx">prev</span><span class="p">.</span><span class="nx">call</span> <span class="o">or</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="nx">IMPLICIT_FUNC</span><span class="p">)</span> <span class="o">and</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="k">in</span> <span class="nx">IMPLICIT_CALL</span> <span class="o">or</span> <span class="o">not</span> <span class="p">(</span><span class="nx">token</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">or</span> <span class="nx">token</span><span class="p">.</span><span class="nx">newLine</span><span class="p">)</span> <span class="o">and</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">IMPLICIT_UNSPACED_CALL</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">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="p">[</span><span class="nx">tag</span><span class="p">]</span> <span class="o">=</span> <span class="nx">token</span>
|
||||
<span class="k">return</span> <span class="kc">yes</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">seenSingle</span> <span class="o">and</span> <span class="nx">token</span><span class="p">.</span><span class="nx">fromThen</span>
|
||||
<span class="nv">seenSingle = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">,</span> <span class="s1">'CATCH'</span><span class="p">,</span> <span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">]</span>
|
||||
<span class="nv">seenControl = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">,</span> <span class="s1">'SWITCH'</span><span class="p">,</span> <span class="s1">'TRY'</span><span class="p">]</span>
|
||||
<span class="k">return</span> <span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</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="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'OUTDENT'</span>
|
||||
<span class="o">not</span> <span class="nx">token</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">isnt</span> <span class="s1">','</span> <span class="o">and</span> <span class="p">(</span><span class="nx">tag</span> <span class="k">in</span> <span class="nx">IMPLICIT_END</span> <span class="o">or</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="o">is</span> <span class="s1">'INDENT'</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">seenControl</span><span class="p">))</span> <span class="o">and</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="o">isnt</span> <span class="s1">'INDENT'</span> <span class="o">or</span>
|
||||
<span class="p">(</span><span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">isnt</span> <span class="s1">'CLASS'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">not</span> <span class="k">in</span> <span class="nx">IMPLICIT_BLOCK</span> <span class="o">and</span>
|
||||
<span class="o">not</span> <span class="p">((</span><span class="nv">post = </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="o">and</span> <span class="nx">post</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">post</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'{'</span><span class="p">)))</span>
|
||||
<span class="p">,</span> <span class="nx">action</span>
|
||||
<span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'FUNC_EXIST'</span> <span class="k">if</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'?'</span>
|
||||
<span class="mi">2</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Because our grammar is LALR(1), it can't handle some single-line
|
||||
<span class="nv">callIndex = </span><span class="nx">i</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">@generate</span> <span class="s">'CALL_START'</span><span class="p">,</span> <span class="s">'('</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
|
||||
<span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s">'FUNC_EXIST'</span> <span class="k">if</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">'?'</span>
|
||||
<span class="mi">2</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Add location data to all tokens generated by the rewriter.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">addLocationDataToGeneratedTokens: </span><span class="nf">-></span>
|
||||
<span class="nx">@scanTokens</span> <span class="nf">(token, i, tokens) -></span>
|
||||
<span class="nv">tag = </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">token</span><span class="p">.</span><span class="nx">generated</span> <span class="o">or</span> <span class="nx">token</span><span class="p">.</span><span class="nx">explicit</span><span class="p">)</span> <span class="o">and</span> <span class="p">(</span><span class="o">not</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">i</span> <span class="o">></span> <span class="mi">0</span>
|
||||
<span class="nv">prevToken = </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">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span>
|
||||
<span class="nv">first_line: </span><span class="nx">prevToken</span><span class="p">[</span><span class="mi">2</span><span class="p">].</span><span class="nx">last_line</span>
|
||||
<span class="nv">first_column: </span><span class="nx">prevToken</span><span class="p">[</span><span class="mi">2</span><span class="p">].</span><span class="nx">last_column</span>
|
||||
<span class="nv">last_line: </span><span class="nx">prevToken</span><span class="p">[</span><span class="mi">2</span><span class="p">].</span><span class="nx">last_line</span>
|
||||
<span class="nv">last_column: </span><span class="nx">prevToken</span><span class="p">[</span><span class="mi">2</span><span class="p">].</span><span class="nx">last_column</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span>
|
||||
<span class="nv">first_line: </span><span class="mi">0</span>
|
||||
<span class="nv">first_column: </span><span class="mi">0</span>
|
||||
<span class="nv">last_line: </span><span class="mi">0</span>
|
||||
<span class="nv">last_column: </span><span class="mi">0</span>
|
||||
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Because our grammar is LALR(1), it can't handle some single-line
|
||||
expressions that lack ending delimiters. The <strong>Rewriter</strong> adds the implicit
|
||||
blocks, so it doesn't need to. ')' can close a single-line block,
|
||||
but we need to make sure it's balanced.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">addImplicitIndentation</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</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="o">-></span>
|
||||
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="nf">-></span>
|
||||
<span class="nv">starter = indent = outdent = </span><span class="kc">null</span>
|
||||
|
||||
<span class="nv">condition = </span><span class="nf">(token, i) -></span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">isnt</span> <span class="s">';'</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="k">in</span> <span class="nx">SINGLE_CLOSERS</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="s">'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="s">'IF'</span><span class="p">,</span> <span class="s">'THEN'</span><span class="p">])</span>
|
||||
|
||||
<span class="nv">action = </span><span class="nf">(token, i) -></span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="p">(</span><span class="k">if</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s">','</span> <span class="k">then</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">else</span> <span class="nx">i</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">outdent</span>
|
||||
|
||||
<span class="nx">@scanTokens</span> <span class="nf">(token, i, tokens) -></span>
|
||||
<span class="p">[</span><span class="nx">tag</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">'TERMINATOR'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'THEN'</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">'TERMINATOR'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s">'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>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'ELSE'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">isnt</span> <span class="s1">'OUTDENT'</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">'ELSE'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">isnt</span> <span class="s">'OUTDENT'</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">@indentation</span><span class="p">(</span><span class="nx">token</span><span class="p">)...</span>
|
||||
<span class="k">return</span> <span class="mi">2</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'CATCH'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">)</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'FINALLY'</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">'CATCH'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">)</span> <span class="k">in</span> <span class="p">[</span><span class="s">'OUTDENT'</span><span class="p">,</span> <span class="s">'TERMINATOR'</span><span class="p">,</span> <span class="s">'FINALLY'</span><span class="p">]</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">@indentation</span><span class="p">(</span><span class="nx">token</span><span class="p">)...</span>
|
||||
<span class="k">return</span> <span class="mi">4</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">SINGLE_LINERS</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">isnt</span> <span class="s1">'INDENT'</span> <span class="o">and</span>
|
||||
<span class="o">not</span> <span class="p">(</span><span class="nx">tag</span> <span class="o">is</span> <span class="s1">'ELSE'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'IF'</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">SINGLE_LINERS</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">isnt</span> <span class="s">'INDENT'</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="s">'ELSE'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s">'IF'</span><span class="p">)</span>
|
||||
<span class="nv">starter = </span><span class="nx">tag</span>
|
||||
<span class="p">[</span><span class="nx">indent</span><span class="p">,</span> <span class="nx">outdent</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@indentation</span> <span class="nx">token</span>
|
||||
<span class="nv">indent.fromThen = </span><span class="kc">true</span> <span class="k">if</span> <span class="nx">starter</span> <span class="o">is</span> <span class="s1">'THEN'</span>
|
||||
<span class="nv">indent.generated = outdent.generated = </span><span class="kc">true</span>
|
||||
<span class="p">[</span><span class="nx">indent</span><span class="p">,</span> <span class="nx">outdent</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@indentation</span> <span class="nx">token</span><span class="p">,</span> <span class="kc">yes</span>
|
||||
<span class="nv">indent.fromThen = </span><span class="kc">true</span> <span class="k">if</span> <span class="nx">starter</span> <span class="o">is</span> <span class="s">'THEN'</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">indent</span>
|
||||
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">';'</span> <span class="o">and</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="nx">SINGLE_CLOSERS</span> <span class="o">and</span>
|
||||
<span class="o">not</span> <span class="p">(</span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'ELSE'</span> <span class="o">and</span> <span class="nx">starter</span> <span class="o">not</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'THEN'</span><span class="p">])</span>
|
||||
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="p">(</span><span class="k">if</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s1">','</span> <span class="k">then</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">else</span> <span class="nx">i</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">outdent</span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">tag</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">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">'THEN'</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-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Tag postfix conditionals as such, so that we can parse them with a
|
||||
different precedence.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">tagPostfixConditionals</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'INDENT'</span><span class="p">]</span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'IF'</span>
|
||||
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Tag postfix conditionals as such, so that we can parse them with a
|
||||
different precedence.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tagPostfixConditionals: </span><span class="nf">-></span>
|
||||
|
||||
<span class="nv">original = </span><span class="kc">null</span>
|
||||
|
||||
<span class="nv">condition = </span><span class="nf">(token, i) -></span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s">'TERMINATOR'</span><span class="p">,</span> <span class="s">'INDENT'</span><span class="p">]</span>
|
||||
|
||||
<span class="nv">action = </span><span class="nf">(token, i) -></span>
|
||||
<span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s">'INDENT'</span> <span class="o">or</span> <span class="p">(</span><span class="nx">token</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">token</span><span class="p">.</span><span class="nx">fromThen</span><span class="p">)</span>
|
||||
<span class="nx">original</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s">'POST_'</span> <span class="o">+</span> <span class="nx">original</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
|
||||
<span class="nx">@scanTokens</span> <span class="nf">(token, i) -></span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="k">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="s">'IF'</span>
|
||||
<span class="nv">original = </span><span class="nx">token</span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">original</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'POST_'</span> <span class="o">+</span> <span class="nx">original</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'INDENT'</span>
|
||||
<span class="mi">1</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Generate the indentation tokens, based on another token on the same line.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">indentation</span><span class="o">:</span> <span class="p">(</span><span class="nx">token</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="p">[[</span><span class="s1">'INDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]],</span> <span class="p">[</span><span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]]</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>Look up a tag by token index.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">tag</span><span class="o">:</span> <span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="o">-></span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>List of the token pairs that must be balanced.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BALANCED_PAIRS = </span><span class="p">[</span>
|
||||
<span class="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">'CALL_START'</span><span class="p">,</span> <span class="s1">'CALL_END'</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">'INDEX_START'</span><span class="p">,</span> <span class="s1">'INDEX_END'</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <p>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">exports.INVERSES = INVERSES = </span><span class="p">{}</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</a> </div> <p>The tokens that signal the start/end of a balanced pair.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_START = </span><span class="p">[]</span>
|
||||
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
|
||||
<span class="mi">1</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>Generate the indentation tokens, based on another token on the same line.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">indentation: </span><span class="nf">(token, implicit = no) -></span>
|
||||
<span class="nv">indent = </span><span class="p">[</span><span class="s">'INDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
|
||||
<span class="nv">outdent = </span><span class="p">[</span><span class="s">'OUTDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
|
||||
<span class="nv">indent.generated = outdent.generated = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">implicit</span>
|
||||
<span class="nv">indent.explicit = outdent.explicit = </span><span class="kc">yes</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">implicit</span>
|
||||
<span class="p">[</span><span class="nx">indent</span><span class="p">,</span> <span class="nx">outdent</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>Create a generated token: one that exists due to a use of implicit syntax.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">generate: </span><span class="nf">(tag, value) -></span>
|
||||
<span class="nv">tok = </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="nv">tok.generated = </span><span class="kc">yes</span>
|
||||
<span class="nx">tok</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>Look up a tag by token index.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tag: </span><span class="nf">(i) -></span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</a> </div> <p>List of the token pairs that must be balanced.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BALANCED_PAIRS = </span><span class="p">[</span>
|
||||
<span class="p">[</span><span class="s">'('</span><span class="p">,</span> <span class="s">')'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'['</span><span class="p">,</span> <span class="s">']'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'{'</span><span class="p">,</span> <span class="s">'}'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'INDENT'</span><span class="p">,</span> <span class="s">'OUTDENT'</span><span class="p">],</span>
|
||||
<span class="p">[</span><span class="s">'CALL_START'</span><span class="p">,</span> <span class="s">'CALL_END'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'PARAM_START'</span><span class="p">,</span> <span class="s">'PARAM_END'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s">'INDEX_START'</span><span class="p">,</span> <span class="s">'INDEX_END'</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</a> </div> <p>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">exports.INVERSES = INVERSES = </span><span class="p">{}</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">¶</a> </div> <p>The tokens that signal the start/end of a balanced pair.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_START = </span><span class="p">[]</span>
|
||||
<span class="nv">EXPRESSION_END = </span><span class="p">[]</span>
|
||||
|
||||
<span class="k">for</span> <span class="p">[</span><span class="nx">left</span><span class="p">,</span> <span class="nx">rite</span><span class="p">]</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span>
|
||||
<span class="nx">EXPRESSION_START</span><span class="p">.</span><span class="nx">push</span> <span class="nx">INVERSES</span><span class="p">[</span><span class="nx">rite</span><span class="p">]</span> <span class="o">=</span> <span class="nx">left</span>
|
||||
<span class="nx">EXPRESSION_END</span> <span class="p">.</span><span class="nx">push</span> <span class="nx">INVERSES</span><span class="p">[</span><span class="nx">left</span><span class="p">]</span> <span class="o">=</span> <span class="nx">rite</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</a> </div> <p>Tokens that indicate the close of a clause of an expression.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_CLOSE = </span><span class="p">[</span><span class="s1">'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-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">¶</a> </div> <p>Tokens that, if followed by an <code>IMPLICIT_CALL</code>, indicate a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_FUNC = </span><span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'SUPER'</span><span class="p">,</span> <span class="s1">')'</span><span class="p">,</span> <span class="s1">'CALL_END'</span><span class="p">,</span> <span class="s1">']'</span><span class="p">,</span> <span class="s1">'INDEX_END'</span><span class="p">,</span> <span class="s1">'@'</span><span class="p">,</span> <span class="s1">'THIS'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">¶</a> </div> <p>If preceded by an <code>IMPLICIT_FUNC</code>, indicates a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_CALL = </span><span class="p">[</span>
|
||||
<span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'NUMBER'</span><span class="p">,</span> <span class="s1">'STRING'</span><span class="p">,</span> <span class="s1">'JS'</span><span class="p">,</span> <span class="s1">'REGEX'</span><span class="p">,</span> <span class="s1">'NEW'</span><span class="p">,</span> <span class="s1">'PARAM_START'</span><span class="p">,</span> <span class="s1">'CLASS'</span>
|
||||
<span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'TRY'</span><span class="p">,</span> <span class="s1">'SWITCH'</span><span class="p">,</span> <span class="s1">'THIS'</span><span class="p">,</span> <span class="s1">'BOOL'</span><span class="p">,</span> <span class="s1">'UNARY'</span><span class="p">,</span> <span class="s1">'SUPER'</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="nx">EXPRESSION_END</span> <span class="p">.</span><span class="nx">push</span> <span class="nx">INVERSES</span><span class="p">[</span><span class="nx">left</span><span class="p">]</span> <span class="o">=</span> <span class="nx">rite</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">¶</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="s">'CATCH'</span><span class="p">,</span> <span class="s">'WHEN'</span><span class="p">,</span> <span class="s">'ELSE'</span><span class="p">,</span> <span class="s">'FINALLY'</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">EXPRESSION_END</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">¶</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="s">'IDENTIFIER'</span><span class="p">,</span> <span class="s">'SUPER'</span><span class="p">,</span> <span class="s">')'</span><span class="p">,</span> <span class="s">'CALL_END'</span><span class="p">,</span> <span class="s">']'</span><span class="p">,</span> <span class="s">'INDEX_END'</span><span class="p">,</span> <span class="s">'@'</span><span class="p">,</span> <span class="s">'THIS'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">¶</a> </div> <p>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="s">'IDENTIFIER'</span><span class="p">,</span> <span class="s">'NUMBER'</span><span class="p">,</span> <span class="s">'STRING'</span><span class="p">,</span> <span class="s">'JS'</span><span class="p">,</span> <span class="s">'REGEX'</span><span class="p">,</span> <span class="s">'NEW'</span><span class="p">,</span> <span class="s">'PARAM_START'</span><span class="p">,</span> <span class="s">'CLASS'</span>
|
||||
<span class="s">'IF'</span><span class="p">,</span> <span class="s">'TRY'</span><span class="p">,</span> <span class="s">'SWITCH'</span><span class="p">,</span> <span class="s">'THIS'</span><span class="p">,</span> <span class="s">'BOOL'</span><span class="p">,</span> <span class="s">'NULL'</span><span class="p">,</span> <span class="s">'UNDEFINED'</span><span class="p">,</span> <span class="s">'UNARY'</span><span class="p">,</span> <span class="s">'SUPER'</span>
|
||||
<span class="s">'@'</span><span class="p">,</span> <span class="s">'->'</span><span class="p">,</span> <span class="s">'=>'</span><span class="p">,</span> <span class="s">'['</span><span class="p">,</span> <span class="s">'('</span><span class="p">,</span> <span class="s">'{'</span><span class="p">,</span> <span class="s">'--'</span><span class="p">,</span> <span class="s">'++'</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nv">IMPLICIT_UNSPACED_CALL = </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="pilwrap"> <a class="pilcrow" href="#section-23">¶</a> </div> <p>Tokens indicating that the implicit call must enclose a block of expressions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_BLOCK = </span><span class="p">[</span><span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">,</span> <span class="s1">'{'</span><span class="p">,</span> <span class="s1">'['</span><span class="p">,</span> <span class="s1">','</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">¶</a> </div> <p>Tokens that always mark the end of an implicit call for single-liners.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_END = </span><span class="p">[</span><span class="s1">'POST_IF'</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">'WHEN'</span><span class="p">,</span> <span class="s1">'BY'</span><span class="p">,</span> <span class="s1">'LOOP'</span><span class="p">,</span> <span class="s1">'TERMINATOR'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">¶</a> </div> <p>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="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</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> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">¶</a> </div> <p>Tokens that end a line.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">LINEBREAKS = </span><span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'INDENT'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">]</span>
|
||||
<span class="nv">IMPLICIT_UNSPACED_CALL = </span><span class="p">[</span><span class="s">'+'</span><span class="p">,</span> <span class="s">'-'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">¶</a> </div> <p>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="s">'->'</span><span class="p">,</span> <span class="s">'=>'</span><span class="p">,</span> <span class="s">'{'</span><span class="p">,</span> <span class="s">'['</span><span class="p">,</span> <span class="s">','</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">¶</a> </div> <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="s">'POST_IF'</span><span class="p">,</span> <span class="s">'FOR'</span><span class="p">,</span> <span class="s">'WHILE'</span><span class="p">,</span> <span class="s">'UNTIL'</span><span class="p">,</span> <span class="s">'WHEN'</span><span class="p">,</span> <span class="s">'BY'</span><span class="p">,</span> <span class="s">'LOOP'</span><span class="p">,</span> <span class="s">'TERMINATOR'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">¶</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="s">'ELSE'</span><span class="p">,</span> <span class="s">'->'</span><span class="p">,</span> <span class="s">'=>'</span><span class="p">,</span> <span class="s">'TRY'</span><span class="p">,</span> <span class="s">'FINALLY'</span><span class="p">,</span> <span class="s">'THEN'</span><span class="p">]</span>
|
||||
<span class="nv">SINGLE_CLOSERS = </span><span class="p">[</span><span class="s">'TERMINATOR'</span><span class="p">,</span> <span class="s">'CATCH'</span><span class="p">,</span> <span class="s">'FINALLY'</span><span class="p">,</span> <span class="s">'ELSE'</span><span class="p">,</span> <span class="s">'OUTDENT'</span><span class="p">,</span> <span class="s">'LEADING_WHEN'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">¶</a> </div> <p>Tokens that end a line.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">LINEBREAKS = </span><span class="p">[</span><span class="s">'TERMINATOR'</span><span class="p">,</span> <span class="s">'INDENT'</span><span class="p">,</span> <span class="s">'OUTDENT'</span><span class="p">]</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -3,52 +3,56 @@ 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="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>Import the helpers we plan to use.</p> </td> <td class="code"> <div class="highlight"><pre><span class="p">{</span><span class="nx">extend</span><span class="p">,</span> <span class="nx">last</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'./helpers'</span>
|
||||
with the outside.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>Import the helpers we plan to use.</p> </td> <td class="code"> <div class="highlight"><pre><span class="p">{</span><span class="nx">extend</span><span class="p">,</span> <span class="nx">last</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">'./helpers'</span>
|
||||
|
||||
<span class="nv">exports.Scope = </span><span class="nx">class</span> <span class="nx">Scope</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>The top-level <strong>Scope</strong> object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">@root</span><span class="o">:</span> <span class="kc">null</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Initialize a scope with its parent, for lookups up the chain,
|
||||
<span class="nv">exports.Scope = </span><span class="k">class</span> <span class="nx">Scope</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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="pilwrap"> <a class="pilcrow" 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>Block</strong> node it 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="nx">constructor</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="vi">@variables = </span><span class="p">[{</span><span class="nx">name</span><span class="o">:</span> <span class="s1">'arguments'</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="s1">'arguments'</span><span class="p">}]</span>
|
||||
it wraps.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">constructor: </span><span class="nf">(@parent, @expressions, @method) -></span>
|
||||
<span class="vi">@variables = </span><span class="p">[{</span><span class="nv">name: </span><span class="s">'arguments'</span><span class="p">,</span> <span class="nv">type: </span><span class="s">'arguments'</span><span class="p">}]</span>
|
||||
<span class="vi">@positions = </span><span class="p">{}</span>
|
||||
<span class="nv">Scope.root = </span><span class="k">this</span> <span class="nx">unless</span> <span class="nx">@parent</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Adds a new variable or overrides an existing one.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">add</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">type</span><span class="p">,</span> <span class="nx">immediate</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">Scope.root = </span><span class="k">this</span> <span class="k">unless</span> <span class="nx">@parent</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Adds a new variable or overrides an existing one.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">add: </span><span class="nf">(name, type, immediate) -></span>
|
||||
<span class="k">return</span> <span class="nx">@parent</span><span class="p">.</span><span class="nx">add</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">type</span><span class="p">,</span> <span class="nx">immediate</span> <span class="k">if</span> <span class="nx">@shared</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">immediate</span>
|
||||
<span class="k">if</span> <span class="k">typeof</span> <span class="p">(</span><span class="nv">pos = </span><span class="nx">@positions</span><span class="p">[</span><span class="nx">name</span><span class="p">])</span> <span class="o">is</span> <span class="s1">'number'</span>
|
||||
<span class="nx">@variables</span><span class="p">[</span><span class="nx">pos</span><span class="p">].</span><span class="nv">type = </span><span class="nx">type</span>
|
||||
<span class="k">if</span> <span class="nb">Object</span><span class="o">::</span><span class="nx">hasOwnProperty</span><span class="p">.</span><span class="nx">call</span> <span class="nx">@positions</span><span class="p">,</span> <span class="nx">name</span>
|
||||
<span class="nx">@variables</span><span class="p">[</span><span class="nx">@positions</span><span class="p">[</span><span class="nx">name</span><span class="p">]].</span><span class="nv">type = </span><span class="nx">type</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">@positions</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">push</span><span class="p">({</span><span class="nx">name</span><span class="p">,</span> <span class="nx">type</span><span class="p">})</span> <span class="o">-</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Look up a variable name in lexical scope, and declare it if it does not
|
||||
already exist.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">find</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">yes</span> <span class="k">if</span> <span class="nx">@check</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">options</span>
|
||||
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="s1">'var'</span>
|
||||
<span class="kc">no</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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="nx">parameter</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@positions</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">push</span><span class="p">({</span><span class="nx">name</span><span class="p">,</span> <span class="nx">type</span><span class="p">})</span> <span class="o">-</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>When <code>super</code> is called, we need to find the name of the current method we're
|
||||
in, so that we know how to invoke the same method of the parent class. This
|
||||
can get complicated if super is being called from an inner function.
|
||||
<code>namedMethod</code> will walk up the scope tree until it either finds the first
|
||||
function object that has a name filled in, or bottoms out.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">namedMethod: </span><span class="nf">-></span>
|
||||
<span class="k">return</span> <span class="nx">@method</span> <span class="k">if</span> <span class="nx">@method</span><span class="p">.</span><span class="nx">name</span> <span class="o">or</span> <span class="o">!</span><span class="nx">@parent</span>
|
||||
<span class="nx">@parent</span><span class="p">.</span><span class="nx">namedMethod</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>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="nf">(name) -></span>
|
||||
<span class="k">return</span> <span class="kc">yes</span> <span class="k">if</span> <span class="nx">@check</span> <span class="nx">name</span>
|
||||
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="s">'var'</span>
|
||||
<span class="kc">no</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</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="nf">(name) -></span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@shared</span> <span class="o">and</span> <span class="nx">@parent</span><span class="p">.</span><span class="nx">check</span> <span class="nx">name</span><span class="p">,</span> <span class="kc">yes</span>
|
||||
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="s1">'param'</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Just check to see if a variable has already been declared, without reserving,
|
||||
walks up to the root scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">check</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">immediate</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">found = </span><span class="o">!!</span><span class="nx">@type</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="nx">found</span> <span class="k">if</span> <span class="nx">found</span> <span class="o">or</span> <span class="nx">immediate</span>
|
||||
<span class="o">!!</span><span class="nx">@parent</span><span class="o">?</span><span class="p">.</span><span class="nx">check</span> <span class="nx">name</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Generate a temporary variable name at the given index.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">temporary</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">index</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="s">'param'</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Just check to see if a variable has already been declared, without reserving,
|
||||
walks up to the root scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">check: </span><span class="nf">(name) -></span>
|
||||
<span class="o">!!</span><span class="p">(</span><span class="nx">@type</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">or</span> <span class="nx">@parent</span><span class="o">?</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-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Generate a temporary variable name at the given index.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">temporary: </span><span class="nf">(name, index) -></span>
|
||||
<span class="k">if</span> <span class="nx">name</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">1</span>
|
||||
<span class="s1">'_'</span> <span class="o">+</span> <span class="nx">name</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">index</span> <span class="o">></span> <span class="mi">1</span> <span class="k">then</span> <span class="nx">index</span> <span class="k">else</span> <span class="s1">''</span>
|
||||
<span class="s">'_'</span> <span class="o">+</span> <span class="nx">name</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">index</span> <span class="o">></span> <span class="mi">1</span> <span class="k">then</span> <span class="nx">index</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">else</span> <span class="s">''</span>
|
||||
<span class="k">else</span>
|
||||
<span class="s1">'_'</span> <span class="o">+</span> <span class="p">(</span><span class="nx">index</span> <span class="o">+</span> <span class="nb">parseInt</span> <span class="nx">name</span><span class="p">,</span> <span class="mi">36</span><span class="p">).</span><span class="nx">toString</span><span class="p">(</span><span class="mi">36</span><span class="p">).</span><span class="nx">replace</span> <span class="sr">/\d/g</span><span class="p">,</span> <span class="s1">'a'</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Gets the type of a variable.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">type</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="s">'_'</span> <span class="o">+</span> <span class="p">(</span><span class="nx">index</span> <span class="o">+</span> <span class="nb">parseInt</span> <span class="nx">name</span><span class="p">,</span> <span class="mi">36</span><span class="p">).</span><span class="nx">toString</span><span class="p">(</span><span class="mi">36</span><span class="p">).</span><span class="nx">replace</span> <span class="sr">/\d/g</span><span class="p">,</span> <span class="s">'a'</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Gets the type of a variable.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">type: </span><span class="nf">(name) -></span>
|
||||
<span class="k">return</span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span> <span class="k">for</span> <span class="nx">v</span> <span class="k">in</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">v</span><span class="p">.</span><span class="nx">name</span> <span class="o">is</span> <span class="nx">name</span>
|
||||
<span class="kc">null</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>If we need to store an intermediate result, find an available name for a
|
||||
compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on...</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">freeVariable</span><span class="o">:</span> <span class="p">(</span><span class="nx">type</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="kc">null</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>If we need to store an intermediate result, find an available name for a
|
||||
compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on...</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">freeVariable: </span><span class="nf">(name, reserve=true) -></span>
|
||||
<span class="nv">index = </span><span class="mi">0</span>
|
||||
<span class="nx">index</span><span class="o">++</span> <span class="k">while</span> <span class="nx">@check</span><span class="p">((</span><span class="nv">temp = </span><span class="nx">@temporary</span> <span class="nx">type</span><span class="p">,</span> <span class="nx">index</span><span class="p">))</span>
|
||||
<span class="nx">@add</span> <span class="nx">temp</span><span class="p">,</span> <span class="s1">'var'</span><span class="p">,</span> <span class="kc">yes</span>
|
||||
<span class="nx">temp</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Ensure that an assignment is made at the top of this scope
|
||||
(or at the top-level scope, if requested).</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">assign</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">value</span><span class="o">:</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">assigned</span><span class="o">:</span> <span class="kc">true</span>
|
||||
<span class="vi">@hasAssignments = </span><span class="kc">yes</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Does this scope have any declared variables?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">hasDeclarations</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="o">!!</span><span class="nx">@declaredVariables</span><span class="p">().</span><span class="nx">length</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Return the list of variables first declared in this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">declaredVariables</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">index</span><span class="o">++</span> <span class="k">while</span> <span class="nx">@check</span><span class="p">((</span><span class="nv">temp = </span><span class="nx">@temporary</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">index</span><span class="p">))</span>
|
||||
<span class="nx">@add</span> <span class="nx">temp</span><span class="p">,</span> <span class="s">'var'</span><span class="p">,</span> <span class="kc">yes</span> <span class="k">if</span> <span class="nx">reserve</span>
|
||||
<span class="nx">temp</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Ensure that an assignment is made at the top of this scope
|
||||
(or at the top-level scope, if requested).</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">assign: </span><span class="nf">(name, value) -></span>
|
||||
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="p">{</span><span class="nx">value</span><span class="p">,</span> <span class="nv">assigned: </span><span class="kc">yes</span><span class="p">},</span> <span class="kc">yes</span>
|
||||
<span class="vi">@hasAssignments = </span><span class="kc">yes</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Does this scope have any declared variables?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">hasDeclarations: </span><span class="nf">-></span>
|
||||
<span class="o">!!</span><span class="nx">@declaredVariables</span><span class="p">().</span><span class="nx">length</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</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="nf">-></span>
|
||||
<span class="nv">realVars = </span><span class="p">[]</span>
|
||||
<span class="nv">tempVars = </span><span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="nx">v</span> <span class="k">in</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s1">'var'</span>
|
||||
<span class="p">(</span><span class="k">if</span> <span class="nx">v</span><span class="p">.</span><span class="nx">name</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'_'</span> <span class="k">then</span> <span class="nx">tempVars</span> <span class="k">else</span> <span class="nx">realVars</span><span class="p">).</span><span class="nx">push</span> <span class="nx">v</span><span class="p">.</span><span class="nx">name</span>
|
||||
<span class="nx">realVars</span><span class="p">.</span><span class="nx">sort</span><span class="p">().</span><span class="nx">concat</span> <span class="nx">tempVars</span><span class="p">.</span><span class="nx">sort</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>Return the list of assignments that are supposed to be made at the top
|
||||
of this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">assignedVariables</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="s2">"#{v.name} = #{v.type.value}"</span> <span class="k">for</span> <span class="nx">v</span> <span class="k">in</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span><span class="p">.</span><span class="nx">assigned</span>
|
||||
<span class="k">for</span> <span class="nx">v</span> <span class="k">in</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s">'var'</span>
|
||||
<span class="p">(</span><span class="k">if</span> <span class="nx">v</span><span class="p">.</span><span class="nx">name</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">is</span> <span class="s">'_'</span> <span class="k">then</span> <span class="nx">tempVars</span> <span class="k">else</span> <span class="nx">realVars</span><span class="p">).</span><span class="nx">push</span> <span class="nx">v</span><span class="p">.</span><span class="nx">name</span>
|
||||
<span class="nx">realVars</span><span class="p">.</span><span class="nx">sort</span><span class="p">().</span><span class="nx">concat</span> <span class="nx">tempVars</span><span class="p">.</span><span class="nx">sort</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</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="nf">-></span>
|
||||
<span class="s">"</span><span class="si">#{</span><span class="nx">v</span><span class="p">.</span><span class="nx">name</span><span class="si">}</span><span class="s"> = </span><span class="si">#{</span><span class="nx">v</span><span class="p">.</span><span class="nx">type</span><span class="p">.</span><span class="nx">value</span><span class="si">}</span><span class="s">"</span> <span class="k">for</span> <span class="nx">v</span> <span class="k">in</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span><span class="p">.</span><span class="nx">assigned</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
File diff suppressed because one or more lines are too long
@@ -7,6 +7,7 @@
|
||||
return '' unless File.exists?("documentation/js/#{file}.js")
|
||||
cs = File.read("documentation/coffee/#{file}.coffee")
|
||||
js = File.read("documentation/js/#{file}.js")
|
||||
js = js.sub(/^\/\/ generated.*?\n/i, '')
|
||||
cshtml = Uv.parse(cs, 'xhtml', 'coffeescript', false, 'idle', false)
|
||||
jshtml = Uv.parse(js, 'xhtml', 'javascript', false, 'idle', false)
|
||||
append = executable == true ? '' : "alert(#{executable});"
|
||||
@@ -28,6 +29,7 @@
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
|
||||
<title>CoffeeScript</title>
|
||||
<link rel="canonical" href="http://coffeescript.org" />
|
||||
<link rel="stylesheet" type="text/css" href="documentation/css/docs.css" />
|
||||
<link rel="stylesheet" type="text/css" href="documentation/css/idle.css" />
|
||||
<link rel="shortcut icon" href="documentation/images/favicon.ico" />
|
||||
@@ -44,7 +46,9 @@
|
||||
</div>
|
||||
<div class="contents menu">
|
||||
<a href="#overview">Overview</a>
|
||||
<a href="#installation">Installation and Usage</a>
|
||||
<a href="#installation">Installation</a>
|
||||
<a href="#usage">Usage</a>
|
||||
<a href="#literate">Literate CoffeeScript</a>
|
||||
<a href="#language">Language Reference</a>
|
||||
<a href="#literals">Literals: Functions, Objects and Arrays</a>
|
||||
<a href="#lexical_scope">Lexical Scoping and Variable Safety</a>
|
||||
@@ -60,12 +64,12 @@
|
||||
<a href="#embedded">Embedded JavaScript</a>
|
||||
<a href="#switch">Switch and Try/Catch</a>
|
||||
<a href="#comparisons">Chained Comparisons</a>
|
||||
<a href="#strings">String Interpolation, Heredocs, and Block Comments</a>
|
||||
<a href="#regexes">Extended Regular Expressions</a>
|
||||
<a href="#strings">String Interpolation, Block Strings, and Block Comments</a>
|
||||
<a href="#regexes">Block Regular Expressions</a>
|
||||
<a href="#cake">Cake, and Cakefiles</a>
|
||||
<a href="#scripts">"text/coffeescript" Script Tags</a>
|
||||
<a href="#resources">Books, Screencasts, Examples and Resources</a>
|
||||
<a href="#change_log">Change Log</a>
|
||||
<a href="#changelog">Change Log</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navigation try">
|
||||
@@ -114,9 +118,9 @@
|
||||
<span class="bookmark" id="top"></span>
|
||||
|
||||
<p>
|
||||
<b>CoffeeScript is a little language that compiles into JavaScript.</b> Underneath
|
||||
all those awkward braces and semicolons, JavaScript has always had
|
||||
a gorgeous object model at its heart. CoffeeScript is an attempt to expose
|
||||
<b>CoffeeScript is a little language that compiles into JavaScript.</b>
|
||||
Underneath that awkward Java-esque patina, JavaScript has always had
|
||||
a gorgeous heart. CoffeeScript is an attempt to expose
|
||||
the good parts of JavaScript in a simple way.
|
||||
</p>
|
||||
|
||||
@@ -124,16 +128,16 @@
|
||||
The golden rule of CoffeeScript is: <i>"It's just JavaScript"</i>. The code
|
||||
compiles one-to-one into the equivalent JS, and there is
|
||||
no interpretation at runtime. You can use any existing JavaScript library
|
||||
seamlessly from CoffeeScript (and vice-versa). The compiled output is
|
||||
readable and pretty-printed, passes through
|
||||
seamlessly from CoffeeScript (and vice-versa). The compiled output is
|
||||
readable and pretty-printed, passes through
|
||||
<a href="http://www.javascriptlint.com/">JavaScript Lint</a>
|
||||
without warnings, will work in every JavaScript implementation, and tends
|
||||
without warnings, will work in every JavaScript runtime, and tends
|
||||
to run as fast or faster than the equivalent handwritten JavaScript.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Latest Version:</b>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/1.1.3">1.1.3</a>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/1.5.0">1.5.0</a>
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
@@ -147,7 +151,7 @@
|
||||
|
||||
<h2>
|
||||
<span id="installation" class="bookmark"></span>
|
||||
Installation and Usage
|
||||
Installation
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
@@ -175,26 +179,29 @@ npm install -g coffee-script</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If you'd prefer to install the latest master version of CoffeeScript, you
|
||||
If you'd prefer to install the latest <b>master</b> version of CoffeeScript, you
|
||||
can clone the CoffeeScript
|
||||
<a href="http://github.com/jashkenas/coffee-script">source repository</a>
|
||||
from GitHub, or download
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/master">the source</a> directly.
|
||||
To install the CoffeeScript compiler system-wide
|
||||
under <tt>/usr/local</tt>, open the directory and run:
|
||||
To install the lastest master CoffeeScript compiler with npm:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
npm install -g http://github.com/jashkenas/coffee-script/tarball/master</pre>
|
||||
|
||||
<p>
|
||||
Or, if you want to install to <tt>/usr/local</tt>, and don't want to use
|
||||
npm to manage it, open the <tt>coffee-script</tt> directory and run:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
sudo bin/cake install</pre>
|
||||
|
||||
<p>
|
||||
If installing on Ubuntu or Debian,
|
||||
<a href="http://opinionated-programmer.com/2010/12/installing-coffeescript-on-debian-or-ubuntu/">be
|
||||
careful not to use the existing out-of-date package</a>. If installing on
|
||||
Windows, your best bet is probably to run Node.js under Cygwin. If you'd
|
||||
just like to experiment, you can try the
|
||||
<a href="https://github.com/alisey/CoffeeScript-Compiler-for-Windows">CoffeeScript Compiler For Windows</a>.
|
||||
</p>
|
||||
<h2>
|
||||
<span id="usage" class="bookmark"></span>
|
||||
Usage
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
Once installed, you should have access to the <tt>coffee</tt> command,
|
||||
@@ -282,7 +289,7 @@ sudo bin/cake install</pre>
|
||||
<tr>
|
||||
<td><code>-b, --bare</code></td>
|
||||
<td>
|
||||
Compile the JavaScript without the
|
||||
Compile the JavaScript without the
|
||||
<a href="#lexical_scope">top-level function safety wrapper</a>.
|
||||
</td>
|
||||
</tr>
|
||||
@@ -312,8 +319,9 @@ Expressions
|
||||
<td><code>--nodejs</code></td>
|
||||
<td>
|
||||
The <tt>node</tt> executable has some useful options you can set,
|
||||
such as<br /> <tt>--debug</tt>, <tt>--debug-brk</tt> and <tt>--max-stack-size</tt>. Use this
|
||||
flag to forward options directly to Node.js.
|
||||
such as<br /> <tt>--debug</tt>, <tt>--debug-brk</tt>, <tt>--max-stack-size</tt>,
|
||||
and <tt>--expose-gc</tt>. Use this flag to forward options directly to Node.js.
|
||||
To pass multiple flags, use <tt>--nodejs</tt> multiple times.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -345,11 +353,38 @@ Expressions
|
||||
<tt>coffee -o lib/ -cw src/</tt>
|
||||
</li>
|
||||
<li>
|
||||
Start the CoffeeScript REPL:<br />
|
||||
Start the CoffeeScript REPL (<tt>Ctrl-D</tt> to exit, <tt>Ctrl-V</tt>for multi-line):<br />
|
||||
<tt>coffee</tt>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
<span id="literate" class="bookmark"></span>
|
||||
Literate CoffeeScript
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
Besides being used as an ordinary programming language, CoffeeScript may
|
||||
also be written in "literate" mode. If you name your file with a
|
||||
<tt>.litcoffee</tt> extension, you can write it as a Markdown document —
|
||||
a document that also happens to be executable CoffeeScript code.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Just for kicks, a little bit of the compiler is currently implemented in this fashion:
|
||||
See it
|
||||
<a href="https://gist.github.com/jashkenas/3fc3c1a8b1009c00d9df">as a document</a>,
|
||||
<a href="https://raw.github.com/jashkenas/coffee-script/master/src/scope.litcoffee">raw</a>,
|
||||
and <a href="http://cl.ly/LxEu">properly highlighted in a text editor</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
I'm fairly excited about this direction for the language, and am looking
|
||||
forward to writing (and more importantly, reading) more programs in this style.
|
||||
As <b>1.5.0</b> is the first version of CoffeeScript that supports it, let us know
|
||||
if you have any ideas for improving the feature.
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<span id="language" class="bookmark"></span>
|
||||
Language Reference
|
||||
@@ -377,7 +412,7 @@ Expressions
|
||||
ending the line will do just as well (although semicolons can still
|
||||
be used to fit multiple expressions onto a single line).
|
||||
Instead of using curly braces
|
||||
<tt>{ }</tt> to surround blocks of code in <a href="#functions">functions</a>,
|
||||
<tt>{ }</tt> to surround blocks of code in <a href="#literals">functions</a>,
|
||||
<a href="#conditionals">if-statements</a>,
|
||||
<a href="#switch">switch</a>, and <a href="#try">try/catch</a>,
|
||||
use indentation.
|
||||
@@ -496,7 +531,7 @@ Expressions
|
||||
<%= code_for('array_comprehensions') %>
|
||||
<p>
|
||||
Comprehensions should be able to handle most places where you otherwise
|
||||
would use a loop, <b>each</b>/<b>forEach</b>, <b>map</b>, or <b>select</b>/<b>filter</b>:
|
||||
would use a loop, <b>each</b>/<b>forEach</b>, <b>map</b>, or <b>select</b>/<b>filter</b>, for example:
|
||||
<tt>shortNames = (name for name in list when name.length < 5)</tt><br />
|
||||
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
|
||||
@@ -526,7 +561,7 @@ Expressions
|
||||
<p>
|
||||
If you would like to iterate over just the keys that are defined on the
|
||||
object itself, by adding a <tt>hasOwnProperty</tt>
|
||||
check to avoid properties that may be interited from the prototype, use<br />
|
||||
check to avoid properties that may be inherited from the prototype, use<br />
|
||||
<tt>for own key, value of object</tt>
|
||||
</p>
|
||||
<p>
|
||||
@@ -555,6 +590,8 @@ Expressions
|
||||
Ranges can also be used to extract slices of arrays.
|
||||
With two dots (<tt>3..6</tt>), the range is inclusive (<tt>3, 4, 5, 6</tt>);
|
||||
with three dots (<tt>3...6</tt>), the range excludes the end (<tt>3, 4, 5</tt>).
|
||||
Slices indices have useful defaults. An omitted first index defaults to
|
||||
zero and an omitted second index defaults to the size of the array.
|
||||
</p>
|
||||
<%= code_for('slices', 'middle') %>
|
||||
<p>
|
||||
@@ -714,6 +751,7 @@ Expressions
|
||||
</p>
|
||||
<p>
|
||||
Constructor functions are named, to better support helpful stack traces.
|
||||
In the first class in the example below, <tt>this.constructor.name is "Animal"</tt>.
|
||||
</p>
|
||||
<%= code_for('classes', true) %>
|
||||
<p>
|
||||
@@ -780,10 +818,15 @@ Expressions
|
||||
</p>
|
||||
<%= code_for('fat_arrow') %>
|
||||
<p>
|
||||
If we had used <tt>-></tt> in the callback above, <tt>@customer</tt> would
|
||||
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>
|
||||
When used in a class definition, methods declared with the fat arrow will
|
||||
be automatically bound to each instance of the class when the instance is
|
||||
constructed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<span id="embedded" class="bookmark"></span>
|
||||
@@ -831,7 +874,7 @@ Expressions
|
||||
|
||||
<p>
|
||||
<span id="strings" class="bookmark"></span>
|
||||
<b class="header">String Interpolation, Heredocs, and Block Comments</b>
|
||||
<b class="header">String Interpolation, Block Strings, and Block Comments</b>
|
||||
Ruby-style string interpolation is included in CoffeeScript. Double-quoted
|
||||
strings allow for interpolated values, using <tt>#{ ... }</tt>,
|
||||
and single-quoted strings are literal.
|
||||
@@ -842,31 +885,31 @@ Expressions
|
||||
</p>
|
||||
<%= code_for('strings', 'mobyDick') %>
|
||||
<p>
|
||||
Heredocs can be used to hold formatted or indentation-sensitive text
|
||||
Block strings can be used to hold formatted or indentation-sensitive text
|
||||
(or, if you just don't feel like escaping quotes and apostrophes). The
|
||||
indentation level that begins the heredoc is maintained throughout, so
|
||||
indentation level that begins the block is maintained throughout, so
|
||||
you can keep it all aligned with the body of your code.
|
||||
</p>
|
||||
<%= code_for('heredocs', 'html') %>
|
||||
<p>
|
||||
Double-quoted heredocs, like double-quoted strings, allow interpolation.
|
||||
Double-quoted block strings, like other double-quoted strings, allow interpolation.
|
||||
</p>
|
||||
<p>
|
||||
Sometimes you'd like to pass a block comment through to the generated
|
||||
JavaScript. For example, when you need to embed a licensing header at
|
||||
the top of a file. Block comments, which mirror the syntax for heredocs,
|
||||
the top of a file. Block comments, which mirror the syntax for block strings,
|
||||
are preserved in the generated code.
|
||||
</p>
|
||||
<%= code_for('block_comment') %>
|
||||
|
||||
<p>
|
||||
<span id="regexes" class="bookmark"></span>
|
||||
<b class="header">Extended Regular Expressions</b>
|
||||
Similar to "heredocs" and "herecomments", CoffeeScript supports "heregexes" —
|
||||
<b class="header">Block Regular Expressions</b>
|
||||
Similar to block strings and comments, CoffeeScript supports block regexes —
|
||||
extended regular expressions that ignore internal whitespace and can contain
|
||||
comments, after Perl's <tt>/x</tt> modifier, but delimited by <tt>///</tt>.
|
||||
They go a long way towards making complex regular expressions readable.
|
||||
To quote from the CoffeeScript source:
|
||||
comments and interpolation. Modeled after Perl's <tt>/x</tt> modifier, CoffeeSctipt's
|
||||
block regexes are delimited by <tt>///</tt> and go a long way towards making complex
|
||||
regular expressions readable. To quote from the CoffeeScript source:
|
||||
</p>
|
||||
<%= code_for('heregexes') %>
|
||||
|
||||
@@ -935,11 +978,11 @@ Expressions
|
||||
|
||||
<h2>
|
||||
<span id="resources" class="bookmark"></span>
|
||||
Books and Screencasts
|
||||
Books
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
There are a number of excellent books and screencasts to help you get
|
||||
There are a number of excellent resources to help you get
|
||||
started with CoffeeScript, some of which are freely available online.
|
||||
</p>
|
||||
|
||||
@@ -955,7 +998,7 @@ Expressions
|
||||
is a reimagination of the excellent book
|
||||
<a href="http://eloquentjavascript.net/">Eloquent JavaScript</a>, as if
|
||||
it had been written in CoffeeScript instead. Covers language features
|
||||
as well a the functional and object oriented programming styles. By
|
||||
as well as the functional and object oriented programming styles. By
|
||||
<a href="https://github.com/autotelicum">E. Hoigaard</a>.
|
||||
</li>
|
||||
<li>
|
||||
@@ -965,6 +1008,28 @@ Expressions
|
||||
a fast-paced multiplayer word game, writing both the client-side and Node.js
|
||||
portions in CoffeeScript.
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://ristrettolo.gy">CoffeeScript Ristretto</a>
|
||||
is a deep dive into CoffeeScript's semantics from simple functions up through
|
||||
closures, higher-order functions, objects, classes, combinators, and decorators.
|
||||
By <a href="http://braythwayt.com/">Reg Braithwaite</a>.
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://efendibooks.com/minibooks/testing-with-coffeescript">Testing with CoffeeScript</a>
|
||||
is a succinct and freely downloadable guide to building testable
|
||||
applications with CoffeeScript and Jasmine.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
Screencasts
|
||||
</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="http://coffeescript.codeschool.com">A Sip of CoffeeScript</a> is a <a href="http://www.codeschool.com">Code School Course</a>
|
||||
which combines 6 screencasts with in-browser coding to make learning fun. The first level is free to try out.
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://peepcode.com/products/coffeescript">Meet CoffeeScript</a>
|
||||
is a 75-minute long screencast by <a href="http://peepcode.com/">PeepCode</a>.
|
||||
@@ -982,9 +1047,9 @@ Expressions
|
||||
<h2>
|
||||
Examples
|
||||
</h2>
|
||||
|
||||
|
||||
<p>
|
||||
The <a href="https://github.com/languages/coffeescript">best list of
|
||||
The <a href="https://github.com/languages/coffeescript">best list of
|
||||
open-source CoffeeScript examples</a> can be found on GitHub. But just
|
||||
to throw out few more:
|
||||
</p>
|
||||
@@ -998,11 +1063,6 @@ Expressions
|
||||
<b>sstephenson</b>'s <a href="http://pow.cx/">Pow</a>,
|
||||
a zero-configuration Rack server, with comprehensive annotated source.
|
||||
</li>
|
||||
<li>
|
||||
<b>frank06</b>'s <a href="http://riakjs.org/">riak-js</a>, a Node.js client for
|
||||
<a href="http://www.basho.com/Riak.html">Riak</a>, with support for HTTP
|
||||
and Protocol Buffers.
|
||||
</li>
|
||||
<li>
|
||||
<b>technoweenie</b>'s <a href="https://github.com/technoweenie/coffee-resque">Coffee-Resque</a>,
|
||||
a port of <a href="https://github.com/defunkt/resque">Resque</a> for Node.js.
|
||||
@@ -1064,6 +1124,11 @@ Expressions
|
||||
<a href="http://github.com/jashkenas/coffee-script/wiki/FAQ">The FAQ</a><br />
|
||||
Perhaps your CoffeeScript-related question has been asked before. Check the FAQ first.
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://github.com/jashkenas/coffee-script/downloads">High-Rez Logo</a><br />
|
||||
The CoffeeScript logo is available in Illustrator, EPS and PSD formats, for use
|
||||
in presentations.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
@@ -1082,10 +1147,165 @@ Expressions
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
<span id="change_log" class="bookmark"></span>
|
||||
<span id="changelog" class="bookmark"></span>
|
||||
Change Log
|
||||
</h2>
|
||||
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">
|
||||
<a href="https://github.com/jashkenas/coffee-script/compare/1.4.0...1.5.0">1.5.0</a>
|
||||
<span class="timestamp"> – <small>Feb 25, 2013</small></span>
|
||||
</b>
|
||||
<ul>
|
||||
<li>
|
||||
First release of <a href="#literate">Literate CoffeeScript</a>.
|
||||
</li>
|
||||
<li>
|
||||
The CoffeeScript REPL is now based on the Node.js REPL, and should work
|
||||
better and more familiarly.
|
||||
</li>
|
||||
<li>
|
||||
Returning explicit values from constructors is now forbidden. If you want
|
||||
to return an arbitrary value, use a function, not a constructor.
|
||||
</li>
|
||||
<li>
|
||||
You can now loop over an array backwards, without having to manually
|
||||
deal with the indexes.
|
||||
</li>
|
||||
<li>
|
||||
Source locations are now preserved in the CoffeeScript AST, although
|
||||
source maps are not yet being emitted.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">
|
||||
<a href="https://github.com/jashkenas/coffee-script/compare/1.3.3...1.4.0">1.4.0</a>
|
||||
<span class="timestamp"> – <small>Oct 23, 2012</small></span>
|
||||
</b>
|
||||
<ul>
|
||||
<li>
|
||||
The CoffeeScript compiler now strips Microsoft's UTF-8 BOM if it
|
||||
exists, allowing you to compile BOM-borked source files.
|
||||
</li>
|
||||
<li>
|
||||
Fix Node/compiler deprecation warnings by removing <tt>registerExtension</tt>,
|
||||
and moving from <tt>path.exists</tt> to <tt>fs.exists</tt>.
|
||||
</li>
|
||||
<li>
|
||||
Small tweaks to splat compilation, backticks, slicing, and the
|
||||
error for duplicate keys in object literals.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">
|
||||
<a href="https://github.com/jashkenas/coffee-script/compare/1.3.1...1.3.3">1.3.3</a>
|
||||
<span class="timestamp"> – <small>May 15, 2012</small></span>
|
||||
</b>
|
||||
<ul>
|
||||
<li>
|
||||
Due to the new semantics of JavaScript's strict mode, CoffeeScript no
|
||||
longer guarantees that constructor functions have names in all runtimes.
|
||||
See <a href="https://github.com/jashkenas/coffee-script/issues/2052">#2052</a>
|
||||
for discussion.
|
||||
</li>
|
||||
<li>
|
||||
Inside of a nested function inside of an instance method, it's now possible
|
||||
to call <tt>super</tt> more reliably (walks recursively up).
|
||||
</li>
|
||||
<li>
|
||||
Named loop variables no longer have different scoping heuristics than
|
||||
other local variables. (Reverts #643)
|
||||
</li>
|
||||
<li>
|
||||
Fix for splats nested within the LHS of destructuring assignment.
|
||||
</li>
|
||||
<li>
|
||||
Corrections to our compile time strict mode forbidding of octal literals.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">
|
||||
<a href="https://github.com/jashkenas/coffee-script/compare/1.2.0...1.3.1">1.3.1</a>
|
||||
<span class="timestamp"> – <small>April 10, 2012</small></span>
|
||||
</b>
|
||||
<ul>
|
||||
<li>
|
||||
CoffeeScript now enforces all of JavaScript's <b>Strict Mode</b> early syntax
|
||||
errors at compile time. This includes old-style octal literals,
|
||||
duplicate property names in object literals, duplicate parameters in
|
||||
a function definition, deleting naked variables, setting the value of
|
||||
<tt>eval</tt> or <tt>arguments</tt>, and more.
|
||||
See a full discussion at
|
||||
<a href="https://github.com/jashkenas/coffee-script/issues/1547">#1547</a>.
|
||||
</li>
|
||||
<li>
|
||||
The REPL now has a handy new multi-line mode for entering large
|
||||
blocks of code. It's useful when copy-and-pasting examples into the
|
||||
REPL. Enter multi-line mode with <tt>Ctrl-V</tt>. You may also now
|
||||
pipe input directly into the REPL.
|
||||
</li>
|
||||
<li>
|
||||
CoffeeScript now prints a <tt>Generated by CoffeeScript VERSION</tt>
|
||||
header at the top of each compiled file.
|
||||
</li>
|
||||
<li>
|
||||
Conditional assignment of previously undefined variables
|
||||
<tt>a or= b</tt> is now considered a syntax error.
|
||||
</li>
|
||||
<li>
|
||||
A tweak to the semantics of <tt>do</tt>, which can now be used to
|
||||
more easily simulate a namespace: <tt>do (x = 1, y = 2) -> ...</tt>
|
||||
</li>
|
||||
<li>
|
||||
Loop indices are now mutable within a loop iteration, and immutable
|
||||
between them.
|
||||
</li>
|
||||
<li>
|
||||
Both endpoints of a slice are now allowed to be omitted for consistency,
|
||||
effectively creating a shallow copy of the list.
|
||||
</li>
|
||||
<li>
|
||||
Additional tweaks and improvments to <tt>coffee --watch</tt> under
|
||||
Node's "new" file watching API. Watch will now beep by default
|
||||
if you introduce a syntax error into a watched script. We also now
|
||||
ignore hidden directories by default when watching recursively.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">
|
||||
<a href="https://github.com/jashkenas/coffee-script/compare/1.1.3...1.2.0">1.2.0</a>
|
||||
<span class="timestamp"> – <small>Dec. 18, 2011</small></span>
|
||||
</b>
|
||||
<ul>
|
||||
<li>
|
||||
Multiple improvements to <tt>coffee --watch</tt> and <tt>--join</tt>.
|
||||
You may now use both together, as well as add and remove
|
||||
files and directories within a <tt>--watch</tt>'d folder.
|
||||
</li>
|
||||
<li>
|
||||
The <tt>throw</tt> statement can now be used as part of an expression.
|
||||
</li>
|
||||
<li>
|
||||
Block comments at the top of the file will now appear outside of the
|
||||
safety closure wrapper.
|
||||
</li>
|
||||
<li>
|
||||
Fixed a number of minor 1.1.3 regressions having to do with trailing
|
||||
operators and unfinished lines, and a more major 1.1.3 regression that
|
||||
caused bound functions <i>within</i> bound class functions to have the incorrect
|
||||
<tt>this</tt>.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">
|
||||
<a href="https://github.com/jashkenas/coffee-script/compare/1.1.2...1.1.3">1.1.3</a>
|
||||
@@ -1097,7 +1317,7 @@ Expressions
|
||||
out and keep it readable, as you can see in the examples on this page.
|
||||
</li>
|
||||
<li>
|
||||
You can now call <tt>super</tt> in class level methods in class bodies,
|
||||
You can now call <tt>super</tt> in class level methods in class bodies,
|
||||
and bound class methods now preserve their correct context.
|
||||
</li>
|
||||
<li>
|
||||
@@ -1106,7 +1326,7 @@ Expressions
|
||||
also supports binary numbers: <tt>0b10 is 2</tt>.
|
||||
</li>
|
||||
<li>
|
||||
The CoffeeScript module has been nested under a subdirectory to make
|
||||
The CoffeeScript module has been nested under a subdirectory to make
|
||||
it easier to <tt>require</tt> individual components separately, without
|
||||
having to use <b>npm</b>. For example, after adding the CoffeeScript
|
||||
folder to your path: <tt>require('coffee-script/lexer')</tt>
|
||||
@@ -1116,11 +1336,11 @@ Expressions
|
||||
it to get a shareable permalink for your example script.
|
||||
</li>
|
||||
<li>
|
||||
The <tt>coffee --watch</tt> feature now only works on Node.js 0.6.0
|
||||
The <tt>coffee --watch</tt> feature now only works on Node.js 0.6.0
|
||||
and higher, but now also works properly on Windows.
|
||||
</li>
|
||||
<li>
|
||||
Lots of small bug fixes from
|
||||
Lots of small bug fixes from
|
||||
<b><a href="https://github.com/michaelficarra">@michaelficarra</a></b>,
|
||||
<b><a href="https://github.com/geraldalewis">@geraldalewis</a></b>,
|
||||
<b><a href="https://github.com/satyr">@satyr</a></b>, and
|
||||
@@ -1675,7 +1895,7 @@ Expressions
|
||||
closeMenus = ->
|
||||
$('.navigation.active').removeClass 'active'
|
||||
|
||||
$('.minibutton.run').click evalJS
|
||||
$('.minibutton.run').click -> evalJS()
|
||||
|
||||
# Bind navigation buttons to open the menus.
|
||||
$('.navigation').click (e) ->
|
||||
|
||||
@@ -1,13 +1,24 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var volume, winner;
|
||||
|
||||
if (ignition === true) launch();
|
||||
if (ignition === true) {
|
||||
launch();
|
||||
}
|
||||
|
||||
if (band !== SpinalTap) volume = 10;
|
||||
if (band !== SpinalTap) {
|
||||
volume = 10;
|
||||
}
|
||||
|
||||
if (answer !== false) letTheWildRumpusBegin();
|
||||
if (answer !== false) {
|
||||
letTheWildRumpusBegin();
|
||||
}
|
||||
|
||||
if (car.speed < limit) accelerate();
|
||||
if (car.speed < limit) {
|
||||
accelerate();
|
||||
}
|
||||
|
||||
if (pick === 47 || pick === 92 || pick === 13) winner = true;
|
||||
if (pick === 47 || pick === 92 || pick === 13) {
|
||||
winner = true;
|
||||
}
|
||||
|
||||
print(inspect("My name is " + this.name));
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var course, courses, dish, food, foods, _i, _j, _len, _len2, _len3, _ref;
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var courses, dish, food, foods, i, _i, _j, _k, _len, _len1, _len2, _ref;
|
||||
|
||||
_ref = ['toast', 'cheese', 'wine'];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
@@ -6,16 +7,18 @@ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
eat(food);
|
||||
}
|
||||
|
||||
courses = ['salad', 'entree', 'dessert'];
|
||||
courses = ['greens', 'caviar', 'truffles', 'roast', 'cake'];
|
||||
|
||||
for (course = 0, _len2 = courses.length; course < _len2; course++) {
|
||||
dish = courses[course];
|
||||
menu(course + 1, dish);
|
||||
for (i = _j = 0, _len1 = courses.length; _j < _len1; i = ++_j) {
|
||||
dish = courses[i];
|
||||
menu(i + 1, dish);
|
||||
}
|
||||
|
||||
foods = ['broccoli', 'spinach', 'chocolate'];
|
||||
|
||||
for (_j = 0, _len3 = foods.length; _j < _len3; _j++) {
|
||||
food = foods[_j];
|
||||
if (food !== 'chocolate') eat(food);
|
||||
for (_k = 0, _len2 = foods.length; _k < _len2; _k++) {
|
||||
food = foods[_k];
|
||||
if (food !== 'chocolate') {
|
||||
eat(food);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
/*
|
||||
CoffeeScript Compiler v1.1.3
|
||||
CoffeeScript Compiler v1.5.0
|
||||
Released under the MIT License
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var fs;
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
var Animal, Horse, Snake, sam, tom;
|
||||
var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; };
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var Animal, Horse, Snake, sam, tom,
|
||||
__hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
|
||||
Animal = (function() {
|
||||
|
||||
@@ -15,9 +17,9 @@ Animal = (function() {
|
||||
|
||||
})();
|
||||
|
||||
Snake = (function() {
|
||||
Snake = (function(_super) {
|
||||
|
||||
__extends(Snake, Animal);
|
||||
__extends(Snake, _super);
|
||||
|
||||
function Snake() {
|
||||
Snake.__super__.constructor.apply(this, arguments);
|
||||
@@ -30,11 +32,11 @@ Snake = (function() {
|
||||
|
||||
return Snake;
|
||||
|
||||
})();
|
||||
})(Animal);
|
||||
|
||||
Horse = (function() {
|
||||
Horse = (function(_super) {
|
||||
|
||||
__extends(Horse, Animal);
|
||||
__extends(Horse, _super);
|
||||
|
||||
function Horse() {
|
||||
Horse.__super__.constructor.apply(this, arguments);
|
||||
@@ -47,7 +49,7 @@ Horse = (function() {
|
||||
|
||||
return Horse;
|
||||
|
||||
})();
|
||||
})(Animal);
|
||||
|
||||
sam = new Snake("Sammy the Python");
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var cholesterol, healthy;
|
||||
|
||||
cholesterol = 127;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var date, mood;
|
||||
|
||||
if (singing) mood = greatlyImproved;
|
||||
if (singing) {
|
||||
mood = greatlyImproved;
|
||||
}
|
||||
|
||||
if (happy && knowsIt) {
|
||||
clapsHands();
|
||||
@@ -10,5 +13,3 @@ if (happy && knowsIt) {
|
||||
}
|
||||
|
||||
date = friday ? sue : jill;
|
||||
|
||||
options || (options = defaults);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var fill;
|
||||
|
||||
fill = function(container, liquid) {
|
||||
if (liquid == null) liquid = "coffee";
|
||||
if (liquid == null) {
|
||||
liquid = "coffee";
|
||||
}
|
||||
return "Filling the " + container + " with " + liquid + "...";
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var filename, _fn, _i, _len;
|
||||
|
||||
_fn = function(filename) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var hi;
|
||||
|
||||
hi = function() {
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
var footprints, solipsism;
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var footprints, solipsism, speed;
|
||||
|
||||
if ((typeof mind !== "undefined" && mind !== null) && !(typeof world !== "undefined" && world !== null)) {
|
||||
if ((typeof mind !== "undefined" && mind !== null) && (typeof world === "undefined" || world === null)) {
|
||||
solipsism = true;
|
||||
}
|
||||
|
||||
if (typeof speed === "undefined" || speed === null) speed = 75;
|
||||
speed = 0;
|
||||
|
||||
if (speed == null) {
|
||||
speed = 15;
|
||||
}
|
||||
|
||||
footprints = typeof yeti !== "undefined" && yeti !== null ? yeti : "bear";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var eldest, grade;
|
||||
|
||||
grade = function(student) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var one, six, three, two;
|
||||
|
||||
six = (one = 1) + (two = 2) + (three = 3);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var globals, name;
|
||||
|
||||
globals = ((function() {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
|
||||
alert((function() {
|
||||
try {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var Account;
|
||||
|
||||
Account = function(customer, cart) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var cube, square;
|
||||
|
||||
square = function(x) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var html;
|
||||
|
||||
html = '<strong>\n cup of coffeescript\n</strong>';
|
||||
html = "<strong>\n cup of coffeescript\n</strong>";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var OPERATOR;
|
||||
|
||||
OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var author, quote, sentence;
|
||||
|
||||
author = "Wittgenstein";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var city, forecast, temp, weatherReport, _ref;
|
||||
|
||||
weatherReport = function(location) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var age, ages, child, yearsOld;
|
||||
|
||||
yearsOld = {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var city, futurists, name, street, _ref, _ref2;
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var city, futurists, name, street, _ref, _ref1;
|
||||
|
||||
futurists = {
|
||||
sculptor: "Umberto Boccioni",
|
||||
@@ -9,4 +10,4 @@ futurists = {
|
||||
}
|
||||
};
|
||||
|
||||
_ref = futurists.poet, name = _ref.name, (_ref2 = _ref.address, street = _ref2[0], city = _ref2[1]);
|
||||
_ref = futurists.poet, name = _ref.name, (_ref1 = _ref.address, street = _ref1[0], city = _ref1[1]);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var bitlist, kids, singers, song;
|
||||
|
||||
song = ["do", "re", "mi", "fa", "so"];
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
|
||||
$('.account').attr({
|
||||
"class": 'active'
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
var cubes, list, math, num, number, opposite, race, square;
|
||||
var __slice = Array.prototype.slice;
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var cubes, list, math, num, number, opposite, race, square,
|
||||
__slice = [].slice;
|
||||
|
||||
number = 42;
|
||||
|
||||
opposite = true;
|
||||
|
||||
if (opposite) number = -42;
|
||||
if (opposite) {
|
||||
number = -42;
|
||||
}
|
||||
|
||||
square = function(x) {
|
||||
return x * x;
|
||||
@@ -27,7 +30,9 @@ race = function() {
|
||||
return print(winner, runners);
|
||||
};
|
||||
|
||||
if (typeof elvis !== "undefined" && elvis !== null) alert("I knew it!");
|
||||
if (typeof elvis !== "undefined" && elvis !== null) {
|
||||
alert("I knew it!");
|
||||
}
|
||||
|
||||
cubes = (function() {
|
||||
var _i, _len, _results;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var theBait, theSwitch, _ref;
|
||||
|
||||
theBait = 1000;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
var close, contents, open, tag, _i, _ref;
|
||||
var __slice = Array.prototype.slice;
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var close, contents, open, tag, _i, _ref,
|
||||
__slice = [].slice;
|
||||
|
||||
tag = "<impossible>";
|
||||
|
||||
|
||||
1
documentation/js/prototypes.js
vendored
1
documentation/js/prototypes.js
vendored
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
|
||||
String.prototype.dasherize = function() {
|
||||
return this.replace(/_/g, "-");
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var countdown, num;
|
||||
|
||||
countdown = (function() {
|
||||
var _results;
|
||||
var _i, _results;
|
||||
_results = [];
|
||||
for (num = 10; num >= 1; num--) {
|
||||
for (num = _i = 10; _i >= 1; num = --_i) {
|
||||
_results.push(num);
|
||||
}
|
||||
return _results;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var changeNumbers, inner, outer;
|
||||
|
||||
outer = 1;
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
var copy, middle, numbers;
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var copy, end, middle, numbers, start;
|
||||
|
||||
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
|
||||
copy = numbers.slice(0, numbers.length);
|
||||
start = numbers.slice(0, 3);
|
||||
|
||||
middle = copy.slice(3, 7);
|
||||
middle = numbers.slice(3, 6);
|
||||
|
||||
end = numbers.slice(6);
|
||||
|
||||
copy = numbers.slice(0);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var zip, _ref;
|
||||
|
||||
zip = typeof lottery.drawWinner === "function" ? (_ref = lottery.drawWinner().address) != null ? _ref.zipcode : void 0 : void 0;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
var awardMedals, contenders, gold, rest, silver;
|
||||
var __slice = Array.prototype.slice;
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var awardMedals, contenders, gold, rest, silver,
|
||||
__slice = [].slice;
|
||||
|
||||
gold = silver = rest = "unknown";
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var numbers, _ref;
|
||||
|
||||
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var mobyDick;
|
||||
|
||||
mobyDick = "Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
|
||||
switch (day) {
|
||||
case "Mon":
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
|
||||
try {
|
||||
allHellBreaksLoose();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
var lyrics, num;
|
||||
|
||||
if (this.studyingEconomics) {
|
||||
|
||||
@@ -8,7 +8,7 @@ get '/hello', ->
|
||||
# Append.
|
||||
append = (location, data) ->
|
||||
path = new Pathname location
|
||||
throw new Error("Location does not exist") unless path.exists()
|
||||
throw new Error "Location does not exist" unless fs.existsSync(location)
|
||||
|
||||
File.open path, 'a', (file) ->
|
||||
file.console.log YAML.dump data
|
||||
@@ -31,7 +31,7 @@ File.open = (path, mode, block) ->
|
||||
# Write.
|
||||
write = (location, data) ->
|
||||
path = new Pathname location
|
||||
raise "Location does not exist" unless path.exists()
|
||||
throw new Error "Location does not exist" unless fs.existsSync(location)
|
||||
|
||||
File.open path, 'w', (file) ->
|
||||
return false if Digest.MD5.hexdigest(file.read()) is data.hash()
|
||||
|
||||
File diff suppressed because one or more lines are too long
583
index.html
583
index.html
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
(function() {
|
||||
var CoffeeScript, runScripts;
|
||||
|
||||
@@ -5,23 +6,36 @@
|
||||
|
||||
CoffeeScript.require = require;
|
||||
|
||||
CoffeeScript.eval = function(code, options) {
|
||||
CoffeeScript["eval"] = function(code, options) {
|
||||
var _ref;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
if ((_ref = options.bare) == null) {
|
||||
options.bare = true;
|
||||
}
|
||||
return eval(CoffeeScript.compile(code, options));
|
||||
};
|
||||
|
||||
CoffeeScript.run = function(code, options) {
|
||||
if (options == null) options = {};
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
options.bare = true;
|
||||
return Function(CoffeeScript.compile(code, options))();
|
||||
};
|
||||
|
||||
if (typeof window === "undefined" || window === null) return;
|
||||
if (typeof window === "undefined" || window === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoffeeScript.load = function(url, callback) {
|
||||
var xhr;
|
||||
xhr = new (window.ActiveXObject || XMLHttpRequest)('Microsoft.XMLHTTP');
|
||||
xhr = window.ActiveXObject ? new window.ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest();
|
||||
xhr.open('GET', url, true);
|
||||
if ('overrideMimeType' in xhr) xhr.overrideMimeType('text/plain');
|
||||
if ('overrideMimeType' in xhr) {
|
||||
xhr.overrideMimeType('text/plain');
|
||||
}
|
||||
xhr.onreadystatechange = function() {
|
||||
var _ref;
|
||||
if (xhr.readyState === 4) {
|
||||
@@ -30,7 +44,9 @@
|
||||
} else {
|
||||
throw new Error("Could not load " + url);
|
||||
}
|
||||
if (callback) return callback();
|
||||
if (callback) {
|
||||
return callback();
|
||||
}
|
||||
}
|
||||
};
|
||||
return xhr.send(null);
|
||||
@@ -44,7 +60,9 @@
|
||||
_results = [];
|
||||
for (_i = 0, _len = scripts.length; _i < _len; _i++) {
|
||||
s = scripts[_i];
|
||||
if (s.type === 'text/coffeescript') _results.push(s);
|
||||
if (s.type === 'text/coffeescript') {
|
||||
_results.push(s);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
(function() {
|
||||
var CoffeeScript, cakefileDirectory, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks;
|
||||
var CoffeeScript, cakefileDirectory, existsSync, fatalError, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks;
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
@@ -11,6 +12,8 @@
|
||||
|
||||
CoffeeScript = require('./coffee-script');
|
||||
|
||||
existsSync = fs.existsSync || path.existsSync;
|
||||
|
||||
tasks = {};
|
||||
|
||||
options = {};
|
||||
@@ -35,7 +38,9 @@
|
||||
return switches.push([letter, flag, description]);
|
||||
},
|
||||
invoke: function(name) {
|
||||
if (!tasks[name]) missingTask(name);
|
||||
if (!tasks[name]) {
|
||||
missingTask(name);
|
||||
}
|
||||
return tasks[name].action(options);
|
||||
}
|
||||
});
|
||||
@@ -49,9 +54,15 @@
|
||||
filename: 'Cakefile'
|
||||
});
|
||||
oparse = new optparse.OptionParser(switches);
|
||||
if (!args.length) return printTasks();
|
||||
options = oparse.parse(args);
|
||||
_ref = options.arguments;
|
||||
if (!args.length) {
|
||||
return printTasks();
|
||||
}
|
||||
try {
|
||||
options = oparse.parse(args);
|
||||
} catch (e) {
|
||||
return fatalError("" + e);
|
||||
}
|
||||
_ref = options["arguments"];
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
arg = _ref[_i];
|
||||
@@ -61,8 +72,10 @@
|
||||
};
|
||||
|
||||
printTasks = function() {
|
||||
var desc, name, spaces, task;
|
||||
console.log('');
|
||||
var cakefilePath, desc, name, relative, spaces, task;
|
||||
relative = path.relative || path.resolve;
|
||||
cakefilePath = path.join(relative(__originalDirname, process.cwd()), 'Cakefile');
|
||||
console.log("" + cakefilePath + " defines the following tasks:\n");
|
||||
for (name in tasks) {
|
||||
task = tasks[name];
|
||||
spaces = 20 - name.length;
|
||||
@@ -70,19 +83,30 @@
|
||||
desc = task.description ? "# " + task.description : '';
|
||||
console.log("cake " + name + spaces + " " + desc);
|
||||
}
|
||||
if (switches.length) return console.log(oparse.help());
|
||||
if (switches.length) {
|
||||
return console.log(oparse.help());
|
||||
}
|
||||
};
|
||||
|
||||
fatalError = function(message) {
|
||||
console.error(message + '\n');
|
||||
console.log('To see a list of all tasks/options, run "cake"');
|
||||
return process.exit(1);
|
||||
};
|
||||
|
||||
missingTask = function(task) {
|
||||
console.log("No such task: \"" + task + "\"");
|
||||
return process.exit(1);
|
||||
return fatalError("No such task: " + task);
|
||||
};
|
||||
|
||||
cakefileDirectory = function(dir) {
|
||||
var parent;
|
||||
if (path.existsSync(path.join(dir, 'Cakefile'))) return dir;
|
||||
if (existsSync(path.join(dir, 'Cakefile'))) {
|
||||
return dir;
|
||||
}
|
||||
parent = path.normalize(path.join(dir, '..'));
|
||||
if (parent !== dir) return cakefileDirectory(parent);
|
||||
if (parent !== dir) {
|
||||
return cakefileDirectory(parent);
|
||||
}
|
||||
throw new Error("Cakefile not found in " + (process.cwd()));
|
||||
};
|
||||
|
||||
|
||||
@@ -1,47 +1,60 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
(function() {
|
||||
var Lexer, RESERVED, compile, fs, lexer, parser, path, vm, _ref;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
var Lexer, compile, ext, extensions, fs, lexer, loadFile, parser, path, vm, _i, _len,
|
||||
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
|
||||
__hasProp = {}.hasOwnProperty;
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
path = require('path');
|
||||
|
||||
_ref = require('./lexer'), Lexer = _ref.Lexer, RESERVED = _ref.RESERVED;
|
||||
Lexer = require('./lexer').Lexer;
|
||||
|
||||
parser = require('./parser').parser;
|
||||
|
||||
vm = require('vm');
|
||||
|
||||
extensions = ['.coffee', '.litcoffee'];
|
||||
|
||||
loadFile = function(module, filename) {
|
||||
var raw, stripped;
|
||||
raw = fs.readFileSync(filename, 'utf8');
|
||||
stripped = raw.charCodeAt(0) === 0xFEFF ? raw.substring(1) : raw;
|
||||
return module._compile(compile(stripped, {
|
||||
filename: filename
|
||||
}), filename);
|
||||
};
|
||||
|
||||
if (require.extensions) {
|
||||
require.extensions['.coffee'] = function(module, filename) {
|
||||
var content;
|
||||
content = compile(fs.readFileSync(filename, 'utf8'), {
|
||||
filename: filename
|
||||
});
|
||||
return module._compile(content, filename);
|
||||
};
|
||||
} else if (require.registerExtension) {
|
||||
require.registerExtension('.coffee', function(content) {
|
||||
return compile(content);
|
||||
});
|
||||
for (_i = 0, _len = extensions.length; _i < _len; _i++) {
|
||||
ext = extensions[_i];
|
||||
require.extensions[ext] = loadFile;
|
||||
}
|
||||
}
|
||||
|
||||
exports.VERSION = '1.1.3';
|
||||
|
||||
exports.RESERVED = RESERVED;
|
||||
exports.VERSION = '1.5.0';
|
||||
|
||||
exports.helpers = require('./helpers');
|
||||
|
||||
exports.compile = compile = function(code, options) {
|
||||
if (options == null) options = {};
|
||||
var header, js, merge;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
merge = exports.helpers.merge;
|
||||
try {
|
||||
return (parser.parse(lexer.tokenize(code))).compile(options);
|
||||
js = (parser.parse(lexer.tokenize(code, options))).compile(options);
|
||||
if (!options.header) {
|
||||
return js;
|
||||
}
|
||||
} catch (err) {
|
||||
if (options.filename) {
|
||||
err.message = "In " + options.filename + ", " + err.message;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
header = "Generated by CoffeeScript " + this.VERSION;
|
||||
return "// " + header + "\n" + js;
|
||||
};
|
||||
|
||||
exports.tokens = function(code, options) {
|
||||
@@ -57,22 +70,29 @@
|
||||
};
|
||||
|
||||
exports.run = function(code, options) {
|
||||
var mainModule;
|
||||
var mainModule, _ref;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
mainModule = require.main;
|
||||
mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '.';
|
||||
mainModule.moduleCache && (mainModule.moduleCache = {});
|
||||
mainModule.paths = require('module')._nodeModulePaths(path.dirname(options.filename));
|
||||
if (path.extname(mainModule.filename) !== '.coffee' || require.extensions) {
|
||||
mainModule.paths = require('module')._nodeModulePaths(path.dirname(fs.realpathSync(options.filename)));
|
||||
if ((_ref = path.extname(mainModule.filename), __indexOf.call(extensions, _ref) < 0) || require.extensions) {
|
||||
return mainModule._compile(compile(code, options), mainModule.filename);
|
||||
} else {
|
||||
return mainModule._compile(code, mainModule.filename);
|
||||
}
|
||||
};
|
||||
|
||||
exports.eval = function(code, options) {
|
||||
var Module, Script, js, k, o, r, sandbox, v, _i, _len, _module, _ref2, _ref3, _require;
|
||||
if (options == null) options = {};
|
||||
if (!(code = code.trim())) return;
|
||||
exports["eval"] = function(code, options) {
|
||||
var Module, Script, js, k, o, r, sandbox, v, _j, _len1, _module, _ref, _ref1, _require;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
if (!(code = code.trim())) {
|
||||
return;
|
||||
}
|
||||
Script = vm.Script;
|
||||
if (Script) {
|
||||
if (options.sandbox != null) {
|
||||
@@ -80,10 +100,10 @@
|
||||
sandbox = options.sandbox;
|
||||
} else {
|
||||
sandbox = Script.createContext();
|
||||
_ref2 = options.sandbox;
|
||||
for (k in _ref2) {
|
||||
if (!__hasProp.call(_ref2, k)) continue;
|
||||
v = _ref2[k];
|
||||
_ref = options.sandbox;
|
||||
for (k in _ref) {
|
||||
if (!__hasProp.call(_ref, k)) continue;
|
||||
v = _ref[k];
|
||||
sandbox[k] = v;
|
||||
}
|
||||
}
|
||||
@@ -100,10 +120,12 @@
|
||||
return Module._load(path, _module, true);
|
||||
};
|
||||
_module.filename = sandbox.__filename;
|
||||
_ref3 = Object.getOwnPropertyNames(require);
|
||||
for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
|
||||
r = _ref3[_i];
|
||||
if (r !== 'paths') _require[r] = require[r];
|
||||
_ref1 = Object.getOwnPropertyNames(require);
|
||||
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
|
||||
r = _ref1[_j];
|
||||
if (r !== 'paths') {
|
||||
_require[r] = require[r];
|
||||
}
|
||||
}
|
||||
_require.paths = _module.paths = Module._nodeModulePaths(process.cwd());
|
||||
_require.resolve = function(request) {
|
||||
@@ -130,8 +152,14 @@
|
||||
|
||||
parser.lexer = {
|
||||
lex: function() {
|
||||
var tag, _ref2;
|
||||
_ref2 = this.tokens[this.pos++] || [''], tag = _ref2[0], this.yytext = _ref2[1], this.yylineno = _ref2[2];
|
||||
var tag, token;
|
||||
token = this.tokens[this.pos++];
|
||||
if (token) {
|
||||
tag = token[0], this.yytext = token[1], this.yylloc = token[2];
|
||||
this.yylineno = this.yylloc.first_line;
|
||||
} else {
|
||||
tag = '';
|
||||
}
|
||||
return tag;
|
||||
},
|
||||
setInput: function(tokens) {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
(function() {
|
||||
var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compileScript, compileScripts, compileStdio, contents, exec, forkNode, fs, helpers, lint, loadRequires, optionParser, optparse, opts, parseOptions, path, printLine, printTokens, printWarn, sources, spawn, usage, version, watch, writeJs, _ref;
|
||||
var BANNER, CoffeeScript, EventEmitter, SWITCHES, coffee_exts, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, exists, forkNode, fs, helpers, hidden, joinTimeout, lint, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, removeSource, sourceCode, sources, spawn, timeLog, unwatchDir, usage, version, wait, watch, watchDir, watchers, writeJs, _ref,
|
||||
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
@@ -15,6 +17,8 @@
|
||||
|
||||
EventEmitter = require('events').EventEmitter;
|
||||
|
||||
exists = fs.exists || path.exists;
|
||||
|
||||
helpers.extend(CoffeeScript, new EventEmitter);
|
||||
|
||||
printLine = function(line) {
|
||||
@@ -25,109 +29,135 @@
|
||||
return process.stderr.write(line + '\n');
|
||||
};
|
||||
|
||||
BANNER = 'Usage: coffee [options] path/to/script.coffee\n\nIf called without options, `coffee` will run your script.';
|
||||
hidden = function(file) {
|
||||
return /^\.|~$/.test(file);
|
||||
};
|
||||
|
||||
SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-r', '--require [FILE*]', 'require a library before executing your script'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']];
|
||||
BANNER = 'Usage: coffee [options] path/to/script.coffee -- [args]\n\nIf called without options, `coffee` will run your script.';
|
||||
|
||||
SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']];
|
||||
|
||||
opts = {};
|
||||
|
||||
sources = [];
|
||||
|
||||
contents = [];
|
||||
sourceCode = [];
|
||||
|
||||
notSources = {};
|
||||
|
||||
watchers = {};
|
||||
|
||||
optionParser = null;
|
||||
|
||||
exports.run = function() {
|
||||
parseOptions();
|
||||
if (opts.nodejs) return forkNode();
|
||||
if (opts.help) return usage();
|
||||
if (opts.version) return version();
|
||||
if (opts.require) loadRequires();
|
||||
if (opts.interactive) return require('./repl');
|
||||
if (opts.stdio) return compileStdio();
|
||||
if (opts.eval) return compileScript(null, sources[0]);
|
||||
if (!sources.length) return require('./repl');
|
||||
if (opts.run) opts.literals = sources.splice(1).concat(opts.literals);
|
||||
process.argv = process.argv.slice(0, 2).concat(opts.literals);
|
||||
process.argv[0] = 'coffee';
|
||||
process.execPath = require.main.filename;
|
||||
return compileScripts();
|
||||
};
|
||||
coffee_exts = ['.coffee', '.litcoffee'];
|
||||
|
||||
compileScripts = function() {
|
||||
var base, compile, remaining_files, source, trackCompleteFiles, trackUnprocessedFiles, unprocessed, _i, _j, _len, _len2, _results;
|
||||
unprocessed = [];
|
||||
remaining_files = function() {
|
||||
var total, x, _i, _len;
|
||||
total = 0;
|
||||
for (_i = 0, _len = unprocessed.length; _i < _len; _i++) {
|
||||
x = unprocessed[_i];
|
||||
total += x;
|
||||
}
|
||||
return total;
|
||||
};
|
||||
trackUnprocessedFiles = function(sourceIndex, fileCount) {
|
||||
var _ref2;
|
||||
if ((_ref2 = unprocessed[sourceIndex]) == null) unprocessed[sourceIndex] = 0;
|
||||
return unprocessed[sourceIndex] += fileCount;
|
||||
};
|
||||
trackCompleteFiles = function(sourceIndex, fileCount) {
|
||||
unprocessed[sourceIndex] -= fileCount;
|
||||
if (opts.join) {
|
||||
if (helpers.compact(contents).length > 0 && remaining_files() === 0) {
|
||||
return compileJoin();
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.run = function() {
|
||||
var literals, source, _i, _len, _results;
|
||||
parseOptions();
|
||||
if (opts.nodejs) {
|
||||
return forkNode();
|
||||
}
|
||||
if (opts.help) {
|
||||
return usage();
|
||||
}
|
||||
if (opts.version) {
|
||||
return version();
|
||||
}
|
||||
if (opts.interactive) {
|
||||
return require('./repl').start();
|
||||
}
|
||||
if (opts.watch && !fs.watch) {
|
||||
return printWarn("The --watch feature depends on Node v0.6.0+. You are running " + process.version + ".");
|
||||
}
|
||||
if (opts.stdio) {
|
||||
return compileStdio();
|
||||
}
|
||||
if (opts["eval"]) {
|
||||
return compileScript(null, sources[0]);
|
||||
}
|
||||
if (!sources.length) {
|
||||
return require('./repl').start();
|
||||
}
|
||||
literals = opts.run ? sources.splice(1) : [];
|
||||
process.argv = process.argv.slice(0, 2).concat(literals);
|
||||
process.argv[0] = 'coffee';
|
||||
_results = [];
|
||||
for (_i = 0, _len = sources.length; _i < _len; _i++) {
|
||||
source = sources[_i];
|
||||
trackUnprocessedFiles(sources.indexOf(source), 1);
|
||||
}
|
||||
_results = [];
|
||||
for (_j = 0, _len2 = sources.length; _j < _len2; _j++) {
|
||||
source = sources[_j];
|
||||
base = path.join(source);
|
||||
compile = function(source, sourceIndex, topLevel) {
|
||||
return path.exists(source, function(exists) {
|
||||
if (topLevel && !exists && source.slice(-7) !== '.coffee') {
|
||||
return compile("" + source + ".coffee", sourceIndex, topLevel);
|
||||
}
|
||||
if (topLevel && !exists) throw new Error("File not found: " + source);
|
||||
return fs.stat(source, function(err, stats) {
|
||||
if (err) throw err;
|
||||
if (stats.isDirectory()) {
|
||||
return fs.readdir(source, function(err, files) {
|
||||
var file, _k, _len3;
|
||||
if (err) throw err;
|
||||
trackUnprocessedFiles(sourceIndex, files.length);
|
||||
for (_k = 0, _len3 = files.length; _k < _len3; _k++) {
|
||||
file = files[_k];
|
||||
compile(path.join(source, file), sourceIndex);
|
||||
}
|
||||
return trackCompleteFiles(sourceIndex, 1);
|
||||
});
|
||||
} else if (topLevel || path.extname(source) === '.coffee') {
|
||||
fs.readFile(source, function(err, code) {
|
||||
if (err) throw err;
|
||||
if (opts.join) {
|
||||
contents[sourceIndex] = helpers.compact([contents[sourceIndex], code.toString()]).join('\n');
|
||||
} else {
|
||||
compileScript(source, code.toString(), base);
|
||||
}
|
||||
return trackCompleteFiles(sourceIndex, 1);
|
||||
});
|
||||
if (opts.watch && !opts.join) return watch(source, base);
|
||||
} else {
|
||||
return trackCompleteFiles(sourceIndex, 1);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
_results.push(compile(source, sources.indexOf(source), true));
|
||||
_results.push(compilePath(source, true, path.normalize(source)));
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
|
||||
compilePath = function(source, topLevel, base) {
|
||||
return fs.stat(source, function(err, stats) {
|
||||
var _ref1, _ref2;
|
||||
if (err && err.code !== 'ENOENT') {
|
||||
throw err;
|
||||
}
|
||||
if ((err != null ? err.code : void 0) === 'ENOENT') {
|
||||
if (topLevel && source && (_ref1 = path.extname(source), __indexOf.call(coffee_exts, _ref1) < 0)) {
|
||||
source = sources[sources.indexOf(source)] = "" + source + ".coffee";
|
||||
return compilePath(source, topLevel, base);
|
||||
}
|
||||
if (topLevel) {
|
||||
console.error("File not found: " + source);
|
||||
process.exit(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (stats.isDirectory() && path.dirname(source) !== 'node_modules') {
|
||||
if (opts.watch) {
|
||||
watchDir(source, base);
|
||||
}
|
||||
return fs.readdir(source, function(err, files) {
|
||||
var file, index, _ref2, _ref3;
|
||||
if (err && err.code !== 'ENOENT') {
|
||||
throw err;
|
||||
}
|
||||
if ((err != null ? err.code : void 0) === 'ENOENT') {
|
||||
return;
|
||||
}
|
||||
index = sources.indexOf(source);
|
||||
files = files.filter(function(file) {
|
||||
return !hidden(file);
|
||||
});
|
||||
[].splice.apply(sources, [index, index - index + 1].concat(_ref2 = (function() {
|
||||
var _i, _len, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = files.length; _i < _len; _i++) {
|
||||
file = files[_i];
|
||||
_results.push(path.join(source, file));
|
||||
}
|
||||
return _results;
|
||||
})())), _ref2;
|
||||
[].splice.apply(sourceCode, [index, index - index + 1].concat(_ref3 = files.map(function() {
|
||||
return null;
|
||||
}))), _ref3;
|
||||
return files.forEach(function(file) {
|
||||
return compilePath(path.join(source, file), false, base);
|
||||
});
|
||||
});
|
||||
} else if (topLevel || (_ref2 = path.extname(source), __indexOf.call(coffee_exts, _ref2) >= 0)) {
|
||||
if (opts.watch) {
|
||||
watch(source, base);
|
||||
}
|
||||
return fs.readFile(source, function(err, code) {
|
||||
if (err && err.code !== 'ENOENT') {
|
||||
throw err;
|
||||
}
|
||||
if ((err != null ? err.code : void 0) === 'ENOENT') {
|
||||
return;
|
||||
}
|
||||
return compileScript(source, code.toString(), base);
|
||||
});
|
||||
} else {
|
||||
notSources[source] = true;
|
||||
return removeSource(source, base);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
compileScript = function(file, input, base) {
|
||||
var o, options, t, task;
|
||||
o = opts;
|
||||
@@ -140,11 +170,14 @@
|
||||
};
|
||||
CoffeeScript.emit('compile', task);
|
||||
if (o.tokens) {
|
||||
return printTokens(CoffeeScript.tokens(t.input));
|
||||
return printTokens(CoffeeScript.tokens(t.input, t.options));
|
||||
} else if (o.nodes) {
|
||||
return printLine(CoffeeScript.nodes(t.input).toString().trim());
|
||||
return printLine(CoffeeScript.nodes(t.input, t.options).toString().trim());
|
||||
} else if (o.run) {
|
||||
return CoffeeScript.run(t.input, t.options);
|
||||
} else if (o.join && t.file !== o.join) {
|
||||
sourceCode[sources.indexOf(t.file)] = t.input;
|
||||
return compileJoin();
|
||||
} else {
|
||||
t.output = CoffeeScript.compile(t.input, t.options);
|
||||
CoffeeScript.emit('success', task);
|
||||
@@ -158,8 +191,12 @@
|
||||
}
|
||||
} catch (err) {
|
||||
CoffeeScript.emit('failure', err, task);
|
||||
if (CoffeeScript.listeners('failure').length) return;
|
||||
if (o.watch) return printLine(err.message);
|
||||
if (CoffeeScript.listeners('failure').length) {
|
||||
return;
|
||||
}
|
||||
if (o.watch) {
|
||||
return printLine(err.message + '\x07');
|
||||
}
|
||||
printWarn(err instanceof Error && err.stack || ("ERROR: " + err));
|
||||
return process.exit(1);
|
||||
}
|
||||
@@ -170,78 +207,216 @@
|
||||
code = '';
|
||||
stdin = process.openStdin();
|
||||
stdin.on('data', function(buffer) {
|
||||
if (buffer) return code += buffer.toString();
|
||||
if (buffer) {
|
||||
return code += buffer.toString();
|
||||
}
|
||||
});
|
||||
return stdin.on('end', function() {
|
||||
return compileScript(null, code);
|
||||
});
|
||||
};
|
||||
|
||||
compileJoin = function() {
|
||||
var code;
|
||||
code = contents.join('\n');
|
||||
return compileScript(opts.join, code, opts.join);
|
||||
};
|
||||
joinTimeout = null;
|
||||
|
||||
loadRequires = function() {
|
||||
var realFilename, req, _i, _len, _ref2;
|
||||
realFilename = module.filename;
|
||||
module.filename = '.';
|
||||
_ref2 = opts.require;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
req = _ref2[_i];
|
||||
require(req);
|
||||
compileJoin = function() {
|
||||
if (!opts.join) {
|
||||
return;
|
||||
}
|
||||
if (!sourceCode.some(function(code) {
|
||||
return code === null;
|
||||
})) {
|
||||
clearTimeout(joinTimeout);
|
||||
return joinTimeout = wait(100, function() {
|
||||
return compileScript(opts.join, sourceCode.join('\n'), opts.join);
|
||||
});
|
||||
}
|
||||
return module.filename = realFilename;
|
||||
};
|
||||
|
||||
watch = function(source, base) {
|
||||
return fs.stat(source, function(err, prevStats) {
|
||||
if (err) throw err;
|
||||
return fs.watch(source, function(event) {
|
||||
if (event === 'change') {
|
||||
return fs.stat(source, function(err, stats) {
|
||||
if (err) throw err;
|
||||
if (stats.size === prevStats.size && stats.mtime.getTime() === prevStats.mtime.getTime()) {
|
||||
return;
|
||||
var compile, compileTimeout, prevStats, rewatch, watchErr, watcher;
|
||||
prevStats = null;
|
||||
compileTimeout = null;
|
||||
watchErr = function(e) {
|
||||
if (e.code === 'ENOENT') {
|
||||
if (sources.indexOf(source) === -1) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
rewatch();
|
||||
return compile();
|
||||
} catch (e) {
|
||||
removeSource(source, base, true);
|
||||
return compileJoin();
|
||||
}
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
compile = function() {
|
||||
clearTimeout(compileTimeout);
|
||||
return compileTimeout = wait(25, function() {
|
||||
return fs.stat(source, function(err, stats) {
|
||||
if (err) {
|
||||
return watchErr(err);
|
||||
}
|
||||
if (prevStats && stats.size === prevStats.size && stats.mtime.getTime() === prevStats.mtime.getTime()) {
|
||||
return rewatch();
|
||||
}
|
||||
prevStats = stats;
|
||||
return fs.readFile(source, function(err, code) {
|
||||
if (err) {
|
||||
return watchErr(err);
|
||||
}
|
||||
prevStats = stats;
|
||||
return fs.readFile(source, function(err, code) {
|
||||
if (err) throw err;
|
||||
return compileScript(source, code.toString(), base);
|
||||
});
|
||||
compileScript(source, code.toString(), base);
|
||||
return rewatch();
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
try {
|
||||
watcher = fs.watch(source, compile);
|
||||
} catch (e) {
|
||||
watchErr(e);
|
||||
}
|
||||
return rewatch = function() {
|
||||
if (watcher != null) {
|
||||
watcher.close();
|
||||
}
|
||||
return watcher = fs.watch(source, compile);
|
||||
};
|
||||
};
|
||||
|
||||
watchDir = function(source, base) {
|
||||
var readdirTimeout, watcher;
|
||||
readdirTimeout = null;
|
||||
try {
|
||||
return watcher = fs.watch(source, function() {
|
||||
clearTimeout(readdirTimeout);
|
||||
return readdirTimeout = wait(25, function() {
|
||||
return fs.readdir(source, function(err, files) {
|
||||
var file, _i, _len, _results;
|
||||
if (err) {
|
||||
if (err.code !== 'ENOENT') {
|
||||
throw err;
|
||||
}
|
||||
watcher.close();
|
||||
return unwatchDir(source, base);
|
||||
}
|
||||
_results = [];
|
||||
for (_i = 0, _len = files.length; _i < _len; _i++) {
|
||||
file = files[_i];
|
||||
if (!(!hidden(file) && !notSources[file])) {
|
||||
continue;
|
||||
}
|
||||
file = path.join(source, file);
|
||||
if (sources.some(function(s) {
|
||||
return s.indexOf(file) >= 0;
|
||||
})) {
|
||||
continue;
|
||||
}
|
||||
sources.push(file);
|
||||
sourceCode.push(null);
|
||||
_results.push(compilePath(file, false, base));
|
||||
}
|
||||
return _results;
|
||||
});
|
||||
});
|
||||
});
|
||||
} catch (e) {
|
||||
if (e.code !== 'ENOENT') {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
unwatchDir = function(source, base) {
|
||||
var file, prevSources, toRemove, _i, _len;
|
||||
prevSources = sources.slice(0);
|
||||
toRemove = (function() {
|
||||
var _i, _len, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = sources.length; _i < _len; _i++) {
|
||||
file = sources[_i];
|
||||
if (file.indexOf(source) >= 0) {
|
||||
_results.push(file);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
for (_i = 0, _len = toRemove.length; _i < _len; _i++) {
|
||||
file = toRemove[_i];
|
||||
removeSource(file, base, true);
|
||||
}
|
||||
if (!sources.some(function(s, i) {
|
||||
return prevSources[i] !== s;
|
||||
})) {
|
||||
return;
|
||||
}
|
||||
return compileJoin();
|
||||
};
|
||||
|
||||
removeSource = function(source, base, removeJs) {
|
||||
var index, jsPath;
|
||||
index = sources.indexOf(source);
|
||||
sources.splice(index, 1);
|
||||
sourceCode.splice(index, 1);
|
||||
if (removeJs && !opts.join) {
|
||||
jsPath = outputPath(source, base);
|
||||
return exists(jsPath, function(itExists) {
|
||||
if (itExists) {
|
||||
return fs.unlink(jsPath, function(err) {
|
||||
if (err && err.code !== 'ENOENT') {
|
||||
throw err;
|
||||
}
|
||||
return timeLog("removed " + source);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
writeJs = function(source, js, base) {
|
||||
var baseDir, compile, dir, filename, jsPath, srcDir;
|
||||
outputPath = function(source, base) {
|
||||
var baseDir, dir, filename, srcDir;
|
||||
filename = path.basename(source, path.extname(source)) + '.js';
|
||||
srcDir = path.dirname(source);
|
||||
baseDir = base === '.' ? srcDir : srcDir.substring(base.length);
|
||||
dir = opts.output ? path.join(opts.output, baseDir) : srcDir;
|
||||
jsPath = path.join(dir, filename);
|
||||
return path.join(dir, filename);
|
||||
};
|
||||
|
||||
writeJs = function(source, js, base) {
|
||||
var compile, jsDir, jsPath;
|
||||
jsPath = outputPath(source, base);
|
||||
jsDir = path.dirname(jsPath);
|
||||
compile = function() {
|
||||
if (js.length <= 0) js = ' ';
|
||||
if (js.length <= 0) {
|
||||
js = ' ';
|
||||
}
|
||||
return fs.writeFile(jsPath, js, function(err) {
|
||||
if (err) {
|
||||
return printLine(err.message);
|
||||
} else if (opts.compile && opts.watch) {
|
||||
return console.log("" + ((new Date).toLocaleTimeString()) + " - compiled " + source);
|
||||
return timeLog("compiled " + source);
|
||||
}
|
||||
});
|
||||
};
|
||||
return path.exists(dir, function(exists) {
|
||||
if (exists) {
|
||||
return exists(jsDir, function(itExists) {
|
||||
if (itExists) {
|
||||
return compile();
|
||||
} else {
|
||||
return exec("mkdir -p " + dir, compile);
|
||||
return exec("mkdir -p " + jsDir, compile);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
wait = function(milliseconds, func) {
|
||||
return setTimeout(func, milliseconds);
|
||||
};
|
||||
|
||||
timeLog = function(message) {
|
||||
return console.log("" + ((new Date).toLocaleTimeString()) + " - " + message);
|
||||
};
|
||||
|
||||
lint = function(file, js) {
|
||||
var conf, jsl, printIt;
|
||||
printIt = function(buffer) {
|
||||
@@ -256,14 +431,16 @@
|
||||
};
|
||||
|
||||
printTokens = function(tokens) {
|
||||
var strings, tag, token, value;
|
||||
var locationData, strings, tag, token, value;
|
||||
strings = (function() {
|
||||
var _i, _len, _ref2, _results;
|
||||
var _i, _len, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = tokens.length; _i < _len; _i++) {
|
||||
token = tokens[_i];
|
||||
_ref2 = [token[0], token[1].toString().replace(/\n/, '\\n')], tag = _ref2[0], value = _ref2[1];
|
||||
_results.push("[" + tag + " " + value + "]");
|
||||
tag = token[0];
|
||||
value = token[1].toString().replace(/\n/, '\\n');
|
||||
locationData = helpers.locationDataToString(token[2]);
|
||||
_results.push("[" + tag + " " + value + " " + locationData + "]");
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
@@ -271,19 +448,27 @@
|
||||
};
|
||||
|
||||
parseOptions = function() {
|
||||
var o;
|
||||
var i, o, source, _i, _len;
|
||||
optionParser = new optparse.OptionParser(SWITCHES, BANNER);
|
||||
o = opts = optionParser.parse(process.argv.slice(2));
|
||||
o.compile || (o.compile = !!o.output);
|
||||
o.run = !(o.compile || o.print || o.lint);
|
||||
o.print = !!(o.print || (o.eval || o.stdio && o.compile));
|
||||
return sources = o.arguments;
|
||||
o.print = !!(o.print || (o["eval"] || o.stdio && o.compile));
|
||||
sources = o["arguments"];
|
||||
for (i = _i = 0, _len = sources.length; _i < _len; i = ++_i) {
|
||||
source = sources[i];
|
||||
sourceCode[i] = null;
|
||||
}
|
||||
};
|
||||
|
||||
compileOptions = function(filename) {
|
||||
var literate;
|
||||
literate = path.extname(filename) === '.litcoffee';
|
||||
return {
|
||||
filename: filename,
|
||||
bare: opts.bare
|
||||
literate: literate,
|
||||
bare: opts.bare,
|
||||
header: opts.compile
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
(function() {
|
||||
var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;
|
||||
|
||||
@@ -6,13 +7,26 @@
|
||||
unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/;
|
||||
|
||||
o = function(patternString, action, options) {
|
||||
var match;
|
||||
var addLocationDataFn, match, patternCount;
|
||||
patternString = patternString.replace(/\s{2,}/g, ' ');
|
||||
if (!action) return [patternString, '$$ = $1;', options];
|
||||
patternCount = patternString.split(' ').length;
|
||||
if (!action) {
|
||||
return [patternString, '$$ = $1;', options];
|
||||
}
|
||||
action = (match = unwrap.exec(action)) ? match[1] : "(" + action + "())";
|
||||
action = action.replace(/\bnew /g, '$&yy.');
|
||||
action = action.replace(/\b(?:Block\.wrap|extend)\b/g, 'yy.$&');
|
||||
return [patternString, "$$ = " + action + ";", options];
|
||||
action = action.replace(/\b(Op|Value\.(create|wrap))\b/g, 'yy.$&');
|
||||
addLocationDataFn = function(first, last) {
|
||||
if (!last) {
|
||||
return "yy.addLocationDataFn(@" + first + ")";
|
||||
} else {
|
||||
return "yy.addLocationDataFn(@" + first + ", @" + last + ")";
|
||||
}
|
||||
};
|
||||
action = action.replace(/LOC\(([0-9]*)\)/g, addLocationDataFn('$1'));
|
||||
action = action.replace(/LOC\(([0-9]*),\s*([0-9]*)\)/g, addLocationDataFn('$1', '$2'));
|
||||
return [patternString, "$$ = " + (addLocationDataFn(1, patternCount)) + "(" + action + ");", options];
|
||||
};
|
||||
|
||||
grammar = {
|
||||
@@ -30,11 +44,11 @@
|
||||
],
|
||||
Line: [o('Expression'), o('Statement')],
|
||||
Statement: [
|
||||
o('Return'), o('Throw'), o('Comment'), o('STATEMENT', function() {
|
||||
o('Return'), o('Comment'), o('STATEMENT', function() {
|
||||
return new Literal($1);
|
||||
})
|
||||
],
|
||||
Expression: [o('Value'), o('Invocation'), o('Code'), o('Operation'), o('Assign'), o('If'), o('Try'), o('While'), o('For'), o('Switch'), o('Class')],
|
||||
Expression: [o('Value'), o('Invocation'), o('Code'), o('Operation'), o('Assign'), o('If'), o('Try'), o('While'), o('For'), o('Switch'), o('Class'), o('Throw')],
|
||||
Block: [
|
||||
o('INDENT OUTDENT', function() {
|
||||
return new Block;
|
||||
@@ -59,28 +73,33 @@
|
||||
return new Literal($1);
|
||||
}), o('REGEX', function() {
|
||||
return new Literal($1);
|
||||
}), o('DEBUGGER', function() {
|
||||
return new Literal($1);
|
||||
}), o('UNDEFINED', function() {
|
||||
return new Undefined;
|
||||
}), o('NULL', function() {
|
||||
return new Null;
|
||||
}), o('BOOL', function() {
|
||||
var val;
|
||||
val = new Literal($1);
|
||||
if ($1 === 'undefined') val.isUndefined = true;
|
||||
return val;
|
||||
return new Bool($1);
|
||||
})
|
||||
],
|
||||
Assign: [
|
||||
o('Assignable = Expression', function() {
|
||||
return new Assign($1, $3);
|
||||
}), o('Assignable = TERMINATOR Expression', function() {
|
||||
return new Assign($1, $4);
|
||||
}), o('Assignable = INDENT Expression OUTDENT', function() {
|
||||
return new Assign($1, $4);
|
||||
})
|
||||
],
|
||||
AssignObj: [
|
||||
o('ObjAssignable', function() {
|
||||
return new Value($1);
|
||||
return Value.wrap($1);
|
||||
}), o('ObjAssignable : Expression', function() {
|
||||
return new Assign(new Value($1), $3, 'object');
|
||||
return new Assign(LOC(1)(Value.wrap($1)), $3, 'object');
|
||||
}), o('ObjAssignable :\
|
||||
INDENT Expression OUTDENT', function() {
|
||||
return new Assign(new Value($1), $4, 'object');
|
||||
return new Assign(LOC(1)(Value.wrap($1)), $4, 'object');
|
||||
}), o('Comment')
|
||||
],
|
||||
ObjAssignable: [o('Identifier'), o('AlphaNumeric'), o('ThisProperty')],
|
||||
@@ -118,6 +137,10 @@
|
||||
return [$1];
|
||||
}), o('ParamList , Param', function() {
|
||||
return $1.concat($3);
|
||||
}), o('ParamList OptComma TERMINATOR Param', function() {
|
||||
return $1.concat($4);
|
||||
}), o('ParamList OptComma INDENT ParamList OptComma OUTDENT', function() {
|
||||
return $1.concat($4);
|
||||
})
|
||||
],
|
||||
Param: [
|
||||
@@ -137,27 +160,27 @@
|
||||
],
|
||||
SimpleAssignable: [
|
||||
o('Identifier', function() {
|
||||
return new Value($1);
|
||||
return Value.wrap($1);
|
||||
}), o('Value Accessor', function() {
|
||||
return $1.add($2);
|
||||
}), o('Invocation Accessor', function() {
|
||||
return new Value($1, [$2]);
|
||||
return Value.wrap($1, [].concat($2));
|
||||
}), o('ThisProperty')
|
||||
],
|
||||
Assignable: [
|
||||
o('SimpleAssignable'), o('Array', function() {
|
||||
return new Value($1);
|
||||
return Value.wrap($1);
|
||||
}), o('Object', function() {
|
||||
return new Value($1);
|
||||
return Value.wrap($1);
|
||||
})
|
||||
],
|
||||
Value: [
|
||||
o('Assignable'), o('Literal', function() {
|
||||
return new Value($1);
|
||||
return Value.wrap($1);
|
||||
}), o('Parenthetical', function() {
|
||||
return new Value($1);
|
||||
return Value.wrap($1);
|
||||
}), o('Range', function() {
|
||||
return new Value($1);
|
||||
return Value.wrap($1);
|
||||
}), o('This')
|
||||
],
|
||||
Accessor: [
|
||||
@@ -166,7 +189,7 @@
|
||||
}), o('?. Identifier', function() {
|
||||
return new Access($2, 'soak');
|
||||
}), o(':: Identifier', function() {
|
||||
return [new Access(new Literal('prototype')), new Access($2)];
|
||||
return [LOC(1)(new Access(new Literal('prototype'))), LOC(2)(new Access($2))];
|
||||
}), o('::', function() {
|
||||
return new Access(new Literal('prototype'));
|
||||
}), o('Index')
|
||||
@@ -251,14 +274,14 @@
|
||||
],
|
||||
This: [
|
||||
o('THIS', function() {
|
||||
return new Value(new Literal('this'));
|
||||
return Value.wrap(new Literal('this'));
|
||||
}), o('@', function() {
|
||||
return new Value(new Literal('this'));
|
||||
return Value.wrap(new Literal('this'));
|
||||
})
|
||||
],
|
||||
ThisProperty: [
|
||||
o('@ Identifier', function() {
|
||||
return new Value(new Literal('this'), [new Access($2)], 'this');
|
||||
return Value.wrap(LOC(1)(new Literal('this')), [LOC(2)(new Access($2))], 'this');
|
||||
})
|
||||
],
|
||||
Array: [
|
||||
@@ -287,6 +310,8 @@
|
||||
return new Range($1, null, $2);
|
||||
}), o('RangeDots Expression', function() {
|
||||
return new Range(null, $2, $1);
|
||||
}), o('RangeDots', function() {
|
||||
return new Range(null, null, $1);
|
||||
})
|
||||
],
|
||||
ArgList: [
|
||||
@@ -322,6 +347,8 @@
|
||||
Catch: [
|
||||
o('CATCH Identifier Block', function() {
|
||||
return [$2, $3];
|
||||
}), o('CATCH Object Block', function() {
|
||||
return [LOC(2)(Value.wrap($2)), $3];
|
||||
})
|
||||
],
|
||||
Throw: [
|
||||
@@ -358,18 +385,18 @@
|
||||
o('WhileSource Block', function() {
|
||||
return $1.addBody($2);
|
||||
}), o('Statement WhileSource', function() {
|
||||
return $2.addBody(Block.wrap([$1]));
|
||||
return $2.addBody(LOC(1)(Block.wrap([$1])));
|
||||
}), o('Expression WhileSource', function() {
|
||||
return $2.addBody(Block.wrap([$1]));
|
||||
return $2.addBody(LOC(1)(Block.wrap([$1])));
|
||||
}), o('Loop', function() {
|
||||
return $1;
|
||||
})
|
||||
],
|
||||
Loop: [
|
||||
o('LOOP Block', function() {
|
||||
return new While(new Literal('true')).addBody($2);
|
||||
return new While(LOC(1)(new Literal('true'))).addBody($2);
|
||||
}), o('LOOP Expression', function() {
|
||||
return new While(new Literal('true')).addBody(Block.wrap([$2]));
|
||||
return new While(LOC(1)(new Literal('true'))).addBody(LOC(2)(Block.wrap([$2])));
|
||||
})
|
||||
],
|
||||
For: [
|
||||
@@ -384,7 +411,7 @@
|
||||
ForBody: [
|
||||
o('FOR Range', function() {
|
||||
return {
|
||||
source: new Value($2)
|
||||
source: LOC(2)(Value.wrap($2))
|
||||
};
|
||||
}), o('ForStart ForSource', function() {
|
||||
$2.own = $1.own;
|
||||
@@ -402,10 +429,10 @@
|
||||
})
|
||||
],
|
||||
ForValue: [
|
||||
o('Identifier'), o('Array', function() {
|
||||
return new Value($1);
|
||||
o('Identifier'), o('ThisProperty'), o('Array', function() {
|
||||
return Value.wrap($1);
|
||||
}), o('Object', function() {
|
||||
return new Value($1);
|
||||
return Value.wrap($1);
|
||||
})
|
||||
],
|
||||
ForVariables: [
|
||||
@@ -493,12 +520,12 @@
|
||||
o('IfBlock'), o('IfBlock ELSE Block', function() {
|
||||
return $1.addElse($3);
|
||||
}), o('Statement POST_IF Expression', function() {
|
||||
return new If($3, Block.wrap([$1]), {
|
||||
return new If($3, LOC(1)(Block.wrap([$1])), {
|
||||
type: $2,
|
||||
statement: true
|
||||
});
|
||||
}), o('Expression POST_IF Expression', function() {
|
||||
return new If($3, Block.wrap([$1]), {
|
||||
return new If($3, LOC(1)(Block.wrap([$1])), {
|
||||
type: $2,
|
||||
statement: true
|
||||
});
|
||||
@@ -506,42 +533,42 @@
|
||||
],
|
||||
Operation: [
|
||||
o('UNARY Expression', function() {
|
||||
return new Op($1, $2);
|
||||
return Op.create($1, $2);
|
||||
}), o('- Expression', (function() {
|
||||
return new Op('-', $2);
|
||||
return Op.create('-', $2);
|
||||
}), {
|
||||
prec: 'UNARY'
|
||||
}), o('+ Expression', (function() {
|
||||
return new Op('+', $2);
|
||||
return Op.create('+', $2);
|
||||
}), {
|
||||
prec: 'UNARY'
|
||||
}), o('-- SimpleAssignable', function() {
|
||||
return new Op('--', $2);
|
||||
return Op.create('--', $2);
|
||||
}), o('++ SimpleAssignable', function() {
|
||||
return new Op('++', $2);
|
||||
return Op.create('++', $2);
|
||||
}), o('SimpleAssignable --', function() {
|
||||
return new Op('--', $1, null, true);
|
||||
return Op.create('--', $1, null, true);
|
||||
}), o('SimpleAssignable ++', function() {
|
||||
return new Op('++', $1, null, true);
|
||||
return Op.create('++', $1, null, true);
|
||||
}), o('Expression ?', function() {
|
||||
return new Existence($1);
|
||||
}), o('Expression + Expression', function() {
|
||||
return new Op('+', $1, $3);
|
||||
return Op.create('+', $1, $3);
|
||||
}), o('Expression - Expression', function() {
|
||||
return new Op('-', $1, $3);
|
||||
return Op.create('-', $1, $3);
|
||||
}), o('Expression MATH Expression', function() {
|
||||
return new Op($2, $1, $3);
|
||||
return Op.create($2, $1, $3);
|
||||
}), o('Expression SHIFT Expression', function() {
|
||||
return new Op($2, $1, $3);
|
||||
return Op.create($2, $1, $3);
|
||||
}), o('Expression COMPARE Expression', function() {
|
||||
return new Op($2, $1, $3);
|
||||
return Op.create($2, $1, $3);
|
||||
}), o('Expression LOGIC Expression', function() {
|
||||
return new Op($2, $1, $3);
|
||||
return Op.create($2, $1, $3);
|
||||
}), o('Expression RELATION Expression', function() {
|
||||
if ($2.charAt(0) === '!') {
|
||||
return new Op($2.slice(1), $1, $3).invert();
|
||||
return Op.create($2.slice(1), $1, $3).invert();
|
||||
} else {
|
||||
return new Op($2, $1, $3);
|
||||
return Op.create($2, $1, $3);
|
||||
}
|
||||
}), o('SimpleAssignable COMPOUND_ASSIGN\
|
||||
Expression', function() {
|
||||
@@ -549,29 +576,36 @@
|
||||
}), o('SimpleAssignable COMPOUND_ASSIGN\
|
||||
INDENT Expression OUTDENT', function() {
|
||||
return new Assign($1, $4, $2);
|
||||
}), o('SimpleAssignable COMPOUND_ASSIGN TERMINATOR\
|
||||
Expression', function() {
|
||||
return new Assign($1, $4, $2);
|
||||
}), o('SimpleAssignable EXTENDS Expression', function() {
|
||||
return new Extends($1, $3);
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
operators = [['left', '.', '?.', '::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', 'LOGIC'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'DO', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS'], ['right', 'POST_IF']];
|
||||
operators = [['left', '.', '?.', '::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', 'LOGIC'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS'], ['right', 'POST_IF']];
|
||||
|
||||
tokens = [];
|
||||
|
||||
for (name in grammar) {
|
||||
alternatives = grammar[name];
|
||||
grammar[name] = (function() {
|
||||
var _i, _j, _len, _len2, _ref, _results;
|
||||
var _i, _j, _len, _len1, _ref, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = alternatives.length; _i < _len; _i++) {
|
||||
alt = alternatives[_i];
|
||||
_ref = alt[0].split(' ');
|
||||
for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) {
|
||||
for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
|
||||
token = _ref[_j];
|
||||
if (!grammar[token]) tokens.push(token);
|
||||
if (!grammar[token]) {
|
||||
tokens.push(token);
|
||||
}
|
||||
}
|
||||
if (name === 'Root') {
|
||||
alt[1] = "return " + alt[1];
|
||||
}
|
||||
if (name === 'Root') alt[1] = "return " + alt[1];
|
||||
_results.push(alt);
|
||||
}
|
||||
return _results;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
(function() {
|
||||
var extend, flatten;
|
||||
var buildLocationData, extend, flatten, _ref;
|
||||
|
||||
exports.starts = function(string, literal, start) {
|
||||
return literal === string.substr(start, literal.length);
|
||||
@@ -16,7 +17,9 @@
|
||||
_results = [];
|
||||
for (_i = 0, _len = array.length; _i < _len; _i++) {
|
||||
item = array[_i];
|
||||
if (item) _results.push(item);
|
||||
if (item) {
|
||||
_results.push(item);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
@@ -24,7 +27,9 @@
|
||||
exports.count = function(string, substr) {
|
||||
var num, pos;
|
||||
num = pos = 0;
|
||||
if (!substr.length) return 1 / 0;
|
||||
if (!substr.length) {
|
||||
return 1 / 0;
|
||||
}
|
||||
while (pos = 1 + string.indexOf(substr, pos)) {
|
||||
num++;
|
||||
}
|
||||
@@ -69,4 +74,51 @@
|
||||
return array[array.length - (back || 0) - 1];
|
||||
};
|
||||
|
||||
exports.some = (_ref = Array.prototype.some) != null ? _ref : function(fn) {
|
||||
var e, _i, _len;
|
||||
for (_i = 0, _len = this.length; _i < _len; _i++) {
|
||||
e = this[_i];
|
||||
if (fn(e)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
buildLocationData = function(first, last) {
|
||||
if (!last) {
|
||||
return first;
|
||||
} else {
|
||||
return {
|
||||
first_line: first.first_line,
|
||||
first_column: first.first_column,
|
||||
last_line: last.last_line,
|
||||
last_column: last.last_column
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
exports.addLocationDataFn = function(first, last) {
|
||||
return function(obj) {
|
||||
if (((typeof obj) === 'object') && (!!obj['updateLocationDataIfMissing'])) {
|
||||
obj.updateLocationDataIfMissing(buildLocationData(first, last));
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
};
|
||||
|
||||
exports.locationDataToString = function(obj) {
|
||||
var locationData;
|
||||
if (("2" in obj) && ("first_line" in obj[2])) {
|
||||
locationData = obj[2];
|
||||
} else if ("first_line" in obj) {
|
||||
locationData = obj;
|
||||
}
|
||||
if (locationData) {
|
||||
return ("" + (locationData.first_line + 1) + ":" + (locationData.first_column + 1) + "-") + ("" + (locationData.last_line + 1) + ":" + (locationData.last_column + 1));
|
||||
} else {
|
||||
return "No location data";
|
||||
}
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
(function() {
|
||||
var key, val, _ref;
|
||||
|
||||
|
||||
@@ -1,51 +1,93 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
(function() {
|
||||
var BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, INVERSES, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, starts, _ref, _ref2;
|
||||
var __hasProp = Object.prototype.hasOwnProperty, __indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (__hasProp.call(this, i) && this[i] === item) return i; } return -1; };
|
||||
var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, INVERSES, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LITERATE, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, STRICT_PROSCRIBED, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, locationDataToString, starts, _ref, _ref1,
|
||||
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
|
||||
_ref = require('./rewriter'), Rewriter = _ref.Rewriter, INVERSES = _ref.INVERSES;
|
||||
|
||||
_ref2 = require('./helpers'), count = _ref2.count, starts = _ref2.starts, compact = _ref2.compact, last = _ref2.last;
|
||||
_ref1 = require('./helpers'), count = _ref1.count, starts = _ref1.starts, compact = _ref1.compact, last = _ref1.last, locationDataToString = _ref1.locationDataToString;
|
||||
|
||||
exports.Lexer = Lexer = (function() {
|
||||
|
||||
function Lexer() {}
|
||||
|
||||
Lexer.prototype.tokenize = function(code, opts) {
|
||||
var i, tag;
|
||||
if (opts == null) opts = {};
|
||||
if (WHITESPACE.test(code)) code = "\n" + code;
|
||||
code = code.replace(/\r/g, '').replace(TRAILING_SPACES, '');
|
||||
this.code = code;
|
||||
this.line = opts.line || 0;
|
||||
var consumed, i, tag, _ref2;
|
||||
if (opts == null) {
|
||||
opts = {};
|
||||
}
|
||||
this.literate = opts.literate;
|
||||
code = this.clean(code);
|
||||
this.indent = 0;
|
||||
this.indebt = 0;
|
||||
this.outdebt = 0;
|
||||
this.indents = [];
|
||||
this.ends = [];
|
||||
this.tokens = [];
|
||||
this.chunkLine = opts.line || 0;
|
||||
this.chunkColumn = opts.column || 0;
|
||||
i = 0;
|
||||
while (this.chunk = code.slice(i)) {
|
||||
i += this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.heredocToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken();
|
||||
consumed = this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.heredocToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken();
|
||||
_ref2 = this.getLineAndColumnFromChunk(consumed), this.chunkLine = _ref2[0], this.chunkColumn = _ref2[1];
|
||||
i += consumed;
|
||||
}
|
||||
this.closeIndentation();
|
||||
if (tag = this.ends.pop()) this.error("missing " + tag);
|
||||
if (opts.rewrite === false) return this.tokens;
|
||||
if (tag = this.ends.pop()) {
|
||||
this.error("missing " + tag);
|
||||
}
|
||||
if (opts.rewrite === false) {
|
||||
return this.tokens;
|
||||
}
|
||||
return (new Rewriter).rewrite(this.tokens);
|
||||
};
|
||||
|
||||
Lexer.prototype.clean = function(code) {
|
||||
var line, lines, match;
|
||||
if (code.charCodeAt(0) === BOM) {
|
||||
code = code.slice(1);
|
||||
}
|
||||
if (WHITESPACE.test(code)) {
|
||||
code = "\n" + code;
|
||||
}
|
||||
code = code.replace(/\r/g, '').replace(TRAILING_SPACES, '');
|
||||
if (this.literate) {
|
||||
lines = (function() {
|
||||
var _i, _len, _ref2, _results;
|
||||
_ref2 = code.split('\n');
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
line = _ref2[_i];
|
||||
if (match = LITERATE.exec(line)) {
|
||||
_results.push(line.slice(match[0].length));
|
||||
} else {
|
||||
_results.push('# ' + line);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
code = lines.join('\n');
|
||||
}
|
||||
return code;
|
||||
};
|
||||
|
||||
Lexer.prototype.identifierToken = function() {
|
||||
var colon, forcedIdentifier, id, input, match, prev, tag, _ref3, _ref4;
|
||||
if (!(match = IDENTIFIER.exec(this.chunk))) return 0;
|
||||
var colon, colonOffset, forcedIdentifier, id, idLength, input, match, poppedToken, prev, tag, tagToken, _ref2, _ref3, _ref4;
|
||||
if (!(match = IDENTIFIER.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
input = match[0], id = match[1], colon = match[2];
|
||||
idLength = id.length;
|
||||
poppedToken = void 0;
|
||||
if (id === 'own' && this.tag() === 'FOR') {
|
||||
this.token('OWN', id);
|
||||
return id.length;
|
||||
}
|
||||
forcedIdentifier = colon || (prev = last(this.tokens)) && (((_ref3 = prev[0]) === '.' || _ref3 === '?.' || _ref3 === '::') || !prev.spaced && prev[0] === '@');
|
||||
forcedIdentifier = colon || (prev = last(this.tokens)) && (((_ref2 = prev[0]) === '.' || _ref2 === '?.' || _ref2 === '::') || !prev.spaced && prev[0] === '@');
|
||||
tag = 'IDENTIFIER';
|
||||
if (!forcedIdentifier && (__indexOf.call(JS_KEYWORDS, id) >= 0 || __indexOf.call(COFFEE_KEYWORDS, id) >= 0)) {
|
||||
tag = id.toUpperCase();
|
||||
if (tag === 'WHEN' && (_ref4 = this.tag(), __indexOf.call(LINE_BREAK, _ref4) >= 0)) {
|
||||
if (tag === 'WHEN' && (_ref3 = this.tag(), __indexOf.call(LINE_BREAK, _ref3) >= 0)) {
|
||||
tag = 'LEADING_WHEN';
|
||||
} else if (tag === 'FOR') {
|
||||
this.seenFor = true;
|
||||
@@ -60,23 +102,25 @@
|
||||
} else {
|
||||
tag = 'RELATION';
|
||||
if (this.value() === '!') {
|
||||
this.tokens.pop();
|
||||
poppedToken = this.tokens.pop();
|
||||
id = '!' + id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (__indexOf.call(['eval', 'arguments'].concat(JS_FORBIDDEN), id) >= 0) {
|
||||
if (__indexOf.call(JS_FORBIDDEN, id) >= 0) {
|
||||
if (forcedIdentifier) {
|
||||
tag = 'IDENTIFIER';
|
||||
id = new String(id);
|
||||
id.reserved = true;
|
||||
} else if (__indexOf.call(RESERVED, id) >= 0) {
|
||||
this.error("reserved word \"" + word + "\"");
|
||||
this.error("reserved word \"" + id + "\"");
|
||||
}
|
||||
}
|
||||
if (!forcedIdentifier) {
|
||||
if (__indexOf.call(COFFEE_ALIASES, id) >= 0) id = COFFEE_ALIAS_MAP[id];
|
||||
if (__indexOf.call(COFFEE_ALIASES, id) >= 0) {
|
||||
id = COFFEE_ALIAS_MAP[id];
|
||||
}
|
||||
tag = (function() {
|
||||
switch (id) {
|
||||
case '!':
|
||||
@@ -89,60 +133,89 @@
|
||||
return 'LOGIC';
|
||||
case 'true':
|
||||
case 'false':
|
||||
case 'null':
|
||||
case 'undefined':
|
||||
return 'BOOL';
|
||||
case 'break':
|
||||
case 'continue':
|
||||
case 'debugger':
|
||||
return 'STATEMENT';
|
||||
default:
|
||||
return tag;
|
||||
}
|
||||
})();
|
||||
}
|
||||
this.token(tag, id);
|
||||
if (colon) this.token(':', ':');
|
||||
tagToken = this.token(tag, id, 0, idLength);
|
||||
if (poppedToken) {
|
||||
_ref4 = [poppedToken[2].first_line, poppedToken[2].first_column], tagToken[2].first_line = _ref4[0], tagToken[2].first_column = _ref4[1];
|
||||
}
|
||||
if (colon) {
|
||||
colonOffset = input.lastIndexOf(':');
|
||||
this.token(':', ':', colonOffset, colon.length);
|
||||
}
|
||||
return input.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.numberToken = function() {
|
||||
var binaryLiteral, lexedLength, match, number;
|
||||
if (!(match = NUMBER.exec(this.chunk))) return 0;
|
||||
number = match[0];
|
||||
lexedLength = number.length;
|
||||
if (binaryLiteral = /0b([01]+)/.exec(number)) {
|
||||
number = (parseInt(binaryLiteral[1], 2)).toString();
|
||||
var binaryLiteral, lexedLength, match, number, octalLiteral;
|
||||
if (!(match = NUMBER.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
this.token('NUMBER', number);
|
||||
number = match[0];
|
||||
if (/^0[BOX]/.test(number)) {
|
||||
this.error("radix prefix '" + number + "' must be lowercase");
|
||||
} else if (/E/.test(number) && !/^0x/.test(number)) {
|
||||
this.error("exponential notation '" + number + "' must be indicated with a lowercase 'e'");
|
||||
} else if (/^0\d*[89]/.test(number)) {
|
||||
this.error("decimal literal '" + number + "' must not be prefixed with '0'");
|
||||
} else if (/^0\d+/.test(number)) {
|
||||
this.error("octal literal '" + number + "' must be prefixed with '0o'");
|
||||
}
|
||||
lexedLength = number.length;
|
||||
if (octalLiteral = /^0o([0-7]+)/.exec(number)) {
|
||||
number = '0x' + (parseInt(octalLiteral[1], 8)).toString(16);
|
||||
}
|
||||
if (binaryLiteral = /^0b([01]+)/.exec(number)) {
|
||||
number = '0x' + (parseInt(binaryLiteral[1], 2)).toString(16);
|
||||
}
|
||||
this.token('NUMBER', number, 0, lexedLength);
|
||||
return lexedLength;
|
||||
};
|
||||
|
||||
Lexer.prototype.stringToken = function() {
|
||||
var match, string;
|
||||
var match, octalEsc, string;
|
||||
switch (this.chunk.charAt(0)) {
|
||||
case "'":
|
||||
if (!(match = SIMPLESTR.exec(this.chunk))) return 0;
|
||||
this.token('STRING', (string = match[0]).replace(MULTILINER, '\\\n'));
|
||||
if (!(match = SIMPLESTR.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
string = match[0];
|
||||
this.token('STRING', string.replace(MULTILINER, '\\\n'), 0, string.length);
|
||||
break;
|
||||
case '"':
|
||||
if (!(string = this.balancedString(this.chunk, '"'))) return 0;
|
||||
if (!(string = this.balancedString(this.chunk, '"'))) {
|
||||
return 0;
|
||||
}
|
||||
if (0 < string.indexOf('#{', 1)) {
|
||||
this.interpolateString(string.slice(1, -1));
|
||||
this.interpolateString(string.slice(1, -1), {
|
||||
strOffset: 1,
|
||||
lexedLength: string.length
|
||||
});
|
||||
} else {
|
||||
this.token('STRING', this.escapeLines(string));
|
||||
this.token('STRING', this.escapeLines(string, 0, string.length));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
this.line += count(string, '\n');
|
||||
if (octalEsc = /^(?:\\.|[^\\])*\\(?:0[0-7]|[1-7])/.test(string)) {
|
||||
this.error("octal escape sequences " + string + " are not allowed");
|
||||
}
|
||||
return string.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.heredocToken = function() {
|
||||
var doc, heredoc, match, quote;
|
||||
if (!(match = HEREDOC.exec(this.chunk))) return 0;
|
||||
if (!(match = HEREDOC.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
heredoc = match[0];
|
||||
quote = heredoc.charAt(0);
|
||||
doc = this.sanitizeHeredoc(match[2], {
|
||||
@@ -151,27 +224,28 @@
|
||||
});
|
||||
if (quote === '"' && 0 <= doc.indexOf('#{')) {
|
||||
this.interpolateString(doc, {
|
||||
heredoc: true
|
||||
heredoc: true,
|
||||
strOffset: 3,
|
||||
lexedLength: heredoc.length
|
||||
});
|
||||
} else {
|
||||
this.token('STRING', this.makeString(doc, quote, true));
|
||||
this.token('STRING', this.makeString(doc, quote, true), 0, heredoc.length);
|
||||
}
|
||||
this.line += count(heredoc, '\n');
|
||||
return heredoc.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.commentToken = function() {
|
||||
var comment, here, match;
|
||||
if (!(match = this.chunk.match(COMMENT))) return 0;
|
||||
if (!(match = this.chunk.match(COMMENT))) {
|
||||
return 0;
|
||||
}
|
||||
comment = match[0], here = match[1];
|
||||
if (here) {
|
||||
this.token('HERECOMMENT', this.sanitizeHeredoc(here, {
|
||||
herecomment: true,
|
||||
indent: Array(this.indent + 1).join(' ')
|
||||
}));
|
||||
this.token('TERMINATOR', '\n');
|
||||
}), 0, comment.length);
|
||||
}
|
||||
this.line += count(comment, '\n');
|
||||
return comment.length;
|
||||
};
|
||||
|
||||
@@ -180,84 +254,104 @@
|
||||
if (!(this.chunk.charAt(0) === '`' && (match = JSTOKEN.exec(this.chunk)))) {
|
||||
return 0;
|
||||
}
|
||||
this.token('JS', (script = match[0]).slice(1, -1));
|
||||
this.token('JS', (script = match[0]).slice(1, -1), 0, script.length);
|
||||
return script.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.regexToken = function() {
|
||||
var flags, length, match, prev, regex, _ref3, _ref4;
|
||||
if (this.chunk.charAt(0) !== '/') return 0;
|
||||
var flags, length, match, prev, regex, _ref2, _ref3;
|
||||
if (this.chunk.charAt(0) !== '/') {
|
||||
return 0;
|
||||
}
|
||||
if (match = HEREGEX.exec(this.chunk)) {
|
||||
length = this.heregexToken(match);
|
||||
this.line += count(match[0], '\n');
|
||||
return length;
|
||||
}
|
||||
prev = last(this.tokens);
|
||||
if (prev && (_ref3 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref3) >= 0)) {
|
||||
if (prev && (_ref2 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref2) >= 0)) {
|
||||
return 0;
|
||||
}
|
||||
if (!(match = REGEX.exec(this.chunk))) return 0;
|
||||
_ref4 = match, match = _ref4[0], regex = _ref4[1], flags = _ref4[2];
|
||||
if (!(match = REGEX.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
_ref3 = match, match = _ref3[0], regex = _ref3[1], flags = _ref3[2];
|
||||
if (regex.slice(0, 2) === '/*') {
|
||||
this.error('regular expressions cannot begin with `*`');
|
||||
}
|
||||
if (regex === '//') regex = '/(?:)/';
|
||||
this.token('REGEX', "" + regex + flags);
|
||||
if (regex === '//') {
|
||||
regex = '/(?:)/';
|
||||
}
|
||||
this.token('REGEX', "" + regex + flags, 0, match.length);
|
||||
return match.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.heregexToken = function(match) {
|
||||
var body, flags, heregex, re, tag, tokens, value, _i, _len, _ref3, _ref4, _ref5, _ref6;
|
||||
var body, flags, flagsOffset, heregex, plusToken, prev, re, tag, token, tokens, value, _i, _len, _ref2, _ref3, _ref4;
|
||||
heregex = match[0], body = match[1], flags = match[2];
|
||||
if (0 > body.indexOf('#{')) {
|
||||
re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/');
|
||||
if (re.match(/^\*/)) {
|
||||
this.error('regular expressions cannot begin with `*`');
|
||||
}
|
||||
this.token('REGEX', "/" + (re || '(?:)') + "/" + flags);
|
||||
this.token('REGEX', "/" + (re || '(?:)') + "/" + flags, 0, heregex.length);
|
||||
return heregex.length;
|
||||
}
|
||||
this.token('IDENTIFIER', 'RegExp');
|
||||
this.tokens.push(['CALL_START', '(']);
|
||||
this.token('IDENTIFIER', 'RegExp', 0, 0);
|
||||
this.token('CALL_START', '(', 0, 0);
|
||||
tokens = [];
|
||||
_ref3 = this.interpolateString(body, {
|
||||
_ref2 = this.interpolateString(body, {
|
||||
regex: true
|
||||
});
|
||||
for (_i = 0, _len = _ref3.length; _i < _len; _i++) {
|
||||
_ref4 = _ref3[_i], tag = _ref4[0], value = _ref4[1];
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
token = _ref2[_i];
|
||||
tag = token[0], value = token[1];
|
||||
if (tag === 'TOKENS') {
|
||||
tokens.push.apply(tokens, value);
|
||||
} else {
|
||||
if (!(value = value.replace(HEREGEX_OMIT, ''))) continue;
|
||||
} else if (tag === 'NEOSTRING') {
|
||||
if (!(value = value.replace(HEREGEX_OMIT, ''))) {
|
||||
continue;
|
||||
}
|
||||
value = value.replace(/\\/g, '\\\\');
|
||||
tokens.push(['STRING', this.makeString(value, '"', true)]);
|
||||
token[0] = 'STRING';
|
||||
token[1] = this.makeString(value, '"', true);
|
||||
tokens.push(token);
|
||||
} else {
|
||||
this.error("Unexpected " + tag);
|
||||
}
|
||||
tokens.push(['+', '+']);
|
||||
prev = last(this.tokens);
|
||||
plusToken = ['+', '+'];
|
||||
plusToken[2] = prev[2];
|
||||
tokens.push(plusToken);
|
||||
}
|
||||
tokens.pop();
|
||||
if (((_ref5 = tokens[0]) != null ? _ref5[0] : void 0) !== 'STRING') {
|
||||
this.tokens.push(['STRING', '""'], ['+', '+']);
|
||||
if (((_ref3 = tokens[0]) != null ? _ref3[0] : void 0) !== 'STRING') {
|
||||
this.token('STRING', '""', 0, 0);
|
||||
this.token('+', '+', 0, 0);
|
||||
}
|
||||
(_ref6 = this.tokens).push.apply(_ref6, tokens);
|
||||
if (flags) this.tokens.push([',', ','], ['STRING', '"' + flags + '"']);
|
||||
this.token(')', ')');
|
||||
(_ref4 = this.tokens).push.apply(_ref4, tokens);
|
||||
if (flags) {
|
||||
flagsOffset = heregex.lastIndexOf(flags);
|
||||
this.token(',', ',', flagsOffset, 0);
|
||||
this.token('STRING', '"' + flags + '"', flagsOffset, flags.length);
|
||||
}
|
||||
this.token(')', ')', heregex.length - 1, 0);
|
||||
return heregex.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.lineToken = function() {
|
||||
var diff, indent, match, noNewlines, prev, size;
|
||||
if (!(match = MULTI_DENT.exec(this.chunk))) return 0;
|
||||
var diff, indent, match, noNewlines, size;
|
||||
if (!(match = MULTI_DENT.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
indent = match[0];
|
||||
this.line += count(indent, '\n');
|
||||
this.seenFor = false;
|
||||
prev = last(this.tokens, 1);
|
||||
size = indent.length - 1 - indent.lastIndexOf('\n');
|
||||
noNewlines = this.unfinished();
|
||||
if (size - this.indebt === this.indent) {
|
||||
if (noNewlines) {
|
||||
this.suppressNewlines();
|
||||
} else {
|
||||
this.newlineToken();
|
||||
this.newlineToken(0);
|
||||
}
|
||||
return indent.length;
|
||||
}
|
||||
@@ -268,19 +362,19 @@
|
||||
return indent.length;
|
||||
}
|
||||
diff = size - this.indent + this.outdebt;
|
||||
this.token('INDENT', diff);
|
||||
this.token('INDENT', diff, 0, indent.length);
|
||||
this.indents.push(diff);
|
||||
this.ends.push('OUTDENT');
|
||||
this.outdebt = this.indebt = 0;
|
||||
} else {
|
||||
this.indebt = 0;
|
||||
this.outdentToken(this.indent - size, noNewlines);
|
||||
this.outdentToken(this.indent - size, noNewlines, indent.length);
|
||||
}
|
||||
this.indent = size;
|
||||
return indent.length;
|
||||
};
|
||||
|
||||
Lexer.prototype.outdentToken = function(moveOut, noNewlines) {
|
||||
Lexer.prototype.outdentToken = function(moveOut, noNewlines, outdentLength) {
|
||||
var dent, len;
|
||||
while (moveOut > 0) {
|
||||
len = this.indents.length - 1;
|
||||
@@ -293,19 +387,21 @@
|
||||
this.outdebt -= this.indents[len];
|
||||
moveOut -= this.indents[len];
|
||||
} else {
|
||||
dent = this.indents.pop() - this.outdebt;
|
||||
dent = this.indents.pop() + this.outdebt;
|
||||
moveOut -= dent;
|
||||
this.outdebt = 0;
|
||||
this.pair('OUTDENT');
|
||||
this.token('OUTDENT', dent);
|
||||
this.token('OUTDENT', dent, 0, outdentLength);
|
||||
}
|
||||
}
|
||||
if (dent) this.outdebt -= moveOut;
|
||||
if (dent) {
|
||||
this.outdebt -= moveOut;
|
||||
}
|
||||
while (this.value() === ';') {
|
||||
this.tokens.pop();
|
||||
}
|
||||
if (!(this.tag() === 'TERMINATOR' || noNewlines)) {
|
||||
this.token('TERMINATOR', '\n');
|
||||
this.token('TERMINATOR', '\n', outdentLength, 0);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
@@ -316,7 +412,9 @@
|
||||
return 0;
|
||||
}
|
||||
prev = last(this.tokens);
|
||||
if (prev) prev[match ? 'spaced' : 'newLine'] = true;
|
||||
if (prev) {
|
||||
prev[match ? 'spaced' : 'newLine'] = true;
|
||||
}
|
||||
if (match) {
|
||||
return match[0].length;
|
||||
} else {
|
||||
@@ -324,34 +422,40 @@
|
||||
}
|
||||
};
|
||||
|
||||
Lexer.prototype.newlineToken = function() {
|
||||
Lexer.prototype.newlineToken = function(offset) {
|
||||
while (this.value() === ';') {
|
||||
this.tokens.pop();
|
||||
}
|
||||
if (this.tag() !== 'TERMINATOR') this.token('TERMINATOR', '\n');
|
||||
if (this.tag() !== 'TERMINATOR') {
|
||||
this.token('TERMINATOR', '\n', offset, 0);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
Lexer.prototype.suppressNewlines = function() {
|
||||
if (this.value() === '\\') this.tokens.pop();
|
||||
if (this.value() === '\\') {
|
||||
this.tokens.pop();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
Lexer.prototype.literalToken = function() {
|
||||
var match, prev, tag, value, _ref3, _ref4, _ref5, _ref6;
|
||||
var match, prev, tag, value, _ref2, _ref3, _ref4, _ref5;
|
||||
if (match = OPERATOR.exec(this.chunk)) {
|
||||
value = match[0];
|
||||
if (CODE.test(value)) this.tagParameters();
|
||||
if (CODE.test(value)) {
|
||||
this.tagParameters();
|
||||
}
|
||||
} else {
|
||||
value = this.chunk.charAt(0);
|
||||
}
|
||||
tag = value;
|
||||
prev = last(this.tokens);
|
||||
if (value === '=' && prev) {
|
||||
if (!prev[1].reserved && (_ref3 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref3) >= 0)) {
|
||||
if (!prev[1].reserved && (_ref2 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref2) >= 0)) {
|
||||
this.error("reserved word \"" + (this.value()) + "\" can't be assigned");
|
||||
}
|
||||
if ((_ref4 = prev[1]) === '||' || _ref4 === '&&') {
|
||||
if ((_ref3 = prev[1]) === '||' || _ref3 === '&&') {
|
||||
prev[0] = 'COMPOUND_ASSIGN';
|
||||
prev[1] += '=';
|
||||
return value.length;
|
||||
@@ -373,10 +477,12 @@
|
||||
} else if (__indexOf.call(LOGIC, value) >= 0 || value === '?' && (prev != null ? prev.spaced : void 0)) {
|
||||
tag = 'LOGIC';
|
||||
} else if (prev && !prev.spaced) {
|
||||
if (value === '(' && (_ref5 = prev[0], __indexOf.call(CALLABLE, _ref5) >= 0)) {
|
||||
if (prev[0] === '?') prev[0] = 'FUNC_EXIST';
|
||||
if (value === '(' && (_ref4 = prev[0], __indexOf.call(CALLABLE, _ref4) >= 0)) {
|
||||
if (prev[0] === '?') {
|
||||
prev[0] = 'FUNC_EXIST';
|
||||
}
|
||||
tag = 'CALL_START';
|
||||
} else if (value === '[' && (_ref6 = prev[0], __indexOf.call(INDEXABLE, _ref6) >= 0)) {
|
||||
} else if (value === '[' && (_ref5 = prev[0], __indexOf.call(INDEXABLE, _ref5) >= 0)) {
|
||||
tag = 'INDEX_START';
|
||||
switch (prev[0]) {
|
||||
case '?':
|
||||
@@ -400,29 +506,37 @@
|
||||
};
|
||||
|
||||
Lexer.prototype.sanitizeHeredoc = function(doc, options) {
|
||||
var attempt, herecomment, indent, match, _ref3;
|
||||
var attempt, herecomment, indent, match, _ref2;
|
||||
indent = options.indent, herecomment = options.herecomment;
|
||||
if (herecomment) {
|
||||
if (HEREDOC_ILLEGAL.test(doc)) {
|
||||
this.error("block comment cannot contain \"*/\", starting");
|
||||
}
|
||||
if (doc.indexOf('\n') <= 0) return doc;
|
||||
if (doc.indexOf('\n') < 0) {
|
||||
return doc;
|
||||
}
|
||||
} else {
|
||||
while (match = HEREDOC_INDENT.exec(doc)) {
|
||||
attempt = match[1];
|
||||
if (indent === null || (0 < (_ref3 = attempt.length) && _ref3 < indent.length)) {
|
||||
if (indent === null || (0 < (_ref2 = attempt.length) && _ref2 < indent.length)) {
|
||||
indent = attempt;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (indent) doc = doc.replace(RegExp("\\n" + indent, "g"), '\n');
|
||||
if (!herecomment) doc = doc.replace(/^\n/, '');
|
||||
if (indent) {
|
||||
doc = doc.replace(RegExp("\\n" + indent, "g"), '\n');
|
||||
}
|
||||
if (!herecomment) {
|
||||
doc = doc.replace(/^\n/, '');
|
||||
}
|
||||
return doc;
|
||||
};
|
||||
|
||||
Lexer.prototype.tagParameters = function() {
|
||||
var i, stack, tok, tokens;
|
||||
if (this.tag() !== ')') return this;
|
||||
if (this.tag() !== ')') {
|
||||
return this;
|
||||
}
|
||||
stack = [];
|
||||
tokens = this.tokens;
|
||||
i = tokens.length;
|
||||
@@ -452,23 +566,30 @@
|
||||
};
|
||||
|
||||
Lexer.prototype.balancedString = function(str, end) {
|
||||
var i, letter, match, prev, stack, _ref3;
|
||||
var continueCount, i, letter, match, prev, stack, _i, _ref2;
|
||||
continueCount = 0;
|
||||
stack = [end];
|
||||
for (i = 1, _ref3 = str.length; 1 <= _ref3 ? i < _ref3 : i > _ref3; 1 <= _ref3 ? i++ : i--) {
|
||||
for (i = _i = 1, _ref2 = str.length; 1 <= _ref2 ? _i < _ref2 : _i > _ref2; i = 1 <= _ref2 ? ++_i : --_i) {
|
||||
if (continueCount) {
|
||||
--continueCount;
|
||||
continue;
|
||||
}
|
||||
switch (letter = str.charAt(i)) {
|
||||
case '\\':
|
||||
i++;
|
||||
++continueCount;
|
||||
continue;
|
||||
case end:
|
||||
stack.pop();
|
||||
if (!stack.length) return str.slice(0, i + 1);
|
||||
if (!stack.length) {
|
||||
return str.slice(0, +i + 1 || 9e9);
|
||||
}
|
||||
end = stack[stack.length - 1];
|
||||
continue;
|
||||
}
|
||||
if (end === '}' && (letter === '"' || letter === "'")) {
|
||||
stack.push(end = letter);
|
||||
} else if (end === '}' && letter === '/' && (match = HEREGEX.exec(str.slice(i)) || REGEX.exec(str.slice(i)))) {
|
||||
i += match[0].length - 1;
|
||||
continueCount += match[0].length - 1;
|
||||
} else if (end === '}' && letter === '{') {
|
||||
stack.push(end = '}');
|
||||
} else if (end === '"' && prev === '#' && letter === '{') {
|
||||
@@ -480,9 +601,18 @@
|
||||
};
|
||||
|
||||
Lexer.prototype.interpolateString = function(str, options) {
|
||||
var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _len, _ref3, _ref4, _ref5;
|
||||
if (options == null) options = {};
|
||||
heredoc = options.heredoc, regex = options.regex;
|
||||
var column, expr, heredoc, i, inner, interpolated, len, letter, lexedLength, line, locationToken, nested, offsetInChunk, pi, plusToken, popped, regex, strOffset, tag, token, tokens, value, _i, _len, _ref2, _ref3, _ref4;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
heredoc = options.heredoc, regex = options.regex, offsetInChunk = options.offsetInChunk, strOffset = options.strOffset, lexedLength = options.lexedLength;
|
||||
offsetInChunk = offsetInChunk || 0;
|
||||
strOffset = strOffset || 0;
|
||||
lexedLength = lexedLength || str.length;
|
||||
if (heredoc && str.length > 0 && str[0] === '\n') {
|
||||
str = str.slice(1);
|
||||
strOffset++;
|
||||
}
|
||||
tokens = [];
|
||||
pi = 0;
|
||||
i = -1;
|
||||
@@ -494,21 +624,25 @@
|
||||
if (!(letter === '#' && str.charAt(i + 1) === '{' && (expr = this.balancedString(str.slice(i + 1), '}')))) {
|
||||
continue;
|
||||
}
|
||||
if (pi < i) tokens.push(['NEOSTRING', str.slice(pi, i)]);
|
||||
if (pi < i) {
|
||||
tokens.push(this.makeToken('NEOSTRING', str.slice(pi, i), strOffset + pi));
|
||||
}
|
||||
inner = expr.slice(1, -1);
|
||||
if (inner.length) {
|
||||
_ref2 = this.getLineAndColumnFromChunk(strOffset + i + 1), line = _ref2[0], column = _ref2[1];
|
||||
nested = new Lexer().tokenize(inner, {
|
||||
line: this.line,
|
||||
line: line,
|
||||
column: column,
|
||||
rewrite: false
|
||||
});
|
||||
nested.pop();
|
||||
popped = nested.pop();
|
||||
if (((_ref3 = nested[0]) != null ? _ref3[0] : void 0) === 'TERMINATOR') {
|
||||
nested.shift();
|
||||
popped = nested.shift();
|
||||
}
|
||||
if (len = nested.length) {
|
||||
if (len > 1) {
|
||||
nested.unshift(['(', '(']);
|
||||
nested.push([')', ')']);
|
||||
nested.unshift(this.makeToken('(', '(', strOffset + i + 1, 0));
|
||||
nested.push(this.makeToken(')', ')', strOffset + i + 1 + inner.length, 0));
|
||||
}
|
||||
tokens.push(['TOKENS', nested]);
|
||||
}
|
||||
@@ -516,28 +650,58 @@
|
||||
i += expr.length;
|
||||
pi = i + 1;
|
||||
}
|
||||
if ((i > pi && pi < str.length)) tokens.push(['NEOSTRING', str.slice(pi)]);
|
||||
if (regex) return tokens;
|
||||
if (!tokens.length) return this.token('STRING', '""');
|
||||
if (tokens[0][0] !== 'NEOSTRING') tokens.unshift(['', '']);
|
||||
if (interpolated = tokens.length > 1) this.token('(', '(');
|
||||
for (i = 0, _len = tokens.length; i < _len; i++) {
|
||||
_ref4 = tokens[i], tag = _ref4[0], value = _ref4[1];
|
||||
if (i) this.token('+', '+');
|
||||
if ((i > pi && pi < str.length)) {
|
||||
tokens.push(this.makeToken('NEOSTRING', str.slice(pi), strOffset + pi));
|
||||
}
|
||||
if (regex) {
|
||||
return tokens;
|
||||
}
|
||||
if (!tokens.length) {
|
||||
return this.token('STRING', '""', offsetInChunk, lexedLength);
|
||||
}
|
||||
if (tokens[0][0] !== 'NEOSTRING') {
|
||||
tokens.unshift(this.makeToken('NEOSTRING', '', offsetInChunk));
|
||||
}
|
||||
if (interpolated = tokens.length > 1) {
|
||||
this.token('(', '(', offsetInChunk, 0);
|
||||
}
|
||||
for (i = _i = 0, _len = tokens.length; _i < _len; i = ++_i) {
|
||||
token = tokens[i];
|
||||
tag = token[0], value = token[1];
|
||||
if (i) {
|
||||
if (i) {
|
||||
plusToken = this.token('+', '+');
|
||||
}
|
||||
locationToken = tag === 'TOKENS' ? value[0] : token;
|
||||
plusToken[2] = {
|
||||
first_line: locationToken[2].first_line,
|
||||
first_column: locationToken[2].first_column,
|
||||
last_line: locationToken[2].first_line,
|
||||
last_column: locationToken[2].first_column
|
||||
};
|
||||
}
|
||||
if (tag === 'TOKENS') {
|
||||
(_ref5 = this.tokens).push.apply(_ref5, value);
|
||||
(_ref4 = this.tokens).push.apply(_ref4, value);
|
||||
} else if (tag === 'NEOSTRING') {
|
||||
token[0] = 'STRING';
|
||||
token[1] = this.makeString(value, '"', heredoc);
|
||||
this.tokens.push(token);
|
||||
} else {
|
||||
this.token('STRING', this.makeString(value, '"', heredoc));
|
||||
this.error("Unexpected " + tag);
|
||||
}
|
||||
}
|
||||
if (interpolated) this.token(')', ')');
|
||||
if (interpolated) {
|
||||
this.token(')', ')', offsetInChunk + lexedLength, 0);
|
||||
}
|
||||
return tokens;
|
||||
};
|
||||
|
||||
Lexer.prototype.pair = function(tag) {
|
||||
var size, wanted;
|
||||
if (tag !== (wanted = last(this.ends))) {
|
||||
if ('OUTDENT' !== wanted) this.error("unmatched " + tag);
|
||||
if ('OUTDENT' !== wanted) {
|
||||
this.error("unmatched " + tag);
|
||||
}
|
||||
this.indent -= size = last(this.indents);
|
||||
this.outdentToken(size, true);
|
||||
return this.pair(tag);
|
||||
@@ -545,8 +709,46 @@
|
||||
return this.ends.pop();
|
||||
};
|
||||
|
||||
Lexer.prototype.token = function(tag, value) {
|
||||
return this.tokens.push([tag, value, this.line]);
|
||||
Lexer.prototype.getLineAndColumnFromChunk = function(offset) {
|
||||
var column, lineCount, lines, string;
|
||||
if (offset === 0) {
|
||||
return [this.chunkLine, this.chunkColumn];
|
||||
}
|
||||
if (offset >= this.chunk.length) {
|
||||
string = this.chunk;
|
||||
} else {
|
||||
string = this.chunk.slice(0, +(offset - 1) + 1 || 9e9);
|
||||
}
|
||||
lineCount = count(string, '\n');
|
||||
column = this.chunkColumn;
|
||||
if (lineCount > 0) {
|
||||
lines = string.split('\n');
|
||||
column = (last(lines)).length;
|
||||
} else {
|
||||
column += string.length;
|
||||
}
|
||||
return [this.chunkLine + lineCount, column];
|
||||
};
|
||||
|
||||
Lexer.prototype.makeToken = function(tag, value, offsetInChunk, length) {
|
||||
var lastCharacter, locationData, token, _ref2, _ref3;
|
||||
offsetInChunk = offsetInChunk || 0;
|
||||
if (length === void 0) {
|
||||
length = value.length;
|
||||
}
|
||||
locationData = {};
|
||||
_ref2 = this.getLineAndColumnFromChunk(offsetInChunk), locationData.first_line = _ref2[0], locationData.first_column = _ref2[1];
|
||||
lastCharacter = length > 0 ? length - 1 : 0;
|
||||
_ref3 = this.getLineAndColumnFromChunk(offsetInChunk + (length - 1)), locationData.last_line = _ref3[0], locationData.last_column = _ref3[1];
|
||||
token = [tag, value, locationData];
|
||||
return token;
|
||||
};
|
||||
|
||||
Lexer.prototype.token = function(tag, value, offsetInChunk, length) {
|
||||
var token;
|
||||
token = this.makeToken(tag, value, offsetInChunk, length);
|
||||
this.tokens.push(token);
|
||||
return token;
|
||||
};
|
||||
|
||||
Lexer.prototype.tag = function(index, tag) {
|
||||
@@ -560,8 +762,8 @@
|
||||
};
|
||||
|
||||
Lexer.prototype.unfinished = function() {
|
||||
var _ref3;
|
||||
return LINE_CONTINUER.test(this.chunk) || ((_ref3 = this.tag()) === '\\' || _ref3 === '.' || _ref3 === '?.' || _ref3 === 'UNARY' || _ref3 === 'MATH' || _ref3 === '+' || _ref3 === '-' || _ref3 === 'SHIFT' || _ref3 === 'RELATION' || _ref3 === 'COMPARE' || _ref3 === 'LOGIC' || _ref3 === 'COMPOUND_ASSIGN' || _ref3 === 'THROW' || _ref3 === 'EXTENDS');
|
||||
var _ref2;
|
||||
return LINE_CONTINUER.test(this.chunk) || ((_ref2 = this.tag()) === '\\' || _ref2 === '.' || _ref2 === '?.' || _ref2 === 'UNARY' || _ref2 === 'MATH' || _ref2 === '+' || _ref2 === '-' || _ref2 === 'SHIFT' || _ref2 === 'RELATION' || _ref2 === 'COMPARE' || _ref2 === 'LOGIC' || _ref2 === 'THROW' || _ref2 === 'EXTENDS');
|
||||
};
|
||||
|
||||
Lexer.prototype.escapeLines = function(str, heredoc) {
|
||||
@@ -569,7 +771,9 @@
|
||||
};
|
||||
|
||||
Lexer.prototype.makeString = function(body, quote, heredoc) {
|
||||
if (!body) return quote + quote;
|
||||
if (!body) {
|
||||
return quote + quote;
|
||||
}
|
||||
body = body.replace(/\\([\s\S])/g, function(match, contents) {
|
||||
if (contents === '\n' || contents === quote) {
|
||||
return contents;
|
||||
@@ -582,7 +786,7 @@
|
||||
};
|
||||
|
||||
Lexer.prototype.error = function(message) {
|
||||
throw SyntaxError("" + message + " on line " + (this.line + 1));
|
||||
throw SyntaxError("" + message + " on line " + (this.chunkLine + 1));
|
||||
};
|
||||
|
||||
return Lexer;
|
||||
@@ -616,15 +820,21 @@
|
||||
|
||||
COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat(COFFEE_ALIASES);
|
||||
|
||||
RESERVED = ['case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind', '__indexOf'];
|
||||
RESERVED = ['case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind', '__indexOf', 'implements', 'interface', 'package', 'private', 'protected', 'public', 'static', 'yield'];
|
||||
|
||||
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED);
|
||||
STRICT_PROSCRIBED = ['arguments', 'eval'];
|
||||
|
||||
exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS);
|
||||
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED);
|
||||
|
||||
exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS).concat(STRICT_PROSCRIBED);
|
||||
|
||||
exports.STRICT_PROSCRIBED = STRICT_PROSCRIBED;
|
||||
|
||||
BOM = 65279;
|
||||
|
||||
IDENTIFIER = /^([$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)([^\n\S]*:(?!:))?/;
|
||||
|
||||
NUMBER = /^0x[\da-f]+|^0b[01]+|^\d*\.?\d+(?:e[+-]?\d+)?/i;
|
||||
NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i;
|
||||
|
||||
HEREDOC = /^("""|''')([\s\S]*?)(?:\n[^\n\S]*)?\1/;
|
||||
|
||||
@@ -632,7 +842,9 @@
|
||||
|
||||
WHITESPACE = /^[^\n\S]+/;
|
||||
|
||||
COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)?$)|^(?:\s*#(?!##[^#]).*)+/;
|
||||
COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)$)|^(?:\s*#(?!##[^#]).*)+/;
|
||||
|
||||
LITERATE = /^([ ]{4}|\t)/;
|
||||
|
||||
CODE = /^[-=]>/;
|
||||
|
||||
@@ -672,15 +884,15 @@
|
||||
|
||||
RELATION = ['IN', 'OF', 'INSTANCEOF'];
|
||||
|
||||
BOOL = ['TRUE', 'FALSE', 'NULL', 'UNDEFINED'];
|
||||
BOOL = ['TRUE', 'FALSE'];
|
||||
|
||||
NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', '++', '--', ']'];
|
||||
NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', 'NULL', 'UNDEFINED', '++', '--', ']'];
|
||||
|
||||
NOT_SPACED_REGEX = NOT_REGEX.concat(')', '}', 'THIS', 'IDENTIFIER', 'STRING');
|
||||
|
||||
CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER'];
|
||||
|
||||
INDEXABLE = CALLABLE.concat('NUMBER', 'BOOL');
|
||||
INDEXABLE = CALLABLE.concat('NUMBER', 'BOOL', 'NULL', 'UNDEFINED');
|
||||
|
||||
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
(function() {
|
||||
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments;
|
||||
|
||||
@@ -9,39 +10,48 @@
|
||||
}
|
||||
|
||||
OptionParser.prototype.parse = function(args) {
|
||||
var arg, i, isOption, matchedRule, options, originalArgs, pos, rule, value, _i, _len, _len2, _ref;
|
||||
var arg, i, isOption, matchedRule, options, originalArgs, pos, rule, seenNonOptionArg, skippingArgument, value, _i, _j, _len, _len1, _ref;
|
||||
options = {
|
||||
arguments: [],
|
||||
literals: []
|
||||
"arguments": []
|
||||
};
|
||||
skippingArgument = false;
|
||||
originalArgs = args;
|
||||
args = normalizeArguments(args);
|
||||
for (i = 0, _len = args.length; i < _len; i++) {
|
||||
for (i = _i = 0, _len = args.length; _i < _len; i = ++_i) {
|
||||
arg = args[i];
|
||||
if (skippingArgument) {
|
||||
skippingArgument = false;
|
||||
continue;
|
||||
}
|
||||
if (arg === '--') {
|
||||
pos = originalArgs.indexOf('--');
|
||||
options.arguments = [originalArgs[1 + pos]];
|
||||
options.literals = originalArgs.slice(2 + pos);
|
||||
options["arguments"] = options["arguments"].concat(originalArgs.slice(pos + 1));
|
||||
break;
|
||||
}
|
||||
isOption = !!(arg.match(LONG_FLAG) || arg.match(SHORT_FLAG));
|
||||
matchedRule = false;
|
||||
_ref = this.rules;
|
||||
for (_i = 0, _len2 = _ref.length; _i < _len2; _i++) {
|
||||
rule = _ref[_i];
|
||||
if (rule.shortFlag === arg || rule.longFlag === arg) {
|
||||
value = rule.hasArgument ? args[i += 1] : true;
|
||||
options[rule.name] = rule.isList ? (options[rule.name] || []).concat(value) : value;
|
||||
matchedRule = true;
|
||||
break;
|
||||
seenNonOptionArg = options["arguments"].length > 0;
|
||||
if (!seenNonOptionArg) {
|
||||
matchedRule = false;
|
||||
_ref = this.rules;
|
||||
for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
|
||||
rule = _ref[_j];
|
||||
if (rule.shortFlag === arg || rule.longFlag === arg) {
|
||||
value = true;
|
||||
if (rule.hasArgument) {
|
||||
skippingArgument = true;
|
||||
value = args[i + 1];
|
||||
}
|
||||
options[rule.name] = rule.isList ? (options[rule.name] || []).concat(value) : value;
|
||||
matchedRule = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isOption && !matchedRule) {
|
||||
throw new Error("unrecognized option: " + arg);
|
||||
}
|
||||
}
|
||||
if (isOption && !matchedRule) {
|
||||
throw new Error("unrecognized option: " + arg);
|
||||
}
|
||||
if (!isOption) {
|
||||
options.arguments = originalArgs.slice(originalArgs.indexOf(arg));
|
||||
break;
|
||||
if (seenNonOptionArg || !isOption) {
|
||||
options["arguments"].push(arg);
|
||||
}
|
||||
}
|
||||
return options;
|
||||
@@ -50,7 +60,9 @@
|
||||
OptionParser.prototype.help = function() {
|
||||
var letPart, lines, rule, spaces, _i, _len, _ref;
|
||||
lines = [];
|
||||
if (this.banner) lines.unshift("" + this.banner + "\n");
|
||||
if (this.banner) {
|
||||
lines.unshift("" + this.banner + "\n");
|
||||
}
|
||||
_ref = this.rules;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
rule = _ref[_i];
|
||||
@@ -66,9 +78,9 @@
|
||||
|
||||
})();
|
||||
|
||||
LONG_FLAG = /^(--\w[\w\-]+)/;
|
||||
LONG_FLAG = /^(--\w[\w\-]*)/;
|
||||
|
||||
SHORT_FLAG = /^(-\w)/;
|
||||
SHORT_FLAG = /^(-\w)$/;
|
||||
|
||||
MULTI_FLAG = /^-(\w{2,})/;
|
||||
|
||||
@@ -79,7 +91,9 @@
|
||||
_results = [];
|
||||
for (_i = 0, _len = rules.length; _i < _len; _i++) {
|
||||
tuple = rules[_i];
|
||||
if (tuple.length < 3) tuple.unshift(null);
|
||||
if (tuple.length < 3) {
|
||||
tuple.unshift(null);
|
||||
}
|
||||
_results.push(buildRule.apply(null, tuple));
|
||||
}
|
||||
return _results;
|
||||
@@ -87,7 +101,9 @@
|
||||
|
||||
buildRule = function(shortFlag, longFlag, description, options) {
|
||||
var match;
|
||||
if (options == null) options = {};
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
match = longFlag.match(OPTIONAL);
|
||||
longFlag = longFlag.match(LONG_FLAG)[1];
|
||||
return {
|
||||
@@ -101,14 +117,14 @@
|
||||
};
|
||||
|
||||
normalizeArguments = function(args) {
|
||||
var arg, l, match, result, _i, _j, _len, _len2, _ref;
|
||||
var arg, l, match, result, _i, _j, _len, _len1, _ref;
|
||||
args = args.slice(0);
|
||||
result = [];
|
||||
for (_i = 0, _len = args.length; _i < _len; _i++) {
|
||||
arg = args[_i];
|
||||
if (match = arg.match(MULTI_FLAG)) {
|
||||
_ref = match[1].split('');
|
||||
for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) {
|
||||
for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
|
||||
l = _ref[_j];
|
||||
result.push('-' + l);
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,149 +1,104 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
(function() {
|
||||
var ACCESSOR, CoffeeScript, Module, REPL_PROMPT, REPL_PROMPT_CONTINUATION, SIMPLEVAR, Script, autocomplete, backlog, completeAttribute, completeVariable, enableColours, error, getCompletions, inspect, readline, repl, run, stdin, stdout;
|
||||
var CoffeeScript, addMultilineHandler, merge, nodeREPL, replDefaults, vm;
|
||||
|
||||
vm = require('vm');
|
||||
|
||||
nodeREPL = require('repl');
|
||||
|
||||
CoffeeScript = require('./coffee-script');
|
||||
|
||||
readline = require('readline');
|
||||
merge = require('./helpers').merge;
|
||||
|
||||
inspect = require('util').inspect;
|
||||
|
||||
Script = require('vm').Script;
|
||||
|
||||
Module = require('module');
|
||||
|
||||
REPL_PROMPT = 'coffee> ';
|
||||
|
||||
REPL_PROMPT_CONTINUATION = '......> ';
|
||||
|
||||
enableColours = false;
|
||||
|
||||
if (process.platform !== 'win32') {
|
||||
enableColours = !process.env.NODE_DISABLE_COLORS;
|
||||
}
|
||||
|
||||
stdin = process.openStdin();
|
||||
|
||||
stdout = process.stdout;
|
||||
|
||||
error = function(err) {
|
||||
return stdout.write((err.stack || err.toString()) + '\n');
|
||||
};
|
||||
|
||||
backlog = '';
|
||||
|
||||
run = function(buffer) {
|
||||
var code, returnValue, _;
|
||||
if (!buffer.toString().trim() && !backlog) {
|
||||
repl.prompt();
|
||||
return;
|
||||
}
|
||||
code = backlog += buffer;
|
||||
if (code[code.length - 1] === '\\') {
|
||||
backlog = "" + backlog.slice(0, -1) + "\n";
|
||||
repl.setPrompt(REPL_PROMPT_CONTINUATION);
|
||||
repl.prompt();
|
||||
return;
|
||||
}
|
||||
repl.setPrompt(REPL_PROMPT);
|
||||
backlog = '';
|
||||
try {
|
||||
_ = global._;
|
||||
returnValue = CoffeeScript.eval("_=(" + code + "\n)", {
|
||||
filename: 'repl',
|
||||
modulename: 'repl'
|
||||
});
|
||||
if (returnValue === void 0) global._ = _;
|
||||
process.stdout.write(inspect(returnValue, false, 2, enableColours) + '\n');
|
||||
} catch (err) {
|
||||
error(err);
|
||||
}
|
||||
return repl.prompt();
|
||||
};
|
||||
|
||||
ACCESSOR = /\s*([\w\.]+)(?:\.(\w*))$/;
|
||||
|
||||
SIMPLEVAR = /\s*(\w*)$/i;
|
||||
|
||||
autocomplete = function(text) {
|
||||
return completeAttribute(text) || completeVariable(text) || [[], text];
|
||||
};
|
||||
|
||||
completeAttribute = function(text) {
|
||||
var all, completions, match, obj, prefix, val;
|
||||
if (match = text.match(ACCESSOR)) {
|
||||
all = match[0], obj = match[1], prefix = match[2];
|
||||
replDefaults = {
|
||||
prompt: 'coffee> ',
|
||||
"eval": function(input, context, filename, cb) {
|
||||
var js;
|
||||
input = input.replace(/\uFF00/g, '\n');
|
||||
input = input.replace(/(^|[\r\n]+)(\s*)##?(?:[^#\r\n][^\r\n]*|)($|[\r\n])/, '$1$2$3');
|
||||
if (/^\s*$/.test(input)) {
|
||||
return cb(null);
|
||||
}
|
||||
try {
|
||||
val = Script.runInThisContext(obj);
|
||||
} catch (error) {
|
||||
js = CoffeeScript.compile("_=(" + input + "\n)", {
|
||||
filename: filename,
|
||||
bare: true
|
||||
});
|
||||
} catch (err) {
|
||||
cb(err);
|
||||
}
|
||||
return cb(null, vm.runInContext(js, context, filename));
|
||||
}
|
||||
};
|
||||
|
||||
addMultilineHandler = function(repl) {
|
||||
var inputStream, multiline, nodeLineListener, outputStream, rli;
|
||||
rli = repl.rli, inputStream = repl.inputStream, outputStream = repl.outputStream;
|
||||
multiline = {
|
||||
enabled: false,
|
||||
initialPrompt: repl.prompt.replace(/^[^> ]*/, function(x) {
|
||||
return x.replace(/./g, '-');
|
||||
}),
|
||||
prompt: repl.prompt.replace(/^[^> ]*>?/, function(x) {
|
||||
return x.replace(/./g, '.');
|
||||
}),
|
||||
buffer: ''
|
||||
};
|
||||
nodeLineListener = rli.listeners('line')[0];
|
||||
rli.removeListener('line', nodeLineListener);
|
||||
rli.on('line', function(cmd) {
|
||||
if (multiline.enabled) {
|
||||
multiline.buffer += "" + cmd + "\n";
|
||||
rli.setPrompt(multiline.prompt);
|
||||
rli.prompt(true);
|
||||
} else {
|
||||
nodeLineListener(cmd);
|
||||
}
|
||||
});
|
||||
return inputStream.on('keypress', function(char, key) {
|
||||
if (!(key && key.ctrl && !key.meta && !key.shift && key.name === 'v')) {
|
||||
return;
|
||||
}
|
||||
completions = getCompletions(prefix, Object.getOwnPropertyNames(val));
|
||||
return [completions, prefix];
|
||||
}
|
||||
};
|
||||
|
||||
completeVariable = function(text) {
|
||||
var completions, free, keywords, possibilities, r, vars, _ref;
|
||||
free = (_ref = text.match(SIMPLEVAR)) != null ? _ref[1] : void 0;
|
||||
if (free != null) {
|
||||
vars = Script.runInThisContext('Object.getOwnPropertyNames(this)');
|
||||
keywords = (function() {
|
||||
var _i, _len, _ref2, _results;
|
||||
_ref2 = CoffeeScript.RESERVED;
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
r = _ref2[_i];
|
||||
if (r.slice(0, 2) !== '__') _results.push(r);
|
||||
if (multiline.enabled) {
|
||||
if (!multiline.buffer.match(/\n/)) {
|
||||
multiline.enabled = !multiline.enabled;
|
||||
rli.setPrompt(repl.prompt);
|
||||
rli.prompt(true);
|
||||
return;
|
||||
}
|
||||
return _results;
|
||||
})();
|
||||
possibilities = vars.concat(keywords);
|
||||
completions = getCompletions(free, possibilities);
|
||||
return [completions, free];
|
||||
}
|
||||
};
|
||||
|
||||
getCompletions = function(prefix, candidates) {
|
||||
var el, _i, _len, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = candidates.length; _i < _len; _i++) {
|
||||
el = candidates[_i];
|
||||
if (el.indexOf(prefix) === 0) _results.push(el);
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
|
||||
process.on('uncaughtException', error);
|
||||
|
||||
if (readline.createInterface.length < 3) {
|
||||
repl = readline.createInterface(stdin, autocomplete);
|
||||
stdin.on('data', function(buffer) {
|
||||
return repl.write(buffer);
|
||||
if ((rli.line != null) && !rli.line.match(/^\s*$/)) {
|
||||
return;
|
||||
}
|
||||
multiline.enabled = !multiline.enabled;
|
||||
rli.line = '';
|
||||
rli.cursor = 0;
|
||||
rli.output.cursorTo(0);
|
||||
rli.output.clearLine(1);
|
||||
multiline.buffer = multiline.buffer.replace(/\n/g, '\uFF00');
|
||||
rli.emit('line', multiline.buffer);
|
||||
multiline.buffer = '';
|
||||
} else {
|
||||
multiline.enabled = !multiline.enabled;
|
||||
rli.setPrompt(multiline.initialPrompt);
|
||||
rli.prompt(true);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
repl = readline.createInterface(stdin, stdout, autocomplete);
|
||||
}
|
||||
};
|
||||
|
||||
repl.on('attemptClose', function() {
|
||||
if (backlog) {
|
||||
backlog = '';
|
||||
process.stdout.write('\n');
|
||||
repl.setPrompt(REPL_PROMPT);
|
||||
return repl.prompt();
|
||||
} else {
|
||||
return repl.close();
|
||||
module.exports = {
|
||||
start: function(opts) {
|
||||
var repl;
|
||||
if (opts == null) {
|
||||
opts = {};
|
||||
}
|
||||
opts = merge(replDefaults, opts);
|
||||
repl = nodeREPL.start(opts);
|
||||
repl.on('exit', function() {
|
||||
return repl.outputStream.write('\n');
|
||||
});
|
||||
addMultilineHandler(repl);
|
||||
return repl;
|
||||
}
|
||||
});
|
||||
|
||||
repl.on('close', function() {
|
||||
process.stdout.write('\n');
|
||||
return stdin.destroy();
|
||||
});
|
||||
|
||||
repl.on('line', run);
|
||||
|
||||
repl.setPrompt(REPL_PROMPT);
|
||||
|
||||
repl.prompt();
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
(function() {
|
||||
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref;
|
||||
var __hasProp = Object.prototype.hasOwnProperty, __indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (__hasProp.call(this, i) && this[i] === item) return i; } return -1; }, __slice = Array.prototype.slice;
|
||||
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref,
|
||||
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
|
||||
__slice = [].slice;
|
||||
|
||||
exports.Rewriter = (function() {
|
||||
|
||||
@@ -16,6 +18,7 @@
|
||||
this.tagPostfixConditionals();
|
||||
this.addImplicitBraces();
|
||||
this.addImplicitParentheses();
|
||||
this.addLocationDataToGeneratedTokens();
|
||||
return this.tokens;
|
||||
};
|
||||
|
||||
@@ -30,17 +33,19 @@
|
||||
};
|
||||
|
||||
Rewriter.prototype.detectEnd = function(i, condition, action) {
|
||||
var levels, token, tokens, _ref, _ref2;
|
||||
var levels, token, tokens, _ref, _ref1;
|
||||
tokens = this.tokens;
|
||||
levels = 0;
|
||||
while (token = tokens[i]) {
|
||||
if (levels === 0 && condition.call(this, token, i)) {
|
||||
return action.call(this, token, i);
|
||||
}
|
||||
if (!token || levels < 0) return action.call(this, token, i - 1);
|
||||
if (!token || levels < 0) {
|
||||
return action.call(this, token, i - 1);
|
||||
}
|
||||
if (_ref = token[0], __indexOf.call(EXPRESSION_START, _ref) >= 0) {
|
||||
levels += 1;
|
||||
} else if (_ref2 = token[0], __indexOf.call(EXPRESSION_END, _ref2) >= 0) {
|
||||
} else if (_ref1 = token[0], __indexOf.call(EXPRESSION_END, _ref1) >= 0) {
|
||||
levels -= 1;
|
||||
}
|
||||
i += 1;
|
||||
@@ -49,13 +54,17 @@
|
||||
};
|
||||
|
||||
Rewriter.prototype.removeLeadingNewlines = function() {
|
||||
var i, tag, _len, _ref;
|
||||
var i, tag, _i, _len, _ref;
|
||||
_ref = this.tokens;
|
||||
for (i = 0, _len = _ref.length; i < _len; i++) {
|
||||
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
|
||||
tag = _ref[i][0];
|
||||
if (tag !== 'TERMINATOR') break;
|
||||
if (tag !== 'TERMINATOR') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i) {
|
||||
return this.tokens.splice(0, i);
|
||||
}
|
||||
if (i) return this.tokens.splice(0, i);
|
||||
};
|
||||
|
||||
Rewriter.prototype.removeMidExpressionNewlines = function() {
|
||||
@@ -79,7 +88,9 @@
|
||||
return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END';
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
if (token[0] === 'CALL_START') this.detectEnd(i + 1, condition, action);
|
||||
if (token[0] === 'CALL_START') {
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
@@ -94,31 +105,40 @@
|
||||
return token[0] = 'INDEX_END';
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
if (token[0] === 'INDEX_START') this.detectEnd(i + 1, condition, action);
|
||||
if (token[0] === 'INDEX_START') {
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.addImplicitBraces = function() {
|
||||
var action, condition, stack, start, startIndent;
|
||||
var action, condition, sameLine, stack, start, startIndent, startIndex, startsLine;
|
||||
stack = [];
|
||||
start = null;
|
||||
startsLine = null;
|
||||
sameLine = true;
|
||||
startIndent = 0;
|
||||
startIndex = 0;
|
||||
condition = function(token, i) {
|
||||
var one, tag, three, two, _ref, _ref2;
|
||||
_ref = this.tokens.slice(i + 1, (i + 3) + 1 || 9e9), one = _ref[0], two = _ref[1], three = _ref[2];
|
||||
if ('HERECOMMENT' === (one != null ? one[0] : void 0)) return false;
|
||||
var one, tag, three, two, _ref, _ref1;
|
||||
_ref = this.tokens.slice(i + 1, +(i + 3) + 1 || 9e9), one = _ref[0], two = _ref[1], three = _ref[2];
|
||||
if ('HERECOMMENT' === (one != null ? one[0] : void 0)) {
|
||||
return false;
|
||||
}
|
||||
tag = token[0];
|
||||
return ((tag === 'TERMINATOR' || tag === 'OUTDENT') && !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':')) || (tag === ',' && one && ((_ref2 = one[0]) !== 'IDENTIFIER' && _ref2 !== 'NUMBER' && _ref2 !== 'STRING' && _ref2 !== '@' && _ref2 !== 'TERMINATOR' && _ref2 !== 'OUTDENT'));
|
||||
if (__indexOf.call(LINEBREAKS, tag) >= 0) {
|
||||
sameLine = false;
|
||||
}
|
||||
return (((tag === 'TERMINATOR' || tag === 'OUTDENT') || (__indexOf.call(IMPLICIT_END, tag) >= 0 && sameLine && !(i - startIndex === 1))) && ((!startsLine && this.tag(i - 1) !== ',') || !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':'))) || (tag === ',' && one && ((_ref1 = one[0]) !== 'IDENTIFIER' && _ref1 !== 'NUMBER' && _ref1 !== 'STRING' && _ref1 !== '@' && _ref1 !== 'TERMINATOR' && _ref1 !== 'OUTDENT'));
|
||||
};
|
||||
action = function(token, i) {
|
||||
var tok;
|
||||
tok = ['}', '}', token[2]];
|
||||
tok.generated = true;
|
||||
tok = this.generate('}', '}');
|
||||
return this.tokens.splice(i, 0, tok);
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var ago, idx, tag, tok, value, _ref, _ref2;
|
||||
var ago, idx, prevTag, tag, tok, value, _ref, _ref1;
|
||||
if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {
|
||||
stack.push([(tag === 'INDENT' && this.tag(i - 1) === '{' ? '{' : tag), i]);
|
||||
return 1;
|
||||
@@ -127,18 +147,21 @@
|
||||
start = stack.pop();
|
||||
return 1;
|
||||
}
|
||||
if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref2 = stack[stack.length - 1]) != null ? _ref2[0] : void 0) !== '{'))) {
|
||||
if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref1 = stack[stack.length - 1]) != null ? _ref1[0] : void 0) !== '{'))) {
|
||||
return 1;
|
||||
}
|
||||
sameLine = true;
|
||||
startIndex = i + 1;
|
||||
stack.push(['{']);
|
||||
idx = ago === '@' ? i - 2 : i - 1;
|
||||
while (this.tag(idx - 2) === 'HERECOMMENT') {
|
||||
idx -= 2;
|
||||
}
|
||||
prevTag = this.tag(idx - 1);
|
||||
startsLine = !prevTag || (__indexOf.call(LINEBREAKS, prevTag) >= 0);
|
||||
value = new String('{');
|
||||
value.generated = true;
|
||||
tok = ['{', value, token[2]];
|
||||
tok.generated = true;
|
||||
tok = this.generate('{', value);
|
||||
tokens.splice(idx, 0, tok);
|
||||
this.detectEnd(i + 2, condition, action);
|
||||
return 2;
|
||||
@@ -146,49 +169,99 @@
|
||||
};
|
||||
|
||||
Rewriter.prototype.addImplicitParentheses = function() {
|
||||
var action, noCall;
|
||||
noCall = false;
|
||||
var action, callIndex, condition, noCall, seenControl, seenSingle;
|
||||
noCall = seenSingle = seenControl = false;
|
||||
callIndex = null;
|
||||
condition = function(token, i) {
|
||||
var post, tag, _ref, _ref1;
|
||||
tag = token[0];
|
||||
if (!seenSingle && token.fromThen) {
|
||||
return true;
|
||||
}
|
||||
if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>' || tag === 'CLASS') {
|
||||
seenSingle = true;
|
||||
}
|
||||
if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY' || tag === '=') {
|
||||
seenControl = true;
|
||||
}
|
||||
if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') {
|
||||
return true;
|
||||
}
|
||||
return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0 || (tag === 'INDENT' && !seenControl)) && (tag !== 'INDENT' || (((_ref = this.tag(i - 2)) !== 'CLASS' && _ref !== 'EXTENDS') && (_ref1 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref1) < 0) && !(callIndex === i - 1 && (post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens.splice(i, 0, ['CALL_END', ')', token[2]]);
|
||||
return this.tokens.splice(i, 0, this.generate('CALL_END', ')'));
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var callObject, current, next, prev, seenControl, seenSingle, tag, _ref, _ref2, _ref3;
|
||||
var callObject, current, next, prev, tag, _ref, _ref1, _ref2;
|
||||
tag = token[0];
|
||||
if (tag === 'CLASS' || tag === 'IF') noCall = true;
|
||||
_ref = tokens.slice(i - 1, (i + 1) + 1 || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2];
|
||||
callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0);
|
||||
if (tag === 'CLASS' || tag === 'IF' || tag === 'FOR' || tag === 'WHILE') {
|
||||
noCall = true;
|
||||
}
|
||||
_ref = tokens.slice(i - 1, +(i + 1) + 1 || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2];
|
||||
callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref1 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref1) >= 0);
|
||||
seenSingle = false;
|
||||
seenControl = false;
|
||||
if (__indexOf.call(LINEBREAKS, tag) >= 0) noCall = false;
|
||||
if (prev && !prev.spaced && tag === '?') token.call = true;
|
||||
if (token.fromThen) return 1;
|
||||
if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref3 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref3) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) {
|
||||
if (__indexOf.call(LINEBREAKS, tag) >= 0) {
|
||||
noCall = false;
|
||||
}
|
||||
if (prev && !prev.spaced && tag === '?') {
|
||||
token.call = true;
|
||||
}
|
||||
if (token.fromThen) {
|
||||
return 1;
|
||||
}
|
||||
tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
|
||||
this.detectEnd(i + 1, function(token, i) {
|
||||
var post, _ref4;
|
||||
tag = token[0];
|
||||
if (!seenSingle && token.fromThen) return true;
|
||||
if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>') {
|
||||
seenSingle = true;
|
||||
}
|
||||
if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY') {
|
||||
seenControl = true;
|
||||
}
|
||||
if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') {
|
||||
return true;
|
||||
}
|
||||
return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0 || (tag === 'INDENT' && !seenControl)) && (tag !== 'INDENT' || (this.tag(i - 2) !== 'CLASS' && (_ref4 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref4) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
|
||||
}, action);
|
||||
if (prev[0] === '?') prev[0] = 'FUNC_EXIST';
|
||||
if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) {
|
||||
return 1;
|
||||
}
|
||||
callIndex = i;
|
||||
tokens.splice(i, 0, this.generate('CALL_START', '(', token[2]));
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
if (prev[0] === '?') {
|
||||
prev[0] = 'FUNC_EXIST';
|
||||
}
|
||||
return 2;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.addImplicitIndentation = function() {
|
||||
Rewriter.prototype.addLocationDataToGeneratedTokens = function() {
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var action, condition, indent, outdent, starter, tag, _ref, _ref2;
|
||||
var prevToken, tag;
|
||||
tag = token[0];
|
||||
if ((token.generated || token.explicit) && (!token[2])) {
|
||||
if (i > 0) {
|
||||
prevToken = tokens[i - 1];
|
||||
token[2] = {
|
||||
first_line: prevToken[2].last_line,
|
||||
first_column: prevToken[2].last_column,
|
||||
last_line: prevToken[2].last_line,
|
||||
last_column: prevToken[2].last_column
|
||||
};
|
||||
} else {
|
||||
token[2] = {
|
||||
first_line: 0,
|
||||
first_column: 0,
|
||||
last_line: 0,
|
||||
last_column: 0
|
||||
};
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.addImplicitIndentation = function() {
|
||||
var action, condition, indent, outdent, starter;
|
||||
starter = indent = outdent = null;
|
||||
condition = function(token, i) {
|
||||
var _ref;
|
||||
return token[1] !== ';' && (_ref = token[0], __indexOf.call(SINGLE_CLOSERS, _ref) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN'));
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var tag, _ref, _ref1;
|
||||
tag = token[0];
|
||||
if (tag === 'TERMINATOR' && this.tag(i + 1) === 'THEN') {
|
||||
tokens.splice(i, 1);
|
||||
@@ -204,19 +277,15 @@
|
||||
}
|
||||
if (__indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
|
||||
starter = tag;
|
||||
_ref2 = this.indentation(token), indent = _ref2[0], outdent = _ref2[1];
|
||||
if (starter === 'THEN') indent.fromThen = true;
|
||||
indent.generated = outdent.generated = true;
|
||||
_ref1 = this.indentation(token, true), indent = _ref1[0], outdent = _ref1[1];
|
||||
if (starter === 'THEN') {
|
||||
indent.fromThen = true;
|
||||
}
|
||||
tokens.splice(i + 1, 0, indent);
|
||||
condition = function(token, i) {
|
||||
var _ref3;
|
||||
return token[1] !== ';' && (_ref3 = token[0], __indexOf.call(SINGLE_CLOSERS, _ref3) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN'));
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
|
||||
};
|
||||
this.detectEnd(i + 2, condition, action);
|
||||
if (tag === 'THEN') tokens.splice(i, 1);
|
||||
if (tag === 'THEN') {
|
||||
tokens.splice(i, 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
@@ -224,24 +293,48 @@
|
||||
};
|
||||
|
||||
Rewriter.prototype.tagPostfixConditionals = function() {
|
||||
var condition;
|
||||
var action, condition, original;
|
||||
original = null;
|
||||
condition = function(token, i) {
|
||||
var _ref;
|
||||
return (_ref = token[0]) === 'TERMINATOR' || _ref === 'INDENT';
|
||||
};
|
||||
action = function(token, i) {
|
||||
if (token[0] !== 'INDENT' || (token.generated && !token.fromThen)) {
|
||||
return original[0] = 'POST_' + original[0];
|
||||
}
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
var original;
|
||||
if (token[0] !== 'IF') return 1;
|
||||
if (token[0] !== 'IF') {
|
||||
return 1;
|
||||
}
|
||||
original = token;
|
||||
this.detectEnd(i + 1, condition, function(token, i) {
|
||||
if (token[0] !== 'INDENT') return original[0] = 'POST_' + original[0];
|
||||
});
|
||||
this.detectEnd(i + 1, condition, action);
|
||||
return 1;
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.indentation = function(token) {
|
||||
return [['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]]];
|
||||
Rewriter.prototype.indentation = function(token, implicit) {
|
||||
var indent, outdent;
|
||||
if (implicit == null) {
|
||||
implicit = false;
|
||||
}
|
||||
indent = ['INDENT', 2];
|
||||
outdent = ['OUTDENT', 2];
|
||||
if (implicit) {
|
||||
indent.generated = outdent.generated = true;
|
||||
}
|
||||
if (!implicit) {
|
||||
indent.explicit = outdent.explicit = true;
|
||||
}
|
||||
return [indent, outdent];
|
||||
};
|
||||
|
||||
Rewriter.prototype.generate = function(tag, value) {
|
||||
var tok;
|
||||
tok = [tag, value];
|
||||
tok.generated = true;
|
||||
return tok;
|
||||
};
|
||||
|
||||
Rewriter.prototype.tag = function(i) {
|
||||
@@ -271,7 +364,7 @@
|
||||
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
|
||||
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'UNARY', 'SUPER', '@', '->', '=>', '[', '(', '{', '--', '++'];
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'NULL', 'UNDEFINED', 'UNARY', 'SUPER', '@', '->', '=>', '[', '(', '{', '--', '++'];
|
||||
|
||||
IMPLICIT_UNSPACED_CALL = ['+', '-'];
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// Generated by CoffeeScript 1.5.0
|
||||
(function() {
|
||||
var Scope, extend, last, _ref;
|
||||
|
||||
@@ -18,14 +19,17 @@
|
||||
}
|
||||
];
|
||||
this.positions = {};
|
||||
if (!this.parent) Scope.root = this;
|
||||
if (!this.parent) {
|
||||
Scope.root = this;
|
||||
}
|
||||
}
|
||||
|
||||
Scope.prototype.add = function(name, type, immediate) {
|
||||
var pos;
|
||||
if (this.shared && !immediate) return this.parent.add(name, type, immediate);
|
||||
if (typeof (pos = this.positions[name]) === 'number') {
|
||||
return this.variables[pos].type = type;
|
||||
if (this.shared && !immediate) {
|
||||
return this.parent.add(name, type, immediate);
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(this.positions, name)) {
|
||||
return this.variables[this.positions[name]].type = type;
|
||||
} else {
|
||||
return this.positions[name] = this.variables.push({
|
||||
name: name,
|
||||
@@ -34,49 +38,65 @@
|
||||
}
|
||||
};
|
||||
|
||||
Scope.prototype.find = function(name, options) {
|
||||
if (this.check(name, options)) return true;
|
||||
Scope.prototype.namedMethod = function() {
|
||||
if (this.method.name || !this.parent) {
|
||||
return this.method;
|
||||
}
|
||||
return this.parent.namedMethod();
|
||||
};
|
||||
|
||||
Scope.prototype.find = function(name) {
|
||||
if (this.check(name)) {
|
||||
return true;
|
||||
}
|
||||
this.add(name, 'var');
|
||||
return false;
|
||||
};
|
||||
|
||||
Scope.prototype.parameter = function(name) {
|
||||
if (this.shared && this.parent.check(name, true)) return;
|
||||
if (this.shared && this.parent.check(name, true)) {
|
||||
return;
|
||||
}
|
||||
return this.add(name, 'param');
|
||||
};
|
||||
|
||||
Scope.prototype.check = function(name, immediate) {
|
||||
var found, _ref2;
|
||||
found = !!this.type(name);
|
||||
if (found || immediate) return found;
|
||||
return !!((_ref2 = this.parent) != null ? _ref2.check(name) : void 0);
|
||||
Scope.prototype.check = function(name) {
|
||||
var _ref1;
|
||||
return !!(this.type(name) || ((_ref1 = this.parent) != null ? _ref1.check(name) : void 0));
|
||||
};
|
||||
|
||||
Scope.prototype.temporary = function(name, index) {
|
||||
if (name.length > 1) {
|
||||
return '_' + name + (index > 1 ? index : '');
|
||||
return '_' + name + (index > 1 ? index - 1 : '');
|
||||
} else {
|
||||
return '_' + (index + parseInt(name, 36)).toString(36).replace(/\d/g, 'a');
|
||||
}
|
||||
};
|
||||
|
||||
Scope.prototype.type = function(name) {
|
||||
var v, _i, _len, _ref2;
|
||||
_ref2 = this.variables;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
v = _ref2[_i];
|
||||
if (v.name === name) return v.type;
|
||||
var v, _i, _len, _ref1;
|
||||
_ref1 = this.variables;
|
||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||
v = _ref1[_i];
|
||||
if (v.name === name) {
|
||||
return v.type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
Scope.prototype.freeVariable = function(type) {
|
||||
Scope.prototype.freeVariable = function(name, reserve) {
|
||||
var index, temp;
|
||||
if (reserve == null) {
|
||||
reserve = true;
|
||||
}
|
||||
index = 0;
|
||||
while (this.check((temp = this.temporary(type, index)))) {
|
||||
while (this.check((temp = this.temporary(name, index)))) {
|
||||
index++;
|
||||
}
|
||||
this.add(temp, 'var', true);
|
||||
if (reserve) {
|
||||
this.add(temp, 'var', true);
|
||||
}
|
||||
return temp;
|
||||
};
|
||||
|
||||
@@ -84,7 +104,7 @@
|
||||
this.add(name, {
|
||||
value: value,
|
||||
assigned: true
|
||||
});
|
||||
}, true);
|
||||
return this.hasAssignments = true;
|
||||
};
|
||||
|
||||
@@ -93,12 +113,12 @@
|
||||
};
|
||||
|
||||
Scope.prototype.declaredVariables = function() {
|
||||
var realVars, tempVars, v, _i, _len, _ref2;
|
||||
var realVars, tempVars, v, _i, _len, _ref1;
|
||||
realVars = [];
|
||||
tempVars = [];
|
||||
_ref2 = this.variables;
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
v = _ref2[_i];
|
||||
_ref1 = this.variables;
|
||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||
v = _ref1[_i];
|
||||
if (v.type === 'var') {
|
||||
(v.name.charAt(0) === '_' ? tempVars : realVars).push(v.name);
|
||||
}
|
||||
@@ -107,12 +127,14 @@
|
||||
};
|
||||
|
||||
Scope.prototype.assignedVariables = function() {
|
||||
var v, _i, _len, _ref2, _results;
|
||||
_ref2 = this.variables;
|
||||
var v, _i, _len, _ref1, _results;
|
||||
_ref1 = this.variables;
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
|
||||
v = _ref2[_i];
|
||||
if (v.type.assigned) _results.push("" + v.name + " = " + v.type.value);
|
||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||
v = _ref1[_i];
|
||||
if (v.type.assigned) {
|
||||
_results.push("" + v.name + " = " + v.type.value);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
|
||||
12
package.json
12
package.json
@@ -3,10 +3,10 @@
|
||||
"description": "Unfancy JavaScript",
|
||||
"keywords": ["javascript", "language", "coffeescript", "compiler"],
|
||||
"author": "Jeremy Ashkenas",
|
||||
"version": "1.1.3",
|
||||
"version": "1.5.0",
|
||||
"licenses": [{
|
||||
"type": "MIT",
|
||||
"url": "http://github.com/jashkenas/coffee-script/raw/master/LICENSE"
|
||||
"url": "https://raw.github.com/jashkenas/coffee-script/master/LICENSE"
|
||||
}],
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
@@ -19,13 +19,17 @@
|
||||
"coffee": "./bin/coffee",
|
||||
"cake": "./bin/cake"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node ./bin/cake test"
|
||||
},
|
||||
"homepage": "http://coffeescript.org",
|
||||
"bugs": "https://github.com/jashkenas/coffee-script/issues",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/jashkenas/coffee-script.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"uglify-js": "1.0.6",
|
||||
"jison": "0.2.11"
|
||||
"uglify-js": "~2.2",
|
||||
"jison": ">=0.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@ CoffeeScript = require './coffee-script'
|
||||
CoffeeScript.require = require
|
||||
|
||||
# Use standard JavaScript `eval` to eval code.
|
||||
CoffeeScript.eval = (code, options) ->
|
||||
CoffeeScript.eval = (code, options = {}) ->
|
||||
options.bare ?= on
|
||||
eval CoffeeScript.compile code, options
|
||||
|
||||
# Running code does not provide access to this scope.
|
||||
@@ -17,7 +18,10 @@ return unless window?
|
||||
|
||||
# Load a remote script from the current domain via XHR.
|
||||
CoffeeScript.load = (url, callback) ->
|
||||
xhr = new (window.ActiveXObject or XMLHttpRequest)('Microsoft.XMLHTTP')
|
||||
xhr = if window.ActiveXObject
|
||||
new window.ActiveXObject('Microsoft.XMLHTTP')
|
||||
else
|
||||
new XMLHttpRequest()
|
||||
xhr.open 'GET', url, true
|
||||
xhr.overrideMimeType 'text/plain' if 'overrideMimeType' of xhr
|
||||
xhr.onreadystatechange = ->
|
||||
|
||||
@@ -13,6 +13,8 @@ helpers = require './helpers'
|
||||
optparse = require './optparse'
|
||||
CoffeeScript = require './coffee-script'
|
||||
|
||||
existsSync = fs.existsSync or path.existsSync
|
||||
|
||||
# Keep track of the list of defined tasks, the accepted options, and so on.
|
||||
tasks = {}
|
||||
options = {}
|
||||
@@ -41,21 +43,26 @@ helpers.extend global,
|
||||
|
||||
# Run `cake`. 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. Keep a reference to the
|
||||
# original directory name, when running Cake tasks from subdirectories.
|
||||
# If no tasks are passed, print the help screen. Keep a reference to the
|
||||
# original directory name, when running Cake tasks from subdirectories.
|
||||
exports.run = ->
|
||||
global.__originalDirname = fs.realpathSync '.'
|
||||
process.chdir cakefileDirectory __originalDirname
|
||||
args = process.argv.slice 2
|
||||
args = process.argv[2..]
|
||||
CoffeeScript.run fs.readFileSync('Cakefile').toString(), filename: 'Cakefile'
|
||||
oparse = new optparse.OptionParser switches
|
||||
return printTasks() unless args.length
|
||||
options = oparse.parse(args)
|
||||
try
|
||||
options = oparse.parse(args)
|
||||
catch e
|
||||
return fatalError "#{e}"
|
||||
invoke arg for arg in options.arguments
|
||||
|
||||
# Display the list of Cake tasks in a format similar to `rake -T`
|
||||
printTasks = ->
|
||||
console.log ''
|
||||
relative = path.relative or path.resolve
|
||||
cakefilePath = path.join relative(__originalDirname, process.cwd()), 'Cakefile'
|
||||
console.log "#{cakefilePath} defines the following tasks:\n"
|
||||
for name, task of tasks
|
||||
spaces = 20 - name.length
|
||||
spaces = if spaces > 0 then Array(spaces + 1).join(' ') else ''
|
||||
@@ -63,15 +70,18 @@ printTasks = ->
|
||||
console.log "cake #{name}#{spaces} #{desc}"
|
||||
console.log oparse.help() if switches.length
|
||||
|
||||
# Print an error and exit when attempting to call an undefined task.
|
||||
missingTask = (task) ->
|
||||
console.log "No such task: \"#{task}\""
|
||||
# Print an error and exit when attempting to use an invalid task/option.
|
||||
fatalError = (message) ->
|
||||
console.error message + '\n'
|
||||
console.log 'To see a list of all tasks/options, run "cake"'
|
||||
process.exit 1
|
||||
|
||||
# When `cake` is invoked, search in the current and all parent directories
|
||||
missingTask = (task) -> fatalError "No such task: #{task}"
|
||||
|
||||
# When `cake` is invoked, search in the current and all parent directories
|
||||
# to find the relevant Cakefile.
|
||||
cakefileDirectory = (dir) ->
|
||||
return dir if path.existsSync path.join dir, 'Cakefile'
|
||||
return dir if existsSync path.join dir, 'Cakefile'
|
||||
parent = path.normalize path.join dir, '..'
|
||||
return cakefileDirectory parent unless parent is dir
|
||||
throw new Error "Cakefile not found in #{process.cwd()}"
|
||||
|
||||
@@ -6,25 +6,27 @@
|
||||
# If included on a webpage, it will automatically sniff out, compile, and
|
||||
# execute all scripts present in `text/coffeescript` tags.
|
||||
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
{Lexer,RESERVED} = require './lexer'
|
||||
{parser} = require './parser'
|
||||
vm = require 'vm'
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
{Lexer} = require './lexer'
|
||||
{parser} = require './parser'
|
||||
vm = require 'vm'
|
||||
|
||||
# The file extensions that are considered to be CoffeeScript.
|
||||
extensions = ['.coffee', '.litcoffee']
|
||||
|
||||
# Load and run a CoffeeScript file for Node, stripping any `BOM`s.
|
||||
loadFile = (module, filename) ->
|
||||
raw = fs.readFileSync filename, 'utf8'
|
||||
stripped = if raw.charCodeAt(0) is 0xFEFF then raw.substring 1 else raw
|
||||
module._compile compile(stripped, {filename}), filename
|
||||
|
||||
# TODO: Remove registerExtension when fully deprecated.
|
||||
if require.extensions
|
||||
require.extensions['.coffee'] = (module, filename) ->
|
||||
content = compile fs.readFileSync(filename, 'utf8'), {filename}
|
||||
module._compile content, filename
|
||||
else if require.registerExtension
|
||||
require.registerExtension '.coffee', (content) -> compile content
|
||||
for ext in extensions
|
||||
require.extensions[ext] = loadFile
|
||||
|
||||
# The current CoffeeScript version number.
|
||||
exports.VERSION = '1.1.3'
|
||||
|
||||
# Words that cannot be used as identifiers in CoffeeScript code
|
||||
exports.RESERVED = RESERVED
|
||||
exports.VERSION = '1.5.0'
|
||||
|
||||
# Expose helpers for testing.
|
||||
exports.helpers = require './helpers'
|
||||
@@ -32,11 +34,15 @@ exports.helpers = require './helpers'
|
||||
# Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
|
||||
# compiler.
|
||||
exports.compile = compile = (code, options = {}) ->
|
||||
{merge} = exports.helpers
|
||||
try
|
||||
(parser.parse lexer.tokenize code).compile options
|
||||
js = (parser.parse lexer.tokenize(code, options)).compile options
|
||||
return js unless options.header
|
||||
catch err
|
||||
err.message = "In #{options.filename}, #{err.message}" if options.filename
|
||||
throw err
|
||||
header = "Generated by CoffeeScript #{@VERSION}"
|
||||
"// #{header}\n#{js}"
|
||||
|
||||
# Tokenize a string of CoffeeScript code, and return the array of tokens.
|
||||
exports.tokens = (code, options) ->
|
||||
@@ -44,7 +50,7 @@ exports.tokens = (code, options) ->
|
||||
|
||||
# Parse a string of CoffeeScript code or an array of lexed tokens, and
|
||||
# return the AST. You can then compile it by calling `.compile()` on the root,
|
||||
# or traverse it by using `.traverse()` with a callback.
|
||||
# or traverse it by using `.traverseChildren()` with a callback.
|
||||
exports.nodes = (source, options) ->
|
||||
if typeof source is 'string'
|
||||
parser.parse lexer.tokenize source, options
|
||||
@@ -53,7 +59,7 @@ exports.nodes = (source, options) ->
|
||||
|
||||
# Compile and execute a string of CoffeeScript (on the server), correctly
|
||||
# setting `__filename`, `__dirname`, and relative `require()`.
|
||||
exports.run = (code, options) ->
|
||||
exports.run = (code, options = {}) ->
|
||||
mainModule = require.main
|
||||
|
||||
# Set the filename.
|
||||
@@ -64,10 +70,10 @@ exports.run = (code, options) ->
|
||||
mainModule.moduleCache and= {}
|
||||
|
||||
# Assign paths for node_modules loading
|
||||
mainModule.paths = require('module')._nodeModulePaths path.dirname options.filename
|
||||
mainModule.paths = require('module')._nodeModulePaths path.dirname fs.realpathSync options.filename
|
||||
|
||||
# Compile.
|
||||
if path.extname(mainModule.filename) isnt '.coffee' or require.extensions
|
||||
if (path.extname(mainModule.filename) not in extensions) or require.extensions
|
||||
mainModule._compile compile(code, options), mainModule.filename
|
||||
else
|
||||
mainModule._compile code, mainModule.filename
|
||||
@@ -116,7 +122,13 @@ lexer = new Lexer
|
||||
# directly as a "Jison lexer".
|
||||
parser.lexer =
|
||||
lex: ->
|
||||
[tag, @yytext, @yylineno] = @tokens[@pos++] or ['']
|
||||
token = @tokens[@pos++]
|
||||
if token
|
||||
[tag, @yytext, @yylloc] = token
|
||||
@yylineno = @yylloc.first_line
|
||||
else
|
||||
tag = ''
|
||||
|
||||
tag
|
||||
setInput: (@tokens) ->
|
||||
@pos = 0
|
||||
|
||||
@@ -13,18 +13,22 @@ CoffeeScript = require './coffee-script'
|
||||
{spawn, exec} = require 'child_process'
|
||||
{EventEmitter} = require 'events'
|
||||
|
||||
exists = fs.exists or path.exists
|
||||
|
||||
# Allow CoffeeScript to emit Node.js events.
|
||||
helpers.extend CoffeeScript, new EventEmitter
|
||||
|
||||
printLine = (line) -> process.stdout.write line + '\n'
|
||||
printWarn = (line) -> process.stderr.write line + '\n'
|
||||
|
||||
hidden = (file) -> /^\.|~$/.test file
|
||||
|
||||
# The help banner that is printed when `coffee` is called without arguments.
|
||||
BANNER = '''
|
||||
Usage: coffee [options] path/to/script.coffee
|
||||
Usage: coffee [options] path/to/script.coffee -- [args]
|
||||
|
||||
If called without options, `coffee` will run your script.
|
||||
'''
|
||||
'''
|
||||
|
||||
# The list of all the valid option flags that `coffee` knows how to handle.
|
||||
SWITCHES = [
|
||||
@@ -39,7 +43,6 @@ SWITCHES = [
|
||||
[ '--nodejs [ARGS]', 'pass options directly to the "node" binary']
|
||||
['-o', '--output [DIR]', 'set the output directory for compiled JavaScript']
|
||||
['-p', '--print', 'print out the compiled JavaScript']
|
||||
['-r', '--require [FILE*]', 'require a library before executing your script']
|
||||
['-s', '--stdio', 'listen for and compile scripts over stdio']
|
||||
['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce']
|
||||
['-v', '--version', 'display the version number']
|
||||
@@ -49,8 +52,11 @@ SWITCHES = [
|
||||
# Top-level objects shared by all the functions.
|
||||
opts = {}
|
||||
sources = []
|
||||
contents = []
|
||||
sourceCode = []
|
||||
notSources = {}
|
||||
watchers = {}
|
||||
optionParser = null
|
||||
coffee_exts = ['.coffee', '.litcoffee']
|
||||
|
||||
# Run `coffee` by parsing passed options and determining what action to take.
|
||||
# Many flags cause us to divert before compiling anything. Flags passed after
|
||||
@@ -60,65 +66,53 @@ exports.run = ->
|
||||
return forkNode() if opts.nodejs
|
||||
return usage() if opts.help
|
||||
return version() if opts.version
|
||||
loadRequires() if opts.require
|
||||
return require './repl' if opts.interactive
|
||||
return require('./repl').start() if opts.interactive
|
||||
if opts.watch and !fs.watch
|
||||
return printWarn "The --watch feature depends on Node v0.6.0+. You are running #{process.version}."
|
||||
return compileStdio() if opts.stdio
|
||||
return compileScript null, sources[0] if opts.eval
|
||||
return require './repl' unless sources.length
|
||||
if opts.run
|
||||
opts.literals = sources.splice(1).concat opts.literals
|
||||
process.argv = process.argv.slice(0, 2).concat opts.literals
|
||||
return require('./repl').start() unless sources.length
|
||||
literals = if opts.run then sources.splice 1 else []
|
||||
process.argv = process.argv[0..1].concat literals
|
||||
process.argv[0] = 'coffee'
|
||||
process.execPath = require.main.filename
|
||||
compileScripts()
|
||||
for source in sources
|
||||
compilePath source, yes, path.normalize source
|
||||
|
||||
# Compile a path, which could be a script or a directory. If a directory
|
||||
# is passed, recursively compile all '.coffee' and '.litcoffee' extension source
|
||||
# files in it and all subdirectories.
|
||||
compilePath = (source, topLevel, base) ->
|
||||
fs.stat source, (err, stats) ->
|
||||
throw err if err and err.code isnt 'ENOENT'
|
||||
if err?.code is 'ENOENT'
|
||||
if topLevel and source and path.extname(source) not in coffee_exts
|
||||
source = sources[sources.indexOf(source)] = "#{source}.coffee"
|
||||
return compilePath source, topLevel, base
|
||||
if topLevel
|
||||
console.error "File not found: #{source}"
|
||||
process.exit 1
|
||||
return
|
||||
if stats.isDirectory() and path.dirname(source) isnt 'node_modules'
|
||||
watchDir source, base if opts.watch
|
||||
fs.readdir source, (err, files) ->
|
||||
throw err if err and err.code isnt 'ENOENT'
|
||||
return if err?.code is 'ENOENT'
|
||||
index = sources.indexOf source
|
||||
files = files.filter (file) -> not hidden file
|
||||
sources[index..index] = (path.join source, file for file in files)
|
||||
sourceCode[index..index] = files.map -> null
|
||||
files.forEach (file) ->
|
||||
compilePath (path.join source, file), no, base
|
||||
else if topLevel or path.extname(source) in coffee_exts
|
||||
watch source, base if opts.watch
|
||||
fs.readFile source, (err, code) ->
|
||||
throw err if err and err.code isnt 'ENOENT'
|
||||
return if err?.code is 'ENOENT'
|
||||
compileScript(source, code.toString(), base)
|
||||
else
|
||||
notSources[source] = yes
|
||||
removeSource source, base
|
||||
|
||||
# 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.
|
||||
compileScripts = ->
|
||||
unprocessed = []
|
||||
remaining_files = ->
|
||||
total = 0
|
||||
total += x for x in unprocessed
|
||||
total
|
||||
trackUnprocessedFiles = (sourceIndex, fileCount) ->
|
||||
unprocessed[sourceIndex] ?= 0
|
||||
unprocessed[sourceIndex] += fileCount
|
||||
trackCompleteFiles = (sourceIndex, fileCount) ->
|
||||
unprocessed[sourceIndex] -= fileCount
|
||||
if opts.join
|
||||
if helpers.compact(contents).length > 0 and remaining_files() == 0
|
||||
compileJoin()
|
||||
for source in sources
|
||||
trackUnprocessedFiles sources.indexOf(source), 1
|
||||
for source in sources
|
||||
base = path.join(source)
|
||||
compile = (source, sourceIndex, topLevel) ->
|
||||
path.exists source, (exists) ->
|
||||
if topLevel and not exists and source[-7..] isnt '.coffee'
|
||||
return compile "#{source}.coffee", sourceIndex, topLevel
|
||||
throw new Error "File not found: #{source}" if topLevel and not exists
|
||||
fs.stat source, (err, stats) ->
|
||||
throw err if err
|
||||
if stats.isDirectory()
|
||||
fs.readdir source, (err, files) ->
|
||||
throw err if err
|
||||
trackUnprocessedFiles sourceIndex, files.length
|
||||
for file in files
|
||||
compile path.join(source, file), sourceIndex
|
||||
trackCompleteFiles sourceIndex, 1
|
||||
else if topLevel or path.extname(source) is '.coffee'
|
||||
fs.readFile source, (err, code) ->
|
||||
throw err if err
|
||||
if opts.join
|
||||
contents[sourceIndex] = helpers.compact([contents[sourceIndex], code.toString()]).join('\n')
|
||||
else
|
||||
compileScript(source, code.toString(), base)
|
||||
trackCompleteFiles sourceIndex, 1
|
||||
watch source, base if opts.watch and not opts.join
|
||||
else
|
||||
trackCompleteFiles sourceIndex, 1
|
||||
compile source, sources.indexOf(source), true
|
||||
|
||||
# Compile a single source script, containing the given code, according to the
|
||||
# requested options. If evaluating the script directly sets `__filename`,
|
||||
@@ -129,9 +123,12 @@ compileScript = (file, input, base) ->
|
||||
try
|
||||
t = task = {file, input, options}
|
||||
CoffeeScript.emit 'compile', task
|
||||
if o.tokens then printTokens CoffeeScript.tokens t.input
|
||||
else if o.nodes then printLine CoffeeScript.nodes(t.input).toString().trim()
|
||||
if o.tokens then printTokens CoffeeScript.tokens t.input, t.options
|
||||
else if o.nodes then printLine CoffeeScript.nodes(t.input, t.options).toString().trim()
|
||||
else if o.run then CoffeeScript.run t.input, t.options
|
||||
else if o.join and t.file isnt o.join
|
||||
sourceCode[sources.indexOf(t.file)] = t.input
|
||||
compileJoin()
|
||||
else
|
||||
t.output = CoffeeScript.compile t.input, t.options
|
||||
CoffeeScript.emit 'success', task
|
||||
@@ -141,7 +138,7 @@ compileScript = (file, input, base) ->
|
||||
catch err
|
||||
CoffeeScript.emit 'failure', err, task
|
||||
return if CoffeeScript.listeners('failure').length
|
||||
return printLine err.message if o.watch
|
||||
return printLine err.message + '\x07' if o.watch
|
||||
printWarn err instanceof Error and err.stack or "ERROR: #{err}"
|
||||
process.exit 1
|
||||
|
||||
@@ -155,54 +152,130 @@ compileStdio = ->
|
||||
stdin.on 'end', ->
|
||||
compileScript null, code
|
||||
|
||||
# After all of the source files are done being read, concatenate and compile
|
||||
# If all of the source files are done being read, concatenate and compile
|
||||
# them together.
|
||||
joinTimeout = null
|
||||
compileJoin = ->
|
||||
code = contents.join '\n'
|
||||
compileScript opts.join, code, opts.join
|
||||
|
||||
# Load files that are to-be-required before compilation occurs.
|
||||
loadRequires = ->
|
||||
realFilename = module.filename
|
||||
module.filename = '.'
|
||||
require req for req in opts.require
|
||||
module.filename = realFilename
|
||||
return unless opts.join
|
||||
unless sourceCode.some((code) -> code is null)
|
||||
clearTimeout joinTimeout
|
||||
joinTimeout = wait 100, ->
|
||||
compileScript opts.join, sourceCode.join('\n'), opts.join
|
||||
|
||||
# Watch a source CoffeeScript file using `fs.watch`, recompiling it every
|
||||
# time the file is updated. May be used in combination with other options,
|
||||
# such as `--lint` or `--print`.
|
||||
watch = (source, base) ->
|
||||
fs.stat source, (err, prevStats)->
|
||||
throw err if err
|
||||
fs.watch source, (event) ->
|
||||
if event is 'change'
|
||||
fs.stat source, (err, stats) ->
|
||||
throw err if err
|
||||
return if stats.size is prevStats.size and
|
||||
stats.mtime.getTime() is prevStats.mtime.getTime()
|
||||
prevStats = stats
|
||||
fs.readFile source, (err, code) ->
|
||||
throw err if err
|
||||
compileScript(source, code.toString(), base)
|
||||
|
||||
prevStats = null
|
||||
compileTimeout = null
|
||||
|
||||
watchErr = (e) ->
|
||||
if e.code is 'ENOENT'
|
||||
return if sources.indexOf(source) is -1
|
||||
try
|
||||
rewatch()
|
||||
compile()
|
||||
catch e
|
||||
removeSource source, base, yes
|
||||
compileJoin()
|
||||
else throw e
|
||||
|
||||
compile = ->
|
||||
clearTimeout compileTimeout
|
||||
compileTimeout = wait 25, ->
|
||||
fs.stat source, (err, stats) ->
|
||||
return watchErr err if err
|
||||
return rewatch() if prevStats and stats.size is prevStats.size and
|
||||
stats.mtime.getTime() is prevStats.mtime.getTime()
|
||||
prevStats = stats
|
||||
fs.readFile source, (err, code) ->
|
||||
return watchErr err if err
|
||||
compileScript(source, code.toString(), base)
|
||||
rewatch()
|
||||
|
||||
try
|
||||
watcher = fs.watch source, compile
|
||||
catch e
|
||||
watchErr e
|
||||
|
||||
rewatch = ->
|
||||
watcher?.close()
|
||||
watcher = fs.watch source, compile
|
||||
|
||||
|
||||
# Watch a directory of files for new additions.
|
||||
watchDir = (source, base) ->
|
||||
readdirTimeout = null
|
||||
try
|
||||
watcher = fs.watch source, ->
|
||||
clearTimeout readdirTimeout
|
||||
readdirTimeout = wait 25, ->
|
||||
fs.readdir source, (err, files) ->
|
||||
if err
|
||||
throw err unless err.code is 'ENOENT'
|
||||
watcher.close()
|
||||
return unwatchDir source, base
|
||||
for file in files when not hidden(file) and not notSources[file]
|
||||
file = path.join source, file
|
||||
continue if sources.some (s) -> s.indexOf(file) >= 0
|
||||
sources.push file
|
||||
sourceCode.push null
|
||||
compilePath file, no, base
|
||||
catch e
|
||||
throw e unless e.code is 'ENOENT'
|
||||
|
||||
unwatchDir = (source, base) ->
|
||||
prevSources = sources[..]
|
||||
toRemove = (file for file in sources when file.indexOf(source) >= 0)
|
||||
removeSource file, base, yes for file in toRemove
|
||||
return unless sources.some (s, i) -> prevSources[i] isnt s
|
||||
compileJoin()
|
||||
|
||||
# Remove a file from our source list, and source code cache. Optionally remove
|
||||
# the compiled JS version as well.
|
||||
removeSource = (source, base, removeJs) ->
|
||||
index = sources.indexOf source
|
||||
sources.splice index, 1
|
||||
sourceCode.splice index, 1
|
||||
if removeJs and not opts.join
|
||||
jsPath = outputPath source, base
|
||||
exists jsPath, (itExists) ->
|
||||
if itExists
|
||||
fs.unlink jsPath, (err) ->
|
||||
throw err if err and err.code isnt 'ENOENT'
|
||||
timeLog "removed #{source}"
|
||||
|
||||
# Get the corresponding output JavaScript path for a source file.
|
||||
outputPath = (source, base) ->
|
||||
filename = path.basename(source, path.extname(source)) + '.js'
|
||||
srcDir = path.dirname source
|
||||
baseDir = if base is '.' then srcDir else srcDir.substring base.length
|
||||
dir = if opts.output then path.join opts.output, baseDir else srcDir
|
||||
path.join dir, filename
|
||||
|
||||
# Write out a JavaScript source file with the compiled code. By default, files
|
||||
# are written out in `cwd` as `.js` files with the same name, but the output
|
||||
# directory can be customized with `--output`.
|
||||
writeJs = (source, js, base) ->
|
||||
filename = path.basename(source, path.extname(source)) + '.js'
|
||||
srcDir = path.dirname source
|
||||
baseDir = if base is '.' then srcDir else srcDir.substring base.length
|
||||
dir = if opts.output then path.join opts.output, baseDir else srcDir
|
||||
jsPath = path.join dir, filename
|
||||
compile = ->
|
||||
jsPath = outputPath source, base
|
||||
jsDir = path.dirname jsPath
|
||||
compile = ->
|
||||
js = ' ' if js.length <= 0
|
||||
fs.writeFile jsPath, js, (err) ->
|
||||
if err
|
||||
printLine err.message
|
||||
else if opts.compile and opts.watch
|
||||
console.log "#{(new Date).toLocaleTimeString()} - compiled #{source}"
|
||||
path.exists dir, (exists) ->
|
||||
if exists then compile() else exec "mkdir -p #{dir}", compile
|
||||
timeLog "compiled #{source}"
|
||||
exists jsDir, (itExists) ->
|
||||
if itExists then compile() else exec "mkdir -p #{jsDir}", compile
|
||||
|
||||
# Convenience for cleaner setTimeouts.
|
||||
wait = (milliseconds, func) -> setTimeout func, milliseconds
|
||||
|
||||
# When watching scripts, it's useful to log changes with the timestamp.
|
||||
timeLog = (message) ->
|
||||
console.log "#{(new Date).toLocaleTimeString()} - #{message}"
|
||||
|
||||
# Pipe compiled JS through JSLint (requires a working `jsl` command), printing
|
||||
# any errors or warnings that arise.
|
||||
@@ -218,22 +291,28 @@ lint = (file, js) ->
|
||||
# Pretty-print a stream of tokens.
|
||||
printTokens = (tokens) ->
|
||||
strings = for token in tokens
|
||||
[tag, value] = [token[0], token[1].toString().replace(/\n/, '\\n')]
|
||||
"[#{tag} #{value}]"
|
||||
tag = token[0]
|
||||
value = token[1].toString().replace(/\n/, '\\n')
|
||||
locationData = helpers.locationDataToString token[2]
|
||||
"[#{tag} #{value} #{locationData}]"
|
||||
printLine strings.join(' ')
|
||||
|
||||
# Use the [OptionParser module](optparse.html) to extract all options from
|
||||
# `process.argv` that are specified in `SWITCHES`.
|
||||
parseOptions = ->
|
||||
optionParser = new optparse.OptionParser SWITCHES, BANNER
|
||||
o = opts = optionParser.parse process.argv.slice 2
|
||||
o = opts = optionParser.parse process.argv[2..]
|
||||
o.compile or= !!o.output
|
||||
o.run = not (o.compile or o.print or o.lint)
|
||||
o.print = !! (o.print or (o.eval or o.stdio and o.compile))
|
||||
sources = o.arguments
|
||||
sourceCode[i] = null for source, i in sources
|
||||
return
|
||||
|
||||
# The compile-time options to pass to the CoffeeScript compiler.
|
||||
compileOptions = (filename) -> {filename, bare: opts.bare}
|
||||
compileOptions = (filename) ->
|
||||
literate = path.extname(filename) is '.litcoffee'
|
||||
{filename, literate, bare: opts.bare, header: opts.compile}
|
||||
|
||||
# Start up a new Node.js instance with the arguments in `--nodejs` passed to
|
||||
# the `node` binary, preserving the other options.
|
||||
|
||||
@@ -32,11 +32,28 @@ unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/
|
||||
# previous nonterminal.
|
||||
o = (patternString, action, options) ->
|
||||
patternString = patternString.replace /\s{2,}/g, ' '
|
||||
patternCount = patternString.split(' ').length
|
||||
return [patternString, '$$ = $1;', options] unless action
|
||||
action = if match = unwrap.exec action then match[1] else "(#{action}())"
|
||||
|
||||
# All runtime functions we need are defined on "yy"
|
||||
action = action.replace /\bnew /g, '$&yy.'
|
||||
action = action.replace /\b(?:Block\.wrap|extend)\b/g, 'yy.$&'
|
||||
[patternString, "$$ = #{action};", options]
|
||||
action = action.replace /\b(Op|Value\.(create|wrap))\b/g, 'yy.$&'
|
||||
|
||||
# Returns a function which adds location data to the first parameter passed
|
||||
# in, and returns the parameter. If the parameter is not a node, it will
|
||||
# just be passed through unaffected.
|
||||
addLocationDataFn = (first, last) ->
|
||||
if not last
|
||||
"yy.addLocationDataFn(@#{first})"
|
||||
else
|
||||
"yy.addLocationDataFn(@#{first}, @#{last})"
|
||||
|
||||
action = action.replace /LOC\(([0-9]*)\)/g, addLocationDataFn('$1')
|
||||
action = action.replace /LOC\(([0-9]*),\s*([0-9]*)\)/g, addLocationDataFn('$1', '$2')
|
||||
|
||||
[patternString, "$$ = #{addLocationDataFn(1, patternCount)}(#{action});", options]
|
||||
|
||||
# Grammatical Rules
|
||||
# -----------------
|
||||
@@ -77,7 +94,6 @@ grammar =
|
||||
# Pure statements which cannot be expressions.
|
||||
Statement: [
|
||||
o 'Return'
|
||||
o 'Throw'
|
||||
o 'Comment'
|
||||
o 'STATEMENT', -> new Literal $1
|
||||
]
|
||||
@@ -98,6 +114,7 @@ grammar =
|
||||
o 'For'
|
||||
o 'Switch'
|
||||
o 'Class'
|
||||
o 'Throw'
|
||||
]
|
||||
|
||||
# An indented block of expressions. Note that the [Rewriter](rewriter.html)
|
||||
@@ -126,25 +143,26 @@ grammar =
|
||||
o 'AlphaNumeric'
|
||||
o 'JS', -> new Literal $1
|
||||
o 'REGEX', -> new Literal $1
|
||||
o 'BOOL', ->
|
||||
val = new Literal $1
|
||||
val.isUndefined = yes if $1 is 'undefined'
|
||||
val
|
||||
o 'DEBUGGER', -> new Literal $1
|
||||
o 'UNDEFINED', -> new Undefined
|
||||
o 'NULL', -> new Null
|
||||
o 'BOOL', -> new Bool $1
|
||||
]
|
||||
|
||||
# Assignment of a variable, property, or index to a value.
|
||||
Assign: [
|
||||
o 'Assignable = Expression', -> new Assign $1, $3
|
||||
o 'Assignable = TERMINATOR Expression', -> new Assign $1, $4
|
||||
o 'Assignable = INDENT Expression OUTDENT', -> new Assign $1, $4
|
||||
]
|
||||
|
||||
# Assignment when it happens within an object literal. The difference from
|
||||
# the ordinary **Assign** is that these allow numbers and strings as keys.
|
||||
AssignObj: [
|
||||
o 'ObjAssignable', -> new Value $1
|
||||
o 'ObjAssignable : Expression', -> new Assign new Value($1), $3, 'object'
|
||||
o 'ObjAssignable', -> Value.wrap $1
|
||||
o 'ObjAssignable : Expression', -> new Assign LOC(1)(Value.wrap($1)), $3, 'object'
|
||||
o 'ObjAssignable :
|
||||
INDENT Expression OUTDENT', -> new Assign new Value($1), $4, 'object'
|
||||
INDENT Expression OUTDENT', -> new Assign LOC(1)(Value.wrap($1)), $4, 'object'
|
||||
o 'Comment'
|
||||
]
|
||||
|
||||
@@ -191,6 +209,8 @@ grammar =
|
||||
o '', -> []
|
||||
o 'Param', -> [$1]
|
||||
o 'ParamList , Param', -> $1.concat $3
|
||||
o 'ParamList OptComma TERMINATOR Param', -> $1.concat $4
|
||||
o 'ParamList OptComma INDENT ParamList OptComma OUTDENT', -> $1.concat $4
|
||||
]
|
||||
|
||||
# A single parameter in a function definition can be ordinary, or a splat
|
||||
@@ -216,26 +236,26 @@ grammar =
|
||||
|
||||
# Variables and properties that can be assigned to.
|
||||
SimpleAssignable: [
|
||||
o 'Identifier', -> new Value $1
|
||||
o 'Identifier', -> Value.wrap $1
|
||||
o 'Value Accessor', -> $1.add $2
|
||||
o 'Invocation Accessor', -> new Value $1, [$2]
|
||||
o 'Invocation Accessor', -> Value.wrap $1, [].concat $2
|
||||
o 'ThisProperty'
|
||||
]
|
||||
|
||||
# Everything that can be assigned to.
|
||||
Assignable: [
|
||||
o 'SimpleAssignable'
|
||||
o 'Array', -> new Value $1
|
||||
o 'Object', -> new Value $1
|
||||
o 'Array', -> Value.wrap $1
|
||||
o 'Object', -> Value.wrap $1
|
||||
]
|
||||
|
||||
# The types of things that can be treated as values -- assigned to, invoked
|
||||
# as functions, indexed into, named as a class, etc.
|
||||
Value: [
|
||||
o 'Assignable'
|
||||
o 'Literal', -> new Value $1
|
||||
o 'Parenthetical', -> new Value $1
|
||||
o 'Range', -> new Value $1
|
||||
o 'Literal', -> Value.wrap $1
|
||||
o 'Parenthetical', -> Value.wrap $1
|
||||
o 'Range', -> Value.wrap $1
|
||||
o 'This'
|
||||
]
|
||||
|
||||
@@ -244,7 +264,7 @@ grammar =
|
||||
Accessor: [
|
||||
o '. Identifier', -> new Access $2
|
||||
o '?. Identifier', -> new Access $2, 'soak'
|
||||
o ':: Identifier', -> [(new Access new Literal 'prototype'), new Access $2]
|
||||
o ':: Identifier', -> [LOC(1)(new Access new Literal 'prototype'), LOC(2)(new Access $2)]
|
||||
o '::', -> new Access new Literal 'prototype'
|
||||
o 'Index'
|
||||
]
|
||||
@@ -310,13 +330,13 @@ grammar =
|
||||
|
||||
# A reference to the *this* current object.
|
||||
This: [
|
||||
o 'THIS', -> new Value new Literal 'this'
|
||||
o '@', -> new Value new Literal 'this'
|
||||
o 'THIS', -> Value.wrap new Literal 'this'
|
||||
o '@', -> Value.wrap new Literal 'this'
|
||||
]
|
||||
|
||||
# A reference to a property on *this*.
|
||||
ThisProperty: [
|
||||
o '@ Identifier', -> new Value new Literal('this'), [new Access($2)], 'this'
|
||||
o '@ Identifier', -> Value.wrap LOC(1)(new Literal('this')), [LOC(2)(new Access($2))], 'this'
|
||||
]
|
||||
|
||||
# The array literal.
|
||||
@@ -341,6 +361,7 @@ grammar =
|
||||
o 'Expression RangeDots Expression', -> new Range $1, $3, $2
|
||||
o 'Expression RangeDots', -> new Range $1, null, $2
|
||||
o 'RangeDots Expression', -> new Range null, $2, $1
|
||||
o 'RangeDots', -> new Range null, null, $1
|
||||
]
|
||||
|
||||
# The **ArgList** is both the list of objects passed into a function call,
|
||||
@@ -379,6 +400,7 @@ grammar =
|
||||
# A catch clause names its error and runs a block of code.
|
||||
Catch: [
|
||||
o 'CATCH Identifier Block', -> [$2, $3]
|
||||
o 'CATCH Object Block', -> [LOC(2)(Value.wrap($2)), $3]
|
||||
]
|
||||
|
||||
# Throw an exception object.
|
||||
@@ -407,14 +429,14 @@ grammar =
|
||||
# or postfix, with a single expression. There is no do..while.
|
||||
While: [
|
||||
o 'WhileSource Block', -> $1.addBody $2
|
||||
o 'Statement WhileSource', -> $2.addBody Block.wrap [$1]
|
||||
o 'Expression WhileSource', -> $2.addBody Block.wrap [$1]
|
||||
o 'Statement WhileSource', -> $2.addBody LOC(1) Block.wrap([$1])
|
||||
o 'Expression WhileSource', -> $2.addBody LOC(1) Block.wrap([$1])
|
||||
o 'Loop', -> $1
|
||||
]
|
||||
|
||||
Loop: [
|
||||
o 'LOOP Block', -> new While(new Literal 'true').addBody $2
|
||||
o 'LOOP Expression', -> new While(new Literal 'true').addBody Block.wrap [$2]
|
||||
o 'LOOP Block', -> new While(LOC(1) new Literal 'true').addBody $2
|
||||
o 'LOOP Expression', -> new While(LOC(1) new Literal 'true').addBody LOC(2) Block.wrap [$2]
|
||||
]
|
||||
|
||||
# Array, object, and range comprehensions, at the most generic level.
|
||||
@@ -427,7 +449,7 @@ grammar =
|
||||
]
|
||||
|
||||
ForBody: [
|
||||
o 'FOR Range', -> source: new Value($2)
|
||||
o 'FOR Range', -> source: LOC(2) Value.wrap($2)
|
||||
o 'ForStart ForSource', -> $2.own = $1.own; $2.name = $1[0]; $2.index = $1[1]; $2
|
||||
]
|
||||
|
||||
@@ -440,8 +462,9 @@ grammar =
|
||||
# This enables support for pattern matching.
|
||||
ForValue: [
|
||||
o 'Identifier'
|
||||
o 'Array', -> new Value $1
|
||||
o 'Object', -> new Value $1
|
||||
o 'ThisProperty'
|
||||
o 'Array', -> Value.wrap $1
|
||||
o 'Object', -> Value.wrap $1
|
||||
]
|
||||
|
||||
# An array or range comprehension has variables for the current element
|
||||
@@ -496,8 +519,8 @@ grammar =
|
||||
If: [
|
||||
o 'IfBlock'
|
||||
o 'IfBlock ELSE Block', -> $1.addElse $3
|
||||
o 'Statement POST_IF Expression', -> new If $3, Block.wrap([$1]), type: $2, statement: true
|
||||
o 'Expression POST_IF Expression', -> new If $3, Block.wrap([$1]), type: $2, statement: true
|
||||
o 'Statement POST_IF Expression', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, statement: true
|
||||
o 'Expression POST_IF Expression', -> new If $3, LOC(1)(Block.wrap [$1]), type: $2, statement: true
|
||||
]
|
||||
|
||||
# Arithmetic and logical operators, working on one or more operands.
|
||||
@@ -507,35 +530,37 @@ grammar =
|
||||
# -type rule, but in order to make the precedence binding possible, separate
|
||||
# rules are necessary.
|
||||
Operation: [
|
||||
o 'UNARY Expression', -> new Op $1 , $2
|
||||
o '- Expression', (-> new Op '-', $2), prec: 'UNARY'
|
||||
o '+ Expression', (-> new Op '+', $2), prec: 'UNARY'
|
||||
o 'UNARY Expression', -> Op.create $1 , $2
|
||||
o '- Expression', (-> Op.create '-', $2), prec: 'UNARY'
|
||||
o '+ Expression', (-> Op.create '+', $2), prec: 'UNARY'
|
||||
|
||||
o '-- SimpleAssignable', -> new Op '--', $2
|
||||
o '++ SimpleAssignable', -> new Op '++', $2
|
||||
o 'SimpleAssignable --', -> new Op '--', $1, null, true
|
||||
o 'SimpleAssignable ++', -> new Op '++', $1, null, true
|
||||
o '-- SimpleAssignable', -> Op.create '--', $2
|
||||
o '++ SimpleAssignable', -> Op.create '++', $2
|
||||
o 'SimpleAssignable --', -> Op.create '--', $1, null, true
|
||||
o 'SimpleAssignable ++', -> Op.create '++', $1, null, true
|
||||
|
||||
# [The existential operator](http://jashkenas.github.com/coffee-script/#existence).
|
||||
o 'Expression ?', -> new Existence $1
|
||||
|
||||
o 'Expression + Expression', -> new Op '+' , $1, $3
|
||||
o 'Expression - Expression', -> new Op '-' , $1, $3
|
||||
o 'Expression + Expression', -> Op.create '+' , $1, $3
|
||||
o 'Expression - Expression', -> Op.create '-' , $1, $3
|
||||
|
||||
o 'Expression MATH Expression', -> new Op $2, $1, $3
|
||||
o 'Expression SHIFT Expression', -> new Op $2, $1, $3
|
||||
o 'Expression COMPARE Expression', -> new Op $2, $1, $3
|
||||
o 'Expression LOGIC Expression', -> new Op $2, $1, $3
|
||||
o 'Expression MATH Expression', -> Op.create $2, $1, $3
|
||||
o 'Expression SHIFT Expression', -> Op.create $2, $1, $3
|
||||
o 'Expression COMPARE Expression', -> Op.create $2, $1, $3
|
||||
o 'Expression LOGIC Expression', -> Op.create $2, $1, $3
|
||||
o 'Expression RELATION Expression', ->
|
||||
if $2.charAt(0) is '!'
|
||||
new Op($2.slice(1), $1, $3).invert()
|
||||
Op.create($2[1..], $1, $3).invert()
|
||||
else
|
||||
new Op $2, $1, $3
|
||||
Op.create $2, $1, $3
|
||||
|
||||
o 'SimpleAssignable COMPOUND_ASSIGN
|
||||
Expression', -> new Assign $1, $3, $2
|
||||
o 'SimpleAssignable COMPOUND_ASSIGN
|
||||
INDENT Expression OUTDENT', -> new Assign $1, $4, $2
|
||||
o 'SimpleAssignable COMPOUND_ASSIGN TERMINATOR
|
||||
Expression', -> new Assign $1, $4, $2
|
||||
o 'SimpleAssignable EXTENDS Expression', -> new Extends $1, $3
|
||||
]
|
||||
|
||||
@@ -566,7 +591,7 @@ operators = [
|
||||
['nonassoc', 'INDENT', 'OUTDENT']
|
||||
['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS']
|
||||
['right', 'FORIN', 'FOROF', 'BY', 'WHEN']
|
||||
['right', 'IF', 'ELSE', 'FOR', 'DO', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS']
|
||||
['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS']
|
||||
['right', 'POST_IF']
|
||||
]
|
||||
|
||||
|
||||
@@ -54,3 +54,42 @@ exports.del = (obj, key) ->
|
||||
|
||||
# Gets the last item of an array(-like) object.
|
||||
exports.last = (array, back) -> array[array.length - (back or 0) - 1]
|
||||
|
||||
# Typical Array::some
|
||||
exports.some = Array::some ? (fn) ->
|
||||
return true for e in this when fn e
|
||||
false
|
||||
|
||||
# Merge two jison-style location data objects together.
|
||||
# If `last` is not provided, this will simply return `first`.
|
||||
buildLocationData = (first, last) ->
|
||||
if not last
|
||||
first
|
||||
else
|
||||
first_line: first.first_line
|
||||
first_column: first.first_column
|
||||
last_line: last.last_line
|
||||
last_column: last.last_column
|
||||
|
||||
# This returns a function which takes an object as a parameter, and if that object is an AST node,
|
||||
# updates that object's locationData. The object is returned either way.
|
||||
exports.addLocationDataFn = (first, last) ->
|
||||
(obj) ->
|
||||
if ((typeof obj) is 'object') and (!!obj['updateLocationDataIfMissing'])
|
||||
obj.updateLocationDataIfMissing buildLocationData(first, last)
|
||||
|
||||
return obj
|
||||
|
||||
# Convert jison location data to a string.
|
||||
# `obj` can be a token, or a locationData.
|
||||
exports.locationDataToString = (obj) ->
|
||||
if ("2" of obj) and ("first_line" of obj[2]) then locationData = obj[2]
|
||||
else if "first_line" of obj then locationData = obj
|
||||
|
||||
if locationData
|
||||
"#{locationData.first_line + 1}:#{locationData.first_column + 1}-" +
|
||||
"#{locationData.last_line + 1}:#{locationData.last_column + 1}"
|
||||
else
|
||||
"No location data"
|
||||
|
||||
|
||||
|
||||
394
src/lexer.coffee
394
src/lexer.coffee
@@ -3,14 +3,16 @@
|
||||
# a token is produced, we consume the match, and start again. Tokens are in the
|
||||
# form:
|
||||
#
|
||||
# [tag, value, lineNumber]
|
||||
# [tag, value, locationData]
|
||||
#
|
||||
# Which is a format that can be fed directly into [Jison](http://github.com/zaach/jison).
|
||||
# where locationData is {first_line, first_column, last_line, last_column}, which is a
|
||||
# format that can be fed directly into [Jison](http://github.com/zaach/jison). These
|
||||
# are read by jison in the `parser.lexer` function defined in coffee-script.coffee.
|
||||
|
||||
{Rewriter, INVERSES} = require './rewriter'
|
||||
|
||||
# Import the helpers we need.
|
||||
{count, starts, compact, last} = require './helpers'
|
||||
{count, starts, compact, last, locationDataToString} = require './helpers'
|
||||
|
||||
# The Lexer Class
|
||||
# ---------------
|
||||
@@ -32,24 +34,27 @@ exports.Lexer = class Lexer
|
||||
# Before returning the token stream, run it through the [Rewriter](rewriter.html)
|
||||
# unless explicitly asked not to.
|
||||
tokenize: (code, opts = {}) ->
|
||||
code = "\n#{code}" if WHITESPACE.test code
|
||||
code = code.replace(/\r/g, '').replace TRAILING_SPACES, ''
|
||||
@literate = opts.literate # Are we lexing literate CoffeeScript?
|
||||
code = @clean code # The stripped, cleaned original source code.
|
||||
@indent = 0 # The current indentation level.
|
||||
@indebt = 0 # The over-indentation at the current level.
|
||||
@outdebt = 0 # The under-outdentation at the current level.
|
||||
@indents = [] # The stack of all current indentation levels.
|
||||
@ends = [] # The stack for pairing up tokens.
|
||||
@tokens = [] # Stream of parsed tokens in the form `['TYPE', value, line]`.
|
||||
|
||||
@code = code # The remainder of the source code.
|
||||
@line = opts.line or 0 # The current line.
|
||||
@indent = 0 # The current indentation level.
|
||||
@indebt = 0 # The over-indentation at the current level.
|
||||
@outdebt = 0 # The under-outdentation at the current level.
|
||||
@indents = [] # The stack of all current indentation levels.
|
||||
@ends = [] # The stack for pairing up tokens.
|
||||
@tokens = [] # Stream of parsed tokens in the form `['TYPE', value, line]`.
|
||||
@chunkLine =
|
||||
opts.line or 0 # The start line for the current @chunk.
|
||||
@chunkColumn =
|
||||
opts.column or 0 # The start column of the current @chunk.
|
||||
|
||||
# At every position, run through this list of attempted matches,
|
||||
# short-circuiting if any of them succeed. Their order determines precedence:
|
||||
# `@literalToken` is the fallback catch-all.
|
||||
i = 0
|
||||
while @chunk = code.slice i
|
||||
i += @identifierToken() or
|
||||
while @chunk = code[i..]
|
||||
consumed = \
|
||||
@identifierToken() or
|
||||
@commentToken() or
|
||||
@whitespaceToken() or
|
||||
@lineToken() or
|
||||
@@ -60,11 +65,32 @@ exports.Lexer = class Lexer
|
||||
@jsToken() or
|
||||
@literalToken()
|
||||
|
||||
# Update position
|
||||
[@chunkLine, @chunkColumn] = @getLineAndColumnFromChunk consumed
|
||||
|
||||
i += consumed
|
||||
|
||||
@closeIndentation()
|
||||
@error "missing #{tag}" if tag = @ends.pop()
|
||||
return @tokens if opts.rewrite is off
|
||||
(new Rewriter).rewrite @tokens
|
||||
|
||||
# Preprocess the code to remove leading and trailing whitespace, carriage
|
||||
# returns, etc. If we're lexing literate CoffeeScript, strip external Markdown
|
||||
# by removing all lines that aren't indented by at least four spaces or a tab.
|
||||
clean: (code) ->
|
||||
code = code.slice(1) if code.charCodeAt(0) is BOM
|
||||
code = "\n#{code}" if WHITESPACE.test code
|
||||
code = code.replace(/\r/g, '').replace TRAILING_SPACES, ''
|
||||
if @literate
|
||||
lines = for line in code.split('\n')
|
||||
if match = LITERATE.exec line
|
||||
line[match[0].length..]
|
||||
else
|
||||
'# ' + line
|
||||
code = lines.join '\n'
|
||||
code
|
||||
|
||||
# Tokenizers
|
||||
# ----------
|
||||
|
||||
@@ -78,6 +104,10 @@ exports.Lexer = class Lexer
|
||||
return 0 unless match = IDENTIFIER.exec @chunk
|
||||
[input, id, colon] = match
|
||||
|
||||
# Preserve length of id for location data
|
||||
idLength = id.length
|
||||
poppedToken = undefined
|
||||
|
||||
if id is 'own' and @tag() is 'FOR'
|
||||
@token 'OWN', id
|
||||
return id.length
|
||||
@@ -103,29 +133,35 @@ exports.Lexer = class Lexer
|
||||
else
|
||||
tag = 'RELATION'
|
||||
if @value() is '!'
|
||||
@tokens.pop()
|
||||
poppedToken = @tokens.pop()
|
||||
id = '!' + id
|
||||
|
||||
if id in ['eval', 'arguments'].concat JS_FORBIDDEN
|
||||
if id in JS_FORBIDDEN
|
||||
if forcedIdentifier
|
||||
tag = 'IDENTIFIER'
|
||||
id = new String id
|
||||
id.reserved = yes
|
||||
else if id in RESERVED
|
||||
@error "reserved word \"#{word}\""
|
||||
@error "reserved word \"#{id}\""
|
||||
|
||||
unless forcedIdentifier
|
||||
id = COFFEE_ALIAS_MAP[id] if id in COFFEE_ALIASES
|
||||
tag = switch id
|
||||
when '!' then 'UNARY'
|
||||
when '==', '!=' then 'COMPARE'
|
||||
when '&&', '||' then 'LOGIC'
|
||||
when 'true', 'false', 'null', 'undefined' then 'BOOL'
|
||||
when 'break', 'continue', 'debugger' then 'STATEMENT'
|
||||
when '!' then 'UNARY'
|
||||
when '==', '!=' then 'COMPARE'
|
||||
when '&&', '||' then 'LOGIC'
|
||||
when 'true', 'false' then 'BOOL'
|
||||
when 'break', 'continue' then 'STATEMENT'
|
||||
else tag
|
||||
|
||||
@token tag, id
|
||||
@token ':', ':' if colon
|
||||
tagToken = @token tag, id, 0, idLength
|
||||
if poppedToken
|
||||
[tagToken[2].first_line, tagToken[2].first_column] =
|
||||
[poppedToken[2].first_line, poppedToken[2].first_column]
|
||||
if colon
|
||||
colonOffset = input.lastIndexOf ':'
|
||||
@token ':', ':', colonOffset, colon.length
|
||||
|
||||
input.length
|
||||
|
||||
# Matches numbers, including decimals, hex, and exponential notation.
|
||||
@@ -133,10 +169,20 @@ exports.Lexer = class Lexer
|
||||
numberToken: ->
|
||||
return 0 unless match = NUMBER.exec @chunk
|
||||
number = match[0]
|
||||
if /^0[BOX]/.test number
|
||||
@error "radix prefix '#{number}' must be lowercase"
|
||||
else if /E/.test(number) and not /^0x/.test number
|
||||
@error "exponential notation '#{number}' must be indicated with a lowercase 'e'"
|
||||
else if /^0\d*[89]/.test number
|
||||
@error "decimal literal '#{number}' must not be prefixed with '0'"
|
||||
else if /^0\d+/.test number
|
||||
@error "octal literal '#{number}' must be prefixed with '0o'"
|
||||
lexedLength = number.length
|
||||
if binaryLiteral = /0b([01]+)/.exec number
|
||||
number = (parseInt binaryLiteral[1], 2).toString()
|
||||
@token 'NUMBER', number
|
||||
if octalLiteral = /^0o([0-7]+)/.exec number
|
||||
number = '0x' + (parseInt octalLiteral[1], 8).toString 16
|
||||
if binaryLiteral = /^0b([01]+)/.exec number
|
||||
number = '0x' + (parseInt binaryLiteral[1], 2).toString 16
|
||||
@token 'NUMBER', number, 0, lexedLength
|
||||
lexedLength
|
||||
|
||||
# Matches strings, including multi-line strings. Ensures that quotation marks
|
||||
@@ -145,16 +191,18 @@ exports.Lexer = class Lexer
|
||||
switch @chunk.charAt 0
|
||||
when "'"
|
||||
return 0 unless match = SIMPLESTR.exec @chunk
|
||||
@token 'STRING', (string = match[0]).replace MULTILINER, '\\\n'
|
||||
string = match[0]
|
||||
@token 'STRING', string.replace(MULTILINER, '\\\n'), 0, string.length
|
||||
when '"'
|
||||
return 0 unless string = @balancedString @chunk, '"'
|
||||
if 0 < string.indexOf '#{', 1
|
||||
@interpolateString string.slice 1, -1
|
||||
@interpolateString string[1...-1], strOffset: 1, lexedLength: string.length
|
||||
else
|
||||
@token 'STRING', @escapeLines string
|
||||
@token 'STRING', @escapeLines string, 0, string.length
|
||||
else
|
||||
return 0
|
||||
@line += count string, '\n'
|
||||
if octalEsc = /^(?:\\.|[^\\])*\\(?:0[0-7]|[1-7])/.test string
|
||||
@error "octal escape sequences #{string} are not allowed"
|
||||
string.length
|
||||
|
||||
# Matches heredocs, adjusting indentation to the correct level, as heredocs
|
||||
@@ -165,10 +213,9 @@ exports.Lexer = class Lexer
|
||||
quote = heredoc.charAt 0
|
||||
doc = @sanitizeHeredoc match[2], quote: quote, indent: null
|
||||
if quote is '"' and 0 <= doc.indexOf '#{'
|
||||
@interpolateString doc, heredoc: yes
|
||||
@interpolateString doc, heredoc: yes, strOffset: 3, lexedLength: heredoc.length
|
||||
else
|
||||
@token 'STRING', @makeString doc, quote, yes
|
||||
@line += count heredoc, '\n'
|
||||
@token 'STRING', @makeString(doc, quote, yes), 0, heredoc.length
|
||||
heredoc.length
|
||||
|
||||
# Matches and consumes comments.
|
||||
@@ -176,16 +223,16 @@ exports.Lexer = class Lexer
|
||||
return 0 unless match = @chunk.match COMMENT
|
||||
[comment, here] = match
|
||||
if here
|
||||
@token 'HERECOMMENT', @sanitizeHeredoc here,
|
||||
herecomment: true, indent: Array(@indent + 1).join(' ')
|
||||
@token 'TERMINATOR', '\n'
|
||||
@line += count comment, '\n'
|
||||
@token 'HERECOMMENT',
|
||||
(@sanitizeHeredoc here,
|
||||
herecomment: true, indent: Array(@indent + 1).join(' ')),
|
||||
0, comment.length
|
||||
comment.length
|
||||
|
||||
# Matches JavaScript interpolated directly into the source via backticks.
|
||||
jsToken: ->
|
||||
return 0 unless @chunk.charAt(0) is '`' and match = JSTOKEN.exec @chunk
|
||||
@token 'JS', (script = match[0]).slice 1, -1
|
||||
@token 'JS', (script = match[0])[1...-1], 0, script.length
|
||||
script.length
|
||||
|
||||
# Matches regular expression literals. Lexing regular expressions is difficult
|
||||
@@ -195,7 +242,6 @@ exports.Lexer = class Lexer
|
||||
return 0 if @chunk.charAt(0) isnt '/'
|
||||
if match = HEREGEX.exec @chunk
|
||||
length = @heregexToken match
|
||||
@line += count match[0], '\n'
|
||||
return length
|
||||
|
||||
prev = last @tokens
|
||||
@@ -204,7 +250,7 @@ exports.Lexer = class Lexer
|
||||
[match, regex, flags] = match
|
||||
if regex[..1] is '/*' then @error 'regular expressions cannot begin with `*`'
|
||||
if regex is '//' then regex = '/(?:)/'
|
||||
@token 'REGEX', "#{regex}#{flags}"
|
||||
@token 'REGEX', "#{regex}#{flags}", 0, match.length
|
||||
match.length
|
||||
|
||||
# Matches multiline extended regular expressions.
|
||||
@@ -213,24 +259,45 @@ exports.Lexer = class Lexer
|
||||
if 0 > body.indexOf '#{'
|
||||
re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/')
|
||||
if re.match /^\*/ then @error 'regular expressions cannot begin with `*`'
|
||||
@token 'REGEX', "/#{ re or '(?:)' }/#{flags}"
|
||||
@token 'REGEX', "/#{ re or '(?:)' }/#{flags}", 0, heregex.length
|
||||
return heregex.length
|
||||
@token 'IDENTIFIER', 'RegExp'
|
||||
@tokens.push ['CALL_START', '(']
|
||||
@token 'IDENTIFIER', 'RegExp', 0, 0
|
||||
@token 'CALL_START', '(', 0, 0
|
||||
tokens = []
|
||||
for [tag, value] in @interpolateString(body, regex: yes)
|
||||
for token in @interpolateString(body, regex: yes)
|
||||
[tag, value] = token
|
||||
if tag is 'TOKENS'
|
||||
tokens.push value...
|
||||
else
|
||||
else if tag is 'NEOSTRING'
|
||||
continue unless value = value.replace HEREGEX_OMIT, ''
|
||||
# Convert NEOSTRING into STRING
|
||||
value = value.replace /\\/g, '\\\\'
|
||||
tokens.push ['STRING', @makeString(value, '"', yes)]
|
||||
tokens.push ['+', '+']
|
||||
token[0] = 'STRING'
|
||||
token[1] = @makeString(value, '"', yes)
|
||||
tokens.push token
|
||||
else
|
||||
@error "Unexpected #{tag}"
|
||||
|
||||
prev = last @tokens
|
||||
plusToken = ['+', '+']
|
||||
plusToken[2] = prev[2] # Copy location data
|
||||
tokens.push plusToken
|
||||
|
||||
# Remove the extra "+"
|
||||
tokens.pop()
|
||||
@tokens.push ['STRING', '""'], ['+', '+'] unless tokens[0]?[0] is 'STRING'
|
||||
|
||||
unless tokens[0]?[0] is 'STRING'
|
||||
@token 'STRING', '""', 0, 0
|
||||
@token '+', '+', 0, 0
|
||||
@tokens.push tokens...
|
||||
@tokens.push [',', ','], ['STRING', '"' + flags + '"'] if flags
|
||||
@token ')', ')'
|
||||
|
||||
if flags
|
||||
# Find the flags in the heregex
|
||||
flagsOffset = heregex.lastIndexOf flags
|
||||
@token ',', ',', flagsOffset, 0
|
||||
@token 'STRING', '"' + flags + '"', flagsOffset, flags.length
|
||||
|
||||
@token ')', ')', heregex.length-1, 0
|
||||
heregex.length
|
||||
|
||||
# Matches newlines, indents, and outdents, and determines which is which.
|
||||
@@ -246,33 +313,32 @@ exports.Lexer = class Lexer
|
||||
lineToken: ->
|
||||
return 0 unless match = MULTI_DENT.exec @chunk
|
||||
indent = match[0]
|
||||
@line += count indent, '\n'
|
||||
@seenFor = no
|
||||
prev = last @tokens, 1
|
||||
size = indent.length - 1 - indent.lastIndexOf '\n'
|
||||
noNewlines = @unfinished()
|
||||
if size - @indebt is @indent
|
||||
if noNewlines then @suppressNewlines() else @newlineToken()
|
||||
if noNewlines then @suppressNewlines() else @newlineToken 0
|
||||
return indent.length
|
||||
|
||||
if size > @indent
|
||||
if noNewlines
|
||||
@indebt = size - @indent
|
||||
@suppressNewlines()
|
||||
return indent.length
|
||||
diff = size - @indent + @outdebt
|
||||
@token 'INDENT', diff
|
||||
@token 'INDENT', diff, 0, indent.length
|
||||
@indents.push diff
|
||||
@ends .push 'OUTDENT'
|
||||
@ends.push 'OUTDENT'
|
||||
@outdebt = @indebt = 0
|
||||
else
|
||||
@indebt = 0
|
||||
@outdentToken @indent - size, noNewlines
|
||||
@outdentToken @indent - size, noNewlines, indent.length
|
||||
@indent = size
|
||||
indent.length
|
||||
|
||||
# Record an outdent token or multiple tokens, if we happen to be moving back
|
||||
# inwards past several recorded indents.
|
||||
outdentToken: (moveOut, noNewlines) ->
|
||||
outdentToken: (moveOut, noNewlines, outdentLength) ->
|
||||
while moveOut > 0
|
||||
len = @indents.length - 1
|
||||
if @indents[len] is undefined
|
||||
@@ -284,14 +350,15 @@ exports.Lexer = class Lexer
|
||||
@outdebt -= @indents[len]
|
||||
moveOut -= @indents[len]
|
||||
else
|
||||
dent = @indents.pop() - @outdebt
|
||||
dent = @indents.pop() + @outdebt
|
||||
moveOut -= dent
|
||||
@outdebt = 0
|
||||
@pair 'OUTDENT'
|
||||
@token 'OUTDENT', dent
|
||||
@token 'OUTDENT', dent, 0, outdentLength
|
||||
@outdebt -= moveOut if dent
|
||||
@tokens.pop() while @value() is ';'
|
||||
@token 'TERMINATOR', '\n' unless @tag() is 'TERMINATOR' or noNewlines
|
||||
|
||||
@token 'TERMINATOR', '\n', outdentLength, 0 unless @tag() is 'TERMINATOR' or noNewlines
|
||||
this
|
||||
|
||||
# Matches and consumes non-meaningful whitespace. Tag the previous token
|
||||
@@ -304,9 +371,9 @@ exports.Lexer = class Lexer
|
||||
if match then match[0].length else 0
|
||||
|
||||
# Generate a newline token. Consecutive newlines get merged together.
|
||||
newlineToken: ->
|
||||
newlineToken: (offset) ->
|
||||
@tokens.pop() while @value() is ';'
|
||||
@token 'TERMINATOR', '\n' unless @tag() is 'TERMINATOR'
|
||||
@token 'TERMINATOR', '\n', offset, 0 unless @tag() is 'TERMINATOR'
|
||||
this
|
||||
|
||||
# Use a `\` at a line-ending to suppress the newline.
|
||||
@@ -335,9 +402,9 @@ exports.Lexer = class Lexer
|
||||
prev[0] = 'COMPOUND_ASSIGN'
|
||||
prev[1] += '='
|
||||
return value.length
|
||||
if value is ';'
|
||||
@seenFor = no
|
||||
tag = 'TERMINATOR'
|
||||
if value is ';'
|
||||
@seenFor = no
|
||||
tag = 'TERMINATOR'
|
||||
else if value in MATH then tag = 'MATH'
|
||||
else if value in COMPARE then tag = 'COMPARE'
|
||||
else if value in COMPOUND_ASSIGN then tag = 'COMPOUND_ASSIGN'
|
||||
@@ -368,7 +435,7 @@ exports.Lexer = class Lexer
|
||||
if herecomment
|
||||
if HEREDOC_ILLEGAL.test doc
|
||||
@error "block comment cannot contain \"*/\", starting"
|
||||
return doc if doc.indexOf('\n') <= 0
|
||||
return doc if doc.indexOf('\n') < 0
|
||||
else
|
||||
while match = HEREDOC_INDENT.exec doc
|
||||
attempt = match[1]
|
||||
@@ -407,22 +474,26 @@ exports.Lexer = class Lexer
|
||||
# contents of the string. This method allows us to have strings within
|
||||
# interpolations within strings, ad infinitum.
|
||||
balancedString: (str, end) ->
|
||||
continueCount = 0
|
||||
stack = [end]
|
||||
for i in [1...str.length]
|
||||
if continueCount
|
||||
--continueCount
|
||||
continue
|
||||
switch letter = str.charAt i
|
||||
when '\\'
|
||||
i++
|
||||
++continueCount
|
||||
continue
|
||||
when end
|
||||
stack.pop()
|
||||
unless stack.length
|
||||
return str.slice 0, i + 1
|
||||
return str[0..i]
|
||||
end = stack[stack.length - 1]
|
||||
continue
|
||||
if end is '}' and letter in ['"', "'"]
|
||||
stack.push end = letter
|
||||
else if end is '}' and letter is '/' and match = (HEREGEX.exec(str.slice i) or REGEX.exec(str.slice i))
|
||||
i += match[0].length - 1
|
||||
else if end is '}' and letter is '/' and match = (HEREGEX.exec(str[i..]) or REGEX.exec(str[i..]))
|
||||
continueCount += match[0].length - 1
|
||||
else if end is '}' and letter is '{'
|
||||
stack.push end = '}'
|
||||
else if end is '"' and prev is '#' and letter is '{'
|
||||
@@ -438,8 +509,28 @@ exports.Lexer = class Lexer
|
||||
# If it encounters an interpolation, this method will recursively create a
|
||||
# new Lexer, tokenize the interpolated contents, and merge them into the
|
||||
# token stream.
|
||||
#
|
||||
# - `str` is the start of the string contents (IE with the " or """ stripped
|
||||
# off.)
|
||||
# - `options.offsetInChunk` is the start of the interpolated string in the
|
||||
# current chunk, including the " or """, etc... If not provided, this is
|
||||
# assumed to be 0. `options.lexedLength` is the length of the
|
||||
# interpolated string, including both the start and end quotes. Both of these
|
||||
# values are ignored if `options.regex` is true.
|
||||
# - `options.strOffset` is the offset of str, relative to the start of the
|
||||
# current chunk.
|
||||
interpolateString: (str, options = {}) ->
|
||||
{heredoc, regex} = options
|
||||
{heredoc, regex, offsetInChunk, strOffset, lexedLength} = options
|
||||
offsetInChunk = offsetInChunk || 0
|
||||
strOffset = strOffset || 0
|
||||
lexedLength = lexedLength || str.length
|
||||
|
||||
# Clip leading \n from heredoc
|
||||
if heredoc and str.length > 0 and str[0] == '\n'
|
||||
str = str[1...]
|
||||
strOffset++
|
||||
|
||||
# Parse the string.
|
||||
tokens = []
|
||||
pi = 0
|
||||
i = -1
|
||||
@@ -448,33 +539,60 @@ exports.Lexer = class Lexer
|
||||
i += 1
|
||||
continue
|
||||
unless letter is '#' and str.charAt(i+1) is '{' and
|
||||
(expr = @balancedString str.slice(i + 1), '}')
|
||||
(expr = @balancedString str[i + 1..], '}')
|
||||
continue
|
||||
tokens.push ['NEOSTRING', str.slice(pi, i)] if pi < i
|
||||
inner = expr.slice(1, -1)
|
||||
# NEOSTRING is a fake token. This will be converted to a string below.
|
||||
tokens.push @makeToken('NEOSTRING', str[pi...i], strOffset + pi) if pi < i
|
||||
inner = expr[1...-1]
|
||||
if inner.length
|
||||
nested = new Lexer().tokenize inner, line: @line, rewrite: off
|
||||
nested.pop()
|
||||
nested.shift() if nested[0]?[0] is 'TERMINATOR'
|
||||
[line, column] = @getLineAndColumnFromChunk(strOffset + i + 1)
|
||||
nested = new Lexer().tokenize inner, line: line, column: column, rewrite: off
|
||||
popped = nested.pop()
|
||||
popped = nested.shift() if nested[0]?[0] is 'TERMINATOR'
|
||||
if len = nested.length
|
||||
if len > 1
|
||||
nested.unshift ['(', '(']
|
||||
nested.push [')', ')']
|
||||
nested.unshift @makeToken '(', '(', strOffset + i + 1, 0
|
||||
nested.push @makeToken ')', ')', strOffset + i + 1 + inner.length, 0
|
||||
# Push a fake 'TOKENS' token, which will get turned into real tokens below.
|
||||
tokens.push ['TOKENS', nested]
|
||||
i += expr.length
|
||||
pi = i + 1
|
||||
tokens.push ['NEOSTRING', str.slice pi] if i > pi < str.length
|
||||
tokens.push @makeToken('NEOSTRING', str[pi..], strOffset + pi) if i > pi < str.length
|
||||
|
||||
# If regex, then return now and let the regex code deal with all these fake tokens
|
||||
return tokens if regex
|
||||
return @token 'STRING', '""' unless tokens.length
|
||||
tokens.unshift ['', ''] unless tokens[0][0] is 'NEOSTRING'
|
||||
@token '(', '(' if interpolated = tokens.length > 1
|
||||
for [tag, value], i in tokens
|
||||
@token '+', '+' if i
|
||||
|
||||
# If we didn't find any tokens, then just return an empty string.
|
||||
return @token 'STRING', '""', offsetInChunk, lexedLength unless tokens.length
|
||||
|
||||
# If the first token is not a string, add a fake empty string to the beginning.
|
||||
tokens.unshift @makeToken('NEOSTRING', '', offsetInChunk) unless tokens[0][0] is 'NEOSTRING'
|
||||
|
||||
@token '(', '(', offsetInChunk, 0 if interpolated = tokens.length > 1
|
||||
# Push all the tokens
|
||||
for token, i in tokens
|
||||
[tag, value] = token
|
||||
if i
|
||||
# Create a 0-length "+" token.
|
||||
plusToken = @token '+', '+' if i
|
||||
locationToken = if tag == 'TOKENS' then value[0] else token
|
||||
plusToken[2] =
|
||||
first_line: locationToken[2].first_line
|
||||
first_column: locationToken[2].first_column
|
||||
last_line: locationToken[2].first_line
|
||||
last_column: locationToken[2].first_column
|
||||
if tag is 'TOKENS'
|
||||
# Push all the tokens in the fake 'TOKENS' token. These already have
|
||||
# sane location data.
|
||||
@tokens.push value...
|
||||
else if tag is 'NEOSTRING'
|
||||
# Convert NEOSTRING into STRING
|
||||
token[0] = 'STRING'
|
||||
token[1] = @makeString value, '"', heredoc
|
||||
@tokens.push token
|
||||
else
|
||||
@token 'STRING', @makeString value, '"', heredoc
|
||||
@token ')', ')' if interpolated
|
||||
@error "Unexpected #{tag}"
|
||||
@token ')', ')', offsetInChunk + lexedLength, 0 if interpolated
|
||||
tokens
|
||||
|
||||
# Pairs up a closing token, ensuring that all listed pairs of tokens are
|
||||
@@ -495,9 +613,59 @@ exports.Lexer = class Lexer
|
||||
# Helpers
|
||||
# -------
|
||||
|
||||
# Add a token to the results, taking note of the line number.
|
||||
token: (tag, value) ->
|
||||
@tokens.push [tag, value, @line]
|
||||
# Returns the line and column number from an offset into the current chunk.
|
||||
#
|
||||
# `offset` is a number of characters into @chunk.
|
||||
getLineAndColumnFromChunk: (offset) ->
|
||||
if offset is 0
|
||||
return [@chunkLine, @chunkColumn]
|
||||
|
||||
if offset >= @chunk.length
|
||||
string = @chunk
|
||||
else
|
||||
string = @chunk[..offset-1]
|
||||
|
||||
lineCount = count string, '\n'
|
||||
|
||||
column = @chunkColumn
|
||||
if lineCount > 0
|
||||
lines = string.split '\n'
|
||||
column = (last lines).length
|
||||
else
|
||||
column += string.length
|
||||
|
||||
return [@chunkLine + lineCount, column]
|
||||
|
||||
# Same as "token", exception this just returns the token without adding it
|
||||
# to the results.
|
||||
makeToken: (tag, value, offsetInChunk, length) ->
|
||||
offsetInChunk = offsetInChunk || 0
|
||||
if length is undefined then length = value.length
|
||||
|
||||
locationData = {}
|
||||
[locationData.first_line, locationData.first_column] =
|
||||
@getLineAndColumnFromChunk offsetInChunk
|
||||
|
||||
# Use length - 1 for the final offset - we're supplying the last_line and the last_column,
|
||||
# so if last_column == first_column, then we're looking at a character of length 1.
|
||||
lastCharacter = if length > 0 then (length - 1) else 0
|
||||
[locationData.last_line, locationData.last_column] =
|
||||
@getLineAndColumnFromChunk offsetInChunk + (length - 1)
|
||||
|
||||
token = [tag, value, locationData]
|
||||
|
||||
return token
|
||||
|
||||
# Add a token to the results.
|
||||
# `offset` is the offset into the current @chunk where the token starts.
|
||||
# `length` is the length of the token in the @chunk, after the offset. If
|
||||
# not specified, the length of `value` will be used.
|
||||
#
|
||||
# Returns the new token.
|
||||
token: (tag, value, offsetInChunk, length) ->
|
||||
token = @makeToken tag, value, offsetInChunk, length
|
||||
@tokens.push token
|
||||
return token
|
||||
|
||||
# Peek at a tag in the current token stream.
|
||||
tag: (index, tag) ->
|
||||
@@ -511,7 +679,7 @@ exports.Lexer = class Lexer
|
||||
unfinished: ->
|
||||
LINE_CONTINUER.test(@chunk) or
|
||||
@tag() in ['\\', '.', '?.', 'UNARY', 'MATH', '+', '-', 'SHIFT', 'RELATION'
|
||||
'COMPARE', 'LOGIC', 'COMPOUND_ASSIGN', 'THROW', 'EXTENDS']
|
||||
'COMPARE', 'LOGIC', 'THROW', 'EXTENDS']
|
||||
|
||||
# Converts newlines for string literals.
|
||||
escapeLines: (str, heredoc) ->
|
||||
@@ -524,10 +692,12 @@ exports.Lexer = class Lexer
|
||||
if contents in ['\n', quote] then contents else match
|
||||
body = body.replace /// #{quote} ///g, '\\$&'
|
||||
quote + @escapeLines(body, heredoc) + quote
|
||||
|
||||
|
||||
# Throws a syntax error on the current `@line`.
|
||||
error: (message) ->
|
||||
throw SyntaxError "#{message} on line #{ @line + 1}"
|
||||
error: (message) ->
|
||||
# TODO: Are there some cases we could improve the error line number by
|
||||
# passing the offset in the chunk where the error happened?
|
||||
throw SyntaxError "#{message} on line #{ @chunkLine + 1 }"
|
||||
|
||||
# Constants
|
||||
# ---------
|
||||
@@ -562,16 +732,23 @@ COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat COFFEE_ALIASES
|
||||
# used by CoffeeScript internally. We throw an error when these are encountered,
|
||||
# to avoid having a JavaScript error at runtime.
|
||||
RESERVED = [
|
||||
'case', 'default', 'function', 'var', 'void', 'with'
|
||||
'const', 'let', 'enum', 'export', 'import', 'native'
|
||||
'__hasProp', '__extends', '__slice', '__bind', '__indexOf'
|
||||
'case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum'
|
||||
'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind'
|
||||
'__indexOf', 'implements', 'interface', 'package', 'private', 'protected'
|
||||
'public', 'static', 'yield'
|
||||
]
|
||||
|
||||
STRICT_PROSCRIBED = ['arguments', 'eval']
|
||||
|
||||
# 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
|
||||
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED)
|
||||
|
||||
exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS)
|
||||
exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS).concat(STRICT_PROSCRIBED)
|
||||
exports.STRICT_PROSCRIBED = STRICT_PROSCRIBED
|
||||
|
||||
# The character code of the nasty Microsoft madness otherwise known as the BOM.
|
||||
BOM = 65279
|
||||
|
||||
# Token matching regexes.
|
||||
IDENTIFIER = /// ^
|
||||
@@ -580,8 +757,9 @@ IDENTIFIER = /// ^
|
||||
///
|
||||
|
||||
NUMBER = ///
|
||||
^ 0x[\da-f]+ | # hex
|
||||
^ 0b[01]+ | # binary
|
||||
^ 0b[01]+ | # binary
|
||||
^ 0o[0-7]+ | # octal
|
||||
^ 0x[\da-f]+ | # hex
|
||||
^ \d*\.?\d+ (?:e[+-]?\d+)? # decimal
|
||||
///i
|
||||
|
||||
@@ -599,7 +777,9 @@ OPERATOR = /// ^ (
|
||||
|
||||
WHITESPACE = /^[^\n\S]+/
|
||||
|
||||
COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)?$)|^(?:\s*#(?!##[^#]).*)+/
|
||||
COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)$)|^(?:\s*#(?!##[^#]).*)+/
|
||||
|
||||
LITERATE = /^([ ]{4}|\t)/
|
||||
|
||||
CODE = /^[-=]>/
|
||||
|
||||
@@ -663,7 +843,7 @@ MATH = ['*', '/', '%']
|
||||
RELATION = ['IN', 'OF', 'INSTANCEOF']
|
||||
|
||||
# Boolean tokens.
|
||||
BOOL = ['TRUE', 'FALSE', 'NULL', 'UNDEFINED']
|
||||
BOOL = ['TRUE', 'FALSE']
|
||||
|
||||
# Tokens which a regular expression will never immediately follow, but which
|
||||
# a division operator might.
|
||||
@@ -671,7 +851,7 @@ BOOL = ['TRUE', 'FALSE', 'NULL', 'UNDEFINED']
|
||||
# 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', 'BOOL', '++', '--', ']']
|
||||
NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', 'NULL', 'UNDEFINED', '++', '--', ']']
|
||||
|
||||
# If the previous token is not spaced, there are more preceding tokens that
|
||||
# force a division parse:
|
||||
@@ -681,7 +861,7 @@ NOT_SPACED_REGEX = NOT_REGEX.concat ')', '}', 'THIS', 'IDENTIFIER', 'STRING'
|
||||
# parentheses or bracket following these tokens will be recorded as the start
|
||||
# of a function invocation or indexing operation.
|
||||
CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER']
|
||||
INDEXABLE = CALLABLE.concat 'NUMBER', 'BOOL'
|
||||
INDEXABLE = CALLABLE.concat 'NUMBER', 'BOOL', 'NULL', 'UNDEFINED'
|
||||
|
||||
# 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
|
||||
|
||||
518
src/nodes.coffee
518
src/nodes.coffee
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