mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-01-13 16:57:54 -05:00
Compare commits
655 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
485346f0e5 | ||
|
|
a8d4c3a567 | ||
|
|
dfb3a13246 | ||
|
|
f84eb9ed47 | ||
|
|
8136c5f3de | ||
|
|
45669e08c6 | ||
|
|
a5db69e1af | ||
|
|
8aceef20e1 | ||
|
|
7e3c71ed19 | ||
|
|
9d09bee6fb | ||
|
|
cd6ee373ff | ||
|
|
4d0acc9b02 | ||
|
|
393fbf1b66 | ||
|
|
3324b03a5d | ||
|
|
eb91f9922d | ||
|
|
9a7420ccd0 | ||
|
|
be72120311 | ||
|
|
c452c3a101 | ||
|
|
0b3bb66708 | ||
|
|
d0d0fa4d10 | ||
|
|
6222ed622f | ||
|
|
1a03e98057 | ||
|
|
46cea93fc3 | ||
|
|
d64b8fd9d8 | ||
|
|
c051daee2f | ||
|
|
ae70d10996 | ||
|
|
52e6399e02 | ||
|
|
ac05f62f2f | ||
|
|
4d935efd09 | ||
|
|
fa8cc7976a | ||
|
|
ee4e34bf6d | ||
|
|
c8e0f8b149 | ||
|
|
b47188763c | ||
|
|
5e5c9df5c4 | ||
|
|
1a97f599dd | ||
|
|
3b264c9572 | ||
|
|
144c096ae6 | ||
|
|
adbcd320b2 | ||
|
|
17ba44056e | ||
|
|
502abade7c | ||
|
|
b746c9018e | ||
|
|
92af641827 | ||
|
|
b5606a247d | ||
|
|
d62baf5a5d | ||
|
|
e17567866a | ||
|
|
76f9596f22 | ||
|
|
2a3a713811 | ||
|
|
175ebb3cd8 | ||
|
|
95367a4a63 | ||
|
|
8950c3c4c8 | ||
|
|
2d1abd099d | ||
|
|
a894db35fd | ||
|
|
328a14014c | ||
|
|
315a2c63fa | ||
|
|
ca4ea7649d | ||
|
|
08c877ec7b | ||
|
|
212ad45be4 | ||
|
|
e9b37c7578 | ||
|
|
1438cecfad | ||
|
|
49824ce1a6 | ||
|
|
bc0ec9dc07 | ||
|
|
5957b9f155 | ||
|
|
72e6e828f1 | ||
|
|
01b4393fa7 | ||
|
|
bf2a5386f9 | ||
|
|
fb4d4a609b | ||
|
|
1cddb2aa88 | ||
|
|
aac9679282 | ||
|
|
90472685e8 | ||
|
|
7bb764b3e4 | ||
|
|
1aed9c545f | ||
|
|
c937e49689 | ||
|
|
0d860516ac | ||
|
|
4ced1d65b4 | ||
|
|
92540d5e85 | ||
|
|
ea982a627e | ||
|
|
835ecac8db | ||
|
|
c3bbb48041 | ||
|
|
2e842f0146 | ||
|
|
8de2fb9009 | ||
|
|
17e177405a | ||
|
|
ef67561fb3 | ||
|
|
df97effb9c | ||
|
|
8317960f81 | ||
|
|
065bf54094 | ||
|
|
f36acc27e5 | ||
|
|
491ad6de95 | ||
|
|
3eedf8ed1b | ||
|
|
75b260e495 | ||
|
|
2351948291 | ||
|
|
538e518d76 | ||
|
|
de955dacc4 | ||
|
|
19ed63129e | ||
|
|
2e744a1c1b | ||
|
|
89534b88b1 | ||
|
|
c067808b54 | ||
|
|
59ae79d8fb | ||
|
|
ad1c5e1884 | ||
|
|
9958cedd89 | ||
|
|
d1aaed4430 | ||
|
|
89debc87b2 | ||
|
|
9d2c81ea54 | ||
|
|
44765907b3 | ||
|
|
4a85f3d499 | ||
|
|
f99b5ad463 | ||
|
|
8fc631269b | ||
|
|
a1975583a7 | ||
|
|
1c628e7883 | ||
|
|
3605168e85 | ||
|
|
f86fca2739 | ||
|
|
0410748e2d | ||
|
|
2172878f21 | ||
|
|
d3a51fbfa1 | ||
|
|
aae2405de4 | ||
|
|
2b578367a9 | ||
|
|
f9b028b78c | ||
|
|
572aa4e98f | ||
|
|
864275f07e | ||
|
|
998a7c8cb0 | ||
|
|
6d7a04228f | ||
|
|
4a8c2e8a13 | ||
|
|
f3a60edc5d | ||
|
|
1e1146d61d | ||
|
|
832e1d8cb8 | ||
|
|
4936211a9c | ||
|
|
f0d731009f | ||
|
|
a6248d03e5 | ||
|
|
a934cf4947 | ||
|
|
c498b7090e | ||
|
|
ca9e45e8af | ||
|
|
97096696a2 | ||
|
|
27fb3763b4 | ||
|
|
da43c70488 | ||
|
|
76ade0cb4d | ||
|
|
09e1526bca | ||
|
|
7d1fbeb708 | ||
|
|
15217c705e | ||
|
|
9f108e87eb | ||
|
|
1e786d6d8b | ||
|
|
0557eb9b93 | ||
|
|
241f6f3068 | ||
|
|
326656245a | ||
|
|
177ec92c39 | ||
|
|
711dacae5f | ||
|
|
c19183118e | ||
|
|
0af132d0c6 | ||
|
|
83c0e77ca8 | ||
|
|
1e315b5a33 | ||
|
|
6e0e0767f9 | ||
|
|
6df50399a9 | ||
|
|
7b9a8998cf | ||
|
|
7de5253318 | ||
|
|
eaf4a71d32 | ||
|
|
4dd40034ed | ||
|
|
030476d335 | ||
|
|
45aae5e322 | ||
|
|
9763839ed1 | ||
|
|
7ee10e06be | ||
|
|
8f3ea1d0c5 | ||
|
|
b9b87f7d8e | ||
|
|
c9b6e82e2c | ||
|
|
c8f969b4a2 | ||
|
|
ecd1c77f48 | ||
|
|
ad93d2fe4d | ||
|
|
5a4d401582 | ||
|
|
590c069158 | ||
|
|
94185e3f70 | ||
|
|
9adcd16ec6 | ||
|
|
74bcd898e7 | ||
|
|
296808d4d3 | ||
|
|
b7519cb834 | ||
|
|
7d6c050048 | ||
|
|
16f9a2e6b7 | ||
|
|
cbfe7f5822 | ||
|
|
895cd88761 | ||
|
|
f2ea18b0ba | ||
|
|
162f6b9d5c | ||
|
|
4f8ae3ccbe | ||
|
|
acd9be3863 | ||
|
|
ddf18ae34c | ||
|
|
0da61ec47e | ||
|
|
80230414a2 | ||
|
|
ce7c0d176b | ||
|
|
4ec79732f1 | ||
|
|
cc3c314988 | ||
|
|
8553a89af2 | ||
|
|
566321d67a | ||
|
|
a2778bf06d | ||
|
|
29eff23490 | ||
|
|
4ebaa82563 | ||
|
|
69911209ea | ||
|
|
92688c89ef | ||
|
|
fe04f8ce6b | ||
|
|
b72641693d | ||
|
|
0c6ee52cfc | ||
|
|
1f87094628 | ||
|
|
3b22018296 | ||
|
|
5be437deb9 | ||
|
|
8d098194dd | ||
|
|
256525bfa2 | ||
|
|
79e4f30f69 | ||
|
|
884637468e | ||
|
|
6fd7810d89 | ||
|
|
2f97d0d9b1 | ||
|
|
1bb9c57767 | ||
|
|
d880b8b8f2 | ||
|
|
7129f518a4 | ||
|
|
fa6f1c2fb1 | ||
|
|
2bd1c3acca | ||
|
|
70cfc9500e | ||
|
|
61b011cc28 | ||
|
|
391135b1a5 | ||
|
|
12d8d70573 | ||
|
|
04c5aeda2d | ||
|
|
25438be207 | ||
|
|
33f51d76f4 | ||
|
|
e3021909c2 | ||
|
|
61dee1beba | ||
|
|
21e954eec3 | ||
|
|
0b3054a348 | ||
|
|
02f4cb75dd | ||
|
|
3aeb8c6bdb | ||
|
|
8c2b2c7f80 | ||
|
|
745c635a55 | ||
|
|
c7dd31846d | ||
|
|
e87fa4293d | ||
|
|
b269884f8d | ||
|
|
3fed9761a6 | ||
|
|
6ccf196b61 | ||
|
|
a4bd8dc623 | ||
|
|
34f01408c9 | ||
|
|
73074daa07 | ||
|
|
119b80d449 | ||
|
|
60b3103314 | ||
|
|
75ffb9dc84 | ||
|
|
b306d40bf1 | ||
|
|
a27f146338 | ||
|
|
74995358cd | ||
|
|
35da6c32b7 | ||
|
|
701a5c7cb9 | ||
|
|
3c3e7f666b | ||
|
|
89dfa1fd7a | ||
|
|
1da00f0ee3 | ||
|
|
5809a1637f | ||
|
|
e47bea34d5 | ||
|
|
709f17c278 | ||
|
|
3c597dde72 | ||
|
|
0379431812 | ||
|
|
3f9fd85afb | ||
|
|
7b0a235c71 | ||
|
|
55cac23976 | ||
|
|
22a16a3e33 | ||
|
|
db555d12ea | ||
|
|
b9f1390405 | ||
|
|
f2d0aee656 | ||
|
|
2a47727641 | ||
|
|
ccb7f63b8a | ||
|
|
1f9bb6a1c4 | ||
|
|
21b5d2cac5 | ||
|
|
56eeeebed1 | ||
|
|
54627f6807 | ||
|
|
5754d36fdd | ||
|
|
3d14d362a8 | ||
|
|
472e027463 | ||
|
|
b297510d2b | ||
|
|
4932d25540 | ||
|
|
b6c3b743f0 | ||
|
|
1b4edd0e37 | ||
|
|
dcb00b4fe8 | ||
|
|
b33b688373 | ||
|
|
4b97b15c0c | ||
|
|
93c0774036 | ||
|
|
645885d72d | ||
|
|
b5af5f66fb | ||
|
|
fb04f8900a | ||
|
|
3396dce2bb | ||
|
|
3291bd2a4a | ||
|
|
121f01c06f | ||
|
|
6cac2d57ba | ||
|
|
c04b43e047 | ||
|
|
ff20732dd7 | ||
|
|
81af8f296e | ||
|
|
830d1fb42b | ||
|
|
e19cb48d3d | ||
|
|
f755580b11 | ||
|
|
81955005b9 | ||
|
|
62a871773b | ||
|
|
5e52e7f19e | ||
|
|
4c66a6a642 | ||
|
|
9e1deecf13 | ||
|
|
1ce93ccceb | ||
|
|
4b04f8bec1 | ||
|
|
5528bc7b2d | ||
|
|
912f3b19f7 | ||
|
|
9e5e85780b | ||
|
|
10aa3b3ae3 | ||
|
|
bcf7b3f95b | ||
|
|
07f1c784a4 | ||
|
|
465994cff9 | ||
|
|
697ad6cbda | ||
|
|
a840671015 | ||
|
|
7f0ab8308d | ||
|
|
270b9fde04 | ||
|
|
993c9899cb | ||
|
|
c8246e95f1 | ||
|
|
f08de1ed4c | ||
|
|
90f2e0dbb9 | ||
|
|
80a3bd8951 | ||
|
|
b0aec3cbe2 | ||
|
|
5f5e0634dd | ||
|
|
049e605016 | ||
|
|
4687c3e140 | ||
|
|
6d74e223be | ||
|
|
221427a6b4 | ||
|
|
3bf892128d | ||
|
|
abd7f939f2 | ||
|
|
299e9918b9 | ||
|
|
eea83ff613 | ||
|
|
9eceab667c | ||
|
|
026e7649d5 | ||
|
|
c807da7664 | ||
|
|
dde5db621d | ||
|
|
6b95cb4ee0 | ||
|
|
a5f69ef716 | ||
|
|
accccb5f39 | ||
|
|
f8ddccd7d0 | ||
|
|
e06e882962 | ||
|
|
c3f74ca4f1 | ||
|
|
532464f7ae | ||
|
|
570fb013e2 | ||
|
|
71ace9d8d0 | ||
|
|
1cf0326183 | ||
|
|
5b9ebd19d5 | ||
|
|
6ce869b3fb | ||
|
|
06b50ecb98 | ||
|
|
0bc7719572 | ||
|
|
9028f79a27 | ||
|
|
a3e1693a75 | ||
|
|
060b3e23c1 | ||
|
|
612c238157 | ||
|
|
8adbc75811 | ||
|
|
7485e5482c | ||
|
|
659a5436a5 | ||
|
|
c6d7a27848 | ||
|
|
094b198d5d | ||
|
|
22b97a3b54 | ||
|
|
a4f7a5e248 | ||
|
|
45d8cf163e | ||
|
|
d46daa1d7c | ||
|
|
4906cf1aff | ||
|
|
f74fae58e3 | ||
|
|
1602e0e823 | ||
|
|
202ebf06ff | ||
|
|
3e3b71724d | ||
|
|
893fb98522 | ||
|
|
e267226438 | ||
|
|
62626b712b | ||
|
|
7bdf14b210 | ||
|
|
87420e6504 | ||
|
|
c73a3ec356 | ||
|
|
2e23e6a2dc | ||
|
|
5b3ef78101 | ||
|
|
9b262d56a5 | ||
|
|
453b43992d | ||
|
|
a5e3617015 | ||
|
|
c4ad6d1ee6 | ||
|
|
f9cde1b46d | ||
|
|
03bc897b39 | ||
|
|
83fd84745d | ||
|
|
e977967eb5 | ||
|
|
15b00cb3ca | ||
|
|
18e5f72a84 | ||
|
|
47682de0f0 | ||
|
|
b4ea43cbd0 | ||
|
|
08341286a3 | ||
|
|
4c3b0b9a74 | ||
|
|
d250e9e9cc | ||
|
|
75be5eed62 | ||
|
|
e2f86678a4 | ||
|
|
fe7d5dfd19 | ||
|
|
965034e16e | ||
|
|
44398d044f | ||
|
|
3feb874b1e | ||
|
|
f7183e6918 | ||
|
|
707cd2d734 | ||
|
|
c11c3ed2f2 | ||
|
|
5fd0972b5d | ||
|
|
70cb195e6f | ||
|
|
c219adffd5 | ||
|
|
cd6dd5abfd | ||
|
|
29ece0e6ba | ||
|
|
45bad556ab | ||
|
|
30cf63ec92 | ||
|
|
969c2e528d | ||
|
|
bb2bf7ce57 | ||
|
|
2969e156c7 | ||
|
|
b08995cbcc | ||
|
|
47f71f9193 | ||
|
|
fec2eaef7e | ||
|
|
56eb474bf3 | ||
|
|
62b2ab29cd | ||
|
|
a35693554c | ||
|
|
f7427259ee | ||
|
|
e02ab76edf | ||
|
|
9f46c306e5 | ||
|
|
b5c9d779bd | ||
|
|
d2cb1f321e | ||
|
|
8f871a8218 | ||
|
|
4ec7514d10 | ||
|
|
1c7e4c4203 | ||
|
|
7d39fe1c56 | ||
|
|
afa26c37f1 | ||
|
|
2f658ba925 | ||
|
|
0ab810e4cb | ||
|
|
37d086b670 | ||
|
|
5e7f5f390a | ||
|
|
f4cd0bdf29 | ||
|
|
723ea53585 | ||
|
|
93f644fae2 | ||
|
|
82951a469b | ||
|
|
d2d5f649d3 | ||
|
|
5c7526a741 | ||
|
|
17ea48c543 | ||
|
|
55ed202957 | ||
|
|
d5df5505f9 | ||
|
|
dc7f4b4be0 | ||
|
|
406a18067d | ||
|
|
3ae2ebe5ea | ||
|
|
a23dc6b753 | ||
|
|
5f1d3fd775 | ||
|
|
9d4e06e8a8 | ||
|
|
6bc61ec1a1 | ||
|
|
c62f93f930 | ||
|
|
213ae1430e | ||
|
|
ee5d738827 | ||
|
|
eab9bbf04f | ||
|
|
4ed51536bb | ||
|
|
b32a60585b | ||
|
|
66a6568fe7 | ||
|
|
fe32146adc | ||
|
|
69feac3a01 | ||
|
|
05d95acfc3 | ||
|
|
22674bc536 | ||
|
|
23c5ebb00f | ||
|
|
c14869f008 | ||
|
|
c1427d6558 | ||
|
|
2a46e13d33 | ||
|
|
b26e577244 | ||
|
|
9f8710b631 | ||
|
|
aba8cb1b08 | ||
|
|
92cd80226c | ||
|
|
10d335ccb1 | ||
|
|
4eeb8c4bd2 | ||
|
|
4d146bacb1 | ||
|
|
7de4caffca | ||
|
|
8db0cb9fa5 | ||
|
|
c30b3d3c48 | ||
|
|
52db4fbf8c | ||
|
|
5cd8f2c52c | ||
|
|
5a1aa44393 | ||
|
|
432696d6eb | ||
|
|
3df7bd98f4 | ||
|
|
1f870911c9 | ||
|
|
4bb9392753 | ||
|
|
fdffacfb40 | ||
|
|
a64afe6162 | ||
|
|
15b86a5f7a | ||
|
|
9b78fb67cf | ||
|
|
4817b96bac | ||
|
|
6985802eb3 | ||
|
|
aad0ce162d | ||
|
|
f582b73035 | ||
|
|
e795f41bd2 | ||
|
|
5d541232ef | ||
|
|
07513ba928 | ||
|
|
aded80c101 | ||
|
|
5d893947ea | ||
|
|
535cf28220 | ||
|
|
dbe5328c33 | ||
|
|
6e15a4da0e | ||
|
|
fc51f0ef6c | ||
|
|
1f2c8df5fa | ||
|
|
bea40a7a92 | ||
|
|
f679590bef | ||
|
|
bd61131f5c | ||
|
|
ff25361896 | ||
|
|
08dcc7e107 | ||
|
|
b027b5cf0d | ||
|
|
0f2a2ee11e | ||
|
|
a93229b14d | ||
|
|
2d3f6b80c1 | ||
|
|
9503ea3040 | ||
|
|
08539a156e | ||
|
|
b183b091ee | ||
|
|
c39415da44 | ||
|
|
2c461f6474 | ||
|
|
e213964793 | ||
|
|
dd753d3b78 | ||
|
|
45c0d4c2ea | ||
|
|
4f89f90dab | ||
|
|
0270e48a01 | ||
|
|
a278d8f018 | ||
|
|
d4a180c413 | ||
|
|
28a8c05513 | ||
|
|
879b3d76bd | ||
|
|
138692183b | ||
|
|
95f3e2f79f | ||
|
|
dec9950649 | ||
|
|
2f6b69b580 | ||
|
|
ff1fd97924 | ||
|
|
87e60dccf0 | ||
|
|
8ff977dc65 | ||
|
|
fbfa12c733 | ||
|
|
6a45d25777 | ||
|
|
2b5d596e10 | ||
|
|
e2a71d3c2c | ||
|
|
807e0b479d | ||
|
|
dfa63839bb | ||
|
|
0490cb2920 | ||
|
|
2d0ad73af8 | ||
|
|
5a81fcd42e | ||
|
|
6446e0004c | ||
|
|
edf5f4947e | ||
|
|
b674163a40 | ||
|
|
9f2badb3e9 | ||
|
|
0610e20a3c | ||
|
|
bedc005d67 | ||
|
|
a8a46257ae | ||
|
|
b41afe79b4 | ||
|
|
448ed36cd2 | ||
|
|
c4d19cd1fa | ||
|
|
495ca64c46 | ||
|
|
0f2cf552e9 | ||
|
|
f6a1f16146 | ||
|
|
db6bc0ba02 | ||
|
|
e4bb6c91e7 | ||
|
|
561a02c35f | ||
|
|
51e80484e2 | ||
|
|
79fa4723ab | ||
|
|
a3c8c0b492 | ||
|
|
2f389f1d51 | ||
|
|
85e5dffad5 | ||
|
|
fa63288f52 | ||
|
|
4ea8be8e0b | ||
|
|
48c501a7a2 | ||
|
|
63c2b2bc64 | ||
|
|
639be2ff09 | ||
|
|
8b1b3ea402 | ||
|
|
9c3040b704 | ||
|
|
e7291f57ba | ||
|
|
3f6eceac77 | ||
|
|
ba7a454f92 | ||
|
|
3092d74a08 | ||
|
|
ff8e0c9751 | ||
|
|
3e518e3cf9 | ||
|
|
7667e16732 | ||
|
|
e110042275 | ||
|
|
06677b0545 | ||
|
|
20d105ba4e | ||
|
|
e77f4f61aa | ||
|
|
9de729e825 | ||
|
|
c39c2e3599 | ||
|
|
ecfa212189 | ||
|
|
97fd126a7f | ||
|
|
844c756940 | ||
|
|
a90bf75395 | ||
|
|
79bb0da153 | ||
|
|
c88b1f6a15 | ||
|
|
b224d58a36 | ||
|
|
7d348b5eae | ||
|
|
02ac3edebf | ||
|
|
4bad3e0f4f | ||
|
|
8147ef554a | ||
|
|
785c4fb5a0 | ||
|
|
13b2dc8d31 | ||
|
|
a62923ff97 | ||
|
|
dd6be80fca | ||
|
|
8c077f0f65 | ||
|
|
2c4c4cc93e | ||
|
|
1ab3b183a8 | ||
|
|
e6a53bd852 | ||
|
|
b983b3fcdc | ||
|
|
89cac4071e | ||
|
|
506ea8aa52 | ||
|
|
b965fcf32d | ||
|
|
126f6c2d88 | ||
|
|
3dc456572b | ||
|
|
0f26072ad0 | ||
|
|
dc9cec2611 | ||
|
|
c9aeae757b | ||
|
|
094c2682bd | ||
|
|
066ee52615 | ||
|
|
ee1c9b284a | ||
|
|
d9fba94983 | ||
|
|
e02bedcf82 | ||
|
|
1552470413 | ||
|
|
e2f3c2259b | ||
|
|
249bd99656 | ||
|
|
b36196286a | ||
|
|
b21780b738 | ||
|
|
207ec81821 | ||
|
|
d61aaf393a | ||
|
|
19c44c9b62 | ||
|
|
4deabf5e01 | ||
|
|
1a6194e9f0 | ||
|
|
156a0b13d9 | ||
|
|
61a7f7a567 | ||
|
|
dbcb9df22b | ||
|
|
e2ad1190ac | ||
|
|
c0f9058f15 | ||
|
|
12859e575a | ||
|
|
3f765c356a | ||
|
|
fd8b540a66 | ||
|
|
29267593c2 | ||
|
|
1e74805aa4 | ||
|
|
12685aa54a | ||
|
|
04f07f4c15 | ||
|
|
df386a3b3f | ||
|
|
13c49ad865 | ||
|
|
7c01bba4f4 | ||
|
|
950d1199c2 | ||
|
|
38d1381c02 | ||
|
|
98f15d001f | ||
|
|
a379530d41 | ||
|
|
e19b67cb79 | ||
|
|
e883a559ca | ||
|
|
713f6f32e1 | ||
|
|
872b36c11d | ||
|
|
f761c25dcd | ||
|
|
38e1991f82 | ||
|
|
13d3b3a3ce | ||
|
|
0c2a13b468 | ||
|
|
4e7408dc25 | ||
|
|
76dac9c09c | ||
|
|
9339058fc3 | ||
|
|
8e3e06a6e9 | ||
|
|
fd80d784f4 | ||
|
|
ae4f6309e8 | ||
|
|
c466537a26 | ||
|
|
001c915c21 | ||
|
|
91a7102f11 | ||
|
|
a451e90374 | ||
|
|
c6a6788694 | ||
|
|
522df2a355 | ||
|
|
863de88671 | ||
|
|
cb57a1ca1f | ||
|
|
32098e5a13 | ||
|
|
210d673ef0 | ||
|
|
0b5b6113ee | ||
|
|
d5c98165ea | ||
|
|
b8d22bc572 | ||
|
|
69808ba523 | ||
|
|
aabfba9599 | ||
|
|
135620b14a | ||
|
|
78a4974de9 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
raw
|
||||
presentation
|
||||
test.coffee
|
||||
parser.output
|
||||
|
||||
102
Cakefile
Normal file
102
Cakefile
Normal file
@@ -0,0 +1,102 @@
|
||||
fs: require 'fs'
|
||||
{helpers}: require('./lib/helpers')
|
||||
CoffeeScript: require './lib/coffee-script'
|
||||
{spawn, exec}: require('child_process')
|
||||
|
||||
# Run a CoffeeScript through our node/coffee interpreter.
|
||||
run: (args) ->
|
||||
proc: spawn 'bin/coffee', args
|
||||
proc.stderr.addListener 'data', (buffer) -> puts buffer.toString()
|
||||
proc.addListener 'exit', (status) -> process.exit(1) if status != 0
|
||||
|
||||
option '-p', '--prefix [DIR]', 'set the installation prefix for `cake install`'
|
||||
|
||||
task 'install', 'install CoffeeScript into /usr/local (or --prefix)', (options) ->
|
||||
base: options.prefix or '/usr/local'
|
||||
lib: "$base/lib/coffee-script"
|
||||
bin: "$base/bin"
|
||||
exec([
|
||||
"mkdir -p $lib $bin"
|
||||
"cp -rf bin lib LICENSE README package.json src vendor $lib"
|
||||
"ln -sf $lib/bin/coffee $base/bin/coffee"
|
||||
"ln -sf $lib/bin/cake $base/bin/cake"
|
||||
"mkdir -p ~/.node_libraries"
|
||||
"ln -sf $lib/lib ~/.node_libraries/coffee-script"
|
||||
].join(' && '), (err, stdout, stderr) ->
|
||||
if err then print stderr
|
||||
)
|
||||
|
||||
|
||||
task 'build', 'build the CoffeeScript language from source', ->
|
||||
files: fs.readdirSync 'src'
|
||||
files: 'src/' + file for file in files when file.match(/\.coffee$/)
|
||||
run ['-c', '-o', 'lib'].concat(files)
|
||||
|
||||
|
||||
task 'build:full', 'rebuild the source twice, and run the tests', ->
|
||||
exec 'bin/cake build && bin/cake build && bin/cake test', (err, stdout, stderr) ->
|
||||
print stdout if stdout
|
||||
print stderr if stderr
|
||||
throw err if err
|
||||
|
||||
|
||||
task 'build:parser', 'rebuild the Jison parser (run build first)', ->
|
||||
require.paths.unshift 'vendor/jison/lib'
|
||||
parser: require('./lib/grammar').parser
|
||||
js: parser.generate()
|
||||
parser_path: 'lib/parser.js'
|
||||
fs.writeFile parser_path, js
|
||||
|
||||
|
||||
task 'build:ultraviolet', 'build and install the Ultraviolet syntax highlighter', ->
|
||||
exec 'plist2syntax ../coffee-script-tmbundle/Syntaxes/CoffeeScript.tmLanguage', (err) ->
|
||||
throw err if err
|
||||
exec 'sudo mv coffeescript.yaml /usr/local/lib/ruby/gems/1.8/gems/ultraviolet-0.10.2/syntax/coffeescript.syntax'
|
||||
|
||||
|
||||
task 'build:browser', 'rebuild the merged script for inclusion in the browser', ->
|
||||
exec 'rake browser', (err) ->
|
||||
throw err if err
|
||||
|
||||
|
||||
task 'doc:site', 'watch and continually rebuild the documentation for the website', ->
|
||||
exec 'rake doc'
|
||||
|
||||
|
||||
task 'doc:source', 'rebuild the internal documentation', ->
|
||||
exec 'docco src/*.coffee && cp -rf docs documentation && rm -r docs', (err) ->
|
||||
throw err if err
|
||||
|
||||
|
||||
task 'doc:underscore', 'rebuild the Underscore.coffee documentation page', ->
|
||||
exec 'docco examples/underscore.coffee && cp -rf docs documentation && rm -r docs', (err) ->
|
||||
throw err if err
|
||||
|
||||
|
||||
task 'test', 'run the CoffeeScript language test suite', ->
|
||||
helpers.extend global, require 'assert'
|
||||
passed_tests: failed_tests: 0
|
||||
start_time: new Date()
|
||||
original_ok: ok
|
||||
helpers.extend global, {
|
||||
ok: (args...) -> passed_tests += 1; original_ok(args...)
|
||||
CoffeeScript: CoffeeScript
|
||||
}
|
||||
red: '\033[0;31m'
|
||||
green: '\033[0;32m'
|
||||
reset: '\033[0m'
|
||||
process.addListener 'exit', ->
|
||||
time: ((new Date() - start_time) / 1000).toFixed(2)
|
||||
message: "passed $passed_tests tests in $time seconds$reset"
|
||||
puts(if failed_tests then "${red}failed $failed_tests and $message" else "$green$message")
|
||||
fs.readdir 'test', (err, files) ->
|
||||
files.forEach (file) ->
|
||||
return unless file.match(/\.coffee$/i)
|
||||
source: path.join 'test', file
|
||||
fs.readFile source, (err, code) ->
|
||||
try
|
||||
CoffeeScript.run code.toString(), {source: source}
|
||||
catch err
|
||||
failed_tests += 1
|
||||
puts "${red}failed:${reset} $source"
|
||||
puts err.stack
|
||||
33
README
33
README
@@ -22,20 +22,41 @@
|
||||
|
||||
CoffeeScript is a little language that compiles into JavaScript.
|
||||
|
||||
Install the compiler:
|
||||
gem install coffee-script
|
||||
Install Node.js, and then the CoffeeScript compiler:
|
||||
sudo bin/cake install
|
||||
|
||||
Compile a script:
|
||||
coffee /path/to/script.coffee
|
||||
|
||||
For documentation, usage, and examples, see:
|
||||
http://jashkenas.github.com/coffee-script/
|
||||
http://coffeescript.org/
|
||||
|
||||
To suggest a feature or report a bug:
|
||||
To suggest a feature, report a bug, or general discussion:
|
||||
http://github.com/jashkenas/coffee-script/issues/
|
||||
|
||||
If you'd like to chat, drop by #coffeescript on Freenode IRC,
|
||||
or on webchat.freenode.net.
|
||||
|
||||
The source repository:
|
||||
git://github.com/jashkenas/coffee-script.git
|
||||
|
||||
To build CoffeeScript from source, install the "racc" gem and
|
||||
run "rake build:parser". Then bin/coffee will work.
|
||||
|
||||
Contributors:
|
||||
|
||||
Stan Angeloff (StanAngeloff)
|
||||
Jeremy Ashkenas (jashkenas)
|
||||
Zach Carter (zaach)
|
||||
Tim Cuthbertson (gfxmonk)
|
||||
Mathieu D'Amours (matehat)
|
||||
Chris Hoffman (cehoffman)
|
||||
Jason Huggins (hugs)
|
||||
Timothy Jones (Tesco)
|
||||
Chris Lloyd (chrislloyd)
|
||||
Matt Lyon (mattly)
|
||||
Jeff Olson (olsonjeffery)
|
||||
Nathan Ostgard (noonat)
|
||||
Samuel Reis (grgh)
|
||||
Tom Robinson (tlrobinson)
|
||||
Tim Smart (Tim-Smart)
|
||||
Dr. Nic Williams (drnic)
|
||||
|
||||
65
Rakefile
65
Rakefile
@@ -1,52 +1,15 @@
|
||||
require 'erb'
|
||||
require 'fileutils'
|
||||
require 'rake/testtask'
|
||||
|
||||
desc "Run all tests"
|
||||
task :test do
|
||||
$LOAD_PATH.unshift(File.expand_path('test'))
|
||||
require 'redgreen' if Gem.available?('redgreen')
|
||||
require 'test/unit'
|
||||
Dir['test/*/**/test_*.rb'].each {|test| require test }
|
||||
end
|
||||
|
||||
namespace :build do
|
||||
|
||||
desc "Recompile the Racc parser (pass -v and -g for verbose debugging)"
|
||||
task :parser, :racc_args do |t, args|
|
||||
sh "racc #{args[:racc_args]} -o lib/coffee_script/parser.rb lib/coffee_script/grammar.y"
|
||||
end
|
||||
|
||||
desc "Compile the Narwhal interface"
|
||||
task :narwhal do
|
||||
sh "bin/coffee src/narwhal/*.coffee -o lib/coffee_script/narwhal"
|
||||
end
|
||||
|
||||
desc "Continually compile the CoffeeScript/Node.js components with --watch"
|
||||
task :node do
|
||||
sh "bin/coffee -w src/*.coffee -o lib/coffee_script/"
|
||||
end
|
||||
|
||||
desc "Compile and install the Ultraviolet syntax highlighter"
|
||||
task :ultraviolet do
|
||||
sh "plist2syntax extras/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage"
|
||||
sh "sudo mv coffeescript.yaml /usr/local/lib/ruby/gems/1.8/gems/ultraviolet-0.10.2/syntax/coffeescript.syntax"
|
||||
end
|
||||
|
||||
desc "Rebuild the Underscore.coffee documentation page"
|
||||
task :underscore do
|
||||
sh "uv -s coffeescript -t idle -h examples/underscore.coffee > documentation/underscore.html"
|
||||
end
|
||||
|
||||
end
|
||||
require 'rubygems'
|
||||
require 'yui/compressor'
|
||||
|
||||
desc "Build the documentation page"
|
||||
task :doc do
|
||||
source = 'documentation/index.html.erb'
|
||||
child = fork { exec "bin/coffee documentation/coffee/*.coffee -o documentation/js -w" }
|
||||
child = fork { exec "bin/coffee -c documentation/coffee/*.coffee -o documentation/js -w" }
|
||||
at_exit { Process.kill("INT", child) }
|
||||
Signal.trap("INT") { exit }
|
||||
# `uv -t idle -s coffeescript -h examples/underscore.coffee > documentation/underscore.html`
|
||||
loop do
|
||||
mtime = File.stat(source).mtime
|
||||
if !@mtime || mtime > @mtime
|
||||
@@ -58,21 +21,11 @@ task :doc do
|
||||
end
|
||||
end
|
||||
|
||||
namespace :gem do
|
||||
|
||||
desc 'Build and install the coffee-script gem'
|
||||
task :install do
|
||||
verbose = "lib/coffee_script/parser.output"
|
||||
FileUtils.rm(verbose) if File.exists?(verbose)
|
||||
sh "gem build coffee-script.gemspec"
|
||||
sh "sudo gem install #{Dir['*.gem'].join(' ')} --local --no-ri --no-rdoc"
|
||||
end
|
||||
|
||||
desc 'Uninstall the coffee-script gem'
|
||||
task :uninstall do
|
||||
sh "sudo gem uninstall -x coffee-script"
|
||||
end
|
||||
|
||||
desc "Build the single concatenated and minified script for the browser"
|
||||
task :browser do
|
||||
sources = %w(helpers.js rewriter.js lexer.js parser.js scope.js nodes.js coffee-script.js)
|
||||
code = sources.map {|s| File.read('lib/' + s) }.join('')
|
||||
code = YUI::JavaScriptCompressor.new.compress(code)
|
||||
File.open('extras/coffee-script.js', 'w+') {|f| f.write(code) }
|
||||
end
|
||||
|
||||
task :default => :test
|
||||
8
bin/cake
Executable file
8
bin/cake
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
|
||||
|
||||
require(lib + '/helpers').helpers.extend(global, require('sys'));
|
||||
require(lib + '/cake').run();
|
||||
@@ -1,5 +1,8 @@
|
||||
#!/usr/bin/env ruby
|
||||
#!/usr/bin/env node
|
||||
|
||||
require "#{File.dirname(__FILE__)}/../lib/coffee_script/command_line.rb"
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
|
||||
|
||||
CoffeeScript::CommandLine.new
|
||||
require(lib + '/helpers').helpers.extend(global, require('sys'));
|
||||
require(lib + '/command').run();
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
Gem::Specification.new do |s|
|
||||
s.name = 'coffee-script'
|
||||
s.version = '0.3.2' # Keep version in sync with coffee-script.rb
|
||||
s.date = '2010-2-8'
|
||||
|
||||
s.homepage = "http://jashkenas.github.com/coffee-script/"
|
||||
s.summary = "The CoffeeScript Compiler"
|
||||
s.description = <<-EOS
|
||||
CoffeeScript is a little language that compiles into JavaScript. Think
|
||||
of it as JavaScript's less ostentatious kid brother -- the same genes,
|
||||
roughly the same height, but a different sense of style. Apart from a
|
||||
handful of bonus goodies, statements in CoffeeScript correspond
|
||||
one-to-one with their equivalent in JavaScript, it's just another
|
||||
way of saying it.
|
||||
EOS
|
||||
|
||||
s.authors = ['Jeremy Ashkenas']
|
||||
s.email = 'jashkenas@gmail.com'
|
||||
s.rubyforge_project = 'coffee-script'
|
||||
s.has_rdoc = false
|
||||
|
||||
s.require_paths = ['lib']
|
||||
s.executables = ['coffee']
|
||||
|
||||
s.files = Dir['bin/*', 'examples/*', 'extras/**/*', 'lib/**/*',
|
||||
'coffee-script.gemspec', 'LICENSE', 'README', 'package.json']
|
||||
end
|
||||
@@ -1,4 +0,0 @@
|
||||
backwards: ->
|
||||
alert arguments.reverse()
|
||||
|
||||
backwards "stairway", "to", "heaven"
|
||||
@@ -1,5 +1,5 @@
|
||||
# Eat lunch.
|
||||
lunch: eat(food) for food in ['toast', 'cheese', 'wine']
|
||||
lunch: eat food for food in ['toast', 'cheese', 'wine']
|
||||
|
||||
# Naive collision detection.
|
||||
for roid in asteroids
|
||||
|
||||
5
documentation/coffee/binding.coffee
Normal file
5
documentation/coffee/binding.coffee
Normal file
@@ -0,0 +1,5 @@
|
||||
url: "documentation/coffee/binding.coffee"
|
||||
|
||||
get_source: jQuery.get <- jQuery, url
|
||||
|
||||
get_source (response) -> alert response
|
||||
3
documentation/coffee/cake_tasks.coffee
Normal file
3
documentation/coffee/cake_tasks.coffee
Normal file
@@ -0,0 +1,3 @@
|
||||
task 'test', 'run each of the unit tests', ->
|
||||
for test in test_files
|
||||
fs.readFile test, (err, code) -> eval coffee.compile code
|
||||
29
documentation/coffee/classes.coffee
Normal file
29
documentation/coffee/classes.coffee
Normal file
@@ -0,0 +1,29 @@
|
||||
class Animal
|
||||
move: (meters) ->
|
||||
alert @name + " moved " + meters + "m."
|
||||
|
||||
class Snake extends Animal
|
||||
constructor: (name) ->
|
||||
@name: name
|
||||
|
||||
move: ->
|
||||
alert "Slithering..."
|
||||
super 5
|
||||
|
||||
class Horse extends Animal
|
||||
constructor: (name) ->
|
||||
@name: name
|
||||
|
||||
move: ->
|
||||
alert "Galloping..."
|
||||
super 45
|
||||
|
||||
sam: new Snake "Sammy the Python"
|
||||
tom: new Horse "Tommy the Palomino"
|
||||
|
||||
sam.move()
|
||||
tom.move()
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,4 +6,4 @@ if happy and knows_it
|
||||
|
||||
date: if friday then sue else jill
|
||||
|
||||
expensive ||= do_the_math()
|
||||
expensive: or do_the_math()
|
||||
2
documentation/coffee/interpolation.coffee
Normal file
2
documentation/coffee/interpolation.coffee
Normal file
@@ -0,0 +1,2 @@
|
||||
author: "Wittgenstein"
|
||||
quote: "A picture is a fact. -- $author"
|
||||
6
documentation/coffee/interpolation_expression.coffee
Normal file
6
documentation/coffee/interpolation_expression.coffee
Normal file
@@ -0,0 +1,6 @@
|
||||
sentence: "${ 22 / 7 } is a decent approximation of π"
|
||||
|
||||
sep: "[.\\/\\- ]"
|
||||
dates: /\d+$sep\d+$sep\d+/g
|
||||
|
||||
|
||||
@@ -10,4 +10,4 @@ futurists: {
|
||||
}
|
||||
}
|
||||
|
||||
{poet: {name: poet, address: [street, city]}}: futurists
|
||||
{poet: {name, address: [street, city]}}: futurists
|
||||
7
documentation/coffee/patterns_and_splats.coffee
Normal file
7
documentation/coffee/patterns_and_splats.coffee
Normal file
@@ -0,0 +1,7 @@
|
||||
tag: "<impossible>"
|
||||
|
||||
[open, contents..., close]: tag.split("")
|
||||
|
||||
|
||||
|
||||
|
||||
2
documentation/coffee/prototypes.coffee
Normal file
2
documentation/coffee/prototypes.coffee
Normal file
@@ -0,0 +1,2 @@
|
||||
String::dasherize: ->
|
||||
this.replace(/_/g, "-")
|
||||
@@ -1,25 +0,0 @@
|
||||
Animal: ->
|
||||
Animal::move: (meters) ->
|
||||
alert @name + " moved " + meters + "m."
|
||||
|
||||
Snake: (name) -> @name: name
|
||||
Snake extends Animal
|
||||
Snake::move: ->
|
||||
alert "Slithering..."
|
||||
super 5
|
||||
|
||||
Horse: (name) -> @name: name
|
||||
Horse extends Animal
|
||||
Horse::move: ->
|
||||
alert "Galloping..."
|
||||
super 45
|
||||
|
||||
sam: new Snake "Sammy the Python"
|
||||
tom: new Horse "Tommy the Palomino"
|
||||
|
||||
sam.move()
|
||||
tom.move()
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Econ 101
|
||||
if this.studying_economics
|
||||
while supply > demand then buy()
|
||||
while supply < demand then sell()
|
||||
buy() while supply > demand
|
||||
sell() until supply > demand
|
||||
|
||||
# Nursery Rhyme
|
||||
num: 6
|
||||
|
||||
@@ -1,147 +0,0 @@
|
||||
pre.amy .PolymorphicVariants {
|
||||
color: #60B0FF;
|
||||
font-style: italic;
|
||||
}
|
||||
pre.amy .KeywordDecorator {
|
||||
color: #D0D0FF;
|
||||
}
|
||||
pre.amy .Punctuation {
|
||||
color: #805080;
|
||||
}
|
||||
pre.amy .InheritedClass {
|
||||
}
|
||||
pre.amy .InvalidDepricated {
|
||||
background-color: #CC66FF;
|
||||
color: #200020;
|
||||
}
|
||||
pre.amy .LibraryVariable {
|
||||
}
|
||||
pre.amy .TokenReferenceOcamlyacc {
|
||||
color: #3CB0D0;
|
||||
}
|
||||
pre.amy .Storage {
|
||||
color: #B0FFF0;
|
||||
}
|
||||
pre.amy .KeywordOperator {
|
||||
color: #A0A0FF;
|
||||
}
|
||||
pre.amy .CharacterConstant {
|
||||
color: #666666;
|
||||
}
|
||||
pre.amy .line-numbers {
|
||||
background-color: #800000;
|
||||
color: #000000;
|
||||
}
|
||||
pre.amy .ClassName {
|
||||
color: #70E080;
|
||||
}
|
||||
pre.amy .Int64Constant {
|
||||
font-style: italic;
|
||||
}
|
||||
pre.amy .NonTerminalReferenceOcamlyacc {
|
||||
color: #C0F0F0;
|
||||
}
|
||||
pre.amy .TokenDefinitionOcamlyacc {
|
||||
color: #3080A0;
|
||||
}
|
||||
pre.amy .ClassType {
|
||||
color: #70E0A0;
|
||||
}
|
||||
pre.amy .ControlKeyword {
|
||||
color: #80A0FF;
|
||||
}
|
||||
pre.amy .LineNumberDirectives {
|
||||
text-decoration: underline;
|
||||
color: #C080C0;
|
||||
}
|
||||
pre.amy .FloatingPointConstant {
|
||||
text-decoration: underline;
|
||||
}
|
||||
pre.amy .Int32Constant {
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.amy .TagName {
|
||||
color: #009090;
|
||||
}
|
||||
pre.amy .ModuleTypeDefinitions {
|
||||
text-decoration: underline;
|
||||
color: #B000B0;
|
||||
}
|
||||
pre.amy .Integer {
|
||||
color: #7090B0;
|
||||
}
|
||||
pre.amy .Camlp4TempParser {
|
||||
}
|
||||
pre.amy .InvalidIllegal {
|
||||
font-weight: bold;
|
||||
background-color: #FFFF00;
|
||||
color: #400080;
|
||||
}
|
||||
pre.amy .LibraryConstant {
|
||||
background-color: #200020;
|
||||
}
|
||||
pre.amy .ModuleDefinitions {
|
||||
color: #B000B0;
|
||||
}
|
||||
pre.amy .Variants {
|
||||
color: #60B0FF;
|
||||
}
|
||||
pre.amy .CompilerDirectives {
|
||||
color: #C080C0;
|
||||
}
|
||||
pre.amy .FloatingPointInfixOperator {
|
||||
text-decoration: underline;
|
||||
}
|
||||
pre.amy .BuiltInConstant1 {
|
||||
}
|
||||
pre.amy {
|
||||
background-color: #200020;
|
||||
color: #D0D0FF;
|
||||
}
|
||||
pre.amy .FunctionArgument {
|
||||
color: #80B0B0;
|
||||
}
|
||||
pre.amy .FloatingPointPrefixOperator {
|
||||
text-decoration: underline;
|
||||
}
|
||||
pre.amy .NativeintConstant {
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.amy .BuiltInConstant {
|
||||
color: #707090;
|
||||
}
|
||||
pre.amy .BooleanConstant {
|
||||
color: #8080A0;
|
||||
}
|
||||
pre.amy .LibraryClassType {
|
||||
}
|
||||
pre.amy .TagAttribute {
|
||||
}
|
||||
pre.amy .Keyword {
|
||||
color: #A080FF;
|
||||
}
|
||||
pre.amy .UserDefinedConstant {
|
||||
}
|
||||
pre.amy .String {
|
||||
color: #999999;
|
||||
}
|
||||
pre.amy .Camlp4Code {
|
||||
background-color: #350060;
|
||||
}
|
||||
pre.amy .NonTerminalDefinitionOcamlyacc {
|
||||
color: #90E0E0;
|
||||
}
|
||||
pre.amy .FunctionName {
|
||||
color: #50A0A0;
|
||||
}
|
||||
pre.amy .SupportModules {
|
||||
color: #A00050;
|
||||
}
|
||||
pre.amy .Variable {
|
||||
color: #008080;
|
||||
}
|
||||
pre.amy .Comment {
|
||||
background-color: #200020;
|
||||
color: #404080;
|
||||
font-style: italic;
|
||||
}
|
||||
@@ -1,29 +1,29 @@
|
||||
body {
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
background: #f3f3f9;
|
||||
color: #191933;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
div.container {
|
||||
width: 950px;
|
||||
margin: 50px 0 50px 50px;
|
||||
margin: 100px 0 50px 50px;
|
||||
}
|
||||
p {
|
||||
padding-left: 13px;
|
||||
p, li {
|
||||
width: 625px;
|
||||
}
|
||||
a {
|
||||
color: #000055;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
padding-left: 13px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
br.clear {
|
||||
height: 0;
|
||||
clear: both;
|
||||
}
|
||||
ul {
|
||||
padding-left: 20px;
|
||||
}
|
||||
b.header {
|
||||
color: #000055;
|
||||
display: block;
|
||||
@@ -31,7 +31,7 @@ b.header {
|
||||
font-size: 16px;
|
||||
}
|
||||
li {
|
||||
margin-bottom: 7px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
table {
|
||||
margin: 16px 0 0 13px; padding: 0;
|
||||
@@ -43,7 +43,7 @@ table {
|
||||
td {
|
||||
padding: 9px 15px 9px 0;
|
||||
}
|
||||
code, pre, tt {
|
||||
code, pre, tt, textarea {
|
||||
font-family: Monaco, Consolas, "Lucida Console", monospace;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
@@ -63,10 +63,15 @@ code, pre, tt {
|
||||
padding: 3px 0 3px 12px;
|
||||
font-size: 12px;
|
||||
}
|
||||
pre.no_bar {
|
||||
border-left: 0;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
div.code {
|
||||
position: relative;
|
||||
border: 1px solid #cacaca;
|
||||
background: #fff;
|
||||
background: #fafaff;
|
||||
padding: 7px 0 10px 0;
|
||||
-moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px;
|
||||
-webkit-box-shadow: 0px 0px 7px #cacaca;
|
||||
@@ -75,13 +80,188 @@ div.code {
|
||||
position: absolute;
|
||||
right: 8px; bottom: 8px;
|
||||
}
|
||||
div.code pre {
|
||||
div.code pre, div.code textarea {
|
||||
float: left;
|
||||
width: 450px;
|
||||
background: #fafaff;
|
||||
border-left: 1px dotted #559;
|
||||
padding: 0 0 0 12px;
|
||||
margin: 0;
|
||||
}
|
||||
div.code pre:first-child {
|
||||
border-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#fadeout {
|
||||
z-index: 50;
|
||||
position: fixed;
|
||||
left: 0; top: 0; right: 0;
|
||||
height: 100px;
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(rgba(255, 255, 255, 255)), to(rgba(255, 255, 255, 0)));
|
||||
background: -moz-linear-gradient(top, rgba(255, 255, 255, 255), rgba(255, 255, 255, 0));
|
||||
}
|
||||
|
||||
#flybar {
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
height: 50px;
|
||||
min-width: 490px;
|
||||
left: 40px; right: 40px; top: 25px;
|
||||
background: #ddd;
|
||||
padding-left: 235px;
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#d0d0d0));
|
||||
background: -moz-linear-gradient(top, #f5f5f5, #d0d0d0);
|
||||
filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr='#F5F5F5', EndColorStr='#D0D0D0');
|
||||
-webkit-border-radius: 20px; -moz-border-radius: 20px; border-radius: 20px;
|
||||
-webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;
|
||||
}
|
||||
#logo {
|
||||
display: block;
|
||||
width: 215px; height: 50px;
|
||||
background: url('../images/logo.png');
|
||||
position: absolute;
|
||||
top: 0px; left: 10px;
|
||||
}
|
||||
#error {
|
||||
position: absolute;
|
||||
-webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px;
|
||||
right: 15px; top: 15px; left: 722px;
|
||||
height: 15px;
|
||||
padding: 2px 5px;
|
||||
background: #fdcdcc;
|
||||
color: #864544;
|
||||
border: 1px solid #864544;
|
||||
font: 10px/15px Arial;
|
||||
overflow: hidden;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.navigation {
|
||||
height: 50px;
|
||||
font: bold 11px/50px Arial;
|
||||
text-transform: uppercase;
|
||||
position: relative;
|
||||
float: left;
|
||||
padding: 0 20px;
|
||||
border: 1px solid #bbb;
|
||||
border-top: 0; border-bottom: 0; border-left-width: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
body.full_screen .navigation {
|
||||
position: static;
|
||||
}
|
||||
.navigation.toc {
|
||||
border-left-width: 1px;
|
||||
}
|
||||
.navigation:hover,
|
||||
.navigation.active {
|
||||
background: #d0d0d0;
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(#f0f0f0), to(#c0c0c0));
|
||||
background: -moz-linear-gradient(top, #f0f0f0, #c0c0c0);
|
||||
filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr='#F0F0F0', EndColorStr='#C0C0C0');
|
||||
}
|
||||
.navigation .contents {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background: #fff;
|
||||
top: 50px; left: 0;
|
||||
padding: 5px 0;
|
||||
-webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px;
|
||||
-webkit-border-top-left-radius: 0; -moz-border-radius-topleft: 0;
|
||||
-webkit-border-top-right-radius: 0; -moz-border-radius-topright: 0;
|
||||
-webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;
|
||||
}
|
||||
.navigation.active .contents {
|
||||
display: block;
|
||||
}
|
||||
.navigation .contents.repl_wrapper {
|
||||
left: -162px;
|
||||
width: 700px;
|
||||
padding: 0;
|
||||
}
|
||||
body.full_screen .navigation .contents.repl_wrapper {
|
||||
position: fixed;
|
||||
width: auto; height: auto;
|
||||
left: 60px; top: 75px; right: 60px; bottom: 30px;
|
||||
}
|
||||
.navigation .contents.repl_wrapper .code {
|
||||
-webkit-box-shadow: none; -moz-box-shadow: none;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
position: static;
|
||||
}
|
||||
body.full_screen .navigation .contents.repl_wrapper .code {
|
||||
height: 100%;
|
||||
padding: 0; margin: 0;
|
||||
}
|
||||
.navigation .code button {
|
||||
bottom: 10px;
|
||||
text-transform: none;
|
||||
}
|
||||
.navigation .full_screen, .navigation .minimize {
|
||||
right: auto;
|
||||
left: 10px;
|
||||
display: none;
|
||||
}
|
||||
body.minimized .full_screen, body.full_screen .minimize {
|
||||
display: inline;
|
||||
}
|
||||
.navigation .contents a {
|
||||
display: block;
|
||||
width: 290px;
|
||||
text-transform: none;
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
height: 12px;
|
||||
line-height: 12px;
|
||||
padding: 4px 10px;
|
||||
}
|
||||
.navigation .contents a:hover {
|
||||
background: #f0f0f0;
|
||||
}
|
||||
|
||||
.bookmark {
|
||||
display: block;
|
||||
width: 0; height: 0;
|
||||
position: relative;
|
||||
top: -90px;
|
||||
}
|
||||
|
||||
#repl_source, #repl_results {
|
||||
background: transparent;
|
||||
outline: none;
|
||||
margin: 5px 0 20px;
|
||||
}
|
||||
#repl_source_wrap {
|
||||
margin-left: 5px;
|
||||
height: 250px;
|
||||
width: 307px;
|
||||
position: relative;
|
||||
float: left;
|
||||
}
|
||||
#repl_source {
|
||||
width: 96%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
resize: none;
|
||||
}
|
||||
#repl_results {
|
||||
font-family: Monaco, Consolas, "Lucida Console", monospace;
|
||||
text-transform: none;
|
||||
font-weight: normal;
|
||||
height: 260px;
|
||||
margin-bottom: 25px;
|
||||
overflow-y: auto;
|
||||
width: 370px;
|
||||
}
|
||||
body.full_screen #repl_results, body.full_screen #repl_source_wrap {
|
||||
width: auto; height: auto;
|
||||
position: absolute;
|
||||
margin-bottom: 0;
|
||||
top: 10px; left: 10px; right: 10px; bottom: 40px;
|
||||
}
|
||||
body.full_screen #repl_source_wrap {
|
||||
right: 50%;
|
||||
}
|
||||
body.full_screen #repl_results {
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ pre.idle .FunctionName {
|
||||
color: #21439C;
|
||||
}
|
||||
pre.idle .Variable {
|
||||
color: #A535AE;
|
||||
}
|
||||
pre.idle .Comment {
|
||||
color: #919191;
|
||||
|
||||
45
documentation/docs/cake.html
Normal file
45
documentation/docs/cake.html
Normal file
@@ -0,0 +1,45 @@
|
||||
<!DOCTYPE html> <html> <head> <title>cake.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> cake.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p><code>cake</code> is a simplified version of <a href="http://www.gnu.org/software/make/">Make</a>
|
||||
(<a href="http://rake.rubyforge.org/">Rake</a>, <a href="http://github.com/280north/jake">Jake</a>)
|
||||
for CoffeeScript. You define tasks with names and descriptions in a Cakefile,
|
||||
and can call them from the command line, or invoke them from other tasks.</p>
|
||||
|
||||
<p>Running <code>cake</code> with no arguments will print out a list of all the tasks in the
|
||||
current directory's Cakefile.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-2">#</a> </div> <p>External dependencies.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">fs: </span> <span class="nx">require</span> <span class="s1">'fs'</span>
|
||||
<span class="nv">path: </span> <span class="nx">require</span> <span class="s1">'path'</span>
|
||||
<span class="nv">helpers: </span> <span class="nx">require</span><span class="p">(</span><span class="s1">'./helpers'</span><span class="p">).</span><span class="nx">helpers</span>
|
||||
<span class="nv">optparse: </span> <span class="nx">require</span> <span class="s1">'./optparse'</span>
|
||||
<span class="nv">CoffeeScript: </span><span class="nx">require</span> <span class="s1">'./coffee-script'</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>Keep track of the list of defined tasks, the accepted options, and so on.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">tasks: </span><span class="p">{}</span>
|
||||
<span class="nv">options: </span><span class="p">{}</span>
|
||||
<span class="nv">switches: </span><span class="p">[]</span>
|
||||
<span class="nv">oparse: </span><span class="kc">null</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Mixin the top-level Cake functions for Cakefiles to use directly.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">helpers</span><span class="p">.</span><span class="nx">extend</span> <span class="nx">global</span><span class="p">,</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Define a Cake task with a short name, an optional sentence description,
|
||||
and the function to run as the action itself.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">task: </span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">description</span><span class="p">,</span> <span class="nx">action</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="p">[</span><span class="nx">action</span><span class="p">,</span> <span class="nx">description</span><span class="p">]</span><span class="o">:</span> <span class="p">[</span><span class="nx">description</span><span class="p">,</span> <span class="nx">action</span><span class="p">]</span> <span class="nx">unless</span> <span class="nx">action</span>
|
||||
<span class="nx">tasks</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span><span class="o">:</span> <span class="p">{</span><span class="nv">name: </span><span class="nx">name</span><span class="p">,</span> <span class="nv">description: </span><span class="nx">description</span><span class="p">,</span> <span class="nv">action: </span><span class="nx">action</span><span class="p">}</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Define an option that the Cakefile accepts. The parsed options hash,
|
||||
containing all of the command-line options passed, will be made available
|
||||
as the first argument to the action.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">option: </span><span class="p">(</span><span class="nx">letter</span><span class="p">,</span> <span class="nx">flag</span><span class="p">,</span> <span class="nx">description</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">switches</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="nx">letter</span><span class="p">,</span> <span class="nx">flag</span><span class="p">,</span> <span class="nx">description</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Invoke another task in the current Cakefile.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">invoke: </span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">no_such_task</span> <span class="nx">name</span> <span class="nx">unless</span> <span class="nx">tasks</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span>
|
||||
<span class="nx">tasks</span><span class="p">[</span><span class="nx">name</span><span class="p">].</span><span class="nx">action</span> <span class="nx">options</span>
|
||||
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Run <code>cake</code>. Executes all of the tasks you pass, in order. Note that Node's
|
||||
asynchrony may cause tasks to execute in a different order than you'd expect.
|
||||
If no tasks are passed, print the help screen.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run: </span><span class="o">-></span>
|
||||
<span class="nx">path</span><span class="p">.</span><span class="nx">exists</span> <span class="s1">'Cakefile'</span><span class="p">,</span> <span class="p">(</span><span class="nx">exists</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s2">"Cakefile not found in ${process.cwd()}"</span><span class="p">)</span> <span class="nx">unless</span> <span class="nx">exists</span>
|
||||
<span class="nv">args: </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">...</span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">.</span><span class="nx">length</span><span class="p">]</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="s1">'Cakefile'</span><span class="p">).</span><span class="nx">toString</span><span class="p">(),</span> <span class="p">{</span><span class="nv">source: </span><span class="s1">'Cakefile'</span><span class="p">}</span>
|
||||
<span class="nv">oparse: </span><span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">switches</span>
|
||||
<span class="k">return</span> <span class="nx">print_tasks</span><span class="p">()</span> <span class="nx">unless</span> <span class="nx">args</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">options: </span><span class="nx">oparse</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">args</span><span class="p">)</span>
|
||||
<span class="nx">invoke</span> <span class="nx">arg</span> <span class="k">for</span> <span class="nx">arg</span> <span class="k">in</span> <span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Display the list of Cake tasks in a format similar to <code>rake -T</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">print_tasks: </span><span class="o">-></span>
|
||||
<span class="nx">puts</span> <span class="s1">''</span>
|
||||
<span class="k">for</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">task</span> <span class="k">of</span> <span class="nx">tasks</span>
|
||||
<span class="nv">spaces: </span><span class="mi">20</span> <span class="o">-</span> <span class="nx">name</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">spaces: </span><span class="k">if</span> <span class="nx">spaces</span> <span class="o">></span> <span class="mi">0</span> <span class="k">then</span> <span class="p">(</span><span class="s1">' '</span> <span class="k">for</span> <span class="nx">i</span> <span class="k">in</span> <span class="p">[</span><span class="mi">0</span><span class="p">..</span><span class="nx">spaces</span><span class="p">]).</span><span class="nx">join</span><span class="p">(</span><span class="s1">''</span><span class="p">)</span> <span class="k">else</span> <span class="s1">''</span>
|
||||
<span class="nv">desc: </span> <span class="k">if</span> <span class="nx">task</span><span class="p">.</span><span class="nx">description</span> <span class="k">then</span> <span class="s2">"# $task.description"</span> <span class="k">else</span> <span class="s1">''</span>
|
||||
<span class="nx">puts</span> <span class="s2">"cake $name$spaces $desc"</span>
|
||||
<span class="nx">puts</span> <span class="nx">oparse</span><span class="p">.</span><span class="nx">help</span><span class="p">()</span> <span class="k">if</span> <span class="nx">switches</span><span class="p">.</span><span class="nx">length</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Print an error and exit when attempting to all an undefined task.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">no_such_task: </span><span class="p">(</span><span class="nx">task</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">puts</span> <span class="s2">"No such task: \"$task\""</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
65
documentation/docs/coffee-script.html
Normal file
65
documentation/docs/coffee-script.html
Normal file
@@ -0,0 +1,65 @@
|
||||
<!DOCTYPE html> <html> <head> <title>coffee-script.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> coffee-script.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>CoffeeScript can be used both on the server, as a command-line compiler based
|
||||
on Node.js/V8, or to run CoffeeScripts directly in the browser. This module
|
||||
contains the main entry functions for tokenzing, parsing, and compiling source
|
||||
CoffeeScript into JavaScript.</p>
|
||||
|
||||
<p>If included on a webpage, it will automatically sniff out, compile, and
|
||||
execute all scripts present in <code>text/coffeescript</code> tags.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-2">#</a> </div> <p>Set up dependencies correctly for both the server and the browser.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nx">process</span><span class="o">?</span>
|
||||
<span class="nv">path: </span> <span class="nx">require</span> <span class="s1">'path'</span>
|
||||
<span class="nv">Lexer: </span> <span class="nx">require</span><span class="p">(</span><span class="s1">'./lexer'</span><span class="p">).</span><span class="nx">Lexer</span>
|
||||
<span class="nv">parser: </span> <span class="nx">require</span><span class="p">(</span><span class="s1">'./parser'</span><span class="p">).</span><span class="nx">parser</span>
|
||||
<span class="nv">helpers: </span> <span class="nx">require</span><span class="p">(</span><span class="s1">'./helpers'</span><span class="p">).</span><span class="nx">helpers</span>
|
||||
<span class="nx">helpers</span><span class="p">.</span><span class="nx">extend</span> <span class="nx">global</span><span class="p">,</span> <span class="nx">require</span> <span class="s1">'./nodes'</span>
|
||||
<span class="k">if</span> <span class="nx">require</span><span class="p">.</span><span class="nx">registerExtension</span>
|
||||
<span class="nx">require</span><span class="p">.</span><span class="nx">registerExtension</span> <span class="s1">'.coffee'</span><span class="p">,</span> <span class="p">(</span><span class="nx">content</span><span class="p">)</span> <span class="o">-></span> <span class="nx">compile</span> <span class="nx">content</span>
|
||||
<span class="k">else</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nv">exports: </span><span class="k">this</span><span class="p">.</span><span class="nv">CoffeeScript: </span><span class="p">{}</span>
|
||||
<span class="nv">Lexer: </span> <span class="k">this</span><span class="p">.</span><span class="nx">Lexer</span>
|
||||
<span class="nv">parser: </span> <span class="k">this</span><span class="p">.</span><span class="nx">parser</span>
|
||||
<span class="nv">helpers: </span> <span class="k">this</span><span class="p">.</span><span class="nx">helpers</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>The current CoffeeScript version number.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.VERSION: </span><span class="s1">'0.6.2'</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Instantiate a Lexer for our use here.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lexer: </span><span class="k">new</span> <span class="nx">Lexer</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
|
||||
compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.compile: compile: </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">options: </span><span class="o">or</span> <span class="p">{}</span>
|
||||
<span class="k">try</span>
|
||||
<span class="p">(</span><span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="nx">code</span><span class="p">).</span><span class="nx">compile</span> <span class="nx">options</span>
|
||||
<span class="k">catch</span> <span class="nx">err</span>
|
||||
<span class="nv">err.message: </span><span class="s2">"In $options.source, $err.message"</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">source</span>
|
||||
<span class="k">throw</span> <span class="nx">err</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Tokenize a string of CoffeeScript code, and return the array of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.tokens: </span><span class="p">(</span><span class="nx">code</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="nx">code</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Tokenize and parse a string of CoffeeScript code, and return the AST. You can
|
||||
then compile it by calling <code>.compile()</code> on the root, or traverse it by using
|
||||
<code>.traverse()</code> with a callback.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.nodes: </span><span class="p">(</span><span class="nx">code</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="nx">code</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Compile and execute a string of CoffeeScript (on the server), correctly
|
||||
setting <code>__filename</code>, <code>__dirname</code>, and relative <code>require()</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run: </span><span class="p">((</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">module.filename: __filename: </span><span class="nx">options</span><span class="p">.</span><span class="nx">source</span>
|
||||
<span class="nv">__dirname: </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span><span class="p">(</span><span class="nx">__filename</span><span class="p">)</span>
|
||||
<span class="nb">eval</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span>
|
||||
<span class="p">)</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Extend CoffeeScript with a custom language extension. It should hook in to
|
||||
the <strong>Lexer</strong> (as a peer of any of the lexer's tokenizing methods), and
|
||||
push a token on to the stack that contains a <strong>Node</strong> as the value (as a
|
||||
peer of the nodes in <a href="nodes.html">nodes.coffee</a>).</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.extend: </span><span class="p">(</span><span class="nx">func</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">Lexer</span><span class="p">.</span><span class="nx">extensions</span><span class="p">.</span><span class="nx">push</span> <span class="nx">func</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>The real Lexer produces a generic stream of tokens. This object provides a
|
||||
thin wrapper around it, compatible with the Jison API. We can then pass it
|
||||
directly as a "Jison lexer".</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">parser.lexer: </span><span class="p">{</span>
|
||||
<span class="nv">lex: </span><span class="o">-></span>
|
||||
<span class="nv">token: </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">@pos</span><span class="p">]</span> <span class="o">or</span> <span class="p">[</span><span class="s2">""</span><span class="p">]</span>
|
||||
<span class="vi">@pos: </span><span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nv">yylineno: </span><span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nv">yytext: </span> <span class="nx">token</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nv">setInput: </span><span class="p">(</span><span class="nx">tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="vi">@tokens: </span><span class="nx">tokens</span>
|
||||
<span class="vi">@pos: </span><span class="mi">0</span>
|
||||
<span class="nv">upcomingInput: </span><span class="o">-></span> <span class="s2">""</span>
|
||||
<span class="nv">showPosition: </span><span class="o">-></span> <span class="nx">@pos</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Activate CoffeeScript in the browser by having it compile and evaluate
|
||||
all script tags with a content-type of <code>text/coffeescript</code>. This happens
|
||||
on page load. Unfortunately, the text contents of remote scripts cannot be
|
||||
accessed from the browser, so only inline script tags will work.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nb">document</span><span class="o">?</span> <span class="o">and</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span>
|
||||
<span class="nv">process_scripts: </span><span class="o">-></span>
|
||||
<span class="k">for</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="s1">'script'</span><span class="p">)</span> <span class="k">when</span> <span class="nx">tag</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s1">'text/coffeescript'</span>
|
||||
<span class="nb">eval</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">tag</span><span class="p">.</span><span class="nx">innerHTML</span>
|
||||
<span class="k">if</span> <span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span>
|
||||
<span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span> <span class="s1">'load'</span><span class="p">,</span> <span class="nx">process_scripts</span><span class="p">,</span> <span class="kc">false</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nb">window</span><span class="p">.</span><span class="nx">attachEvent</span>
|
||||
<span class="nb">window</span><span class="p">.</span><span class="nx">attachEvent</span> <span class="s1">'onload'</span><span class="p">,</span> <span class="nx">process_scripts</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
126
documentation/docs/command.html
Normal file
126
documentation/docs/command.html
Normal file
@@ -0,0 +1,126 @@
|
||||
<!DOCTYPE html> <html> <head> <title>command.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> command.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>The <code>coffee</code> utility. Handles command-line compilation of CoffeeScript
|
||||
into various forms: saved into <code>.js</code> files or printed to stdout, piped to
|
||||
<a href="http://javascriptlint.com/">JSLint</a> or recompiled every time the source is
|
||||
saved, printed as a token stream or as the syntax tree, or launch an
|
||||
interactive REPL.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-2">#</a> </div> <p>External dependencies.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">fs: </span> <span class="nx">require</span> <span class="s1">'fs'</span>
|
||||
<span class="nv">path: </span> <span class="nx">require</span> <span class="s1">'path'</span>
|
||||
<span class="nv">optparse: </span> <span class="nx">require</span> <span class="s1">'./optparse'</span>
|
||||
<span class="nv">CoffeeScript: </span> <span class="nx">require</span> <span class="s1">'./coffee-script'</span>
|
||||
<span class="p">{</span><span class="nx">spawn</span><span class="p">,</span> <span class="nx">exec</span><span class="p">}</span><span class="o">:</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'child_process'</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>The help banner that is printed when <code>coffee</code> is called without arguments.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BANNER: </span><span class="s1">'''</span>
|
||||
<span class="s1"> coffee compiles CoffeeScript source files into JavaScript.</span>
|
||||
|
||||
<span class="s1"> Usage:</span>
|
||||
<span class="s1"> coffee path/to/script.coffee</span>
|
||||
<span class="s1"> '''</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>The list of all the valid option flags that <code>coffee</code> knows how to handle.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">SWITCHES: </span><span class="p">[</span>
|
||||
<span class="p">[</span><span class="s1">'-c'</span><span class="p">,</span> <span class="s1">'--compile'</span><span class="p">,</span> <span class="s1">'compile to JavaScript and save as .js files'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-i'</span><span class="p">,</span> <span class="s1">'--interactive'</span><span class="p">,</span> <span class="s1">'run an interactive CoffeeScript REPL'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-o'</span><span class="p">,</span> <span class="s1">'--output [DIR]'</span><span class="p">,</span> <span class="s1">'set the directory for compiled JavaScript'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-w'</span><span class="p">,</span> <span class="s1">'--watch'</span><span class="p">,</span> <span class="s1">'watch scripts for changes, and recompile'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-p'</span><span class="p">,</span> <span class="s1">'--print'</span><span class="p">,</span> <span class="s1">'print the compiled JavaScript to stdout'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-l'</span><span class="p">,</span> <span class="s1">'--lint'</span><span class="p">,</span> <span class="s1">'pipe the compiled JavaScript through JSLint'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-s'</span><span class="p">,</span> <span class="s1">'--stdio'</span><span class="p">,</span> <span class="s1">'listen for and compile scripts over stdio'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-e'</span><span class="p">,</span> <span class="s1">'--eval'</span><span class="p">,</span> <span class="s1">'compile a string from the command line'</span><span class="p">]</span>
|
||||
<span class="p">[</span> <span class="s1">'--no-wrap'</span><span class="p">,</span> <span class="s1">'compile without the top-level function wrapper'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-t'</span><span class="p">,</span> <span class="s1">'--tokens'</span><span class="p">,</span> <span class="s1">'print the tokens that the lexer produces'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-n'</span><span class="p">,</span> <span class="s1">'--nodes'</span><span class="p">,</span> <span class="s1">'print the parse tree that Jison produces'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-v'</span><span class="p">,</span> <span class="s1">'--version'</span><span class="p">,</span> <span class="s1">'display CoffeeScript version'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s1">'-h'</span><span class="p">,</span> <span class="s1">'--help'</span><span class="p">,</span> <span class="s1">'display this help message'</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Top-level objects shared by all the functions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">options: </span><span class="p">{}</span>
|
||||
<span class="nv">sources: </span><span class="p">[]</span>
|
||||
<span class="nv">option_parser: </span><span class="kc">null</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Run <code>coffee</code> by parsing passed options and determining what action to take.
|
||||
Many flags cause us to divert before compiling anything. Flags passed after
|
||||
<code>--</code> will be passed verbatim to your script as arguments in <code>process.argv</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run: </span><span class="o">-></span>
|
||||
<span class="nx">parse_options</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="nx">usage</span><span class="p">()</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">help</span>
|
||||
<span class="k">return</span> <span class="nx">version</span><span class="p">()</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">version</span>
|
||||
<span class="k">return</span> <span class="nx">require</span> <span class="s1">'./repl'</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">interactive</span>
|
||||
<span class="k">return</span> <span class="nx">compile_stdio</span><span class="p">()</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">stdio</span>
|
||||
<span class="k">return</span> <span class="nx">compile_script</span> <span class="s1">'console'</span><span class="p">,</span> <span class="nx">sources</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nb">eval</span>
|
||||
<span class="k">return</span> <span class="nx">usage</span><span class="p">()</span> <span class="nx">unless</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">separator: </span><span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span> <span class="s1">'--'</span>
|
||||
<span class="nv">flags: </span><span class="p">[]</span>
|
||||
<span class="k">if</span> <span class="nx">separator</span> <span class="o">>=</span> <span class="mi">0</span>
|
||||
<span class="nv">flags: </span><span class="nx">sources</span><span class="p">[(</span><span class="nx">separator</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)...</span><span class="nx">sources</span><span class="p">.</span><span class="nx">length</span><span class="p">]</span>
|
||||
<span class="nv">sources: </span><span class="nx">sources</span><span class="p">[</span><span class="mi">0</span><span class="p">...</span><span class="nx">separator</span><span class="p">]</span>
|
||||
<span class="nv">process.ARGV: process.argv: </span><span class="nx">flags</span>
|
||||
<span class="nx">compile_scripts</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Asynchronously read in each CoffeeScript in a list of source files and
|
||||
compile them. If a directory is passed, recursively compile all source
|
||||
files in it and all subdirectories.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compile_scripts: </span><span class="o">-></span>
|
||||
<span class="k">for</span> <span class="nx">source</span> <span class="k">in</span> <span class="nx">sources</span>
|
||||
<span class="nv">base: </span><span class="nx">source</span>
|
||||
<span class="nv">compile: </span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">path</span><span class="p">.</span><span class="nx">exists</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">exists</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"File not found: $source"</span> <span class="nx">unless</span> <span class="nx">exists</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">stat</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">stats</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">stats</span><span class="p">.</span><span class="nx">isDirectory</span><span class="p">()</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">readdir</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">files</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">files</span>
|
||||
<span class="nx">compile</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">file</span><span class="p">)</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'.coffee'</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">code</span><span class="p">)</span> <span class="o">-></span> <span class="nx">compile_script</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">code</span><span class="p">.</span><span class="nx">toString</span><span class="p">(),</span> <span class="nx">base</span><span class="p">)</span>
|
||||
<span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">watch</span>
|
||||
<span class="nx">compile</span> <span class="nx">source</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Compile a single source script, containing the given code, according to the
|
||||
requested options. If evaluating the script directly sets <code>__filename</code>,
|
||||
<code>__dirname</code> and <code>module.filename</code> to be correct relative to the script's path.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compile_script: </span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">base</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">o: </span><span class="nx">options</span>
|
||||
<span class="nv">code_opts: </span><span class="nx">compile_options</span> <span class="nx">source</span>
|
||||
<span class="k">try</span>
|
||||
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">tokens</span> <span class="k">then</span> <span class="nx">print_tokens</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">tokens</span> <span class="nx">code</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">nodes</span> <span class="k">then</span> <span class="nx">puts</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">nodes</span><span class="p">(</span><span class="nx">code</span><span class="p">).</span><span class="nx">toString</span><span class="p">()</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">run</span> <span class="k">then</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">code_opts</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">js: </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">code_opts</span>
|
||||
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="k">then</span> <span class="nx">print</span> <span class="nx">js</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="k">then</span> <span class="nx">write_js</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">js</span><span class="p">,</span> <span class="nx">base</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">lint</span> <span class="k">then</span> <span class="nx">lint</span> <span class="nx">js</span>
|
||||
<span class="k">catch</span> <span class="nx">err</span>
|
||||
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">watch</span> <span class="k">then</span> <span class="nx">puts</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span> <span class="k">else</span> <span class="k">throw</span> <span class="nx">err</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Attach the appropriate listeners to compile scripts incoming over <strong>stdin</strong>,
|
||||
and write them back to <strong>stdout</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compile_stdio: </span><span class="o">-></span>
|
||||
<span class="nv">code: </span><span class="s1">''</span>
|
||||
<span class="nv">stdin: </span><span class="nx">process</span><span class="p">.</span><span class="nx">openStdin</span><span class="p">()</span>
|
||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">'data'</span><span class="p">,</span> <span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">code: </span><span class="o">+</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span> <span class="k">if</span> <span class="nx">buffer</span>
|
||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">'end'</span><span class="p">,</span> <span class="o">-></span>
|
||||
<span class="nx">compile_script</span> <span class="s1">'stdio'</span><span class="p">,</span> <span class="nx">code</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Watch a source CoffeeScript file using <code>fs.watchFile</code>, recompiling it every
|
||||
time the file is updated. May be used in combination with other options,
|
||||
such as <code>--lint</code> or <code>--print</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">watch: </span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">base</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">watchFile</span> <span class="nx">source</span><span class="p">,</span> <span class="p">{</span><span class="nv">persistent: </span><span class="kc">true</span><span class="p">,</span> <span class="nv">interval: </span><span class="mi">500</span><span class="p">},</span> <span class="p">(</span><span class="nx">curr</span><span class="p">,</span> <span class="nx">prev</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">curr</span><span class="p">.</span><span class="nx">mtime</span><span class="p">.</span><span class="nx">getTime</span><span class="p">()</span> <span class="o">is</span> <span class="nx">prev</span><span class="p">.</span><span class="nx">mtime</span><span class="p">.</span><span class="nx">getTime</span><span class="p">()</span>
|
||||
<span class="nx">puts</span> <span class="s2">"Compiled $source"</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">compile</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">code</span><span class="p">)</span> <span class="o">-></span> <span class="nx">compile_script</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">code</span><span class="p">.</span><span class="nx">toString</span><span class="p">(),</span> <span class="nx">base</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Write out a JavaScript source file with the compiled code. By default, files
|
||||
are written out in <code>cwd</code> as <code>.js</code> files with the same name, but the output
|
||||
directory can be customized with <code>--output</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">write_js: </span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">js</span><span class="p">,</span> <span class="nx">base</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">filename: </span><span class="nx">path</span><span class="p">.</span><span class="nx">basename</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">source</span><span class="p">))</span> <span class="o">+</span> <span class="s1">'.js'</span>
|
||||
<span class="nv">src_dir: </span> <span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">source</span>
|
||||
<span class="nv">base_dir: </span><span class="nx">src_dir</span><span class="p">.</span><span class="nx">substring</span> <span class="nx">base</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">dir: </span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">output</span> <span class="k">then</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">options</span><span class="p">.</span><span class="nx">output</span><span class="p">,</span> <span class="nx">base_dir</span> <span class="k">else</span> <span class="nx">src_dir</span>
|
||||
<span class="nv">js_path: </span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">dir</span><span class="p">,</span> <span class="nx">filename</span>
|
||||
<span class="nv">compile: </span> <span class="o">-></span> <span class="nx">fs</span><span class="p">.</span><span class="nx">writeFile</span> <span class="nx">js_path</span><span class="p">,</span> <span class="nx">js</span>
|
||||
<span class="nx">path</span><span class="p">.</span><span class="nx">exists</span> <span class="nx">dir</span><span class="p">,</span> <span class="p">(</span><span class="nx">exists</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">exists</span> <span class="k">then</span> <span class="nx">compile</span><span class="p">()</span> <span class="k">else</span> <span class="nx">exec</span> <span class="s2">"mkdir -p $dir"</span><span class="p">,</span> <span class="nx">compile</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>Pipe compiled JS through JSLint (requires a working <code>jsl</code> command), printing
|
||||
any errors or warnings that arise.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lint: </span><span class="p">(</span><span class="nx">js</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">print_it: </span><span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-></span> <span class="nx">print</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span>
|
||||
<span class="nv">jsl: </span><span class="nx">spawn</span> <span class="s1">'jsl'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'-nologo'</span><span class="p">,</span> <span class="s1">'-stdin'</span><span class="p">]</span>
|
||||
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">'data'</span><span class="p">,</span> <span class="nx">print_it</span>
|
||||
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stderr</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">'data'</span><span class="p">,</span> <span class="nx">print_it</span>
|
||||
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdin</span><span class="p">.</span><span class="nx">write</span> <span class="nx">js</span>
|
||||
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdin</span><span class="p">.</span><span class="nx">end</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>Pretty-print a stream of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">print_tokens: </span><span class="p">(</span><span class="nx">tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">strings: </span><span class="k">for</span> <span class="nx">token</span> <span class="k">in</span> <span class="nx">tokens</span>
|
||||
<span class="p">[</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span><span class="p">]</span><span class="o">:</span> <span class="p">[</span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">token</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">toString</span><span class="p">().</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\n/</span><span class="p">,</span> <span class="s1">'\\n'</span><span class="p">)]</span>
|
||||
<span class="s2">"[$tag $value]"</span>
|
||||
<span class="nx">puts</span> <span class="nx">strings</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s1">' '</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</a> </div> <p>Use the <a href="optparse.html">OptionParser module</a> to extract all options from
|
||||
<code>process.argv</code> that are specified in <code>SWITCHES</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">parse_options: </span><span class="o">-></span>
|
||||
<span class="nv">option_parser: </span><span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">SWITCHES</span><span class="p">,</span> <span class="nx">BANNER</span>
|
||||
<span class="nv">o: options: </span> <span class="nx">option_parser</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">)</span>
|
||||
<span class="nv">options.run: </span> <span class="o">not</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">lint</span><span class="p">)</span>
|
||||
<span class="nv">options.print: </span><span class="o">!!</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nb">eval</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">stdio</span> <span class="o">and</span> <span class="nx">o</span><span class="p">.</span><span class="nx">compile</span><span class="p">))</span>
|
||||
<span class="nv">sources: </span> <span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span><span class="p">[</span><span class="mi">2</span><span class="p">...</span><span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span><span class="p">.</span><span class="nx">length</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>The compile-time options to pass to the CoffeeScript compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compile_options: </span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">o: </span><span class="p">{</span><span class="nv">source: </span><span class="nx">source</span><span class="p">}</span>
|
||||
<span class="nx">o</span><span class="p">[</span><span class="s1">'no_wrap'</span><span class="p">]</span><span class="o">:</span> <span class="nx">options</span><span class="p">[</span><span class="s1">'no-wrap'</span><span class="p">]</span>
|
||||
<span class="nx">o</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</a> </div> <p>Print the <code>--help</code> usage message and exit.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">usage: </span><span class="o">-></span>
|
||||
<span class="nx">puts</span> <span class="nx">option_parser</span><span class="p">.</span><span class="nx">help</span><span class="p">()</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">0</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>Print the <code>--version</code> message and exit.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">version: </span><span class="o">-></span>
|
||||
<span class="nx">puts</span> <span class="s2">"CoffeeScript version $CoffeeScript.VERSION"</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">0</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
185
documentation/docs/docco.css
Normal file
185
documentation/docs/docco.css
Normal file
@@ -0,0 +1,185 @@
|
||||
/*--------------------- Layout and Typography ----------------------------*/
|
||||
body {
|
||||
font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #252519;
|
||||
margin: 0; padding: 0;
|
||||
}
|
||||
a {
|
||||
color: #261a3b;
|
||||
}
|
||||
a:visited {
|
||||
color: #261a3b;
|
||||
}
|
||||
p {
|
||||
margin: 0 0 15px 0;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin: 40px 0 15px 0;
|
||||
}
|
||||
h3, h4, h5, h6 {
|
||||
margin-top: 20px;
|
||||
}
|
||||
#container {
|
||||
position: relative;
|
||||
}
|
||||
#background {
|
||||
position: fixed;
|
||||
top: 0; left: 580px; right: 0; bottom: 0;
|
||||
background: #f5f5ff;
|
||||
border-left: 1px solid #e5e5ee;
|
||||
z-index: -1;
|
||||
}
|
||||
#jump_to, #jump_page {
|
||||
background: white;
|
||||
-webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;
|
||||
-webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px;
|
||||
font: 10px Arial;
|
||||
text-transform: uppercase;
|
||||
cursor: pointer;
|
||||
text-align: right;
|
||||
}
|
||||
#jump_to, #jump_wrapper {
|
||||
position: fixed;
|
||||
right: 0; top: 0;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
#jump_wrapper {
|
||||
padding: 0;
|
||||
display: none;
|
||||
}
|
||||
#jump_to:hover #jump_wrapper {
|
||||
display: block;
|
||||
}
|
||||
#jump_page {
|
||||
padding: 5px 0 3px;
|
||||
margin: 0 0 25px 25px;
|
||||
}
|
||||
#jump_page .source {
|
||||
display: block;
|
||||
padding: 5px 10px;
|
||||
text-decoration: none;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
#jump_page .source:hover {
|
||||
background: #f5f5ff;
|
||||
}
|
||||
#jump_page .source:first-child {
|
||||
}
|
||||
table td {
|
||||
border: 0;
|
||||
outline: 0;
|
||||
}
|
||||
td.docs, th.docs {
|
||||
max-width: 500px;
|
||||
min-width: 500px;
|
||||
min-height: 5px;
|
||||
padding: 10px 25px 1px 50px;
|
||||
vertical-align: top;
|
||||
text-align: left;
|
||||
}
|
||||
.docs pre {
|
||||
margin: 15px 0 15px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
.docs p tt, .docs p code {
|
||||
background: #f8f8ff;
|
||||
border: 1px solid #dedede;
|
||||
font-size: 12px;
|
||||
padding: 0 0.2em;
|
||||
}
|
||||
.octowrap {
|
||||
position: relative;
|
||||
}
|
||||
.octothorpe {
|
||||
font: 12px Arial;
|
||||
text-decoration: none;
|
||||
color: #454545;
|
||||
position: absolute;
|
||||
top: 3px; left: -20px;
|
||||
padding: 1px 2px;
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
}
|
||||
td.docs:hover .octothorpe {
|
||||
opacity: 1;
|
||||
}
|
||||
td.code, th.code {
|
||||
padding: 14px 15px 16px 50px;
|
||||
width: 100%;
|
||||
vertical-align: top;
|
||||
background: #f5f5ff;
|
||||
border-left: 1px solid #e5e5ee;
|
||||
}
|
||||
pre, tt, code {
|
||||
font-size: 12px; line-height: 18px;
|
||||
font-family: Monaco, Consolas, "Lucida Console", monospace;
|
||||
margin: 0; padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------- Syntax Highlighting -----------------------------*/
|
||||
td.linenos { background-color: #f0f0f0; padding-right: 10px; }
|
||||
span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
|
||||
body .hll { background-color: #ffffcc }
|
||||
body .c { color: #408080; font-style: italic } /* Comment */
|
||||
body .err { border: 1px solid #FF0000 } /* Error */
|
||||
body .k { color: #954121 } /* Keyword */
|
||||
body .o { color: #666666 } /* Operator */
|
||||
body .cm { color: #408080; font-style: italic } /* Comment.Multiline */
|
||||
body .cp { color: #BC7A00 } /* Comment.Preproc */
|
||||
body .c1 { color: #408080; font-style: italic } /* Comment.Single */
|
||||
body .cs { color: #408080; font-style: italic } /* Comment.Special */
|
||||
body .gd { color: #A00000 } /* Generic.Deleted */
|
||||
body .ge { font-style: italic } /* Generic.Emph */
|
||||
body .gr { color: #FF0000 } /* Generic.Error */
|
||||
body .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||
body .gi { color: #00A000 } /* Generic.Inserted */
|
||||
body .go { color: #808080 } /* Generic.Output */
|
||||
body .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
|
||||
body .gs { font-weight: bold } /* Generic.Strong */
|
||||
body .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||
body .gt { color: #0040D0 } /* Generic.Traceback */
|
||||
body .kc { color: #954121 } /* Keyword.Constant */
|
||||
body .kd { color: #954121; font-weight: bold } /* Keyword.Declaration */
|
||||
body .kn { color: #954121; font-weight: bold } /* Keyword.Namespace */
|
||||
body .kp { color: #954121 } /* Keyword.Pseudo */
|
||||
body .kr { color: #954121; font-weight: bold } /* Keyword.Reserved */
|
||||
body .kt { color: #B00040 } /* Keyword.Type */
|
||||
body .m { color: #666666 } /* Literal.Number */
|
||||
body .s { color: #219161 } /* Literal.String */
|
||||
body .na { color: #7D9029 } /* Name.Attribute */
|
||||
body .nb { color: #954121 } /* Name.Builtin */
|
||||
body .nc { color: #0000FF; font-weight: bold } /* Name.Class */
|
||||
body .no { color: #880000 } /* Name.Constant */
|
||||
body .nd { color: #AA22FF } /* Name.Decorator */
|
||||
body .ni { color: #999999; font-weight: bold } /* Name.Entity */
|
||||
body .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
|
||||
body .nf { color: #0000FF } /* Name.Function */
|
||||
body .nl { color: #A0A000 } /* Name.Label */
|
||||
body .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
|
||||
body .nt { color: #954121; font-weight: bold } /* Name.Tag */
|
||||
body .nv { color: #19469D } /* Name.Variable */
|
||||
body .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
|
||||
body .w { color: #bbbbbb } /* Text.Whitespace */
|
||||
body .mf { color: #666666 } /* Literal.Number.Float */
|
||||
body .mh { color: #666666 } /* Literal.Number.Hex */
|
||||
body .mi { color: #666666 } /* Literal.Number.Integer */
|
||||
body .mo { color: #666666 } /* Literal.Number.Oct */
|
||||
body .sb { color: #219161 } /* Literal.String.Backtick */
|
||||
body .sc { color: #219161 } /* Literal.String.Char */
|
||||
body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */
|
||||
body .s2 { color: #219161 } /* Literal.String.Double */
|
||||
body .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
|
||||
body .sh { color: #219161 } /* Literal.String.Heredoc */
|
||||
body .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
|
||||
body .sx { color: #954121 } /* Literal.String.Other */
|
||||
body .sr { color: #BB6688 } /* Literal.String.Regex */
|
||||
body .s1 { color: #219161 } /* Literal.String.Single */
|
||||
body .ss { color: #19469D } /* Literal.String.Symbol */
|
||||
body .bp { color: #954121 } /* Name.Builtin.Pseudo */
|
||||
body .vc { color: #19469D } /* Name.Variable.Class */
|
||||
body .vg { color: #19469D } /* Name.Variable.Global */
|
||||
body .vi { color: #19469D } /* Name.Variable.Instance */
|
||||
body .il { color: #666666 } /* Literal.Number.Integer.Long */
|
||||
423
documentation/docs/grammar.html
Normal file
423
documentation/docs/grammar.html
Normal file
@@ -0,0 +1,423 @@
|
||||
<!DOCTYPE html> <html> <head> <title>grammar.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> grammar.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>The CoffeeScript parser is generated by <a href="http://github.com/zaach/jison">Jison</a>
|
||||
from this grammar file. Jison is a bottom-up parser generator, similar in
|
||||
style to <a href="http://www.gnu.org/software/bison">Bison</a>, implemented in JavaScript.
|
||||
It can recognize <a href="http://en.wikipedia.org/wiki/LR_grammar">LALR(1), LR(0), SLR(1), and LR(1)</a>
|
||||
type grammars. To create the Jison parser, we list the pattern to match
|
||||
on the left-hand side, and the action to take (usually the creation of syntax
|
||||
tree nodes) on the right. As the parser runs, it
|
||||
shifts tokens from our token stream, from left to right, and
|
||||
<a href="http://en.wikipedia.org/wiki/Bottom-up_parsing">attempts to match</a>
|
||||
the token sequence against the rules below. When a match can be made, it
|
||||
reduces into the <a href="http://en.wikipedia.org/wiki/Terminal_and_nonterminal_symbols">nonterminal</a>
|
||||
(the enclosing name at the top), and we proceed from there.</p>
|
||||
|
||||
<p>If you run the <code>cake build:parser</code> command, Jison constructs a parse table
|
||||
from our rules and saves it into <code>lib/parser.js</code>.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-2">#</a> </div> <p>The only dependency is on the <strong>Jison.Parser</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">Parser: </span><span class="nx">require</span><span class="p">(</span><span class="s1">'jison'</span><span class="p">).</span><span class="nx">Parser</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <h2>Jison DSL</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Since we're going to be wrapped in a function by Jison in any case, if our
|
||||
action immediately returns a value, we can optimize by removing the function
|
||||
wrapper and just returning the value directly.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">unwrap: </span><span class="sr">/function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Our handy DSL for Jison grammar generation, thanks to
|
||||
<a href="http://github.com/creationix">Tim Caswell</a>. For every rule in the grammar,
|
||||
we pass the pattern-defining string, the action to run, and extra options,
|
||||
optionally. If no action is specified, we simply pass the value of the
|
||||
previous nonterminal.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">o: </span><span class="p">(</span><span class="nx">pattern_string</span><span class="p">,</span> <span class="nx">action</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="p">[</span><span class="nx">pattern_string</span><span class="p">,</span> <span class="s1">'$$ = $1;'</span><span class="p">,</span> <span class="nx">options</span><span class="p">]</span> <span class="nx">unless</span> <span class="nx">action</span>
|
||||
<span class="nv">action: </span><span class="k">if</span> <span class="nv">match: </span><span class="p">(</span><span class="nx">action</span> <span class="o">+</span> <span class="s1">''</span><span class="p">).</span><span class="nx">match</span><span class="p">(</span><span class="nx">unwrap</span><span class="p">)</span> <span class="k">then</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">else</span> <span class="s2">"($action())"</span>
|
||||
<span class="p">[</span><span class="nx">pattern_string</span><span class="p">,</span> <span class="s2">"$$ = $action;"</span><span class="p">,</span> <span class="nx">options</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <h2>Grammatical Rules</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>In all of the rules that follow, you'll see the name of the nonterminal as
|
||||
the key to a list of alternative matches. With each match's action, the
|
||||
dollar-sign variables are provided by Jison as references to the value of
|
||||
their numeric position, so in this rule:</p>
|
||||
|
||||
<pre><code>"Expression UNLESS Expression"
|
||||
</code></pre>
|
||||
|
||||
<p><code>$1</code> would be the value of the first <code>Expression</code>, <code>$2</code> would be the token
|
||||
for the <code>UNLESS</code> terminal, and <code>$3</code> would be the value of the second
|
||||
<code>Expression</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">grammar: </span><span class="p">{</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>The <strong>Root</strong> is the top-level node in the syntax tree. Since we parse bottom-up,
|
||||
all parsing must end here.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Root: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">""</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Expressions</span><span class="p">()</span>
|
||||
<span class="nx">o</span> <span class="s2">"TERMINATOR"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Expressions</span><span class="p">()</span>
|
||||
<span class="nx">o</span> <span class="s2">"Body"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Block TERMINATOR"</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Any list of statements and expressions, seperated by line breaks or semicolons.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Body: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Line"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"Body TERMINATOR Line"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">push</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Body TERMINATOR"</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Expressions and statements, which make up a line in a body.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Line: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Statement"</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Pure statements which cannot be expressions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Statement: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Return"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Throw"</span>
|
||||
<span class="nx">o</span> <span class="s2">"BREAK"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s2">"CONTINUE"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>All the different types of expressions in our language. The basic unit of
|
||||
CoffeeScript is the <strong>Expression</strong> -- everything that can be an expression
|
||||
is one. Expressions serve as the building blocks of many other rules, making
|
||||
them somewhat circular.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Expression: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Value"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Call"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Curry"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Code"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Operation"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Assign"</span>
|
||||
<span class="nx">o</span> <span class="s2">"If"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Try"</span>
|
||||
<span class="nx">o</span> <span class="s2">"While"</span>
|
||||
<span class="nx">o</span> <span class="s2">"For"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Switch"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Extends"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Class"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Splat"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Existence"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Comment"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Extension"</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>A an indented block of expressions. Note that the <a href="rewriter.html">Rewriter</a>
|
||||
will convert some postfix forms into blocks for us, by adjusting the
|
||||
token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Block: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"INDENT Body OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"INDENT OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Expressions</span><span class="p">()</span>
|
||||
<span class="nx">o</span> <span class="s2">"TERMINATOR Comment"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$2</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</a> </div> <p>A literal identifier, a variable name or property.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Identifier: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"IDENTIFIER"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>Alphanumerics are separated from the other <strong>Literal</strong> matchers because
|
||||
they can also serve as keys in object literals.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">AlphaNumeric: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"NUMBER"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s2">"STRING"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</a> </div> <p>All of our immediate values. These can (in general), be passed straight
|
||||
through and printed to JavaScript.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Literal: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"AlphaNumeric"</span>
|
||||
<span class="nx">o</span> <span class="s2">"JS"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s2">"REGEX"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s2">"TRUE"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s2">"FALSE"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="kc">false</span>
|
||||
<span class="nx">o</span> <span class="s2">"YES"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s2">"NO"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="kc">false</span>
|
||||
<span class="nx">o</span> <span class="s2">"ON"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s2">"OFF"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="kc">false</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>Assignment of a variable, property, or index to a value.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Assign: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Assignable ASSIGN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">AssignNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-18">#</a> </div> <p>Assignment when it happens within an object literal. The difference from
|
||||
the ordinary <strong>Assign</strong> is that these allow numbers and strings as keys.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">AssignObj: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Identifier"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s2">"AlphaNumeric"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Identifier ASSIGN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">AssignNode</span> <span class="k">new</span> <span class="nx">ValueNode</span><span class="p">(</span><span class="nx">$1</span><span class="p">),</span> <span class="nx">$3</span><span class="p">,</span> <span class="s1">'object'</span>
|
||||
<span class="nx">o</span> <span class="s2">"AlphaNumeric ASSIGN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">AssignNode</span> <span class="k">new</span> <span class="nx">ValueNode</span><span class="p">(</span><span class="nx">$1</span><span class="p">),</span> <span class="nx">$3</span><span class="p">,</span> <span class="s1">'object'</span>
|
||||
<span class="nx">o</span> <span class="s2">"Comment"</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-19">#</a> </div> <p>A return statement from a function body.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Return: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"RETURN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ReturnNode</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"RETURN"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ReturnNode</span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="s1">'null'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-20">#</a> </div> <p>A comment. Because CoffeeScript passes comments through to JavaScript, we
|
||||
have to parse comments like any other construct, and identify all of the
|
||||
positions in which they can occur in the grammar.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Comment: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"COMMENT"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">CommentNode</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s2">"HERECOMMENT"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">CommentNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="s1">'herecomment'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-21">#</a> </div> <p><a href="http://jashkenas.github.com/coffee-script/#existence">The existential operator</a>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Existence: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression ?"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ExistenceNode</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-22">#</a> </div> <p>The <strong>Code</strong> node is the function literal. It's defined by an indented block
|
||||
of <strong>Expressions</strong> preceded by a function arrow, with an optional parameter
|
||||
list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Code: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"PARAM_START ParamList PARAM_END FuncGlyph Block"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">CodeNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$5</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s2">"FuncGlyph Block"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">CodeNode</span> <span class="p">[],</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-23">#</a> </div> <p>CoffeeScript has two different symbols for functions. <code>-></code> is for ordinary
|
||||
functions, and <code>=></code> is for functions bound to the current value of <em>this</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">FuncGlyph: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"->"</span><span class="p">,</span> <span class="o">-></span> <span class="s1">'func'</span>
|
||||
<span class="nx">o</span> <span class="s2">"=>"</span><span class="p">,</span> <span class="o">-></span> <span class="s1">'boundfunc'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-24">#</a> </div> <p>An optional, trailing comma.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">OptComma: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">''</span>
|
||||
<span class="nx">o</span> <span class="s1">','</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-25">#</a> </div> <p>The list of parameters that a function accepts can be of any length.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ParamList: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">""</span><span class="p">,</span> <span class="o">-></span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s2">"Param"</span><span class="p">,</span> <span class="o">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"ParamList , Param"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[</span><span class="nx">$3</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-26">#</a> </div> <p>A single parameter in a function definition can be ordinary, or a splat
|
||||
that hoovers up the remaining arguments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Param: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"PARAM"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s2">"Param . . ."</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">SplatNode</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" 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="nv">Splat: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression . . ."</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">SplatNode</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" 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="nv">SimpleAssignable: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Identifier"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s2">"Value Accessor"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">push</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"Invocation Accessor"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="p">[</span><span class="nx">$2</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"ThisProperty"</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-29">#</a> </div> <p>Everything that can be assigned to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Assignable: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"SimpleAssignable"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Array"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s2">"Object"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" 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="nv">Value: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Assignable"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Literal"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s2">"Parenthetical"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s2">"Range"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s2">"This"</span>
|
||||
<span class="nx">o</span> <span class="s2">"NULL"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="s1">'null'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" 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="nv">Accessor: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"PROPERTY_ACCESS Identifier"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">AccessorNode</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"PROTOTYPE_ACCESS Identifier"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">AccessorNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="s1">'prototype'</span>
|
||||
<span class="nx">o</span> <span class="s2">"::"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">AccessorNode</span><span class="p">(</span><span class="k">new</span> <span class="nx">LiteralNode</span><span class="p">(</span><span class="s1">'prototype'</span><span class="p">))</span>
|
||||
<span class="nx">o</span> <span class="s2">"SOAK_ACCESS Identifier"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">AccessorNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="s1">'soak'</span>
|
||||
<span class="nx">o</span> <span class="s2">"Index"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Slice"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">SliceNode</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" 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="nv">Index: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"INDEX_START Expression INDEX_END"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">IndexNode</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"SOAKED_INDEX_START Expression SOAKED_INDEX_END"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">IndexNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="s1">'soak'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-33">#</a> </div> <p>In CoffeeScript, an object literal is simply a list of assignments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nb">Object</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"{ AssignList OptComma }"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ObjectNode</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" 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="nv">AssignList: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">""</span><span class="p">,</span> <span class="o">-></span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s2">"AssignObj"</span><span class="p">,</span> <span class="o">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"AssignList , AssignObj"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[</span><span class="nx">$3</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"AssignList OptComma TERMINATOR AssignObj"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[</span><span class="nx">$4</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"AssignList OptComma INDENT AssignList OptComma OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-35">#</a> </div> <p>Class definitions have optional bodies of prototype property assignments,
|
||||
and optional references to the superclass.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Class: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"CLASS SimpleAssignable"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ClassNode</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"CLASS SimpleAssignable EXTENDS Value"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ClassNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s2">"CLASS SimpleAssignable INDENT ClassBody OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ClassNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s2">"CLASS SimpleAssignable EXTENDS Value INDENT ClassBody OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ClassNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$6</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-36">#</a> </div> <p>Assignments that can happen directly inside a class declaration.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ClassAssign: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"AssignObj"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s2">"ThisProperty ASSIGN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">AssignNode</span> <span class="k">new</span> <span class="nx">ValueNode</span><span class="p">(</span><span class="nx">$1</span><span class="p">),</span> <span class="nx">$3</span><span class="p">,</span> <span class="s1">'this'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-37"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-37">#</a> </div> <p>A list of assignments to a class.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ClassBody: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">""</span><span class="p">,</span> <span class="o">-></span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s2">"ClassAssign"</span><span class="p">,</span> <span class="o">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"ClassBody TERMINATOR ClassAssign"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-38">#</a> </div> <p>The three flavors of function call: normal, object instantiation with <code>new</code>,
|
||||
and calling <code>super()</code></p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Call: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Invocation"</span>
|
||||
<span class="nx">o</span> <span class="s2">"NEW Invocation"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span><span class="p">.</span><span class="nx">new_instance</span><span class="p">()</span>
|
||||
<span class="nx">o</span> <span class="s2">"Super"</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-39"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-39">#</a> </div> <p>Binds a function call to a context and/or arguments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Curry: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Value <- Arguments"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">CurryNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-40">#</a> </div> <p>Extending an object by setting its prototype chain to reference a parent
|
||||
object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Extends: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"SimpleAssignable EXTENDS Value"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ExtendsNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-41">#</a> </div> <p>Ordinary function invocation, or a chained series of calls.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Invocation: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Value Arguments"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">CallNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"Invocation Arguments"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">CallNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-42">#</a> </div> <p>The list of arguments to a function call.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Arguments: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"CALL_START ArgList OptComma CALL_END"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-43">#</a> </div> <p>Calling super.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Super: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"SUPER CALL_START ArgList OptComma CALL_END"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">CallNode</span> <span class="s1">'super'</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-44">#</a> </div> <p>A reference to the <em>this</em> current object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">This: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"THIS"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="s1">'this'</span>
|
||||
<span class="nx">o</span> <span class="s2">"@"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="s1">'this'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-45"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-45">#</a> </div> <p>A reference to a property on <em>this</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ThisProperty: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"@ Identifier"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="k">new</span> <span class="nx">LiteralNode</span><span class="p">(</span><span class="s1">'this'</span><span class="p">),</span> <span class="p">[</span><span class="k">new</span> <span class="nx">AccessorNode</span><span class="p">(</span><span class="nx">$2</span><span class="p">)]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-46"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-46">#</a> </div> <p>The CoffeeScript range literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Range: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"[ Expression . . Expression ]"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">RangeNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$5</span>
|
||||
<span class="nx">o</span> <span class="s2">"[ Expression . . . Expression ]"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">RangeNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$6</span><span class="p">,</span> <span class="kc">true</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-47">#</a> </div> <p>The slice literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Slice: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"INDEX_START Expression . . Expression INDEX_END"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">RangeNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$5</span>
|
||||
<span class="nx">o</span> <span class="s2">"INDEX_START Expression . . . Expression INDEX_END"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">RangeNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$6</span><span class="p">,</span> <span class="kc">true</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-48"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-48">#</a> </div> <p>The array literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nb">Array</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"[ ArgList OptComma ]"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ArrayNode</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-49">#</a> </div> <p>The <strong>ArgList</strong> is both the list of objects passed into a function call,
|
||||
as well as the contents of an array literal
|
||||
(i.e. comma-separated expressions). Newlines work as well.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ArgList: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">""</span><span class="p">,</span> <span class="o">-></span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"INDENT Expression"</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">o</span> <span class="s2">"ArgList , Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[</span><span class="nx">$3</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"ArgList TERMINATOR Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[</span><span class="nx">$3</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"ArgList , TERMINATOR Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[</span><span class="nx">$4</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"ArgList , INDENT Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[</span><span class="nx">$4</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"ArgList OptComma OUTDENT"</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-50"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-50">#</a> </div> <p>Just simple, comma-separated, required arguments (no fancy syntax). We need
|
||||
this to be separate from the <strong>ArgList</strong> for use in <strong>Switch</strong> blocks, where
|
||||
having the newlines wouldn't make sense.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">SimpleArgs: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression"</span>
|
||||
<span class="nx">o</span> <span class="s2">"SimpleArgs , Expression"</span><span class="p">,</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">$1</span> <span class="k">instanceof</span> <span class="nb">Array</span> <span class="k">then</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span><span class="p">([</span><span class="nx">$3</span><span class="p">])</span> <span class="k">else</span> <span class="p">[</span><span class="nx">$1</span><span class="p">].</span><span class="nx">concat</span><span class="p">([</span><span class="nx">$3</span><span class="p">])</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-51">#</a> </div> <p>The variants of <em>try/catch/finally</em> exception handling blocks.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Try: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"TRY Block Catch"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">TryNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"TRY Block FINALLY Block"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">TryNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$4</span>
|
||||
<span class="nx">o</span> <span class="s2">"TRY Block Catch FINALLY Block"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">TryNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="nx">$5</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-52">#</a> </div> <p>A catch clause names its error and runs a block of code.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Catch: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"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-53"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-53">#</a> </div> <p>Throw an exception object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Throw: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"THROW Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ThrowNode</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-54">#</a> </div> <p>Parenthetical expressions. Note that the <strong>Parenthetical</strong> is a <strong>Value</strong>,
|
||||
not an <strong>Expression</strong>, so if you need to use an expression in a place
|
||||
where only values are accepted, wrapping it in parentheses will always do
|
||||
the trick.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Parenthetical: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"( Line )"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ParentheticalNode</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-55">#</a> </div> <p>A language extension to CoffeeScript from the outside. We simply pass
|
||||
it through unaltered.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Extension: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"EXTENSION"</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-56">#</a> </div> <p>The condition portion of a while loop.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">WhileSource: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"WHILE Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">WhileNode</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"WHILE Expression WHEN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">WhileNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="p">{</span><span class="nv">guard : </span><span class="nx">$4</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"UNTIL Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">WhileNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="p">{</span><span class="nv">invert: </span><span class="kc">true</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"UNTIL Expression WHEN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">WhileNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="p">{</span><span class="nv">invert: </span><span class="kc">true</span><span class="p">,</span> <span class="nv">guard: </span><span class="nx">$4</span><span class="p">}</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-57"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-57">#</a> </div> <p>The while loop can either be normal, with a block of expressions to execute,
|
||||
or postfix, with a single expression. There is no do..while.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">While: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"WhileSource Block"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">add_body</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"Statement WhileSource"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span><span class="p">.</span><span class="nx">add_body</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression WhileSource"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span><span class="p">.</span><span class="nx">add_body</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-58"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-58">#</a> </div> <p>Array, object, and range comprehensions, at the most generic level.
|
||||
Comprehensions can either be normal, with a block of expressions to execute,
|
||||
or postfix, with a single expression.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">For: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Statement FOR ForVariables ForSource"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ForNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression FOR ForVariables ForSource"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ForNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"FOR ForVariables ForSource Block"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ForNode</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-59"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-59">#</a> </div> <p>An array of all accepted values for a variable inside the loop. This
|
||||
enables support for pattern matching.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ForValue: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"Identifier"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Array"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span>
|
||||
<span class="nx">o</span> <span class="s2">"Object"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-60"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-60">#</a> </div> <p>An array or range comprehension has variables for the current element and
|
||||
(optional) reference to the current index. Or, <em>key, value</em>, in the case
|
||||
of object comprehensions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ForVariables: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"ForValue"</span><span class="p">,</span> <span class="o">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
|
||||
<span class="nx">o</span> <span class="s2">"ForValue , ForValue"</span><span class="p">,</span> <span class="o">-></span> <span class="p">[</span><span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-61"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-61">#</a> </div> <p>The source of a comprehension is an array or object with an optional guard
|
||||
clause. If it's an array comprehension, you can also choose to step through
|
||||
in fixed-size increments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ForSource: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"IN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"OF Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">object: </span><span class="kc">true</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"IN Expression WHEN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">guard: </span><span class="nx">$4</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"OF Expression WHEN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">guard: </span><span class="nx">$4</span><span class="p">,</span> <span class="nv">object: </span><span class="kc">true</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"IN Expression BY Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">step: </span> <span class="nx">$4</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"IN Expression WHEN Expression BY Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">guard: </span><span class="nx">$4</span><span class="p">,</span> <span class="nv">step: </span> <span class="nx">$6</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"IN Expression BY Expression WHEN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="p">{</span><span class="nv">source: </span><span class="nx">$2</span><span class="p">,</span> <span class="nv">step: </span> <span class="nx">$4</span><span class="p">,</span> <span class="nv">guard: </span><span class="nx">$6</span><span class="p">}</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-62"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-62">#</a> </div> <p>The CoffeeScript switch/when/else block replaces the JavaScript
|
||||
switch/case/default by compiling into an if-else chain.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Switch: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"SWITCH Expression INDENT Whens OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$4</span><span class="p">.</span><span class="nx">switches_over</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"SWITCH Expression INDENT Whens ELSE Block OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$4</span><span class="p">.</span><span class="nx">switches_over</span><span class="p">(</span><span class="nx">$2</span><span class="p">).</span><span class="nx">add_else</span> <span class="nx">$6</span><span class="p">,</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s2">"SWITCH INDENT Whens OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"SWITCH INDENT Whens ELSE Block OUTDENT"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$3</span><span class="p">.</span><span class="nx">add_else</span> <span class="nx">$5</span><span class="p">,</span> <span class="kc">true</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-63"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-63">#</a> </div> <p>The inner list of whens is left recursive. At code-generation time, the
|
||||
IfNode will rewrite them into a proper chain.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Whens: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"When"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Whens When"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">add_else</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-64">#</a> </div> <p>An individual <strong>When</strong> clause, with action.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">When: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"LEADING_WHEN SimpleArgs Block"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="p">{</span><span class="nv">statement: </span><span class="kc">true</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"LEADING_WHEN SimpleArgs Block TERMINATOR"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="p">{</span><span class="nv">statement: </span><span class="kc">true</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"Comment TERMINATOR When"</span><span class="p">,</span> <span class="o">-></span> <span class="nv">$3.comment: </span><span class="nx">$1</span><span class="p">;</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-65"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-65">#</a> </div> <p>The most basic form of <em>if</em> is a condition and an action. The following
|
||||
if-related rules are broken up along these lines in order to avoid
|
||||
ambiguity.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">IfStart: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"IF Expression Block"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"UNLESS Expression Block"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="p">{</span><span class="nv">invert: </span><span class="kc">true</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"IfStart ElsIf"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">add_else</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-66"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-66">#</a> </div> <p>An <strong>IfStart</strong> can optionally be followed by an else block.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">IfBlock: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"IfStart"</span>
|
||||
<span class="nx">o</span> <span class="s2">"IfStart ELSE Block"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$1</span><span class="p">.</span><span class="nx">add_else</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-67"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-67">#</a> </div> <p>An <em>else if</em> continuation of the <em>if</em> expression.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ElsIf: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"ELSE IF Expression Block"</span><span class="p">,</span> <span class="o">-></span> <span class="p">(</span><span class="k">new</span> <span class="nx">IfNode</span><span class="p">(</span><span class="nx">$3</span><span class="p">,</span> <span class="nx">$4</span><span class="p">)).</span><span class="nx">force_statement</span><span class="p">()</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-68"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-68">#</a> </div> <p>The full complement of <em>if</em> expressions, including postfix one-liner
|
||||
<em>if</em> and <em>unless</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">If: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"IfBlock"</span>
|
||||
<span class="nx">o</span> <span class="s2">"Statement IF Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="nx">$1</span><span class="p">]),</span> <span class="p">{</span><span class="nv">statement: </span><span class="kc">true</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression IF Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="nx">$1</span><span class="p">]),</span> <span class="p">{</span><span class="nv">statement: </span><span class="kc">true</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"Statement UNLESS Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="nx">$1</span><span class="p">]),</span> <span class="p">{</span><span class="nv">statement: </span><span class="kc">true</span><span class="p">,</span> <span class="nv">invert: </span><span class="kc">true</span><span class="p">}</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression UNLESS Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="nx">$1</span><span class="p">]),</span> <span class="p">{</span><span class="nv">statement: </span><span class="kc">true</span><span class="p">,</span> <span class="nv">invert: </span><span class="kc">true</span><span class="p">}</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-69"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-69">#</a> </div> <p>Arithmetic and logical operators, working on one or more operands.
|
||||
Here they are grouped by order of precedence. The actual precedence rules
|
||||
are defined at the bottom of the page. It would be shorter if we could
|
||||
combine most of these rules into a single generic <em>Operand OpSymbol Operand</em>
|
||||
-type rule, but in order to make the precedence binding possible, separate
|
||||
rules are necessary.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Operation: </span><span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s2">"! Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'!'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"!! Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'!!'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span><span class="p">(</span><span class="s2">"- Expression"</span><span class="p">,</span> <span class="p">(</span><span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span><span class="p">(</span><span class="s1">'-'</span><span class="p">,</span> <span class="nx">$2</span><span class="p">)),</span> <span class="p">{</span><span class="nv">prec: </span><span class="s1">'UMINUS'</span><span class="p">})</span>
|
||||
<span class="nx">o</span><span class="p">(</span><span class="s2">"+ Expression"</span><span class="p">,</span> <span class="p">(</span><span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span><span class="p">(</span><span class="s1">'+'</span><span class="p">,</span> <span class="nx">$2</span><span class="p">)),</span> <span class="p">{</span><span class="nv">prec: </span><span class="s1">'UPLUS'</span><span class="p">})</span>
|
||||
<span class="nx">o</span> <span class="s2">"~ Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'~'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"-- Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'--'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"++ Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'++'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"DELETE Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'delete'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"TYPEOF Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'typeof'</span><span class="p">,</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression --"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'--'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">true</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression ++"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'++'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">true</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s2">"Expression * Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'*'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression / Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'/'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression % Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'%'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s2">"Expression + Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'+'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression - Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'-'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s2">"Expression << Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'<<'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression >> Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'>>'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression >>> Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'>>>'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression & Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'&'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression | Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'|'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression ^ Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'^'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s2">"Expression <= Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'<='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression < Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'<'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression > Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'>'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression >= Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'>='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s2">"Expression == Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'=='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression != Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'!='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s2">"Expression && Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'&&'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression || Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'||'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression ? Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'?'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s2">"Expression -= Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'-='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression += Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'+='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression /= Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'/='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression *= Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'*='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression %= Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'%='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression ||= Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'||='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression &&= Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'&&='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression ?= Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'?='</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
|
||||
<span class="nx">o</span> <span class="s2">"Expression INSTANCEOF Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'instanceof'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s2">"Expression IN Expression"</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">'in'</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-70"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-70">#</a> </div> <h2>Precedence</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-71"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-71">#</a> </div> <p>Operators at the top of this list have higher precedence than the ones lower
|
||||
down. Following these rules is what makes <code>2 + 3 * 4</code> parse as:</p>
|
||||
|
||||
<pre><code>2 + (3 * 4)
|
||||
</code></pre>
|
||||
|
||||
<p>And not:</p>
|
||||
|
||||
<pre><code>(2 + 3) * 4
|
||||
</code></pre> </td> <td class="code"> <div class="highlight"><pre><span class="nv">operators: </span><span class="p">[</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'?'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"nonassoc"</span><span class="p">,</span> <span class="s1">'UMINUS'</span><span class="p">,</span> <span class="s1">'UPLUS'</span><span class="p">,</span> <span class="s1">'!'</span><span class="p">,</span> <span class="s1">'!!'</span><span class="p">,</span> <span class="s1">'~'</span><span class="p">,</span> <span class="s1">'++'</span><span class="p">,</span> <span class="s1">'--'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'*'</span><span class="p">,</span> <span class="s1">'/'</span><span class="p">,</span> <span class="s1">'%'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'+'</span><span class="p">,</span> <span class="s1">'-'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'<<'</span><span class="p">,</span> <span class="s1">'>>'</span><span class="p">,</span> <span class="s1">'>>>'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'&'</span><span class="p">,</span> <span class="s1">'|'</span><span class="p">,</span> <span class="s1">'^'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'<='</span><span class="p">,</span> <span class="s1">'<'</span><span class="p">,</span> <span class="s1">'>'</span><span class="p">,</span> <span class="s1">'>='</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"right"</span><span class="p">,</span> <span class="s1">'DELETE'</span><span class="p">,</span> <span class="s1">'INSTANCEOF'</span><span class="p">,</span> <span class="s1">'TYPEOF'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'=='</span><span class="p">,</span> <span class="s1">'!='</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'&&'</span><span class="p">,</span> <span class="s1">'||'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"right"</span><span class="p">,</span> <span class="s1">'-='</span><span class="p">,</span> <span class="s1">'+='</span><span class="p">,</span> <span class="s1">'/='</span><span class="p">,</span> <span class="s1">'*='</span><span class="p">,</span> <span class="s1">'%='</span><span class="p">,</span> <span class="s1">'||='</span><span class="p">,</span> <span class="s1">'&&='</span><span class="p">,</span> <span class="s1">'?='</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'.'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"right"</span><span class="p">,</span> <span class="s1">'INDENT'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"right"</span><span class="p">,</span> <span class="s1">'WHEN'</span><span class="p">,</span> <span class="s1">'LEADING_WHEN'</span><span class="p">,</span> <span class="s1">'IN'</span><span class="p">,</span> <span class="s1">'OF'</span><span class="p">,</span> <span class="s1">'BY'</span><span class="p">,</span> <span class="s1">'THROW'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"right"</span><span class="p">,</span> <span class="s1">'FOR'</span><span class="p">,</span> <span class="s1">'WHILE'</span><span class="p">,</span> <span class="s1">'UNTIL'</span><span class="p">,</span> <span class="s1">'NEW'</span><span class="p">,</span> <span class="s1">'SUPER'</span><span class="p">,</span> <span class="s1">'CLASS'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"left"</span><span class="p">,</span> <span class="s1">'EXTENDS'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"right"</span><span class="p">,</span> <span class="s1">'ASSIGN'</span><span class="p">,</span> <span class="s1">'RETURN'</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="s2">"right"</span><span class="p">,</span> <span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">,</span> <span class="s1">'<-'</span><span class="p">,</span> <span class="s1">'UNLESS'</span><span class="p">,</span> <span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">]</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-72"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-72">#</a> </div> <h2>Wrapping Up</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-73"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-73">#</a> </div> <p>Finally, now what we have our <strong>grammar</strong> and our <strong>operators</strong>, we can create
|
||||
our <strong>Jison.Parser</strong>. We do this by processing all of our rules, recording all
|
||||
terminals (every symbol which does not appear as the name of a rule above)
|
||||
as "tokens".</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">tokens: </span><span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">alternatives</span> <span class="k">of</span> <span class="nx">grammar</span>
|
||||
<span class="nx">grammar</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span><span class="o">:</span> <span class="k">for</span> <span class="nx">alt</span> <span class="k">in</span> <span class="nx">alternatives</span>
|
||||
<span class="k">for</span> <span class="nx">token</span> <span class="k">in</span> <span class="nx">alt</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">split</span> <span class="s1">' '</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="nx">token</span> <span class="nx">unless</span> <span class="nx">grammar</span><span class="p">[</span><span class="nx">token</span><span class="p">]</span>
|
||||
<span class="nx">alt</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"return ${alt[1]}"</span> <span class="k">if</span> <span class="nx">name</span> <span class="o">is</span> <span class="s1">'Root'</span>
|
||||
<span class="nx">alt</span></pre></div> </td> </tr> <tr id="section-74"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-74">#</a> </div> <p>Initialize the <strong>Parser</strong> with our list of terminal <strong>tokens</strong>, our <strong>grammar</strong>
|
||||
rules, and the name of the root. Reverse the operators because Jison orders
|
||||
precedence from low to high, and we have it high to low
|
||||
(as in <a href="http://dinosaur.compilertools.net/yacc/index.html">Yacc</a>).</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.parser: </span><span class="k">new</span> <span class="nx">Parser</span> <span class="p">{</span>
|
||||
<span class="nv">tokens: </span> <span class="nx">tokens</span><span class="p">.</span><span class="nx">join</span> <span class="s1">' '</span>
|
||||
<span class="nv">bnf: </span> <span class="nx">grammar</span>
|
||||
<span class="nv">operators: </span> <span class="nx">operators</span><span class="p">.</span><span class="nx">reverse</span><span class="p">()</span>
|
||||
<span class="nv">startSymbol: </span> <span class="s1">'Root'</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
64
documentation/docs/helpers.html
Normal file
64
documentation/docs/helpers.html
Normal file
@@ -0,0 +1,64 @@
|
||||
<!DOCTYPE html> <html> <head> <title>helpers.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> helpers.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>This file contains the common helper functions that we'd like to share among
|
||||
the <strong>Lexer</strong>, <strong>Rewriter</strong>, and the <strong>Nodes</strong>. Merge objects, flatten
|
||||
arrays, count characters, that sort of thing.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-2">#</a> </div> <p>Set up exported variables for both <strong>Node.js</strong> and the browser.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">this</span><span class="p">.</span><span class="nv">exports: </span><span class="k">this</span> <span class="nx">unless</span> <span class="nx">process</span><span class="o">?</span>
|
||||
<span class="nv">helpers: exports.helpers: </span><span class="p">{}</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>Cross-browser indexOf, so that IE can join the party.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.index_of: index_of: </span><span class="p">(</span><span class="nx">array</span><span class="p">,</span> <span class="nx">item</span><span class="p">,</span> <span class="nx">from</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="nx">array</span><span class="p">.</span><span class="nx">indexOf</span> <span class="nx">item</span><span class="p">,</span> <span class="nx">from</span> <span class="k">if</span> <span class="nx">array</span><span class="p">.</span><span class="nx">indexOf</span>
|
||||
<span class="k">for</span> <span class="nx">other</span><span class="p">,</span> <span class="nx">index</span> <span class="k">in</span> <span class="nx">array</span>
|
||||
<span class="k">if</span> <span class="nx">other</span> <span class="o">is</span> <span class="nx">item</span> <span class="o">and</span> <span class="p">(</span><span class="o">not</span> <span class="nx">from</span> <span class="o">or</span> <span class="p">(</span><span class="nx">from</span> <span class="o"><=</span> <span class="nx">index</span><span class="p">))</span>
|
||||
<span class="k">return</span> <span class="nx">index</span>
|
||||
<span class="o">-</span><span class="mi">1</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Does a list include a value?</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.include: include: </span><span class="p">(</span><span class="nx">list</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">index_of</span><span class="p">(</span><span class="nx">list</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Peek at the beginning of a given string to see if it matches a sequence.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.starts: starts: </span><span class="p">(</span><span class="nx">string</span><span class="p">,</span> <span class="nx">literal</span><span class="p">,</span> <span class="nx">start</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">string</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span> <span class="p">(</span><span class="nx">start</span> <span class="o">or</span> <span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="nx">literal</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="o">is</span> <span class="nx">literal</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Trim out all falsy values from an array.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.compact: compact: </span><span class="p">(</span><span class="nx">array</span><span class="p">)</span> <span class="o">-></span> <span class="nx">item</span> <span class="k">for</span> <span class="nx">item</span> <span class="k">in</span> <span class="nx">array</span> <span class="k">when</span> <span class="nx">item</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Count the number of occurences of a character in a string.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.count: count: </span><span class="p">(</span><span class="nx">string</span><span class="p">,</span> <span class="nx">letter</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">num: </span><span class="mi">0</span>
|
||||
<span class="nv">pos: </span><span class="nx">index_of</span> <span class="nx">string</span><span class="p">,</span> <span class="nx">letter</span>
|
||||
<span class="k">while</span> <span class="nx">pos</span> <span class="o">isnt</span> <span class="o">-</span><span class="mi">1</span>
|
||||
<span class="nv">num: </span><span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="nv">pos: </span><span class="nx">index_of</span> <span class="nx">string</span><span class="p">,</span> <span class="nx">letter</span><span class="p">,</span> <span class="nx">pos</span> <span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="nx">num</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Merge objects, returning a fresh copy with attributes from both sides.
|
||||
Used every time <code>BaseNode#compile</code> is called, to allow properties in the
|
||||
options hash to propagate down the tree without polluting other branches.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.merge: merge: </span><span class="p">(</span><span class="nx">options</span><span class="p">,</span> <span class="nx">overrides</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">fresh: </span><span class="p">{}</span>
|
||||
<span class="p">(</span><span class="nx">fresh</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span><span class="o">:</span> <span class="nx">val</span><span class="p">)</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">options</span>
|
||||
<span class="p">(</span><span class="nx">fresh</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span><span class="o">:</span> <span class="nx">val</span><span class="p">)</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">overrides</span> <span class="k">if</span> <span class="nx">overrides</span>
|
||||
<span class="nx">fresh</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Extend a source object with the properties of another object (shallow copy).
|
||||
We use this to simulate Node's deprecated <code>process.mixin</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.extend: extend: </span><span class="p">(</span><span class="nx">object</span><span class="p">,</span> <span class="nx">properties</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="p">(</span><span class="nx">object</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span><span class="o">:</span> <span class="nx">val</span><span class="p">)</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">properties</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Return a completely flattened version of an array. Handy for getting a
|
||||
list of <code>children</code> from the nodes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.flatten: flatten: </span><span class="p">(</span><span class="nx">array</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">memo: </span><span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="nx">item</span> <span class="k">in</span> <span class="nx">array</span>
|
||||
<span class="k">if</span> <span class="nx">item</span> <span class="k">instanceof</span> <span class="nb">Array</span> <span class="k">then</span> <span class="nv">memo: </span><span class="nx">memo</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">item</span><span class="p">)</span> <span class="k">else</span> <span class="nx">memo</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">item</span><span class="p">)</span>
|
||||
<span class="nx">memo</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Delete a key from an object, returning the value. Useful when a node is
|
||||
looking for a particular method in an options hash.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.del: del: </span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">key</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">val: </span><span class="nx">obj</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span>
|
||||
<span class="k">delete</span> <span class="nx">obj</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span>
|
||||
<span class="nx">val</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>Matches a balanced group such as a single or double-quoted string. Pass in
|
||||
a series of delimiters, all of which must be nested correctly within the
|
||||
contents of the string. This method allows us to have strings within
|
||||
interpolations within strings, ad infinitum.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">helpers.balanced_string: balanced_string: </span><span class="p">(</span><span class="nx">str</span><span class="p">,</span> <span class="nx">delimited</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">options: </span><span class="o">or</span> <span class="p">{}</span>
|
||||
<span class="nv">slash: </span><span class="nx">delimited</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'/'</span>
|
||||
<span class="nv">levels: </span><span class="p">[]</span>
|
||||
<span class="nv">i: </span><span class="mi">0</span>
|
||||
<span class="k">while</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">str</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="k">if</span> <span class="nx">levels</span><span class="p">.</span><span class="nx">length</span> <span class="o">and</span> <span class="nx">starts</span> <span class="nx">str</span><span class="p">,</span> <span class="s1">'\\'</span><span class="p">,</span> <span class="nx">i</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="k">else</span>
|
||||
<span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">delimited</span>
|
||||
<span class="p">[</span><span class="nx">open</span><span class="p">,</span> <span class="nx">close</span><span class="p">]</span><span class="o">:</span> <span class="nx">pair</span>
|
||||
<span class="k">if</span> <span class="nx">levels</span><span class="p">.</span><span class="nx">length</span> <span class="o">and</span> <span class="nx">starts</span><span class="p">(</span><span class="nx">str</span><span class="p">,</span> <span class="nx">close</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">and</span> <span class="nx">levels</span><span class="p">[</span><span class="nx">levels</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">is</span> <span class="nx">pair</span>
|
||||
<span class="nx">levels</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="nx">close</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">levels</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="k">break</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">starts</span> <span class="nx">str</span><span class="p">,</span> <span class="nx">open</span><span class="p">,</span> <span class="nx">i</span>
|
||||
<span class="nx">levels</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">pair</span><span class="p">)</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="nx">open</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="k">break</span>
|
||||
<span class="k">break</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">levels</span><span class="p">.</span><span class="nx">length</span> <span class="o">or</span> <span class="nx">slash</span> <span class="o">and</span> <span class="nx">starts</span> <span class="nx">str</span><span class="p">,</span> <span class="s1">'\n'</span><span class="p">,</span> <span class="nx">i</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="k">if</span> <span class="nx">levels</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="k">if</span> <span class="nx">slash</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"SyntaxError: Unterminated ${levels.pop()[0]} starting on line ${@line + 1}"</span>
|
||||
<span class="k">if</span> <span class="o">not</span> <span class="nx">i</span> <span class="k">then</span> <span class="kc">false</span> <span class="k">else</span> <span class="nx">str</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
3
documentation/docs/index.html
Normal file
3
documentation/docs/index.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<!DOCTYPE html> <html> <head> <title>index.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> index.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>Loader for CoffeeScript as a Node.js library.</p> </td> <td class="code"> <div class="highlight"><pre><span class="p">(</span><span class="nx">exports</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span><span class="o">:</span> <span class="nx">val</span><span class="p">)</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">require</span> <span class="s1">'./coffee-script'</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
383
documentation/docs/lexer.html
Normal file
383
documentation/docs/lexer.html
Normal file
@@ -0,0 +1,383 @@
|
||||
<!DOCTYPE html> <html> <head> <title>lexer.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> lexer.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>The CoffeeScript Lexer. Uses a series of token-matching regexes to attempt
|
||||
matches against the beginning of the source code. When a match is found,
|
||||
a token is produced, we consume the match, and start again. Tokens are in the
|
||||
form:</p>
|
||||
|
||||
<pre><code>[tag, value, line_number]
|
||||
</code></pre>
|
||||
|
||||
<p>Which is a format that can be fed directly into <a href="http://github.com/zaach/jison">Jison</a>.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-2">#</a> </div> <p>Set up the Lexer for both Node.js and the browser, depending on where we are.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nx">process</span><span class="o">?</span>
|
||||
<span class="p">{</span><span class="nx">Rewriter</span><span class="p">}</span><span class="o">:</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'./rewriter'</span><span class="p">)</span>
|
||||
<span class="p">{</span><span class="nx">helpers</span><span class="p">}</span><span class="o">:</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'./helpers'</span><span class="p">)</span>
|
||||
<span class="k">else</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nv">exports: </span><span class="k">this</span>
|
||||
<span class="nv">Rewriter: </span> <span class="k">this</span><span class="p">.</span><span class="nx">Rewriter</span>
|
||||
<span class="nv">helpers: </span> <span class="k">this</span><span class="p">.</span><span class="nx">helpers</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>Import the helpers we need.</p> </td> <td class="code"> <div class="highlight"><pre><span class="p">{</span><span class="nx">include</span><span class="p">,</span> <span class="nx">count</span><span class="p">,</span> <span class="nx">starts</span><span class="p">,</span> <span class="nx">compact</span><span class="p">,</span> <span class="nx">balanced_string</span><span class="p">}</span><span class="o">:</span> <span class="nx">helpers</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <h2>The Lexer Class</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>The Lexer class reads a stream of CoffeeScript and divvys it up into tagged
|
||||
tokens. Some potential ambiguity in the grammar has been avoided by
|
||||
pushing some extra smarts into the Lexer.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Lexer: </span><span class="nx">class</span> <span class="nx">Lexer</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p><strong>tokenize</strong> is the Lexer's main method. Scan by attempting to match tokens
|
||||
one at a time, using a regular expression anchored at the start of the
|
||||
remaining code, or a custom recursive token-matching method
|
||||
(for interpolations). When the next token has been recorded, we move forward
|
||||
within the code past the token, and begin again.</p>
|
||||
|
||||
<p>Each tokenizing method is responsible for incrementing <code>@i</code> by the number of
|
||||
characters it has consumed. <code>@i</code> can be thought of as our finger on the page
|
||||
of source.</p>
|
||||
|
||||
<p>Before returning the token stream, run it through the <a href="rewriter.html">Rewriter</a>
|
||||
unless explicitly asked not to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tokenize: </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">code : </span><span class="nx">code</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/(\r|\s+$)/g</span><span class="p">,</span> <span class="s1">''</span>
|
||||
<span class="nv">o : </span><span class="nx">options</span> <span class="o">or</span> <span class="p">{}</span>
|
||||
<span class="vi">@code : </span><span class="nx">code</span> <span class="c1"># The remainder of the source code.</span>
|
||||
<span class="vi">@i : </span><span class="mi">0</span> <span class="c1"># Current character position we're parsing.</span>
|
||||
<span class="vi">@line : </span><span class="nx">o</span><span class="p">.</span><span class="nx">line</span> <span class="o">or</span> <span class="mi">0</span> <span class="c1"># The current line.</span>
|
||||
<span class="vi">@indent : </span><span class="mi">0</span> <span class="c1"># The current indentation level.</span>
|
||||
<span class="vi">@indents : </span><span class="p">[]</span> <span class="c1"># The stack of all current indentation levels.</span>
|
||||
<span class="vi">@tokens : </span><span class="p">[]</span> <span class="c1"># Stream of parsed tokens in the form ['TYPE', value, line]</span>
|
||||
<span class="k">while</span> <span class="nx">@i</span> <span class="o"><</span> <span class="nx">@code</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="vi">@chunk: </span><span class="nx">@code</span><span class="p">.</span><span class="nx">slice</span> <span class="nx">@i</span>
|
||||
<span class="nx">@extract_next_token</span><span class="p">()</span>
|
||||
<span class="nx">@close_indentation</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="nx">@tokens</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">rewrite</span> <span class="o">is</span> <span class="kc">off</span>
|
||||
<span class="p">(</span><span class="k">new</span> <span class="nx">Rewriter</span><span class="p">()).</span><span class="nx">rewrite</span> <span class="nx">@tokens</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>At every position, run through this list of attempted matches,
|
||||
short-circuiting if any of them succeed. Their order determines precedence:
|
||||
<code>@literal_token</code> is the fallback catch-all.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">extract_next_token: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@extension_token</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@identifier_token</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@number_token</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@heredoc_token</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@regex_token</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@comment_token</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@line_token</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@whitespace_token</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@js_token</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@string_token</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="nx">@literal_token</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <h2>Tokenizers</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Language extensions get the highest priority, first chance to tag tokens
|
||||
as something else.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">extension_token: </span><span class="o">-></span>
|
||||
<span class="k">for</span> <span class="nx">extension</span> <span class="k">in</span> <span class="nx">Lexer</span><span class="p">.</span><span class="nx">extensions</span>
|
||||
<span class="k">return</span> <span class="kc">true</span> <span class="k">if</span> <span class="nx">extension</span><span class="p">.</span><span class="nx">call</span> <span class="k">this</span>
|
||||
<span class="kc">false</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Matches identifying literals: variables, keywords, method names, etc.
|
||||
Check to ensure that JavaScript reserved words aren't being used as
|
||||
identifiers. Because CoffeeScript reserves a handful of keywords that are
|
||||
allowed in JavaScript, we're careful not to tag them as keywords when
|
||||
referenced as property names here, so you can still do <code>jQuery.is()</code> even
|
||||
though <code>is</code> means <code>===</code> otherwise.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">identifier_token: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">id: </span><span class="nx">@match</span> <span class="nx">IDENTIFIER</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="nx">@name_access_type</span><span class="p">()</span>
|
||||
<span class="nv">accessed: </span><span class="nx">include</span> <span class="nx">ACCESSORS</span><span class="p">,</span> <span class="nx">@tag</span> <span class="mi">0</span>
|
||||
<span class="nv">tag: </span><span class="s1">'IDENTIFIER'</span>
|
||||
<span class="nv">tag: </span><span class="nx">id</span><span class="p">.</span><span class="nx">toUpperCase</span><span class="p">()</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">accessed</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">KEYWORDS</span><span class="p">,</span> <span class="nx">id</span><span class="p">)</span>
|
||||
<span class="nx">@identifier_error</span> <span class="nx">id</span> <span class="k">if</span> <span class="nx">include</span> <span class="nx">RESERVED</span><span class="p">,</span> <span class="nx">id</span>
|
||||
<span class="nv">tag: </span><span class="s1">'LEADING_WHEN'</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'WHEN'</span> <span class="o">and</span> <span class="nx">include</span> <span class="nx">LINE_BREAK</span><span class="p">,</span> <span class="nx">@tag</span><span class="p">()</span>
|
||||
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">id</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nx">unless</span> <span class="nx">accessed</span>
|
||||
<span class="nv">tag: id: </span><span class="nx">CONVERSIONS</span><span class="p">[</span><span class="nx">id</span><span class="p">]</span> <span class="k">if</span> <span class="nx">include</span> <span class="nx">COFFEE_ALIASES</span><span class="p">,</span> <span class="nx">id</span>
|
||||
<span class="k">return</span> <span class="nx">@tag_half_assignment</span> <span class="nx">tag</span> <span class="k">if</span> <span class="nx">@prev</span><span class="p">()</span> <span class="o">and</span> <span class="nx">@prev</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'ASSIGN'</span> <span class="o">and</span> <span class="nx">include</span> <span class="nx">HALF_ASSIGNMENTS</span><span class="p">,</span> <span class="nx">tag</span>
|
||||
<span class="nx">@token</span> <span class="nx">tag</span><span class="p">,</span> <span class="nx">id</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Matches numbers, including decimals, hex, and exponential notation.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">number_token: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">number: </span><span class="nx">@match</span> <span class="nx">NUMBER</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="nx">@token</span> <span class="s1">'NUMBER'</span><span class="p">,</span> <span class="nx">number</span>
|
||||
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">number</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>Matches strings, including multi-line strings. Ensures that quotation marks
|
||||
are balanced within the string's contents, and within nested interpolations.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">string_token: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nx">starts</span><span class="p">(</span><span class="nx">@chunk</span><span class="p">,</span> <span class="s1">'"'</span><span class="p">)</span> <span class="o">or</span> <span class="nx">starts</span><span class="p">(</span><span class="nx">@chunk</span><span class="p">,</span> <span class="s2">"'"</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">string:</span>
|
||||
<span class="nx">@balanced_token</span><span class="p">([</span><span class="s1">'"'</span><span class="p">,</span> <span class="s1">'"'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'${'</span><span class="p">,</span> <span class="s1">'}'</span><span class="p">])</span> <span class="o">or</span>
|
||||
<span class="nx">@balanced_token</span> <span class="p">[</span><span class="s2">"'"</span><span class="p">,</span> <span class="s2">"'"</span><span class="p">]</span>
|
||||
<span class="nx">@interpolate_string</span> <span class="nx">string</span><span class="p">.</span><span class="nx">replace</span> <span class="nx">STRING_NEWLINES</span><span class="p">,</span> <span class="s2">" \\\n"</span>
|
||||
<span class="vi">@line: </span><span class="o">+</span> <span class="nx">count</span> <span class="nx">string</span><span class="p">,</span> <span class="s2">"\n"</span>
|
||||
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">string</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>Matches heredocs, adjusting indentation to the correct level, as heredocs
|
||||
preserve whitespace, but ignore indentation to the left.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">heredoc_token: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">match: </span><span class="nx">@chunk</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">HEREDOC</span><span class="p">)</span>
|
||||
<span class="nv">quote: </span><span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">substr</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="nv">doc: </span><span class="nx">@sanitize_heredoc</span> <span class="nx">match</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">or</span> <span class="nx">match</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="p">{</span><span class="nx">quote</span><span class="p">}</span>
|
||||
<span class="nx">@interpolate_string</span> <span class="s2">"$quote$doc$quote"</span>
|
||||
<span class="vi">@line: </span><span class="o">+</span> <span class="nx">count</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="s2">"\n"</span>
|
||||
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">length</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</a> </div> <p>Matches and conumes comments. We pass through comments into JavaScript,
|
||||
so they're treated as real tokens, like any other part of the language.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">comment_token: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">match: </span><span class="nx">@chunk</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">COMMENT</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="nx">match</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span>
|
||||
<span class="nv">comment: </span><span class="nx">@sanitize_heredoc</span> <span class="nx">match</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="p">{</span><span class="nv">herecomment: </span><span class="kc">true</span><span class="p">}</span>
|
||||
<span class="nx">@token</span> <span class="s1">'HERECOMMENT'</span><span class="p">,</span> <span class="nx">comment</span><span class="p">.</span><span class="nx">split</span> <span class="nx">MULTILINER</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">lines: </span><span class="nx">compact</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">replace</span><span class="p">(</span><span class="nx">COMMENT_CLEANER</span><span class="p">,</span> <span class="s1">''</span><span class="p">).</span><span class="nx">split</span> <span class="nx">MULTILINER</span>
|
||||
<span class="nv">i: </span><span class="nx">@tokens</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="k">if</span> <span class="nx">@unfinished</span><span class="p">()</span>
|
||||
<span class="nv">i: </span><span class="o">-</span> <span class="mi">1</span> <span class="k">while</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">include</span> <span class="nx">LINE_BREAK</span><span class="p">,</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">'COMMENT'</span><span class="p">,</span> <span class="nx">lines</span><span class="p">,</span> <span class="nx">@line</span><span class="p">],</span> <span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'\n'</span><span class="p">,</span> <span class="nx">@line</span><span class="p">])</span>
|
||||
<span class="vi">@line: </span><span class="o">+</span> <span class="nx">count</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="s2">"\n"</span>
|
||||
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">length</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>Matches JavaScript interpolated directly into the source via backticks.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">js_token: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nx">starts</span> <span class="nx">@chunk</span><span class="p">,</span> <span class="s1">'`'</span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">script: </span><span class="nx">@balanced_token</span> <span class="p">[</span><span class="s1">'`'</span><span class="p">,</span> <span class="s1">'`'</span><span class="p">]</span>
|
||||
<span class="nx">@token</span> <span class="s1">'JS'</span><span class="p">,</span> <span class="nx">script</span><span class="p">.</span><span class="nx">replace</span> <span class="nx">JS_CLEANER</span><span class="p">,</span> <span class="s1">''</span>
|
||||
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">script</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</a> </div> <p>Matches regular expression literals. Lexing regular expressions is difficult
|
||||
to distinguish from division, so we borrow some basic heuristics from
|
||||
JavaScript and Ruby, borrow slash balancing from <code>@balanced_token</code>, and
|
||||
borrow interpolation from <code>@interpolate_string</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">regex_token: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nx">@chunk</span><span class="p">.</span><span class="nx">match</span> <span class="nx">REGEX_START</span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="k">if</span> <span class="nx">include</span> <span class="nx">NOT_REGEX</span><span class="p">,</span> <span class="nx">@tag</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">regex: </span><span class="nx">@balanced_token</span> <span class="p">[</span><span class="s1">'/'</span><span class="p">,</span> <span class="s1">'/'</span><span class="p">]</span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">end: </span><span class="nx">@chunk</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="nx">regex</span><span class="p">.</span><span class="nx">length</span><span class="p">).</span><span class="nx">match</span> <span class="nx">REGEX_END</span>
|
||||
<span class="nv">regex: </span><span class="o">+</span> <span class="nv">flags: </span><span class="nx">end</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="k">if</span> <span class="nx">end</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="nx">regex</span><span class="p">.</span><span class="nx">match</span> <span class="nx">REGEX_INTERPOLATION</span>
|
||||
<span class="nv">str: </span><span class="nx">regex</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">1</span><span class="p">).</span><span class="nx">split</span><span class="p">(</span><span class="s1">'/'</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nv">str: </span><span class="nx">str</span><span class="p">.</span><span class="nx">replace</span> <span class="nx">REGEX_ESCAPE</span><span class="p">,</span> <span class="p">(</span><span class="nx">escaped</span><span class="p">)</span> <span class="o">-></span> <span class="s1">'\\'</span> <span class="o">+</span> <span class="nx">escaped</span>
|
||||
<span class="vi">@tokens: </span><span class="nx">@tokens</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[[</span><span class="s1">'('</span><span class="p">,</span> <span class="s1">'('</span><span class="p">],</span> <span class="p">[</span><span class="s1">'NEW'</span><span class="p">,</span> <span class="s1">'new'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'RegExp'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'CALL_START'</span><span class="p">,</span> <span class="s1">'('</span><span class="p">]]</span>
|
||||
<span class="nx">@interpolate_string</span> <span class="s2">"\"$str\""</span><span class="p">,</span> <span class="kc">yes</span>
|
||||
<span class="vi">@tokens: </span><span class="nx">@tokens</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[[</span><span class="s1">','</span><span class="p">,</span> <span class="s1">','</span><span class="p">],</span> <span class="p">[</span><span class="s1">'STRING'</span><span class="p">,</span> <span class="s2">"\"$flags\""</span><span class="p">],</span> <span class="p">[</span><span class="s1">')'</span><span class="p">,</span> <span class="s1">')'</span><span class="p">],</span> <span class="p">[</span><span class="s1">')'</span><span class="p">,</span> <span class="s1">')'</span><span class="p">]]</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">@token</span> <span class="s1">'REGEX'</span><span class="p">,</span> <span class="nx">regex</span>
|
||||
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">regex</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>Matches a token in which which the passed delimiter pairs must be correctly
|
||||
balanced (ie. strings, JS literals).</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">balanced_token: </span><span class="p">(</span><span class="nx">delimited</span><span class="p">...)</span> <span class="o">-></span>
|
||||
<span class="nx">balanced_string</span> <span class="nx">@chunk</span><span class="p">,</span> <span class="nx">delimited</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-18">#</a> </div> <p>Matches newlines, indents, and outdents, and determines which is which.
|
||||
If we can detect that the current line is continued onto the the next line,
|
||||
then the newline is suppressed:</p>
|
||||
|
||||
<pre><code>elements
|
||||
.each( ... )
|
||||
.map( ... )
|
||||
</code></pre>
|
||||
|
||||
<p>Keeps track of the level of indentation, because a single outdent token
|
||||
can close multiple indents, so we need to know how far in we happen to be.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">line_token: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">indent: </span><span class="nx">@match</span> <span class="nx">MULTI_DENT</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="vi">@line: </span><span class="o">+</span> <span class="nx">count</span> <span class="nx">indent</span><span class="p">,</span> <span class="s2">"\n"</span>
|
||||
<span class="vi">@i : </span><span class="o">+</span> <span class="nx">indent</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">prev: </span><span class="nx">@prev</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
|
||||
<span class="nv">size: </span><span class="nx">indent</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">LAST_DENTS</span><span class="p">).</span><span class="nx">reverse</span><span class="p">()[</span><span class="mi">0</span><span class="p">].</span><span class="nx">match</span><span class="p">(</span><span class="nx">LAST_DENT</span><span class="p">)[</span><span class="mi">1</span><span class="p">].</span><span class="nx">length</span>
|
||||
<span class="nv">next_character: </span><span class="nx">@chunk</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">MULTI_DENT</span><span class="p">)[</span><span class="mi">4</span><span class="p">]</span>
|
||||
<span class="nv">no_newlines: </span><span class="nx">next_character</span> <span class="o">is</span> <span class="s1">'.'</span> <span class="o">or</span> <span class="nx">@unfinished</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="nx">size</span> <span class="o">is</span> <span class="nx">@indent</span>
|
||||
<span class="k">return</span> <span class="nx">@suppress_newlines</span><span class="p">()</span> <span class="k">if</span> <span class="nx">no_newlines</span>
|
||||
<span class="k">return</span> <span class="nx">@newline_token</span> <span class="nx">indent</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">size</span> <span class="o">></span> <span class="nx">@indent</span>
|
||||
<span class="k">return</span> <span class="nx">@suppress_newlines</span><span class="p">()</span> <span class="k">if</span> <span class="nx">no_newlines</span>
|
||||
<span class="nv">diff: </span><span class="nx">size</span> <span class="o">-</span> <span class="nx">@indent</span>
|
||||
<span class="nx">@token</span> <span class="s1">'INDENT'</span><span class="p">,</span> <span class="nx">diff</span>
|
||||
<span class="nx">@indents</span><span class="p">.</span><span class="nx">push</span> <span class="nx">diff</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">@outdent_token</span> <span class="nx">@indent</span> <span class="o">-</span> <span class="nx">size</span><span class="p">,</span> <span class="nx">no_newlines</span>
|
||||
<span class="vi">@indent: </span><span class="nx">size</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-19">#</a> </div> <p>Record an outdent token or multiple tokens, if we happen to be moving back
|
||||
inwards past several recorded indents.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">outdent_token: </span><span class="p">(</span><span class="nx">move_out</span><span class="p">,</span> <span class="nx">no_newlines</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">while</span> <span class="nx">move_out</span> <span class="o">></span> <span class="mi">0</span> <span class="o">and</span> <span class="nx">@indents</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">last_indent: </span><span class="nx">@indents</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="nx">@token</span> <span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="nx">last_indent</span>
|
||||
<span class="nv">move_out: </span><span class="o">-</span> <span class="nx">last_indent</span>
|
||||
<span class="nx">@token</span> <span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s2">"\n"</span> <span class="nx">unless</span> <span class="nx">@tag</span><span class="p">()</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span> <span class="o">or</span> <span class="nx">no_newlines</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-20">#</a> </div> <p>Matches and consumes non-meaningful whitespace. Tag the previous token
|
||||
as being "spaced", because there are some cases where it makes a difference.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">whitespace_token: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">space: </span><span class="nx">@match</span> <span class="nx">WHITESPACE</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="nv">prev: </span><span class="nx">@prev</span><span class="p">()</span>
|
||||
<span class="nv">prev.spaced: </span><span class="kc">true</span> <span class="k">if</span> <span class="nx">prev</span>
|
||||
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">space</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-21">#</a> </div> <p>Generate a newline token. Consecutive newlines get merged together.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">newline_token: </span><span class="p">(</span><span class="nx">newlines</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@token</span> <span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s2">"\n"</span> <span class="nx">unless</span> <span class="nx">@tag</span><span class="p">()</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-22">#</a> </div> <p>Use a <code>\</code> at a line-ending to suppress the newline.
|
||||
The slash is removed here once its job is done.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">suppress_newlines: </span><span class="o">-></span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span> <span class="k">if</span> <span class="nx">@value</span><span class="p">()</span> <span class="o">is</span> <span class="s2">"\\"</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-23">#</a> </div> <p>We treat all other single characters as a token. Eg.: <code>( ) , . !</code>
|
||||
Multi-character operators are also literal tokens, so that Jison can assign
|
||||
the proper order of operations. There are some symbols that we tag specially
|
||||
here. <code>;</code> and newlines are both treated as a <code>TERMINATOR</code>, we distinguish
|
||||
parentheses that indicate a method call from regular parentheses, and so on.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">literal_token: </span><span class="o">-></span>
|
||||
<span class="nv">match: </span><span class="nx">@chunk</span><span class="p">.</span><span class="nx">match</span> <span class="nx">OPERATOR</span>
|
||||
<span class="nv">value: </span><span class="nx">match</span> <span class="o">and</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nv">space: </span><span class="nx">match</span> <span class="o">and</span> <span class="nx">match</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
|
||||
<span class="nx">@tag_parameters</span><span class="p">()</span> <span class="k">if</span> <span class="nx">value</span> <span class="o">and</span> <span class="nx">value</span><span class="p">.</span><span class="nx">match</span> <span class="nx">CODE</span>
|
||||
<span class="nv">value: </span><span class="o">or</span> <span class="nx">@chunk</span><span class="p">.</span><span class="nx">substr</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="nv">prev_spaced: </span><span class="nx">@prev</span><span class="p">()</span> <span class="o">and</span> <span class="nx">@prev</span><span class="p">().</span><span class="nx">spaced</span>
|
||||
<span class="nv">tag: </span><span class="nx">value</span>
|
||||
<span class="k">if</span> <span class="nx">value</span><span class="p">.</span><span class="nx">match</span> <span class="nx">ASSIGNMENT</span>
|
||||
<span class="nv">tag: </span><span class="s1">'ASSIGN'</span>
|
||||
<span class="nx">@assignment_error</span><span class="p">()</span> <span class="k">if</span> <span class="nx">include</span> <span class="nx">JS_FORBIDDEN</span><span class="p">,</span> <span class="nx">@value</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">value</span> <span class="o">is</span> <span class="s1">';'</span>
|
||||
<span class="nv">tag: </span><span class="s1">'TERMINATOR'</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">value</span> <span class="o">is</span> <span class="s1">'['</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">()</span> <span class="o">is</span> <span class="s1">'?'</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">prev_spaced</span>
|
||||
<span class="nv">tag: </span><span class="s1">'SOAKED_INDEX_START'</span>
|
||||
<span class="vi">@soaked_index: </span><span class="kc">true</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">value</span> <span class="o">is</span> <span class="s1">']'</span> <span class="o">and</span> <span class="nx">@soaked_index</span>
|
||||
<span class="nv">tag: </span><span class="s1">'SOAKED_INDEX_END'</span>
|
||||
<span class="vi">@soaked_index: </span><span class="kc">false</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">include</span><span class="p">(</span><span class="nx">CALLABLE</span><span class="p">,</span> <span class="nx">@tag</span><span class="p">())</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">prev_spaced</span>
|
||||
<span class="nv">tag: </span><span class="s1">'CALL_START'</span> <span class="k">if</span> <span class="nx">value</span> <span class="o">is</span> <span class="s1">'('</span>
|
||||
<span class="nv">tag: </span><span class="s1">'INDEX_START'</span> <span class="k">if</span> <span class="nx">value</span> <span class="o">is</span> <span class="s1">'['</span>
|
||||
<span class="vi">@i: </span><span class="o">+</span> <span class="nx">value</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="k">return</span> <span class="nx">@tag_half_assignment</span> <span class="nx">tag</span> <span class="k">if</span> <span class="nx">space</span> <span class="o">and</span> <span class="nx">prev_spaced</span> <span class="o">and</span> <span class="nx">@prev</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'ASSIGN'</span> <span class="o">and</span> <span class="nx">include</span> <span class="nx">HALF_ASSIGNMENTS</span><span class="p">,</span> <span class="nx">tag</span>
|
||||
<span class="nx">@token</span> <span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-24">#</a> </div> <h2>Token Manipulators</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-25">#</a> </div> <p>As we consume a new <code>IDENTIFIER</code>, look at the previous token to determine
|
||||
if it's a special kind of accessor.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">name_access_type: </span><span class="o">-></span>
|
||||
<span class="nx">@tag</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s1">'PROTOTYPE_ACCESS'</span><span class="p">)</span> <span class="k">if</span> <span class="nx">@value</span><span class="p">()</span> <span class="o">is</span> <span class="s1">'::'</span>
|
||||
<span class="k">if</span> <span class="nx">@value</span><span class="p">()</span> <span class="o">is</span> <span class="s1">'.'</span> <span class="o">and</span> <span class="o">not</span> <span class="p">(</span><span class="nx">@value</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'.'</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="nx">@tag</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'?'</span>
|
||||
<span class="nx">@tag</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s1">'SOAK_ACCESS'</span><span class="p">)</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">@tag</span> <span class="mi">1</span><span class="p">,</span> <span class="s1">'PROPERTY_ACCESS'</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-26">#</a> </div> <p>Sanitize a heredoc or herecomment by escaping internal double quotes and
|
||||
erasing all external indentation on the left-hand side.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">sanitize_heredoc: </span><span class="p">(</span><span class="nx">doc</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">while</span> <span class="nv">match: </span><span class="nx">HEREDOC_INDENT</span><span class="p">.</span><span class="nx">exec</span> <span class="nx">doc</span>
|
||||
<span class="nv">attempt: </span><span class="k">if</span> <span class="nx">match</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">?</span> <span class="k">then</span> <span class="nx">match</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="k">else</span> <span class="nx">match</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span>
|
||||
<span class="nv">indent: </span><span class="nx">attempt</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">indent</span> <span class="o">or</span> <span class="nx">attempt</span><span class="p">.</span><span class="nx">length</span> <span class="o"><</span> <span class="nx">indent</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">doc: </span><span class="nx">doc</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="s2">"^"</span> <span class="o">+</span><span class="nx">indent</span><span class="p">,</span> <span class="s1">'gm'</span><span class="p">),</span> <span class="s1">''</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="nx">doc</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">herecomment</span>
|
||||
<span class="nx">doc</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="nx">MULTILINER</span><span class="p">,</span> <span class="s2">"\\n"</span><span class="p">)</span>
|
||||
<span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">quote</span><span class="p">,</span> <span class="s1">'g'</span><span class="p">),</span> <span class="s1">'\\"'</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-27">#</a> </div> <p>Tag a half assignment.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tag_half_assignment: </span><span class="p">(</span><span class="nx">tag</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">last: </span><span class="nx">@tokens</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s2">"$tag="</span><span class="p">,</span> <span class="s2">"$tag="</span><span class="p">,</span> <span class="nx">last</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-28">#</a> </div> <p>A source of ambiguity in our grammar used to be parameter lists in function
|
||||
definitions versus argument lists in function calls. Walk backwards, tagging
|
||||
parameters specially in order to make things easier for the parser.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tag_parameters: </span><span class="o">-></span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@tag</span><span class="p">()</span> <span class="o">isnt</span> <span class="s1">')'</span>
|
||||
<span class="nv">i: </span><span class="mi">0</span>
|
||||
<span class="k">while</span> <span class="kc">true</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="nv">tok: </span><span class="nx">@prev</span> <span class="nx">i</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">tok</span>
|
||||
<span class="k">switch</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="k">when</span> <span class="s1">'IDENTIFIER'</span> <span class="k">then</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">:</span> <span class="s1">'PARAM'</span>
|
||||
<span class="k">when</span> <span class="s1">')'</span> <span class="k">then</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">:</span> <span class="s1">'PARAM_END'</span>
|
||||
<span class="k">when</span> <span class="s1">'('</span><span class="p">,</span> <span class="s1">'CALL_START'</span> <span class="k">then</span> <span class="k">return</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">:</span> <span class="s1">'PARAM_START'</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-29">#</a> </div> <p>Close up all remaining open blocks at the end of the file.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">close_indentation: </span><span class="o">-></span>
|
||||
<span class="nx">@outdent_token</span> <span class="nx">@indent</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-30">#</a> </div> <p>The error for when you try to use a forbidden word in JavaScript as
|
||||
an identifier.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">identifier_error: </span><span class="p">(</span><span class="nx">word</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"SyntaxError: Reserved word \"$word\" on line ${@line + 1}"</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-31">#</a> </div> <p>The error for when you try to assign to a reserved word in JavaScript,
|
||||
like "function" or "default".</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">assignment_error: </span><span class="o">-></span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"SyntaxError: Reserved word \"${@value()}\" on line ${@line + 1} can't be assigned"</span></pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-32">#</a> </div> <p>Expand variables and expressions inside double-quoted strings using
|
||||
<a href="http://wiki.ecmascript.org/doku.php?id=strawman:string_interpolation">ECMA Harmony's interpolation syntax</a>
|
||||
for substitution of bare variables as well as arbitrary expressions.</p>
|
||||
|
||||
<pre><code>"Hello $name."
|
||||
"Hello ${name.capitalize()}."
|
||||
</code></pre>
|
||||
|
||||
<p>If it encounters an interpolation, this method will recursively create a
|
||||
new Lexer, tokenize the interpolated contents, and merge them into the
|
||||
token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">interpolate_string: </span><span class="p">(</span><span class="nx">str</span><span class="p">,</span> <span class="nx">escape_quotes</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">str</span><span class="p">.</span><span class="nx">length</span> <span class="o"><</span> <span class="mi">3</span> <span class="o">or</span> <span class="o">not</span> <span class="nx">starts</span> <span class="nx">str</span><span class="p">,</span> <span class="s1">'"'</span>
|
||||
<span class="nx">@token</span> <span class="s1">'STRING'</span><span class="p">,</span> <span class="nx">str</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">lexer: </span> <span class="k">new</span> <span class="nx">Lexer</span><span class="p">()</span>
|
||||
<span class="nv">tokens: </span> <span class="p">[]</span>
|
||||
<span class="nv">quote: </span> <span class="nx">str</span><span class="p">.</span><span class="nx">substring</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="p">[</span><span class="nx">i</span><span class="p">,</span> <span class="nx">pi</span><span class="p">]</span><span class="o">:</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
|
||||
<span class="k">while</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">str</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="k">if</span> <span class="nx">starts</span> <span class="nx">str</span><span class="p">,</span> <span class="s1">'\\'</span><span class="p">,</span> <span class="nx">i</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nv">match: </span><span class="nx">str</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="nx">i</span><span class="p">).</span><span class="nx">match</span> <span class="nx">INTERPOLATION</span>
|
||||
<span class="p">[</span><span class="nx">group</span><span class="p">,</span> <span class="nx">interp</span><span class="p">]</span><span class="o">:</span> <span class="nx">match</span>
|
||||
<span class="nv">interp: </span><span class="s2">"this.${ interp.substring(1) }"</span> <span class="k">if</span> <span class="nx">starts</span> <span class="nx">interp</span><span class="p">,</span> <span class="s1">'@'</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">'STRING'</span><span class="p">,</span> <span class="s2">"$quote${ str.substring(pi, i) }$quote"</span><span class="p">]</span> <span class="k">if</span> <span class="nx">pi</span> <span class="o"><</span> <span class="nx">i</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="nx">interp</span><span class="p">]</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="nx">group</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nv">pi: </span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nv">expr: </span><span class="nx">balanced_string</span> <span class="nx">str</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="nx">i</span><span class="p">),</span> <span class="p">[[</span><span class="s1">'${'</span><span class="p">,</span> <span class="s1">'}'</span><span class="p">]])</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">'STRING'</span><span class="p">,</span> <span class="s2">"$quote${ str.substring(pi, i) }$quote"</span><span class="p">]</span> <span class="k">if</span> <span class="nx">pi</span> <span class="o"><</span> <span class="nx">i</span>
|
||||
<span class="nv">inner: </span><span class="nx">expr</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="nx">inner</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">nested: </span><span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="s2">"($inner)"</span><span class="p">,</span> <span class="p">{</span><span class="nv">line: </span><span class="nx">@line</span><span class="p">}</span>
|
||||
<span class="p">(</span><span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">:</span> <span class="s1">')'</span><span class="p">)</span> <span class="k">for</span> <span class="nx">tok</span><span class="p">,</span> <span class="nx">idx</span> <span class="k">in</span> <span class="nx">nested</span> <span class="k">when</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'CALL_END'</span>
|
||||
<span class="nx">nested</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">'TOKENS'</span><span class="p">,</span> <span class="nx">nested</span><span class="p">]</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">'STRING'</span><span class="p">,</span> <span class="s2">"$quote$quote"</span><span class="p">]</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nv">pi: </span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">'STRING'</span><span class="p">,</span> <span class="s2">"$quote${ str.substring(pi, i) }$quote"</span><span class="p">]</span> <span class="k">if</span> <span class="nx">pi</span> <span class="o"><</span> <span class="nx">i</span> <span class="o">and</span> <span class="nx">pi</span> <span class="o"><</span> <span class="nx">str</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">unshift</span> <span class="p">[</span><span class="s1">'STRING'</span><span class="p">,</span> <span class="s1">'""'</span><span class="p">]</span> <span class="nx">unless</span> <span class="nx">tokens</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'STRING'</span>
|
||||
<span class="nv">interpolated: </span><span class="nx">tokens</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">1</span>
|
||||
<span class="nx">@token</span> <span class="s1">'('</span><span class="p">,</span> <span class="s1">'('</span> <span class="k">if</span> <span class="nx">interpolated</span>
|
||||
<span class="k">for</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">tokens</span>
|
||||
<span class="p">[</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span><span class="p">]</span><span class="o">:</span> <span class="nx">token</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'TOKENS'</span>
|
||||
<span class="vi">@tokens: </span><span class="nx">@tokens</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">value</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'STRING'</span> <span class="o">and</span> <span class="nx">escape_quotes</span>
|
||||
<span class="nv">escaped: </span><span class="nx">value</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nx">value</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">).</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/"/g</span><span class="p">,</span> <span class="s1">'\\"'</span><span class="p">)</span>
|
||||
<span class="nx">@token</span> <span class="nx">tag</span><span class="p">,</span> <span class="s2">"\"$escaped\""</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">@token</span> <span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span>
|
||||
<span class="nx">@token</span> <span class="s1">'+'</span><span class="p">,</span> <span class="s1">'+'</span> <span class="k">if</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">tokens</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nx">@token</span> <span class="s1">')'</span><span class="p">,</span> <span class="s1">')'</span> <span class="k">if</span> <span class="nx">interpolated</span>
|
||||
<span class="nx">tokens</span></pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-33">#</a> </div> <h2>Helpers</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-34">#</a> </div> <p>Add a token to the results, taking note of the line number.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">token: </span><span class="p">(</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">@line</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-35">#</a> </div> <p>Peek at a tag in the current token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tag: </span><span class="p">(</span><span class="nx">index</span><span class="p">,</span> <span class="nx">new_tag</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="nx">unless</span> <span class="nv">tok: </span><span class="nx">@prev</span> <span class="nx">index</span>
|
||||
<span class="k">return</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">:</span> <span class="nx">new_tag</span> <span class="k">if</span> <span class="nx">new_tag</span><span class="o">?</span>
|
||||
<span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-36">#</a> </div> <p>Peek at a value in the current token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">value: </span><span class="p">(</span><span class="nx">index</span><span class="p">,</span> <span class="nx">val</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="nx">unless</span> <span class="nv">tok: </span><span class="nx">@prev</span> <span class="nx">index</span>
|
||||
<span class="k">return</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">:</span> <span class="nx">val</span> <span class="k">if</span> <span class="nx">val</span><span class="o">?</span>
|
||||
<span class="nx">tok</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-37"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-37">#</a> </div> <p>Peek at a previous token, entire.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">prev: </span><span class="p">(</span><span class="nx">index</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@tokens</span><span class="p">[</span><span class="nx">@tokens</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="p">(</span><span class="nx">index</span> <span class="o">or</span> <span class="mi">1</span><span class="p">)]</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-38">#</a> </div> <p>Attempt to match a string against the current chunk, returning the indexed
|
||||
match if successful, and <code>false</code> otherwise.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">match: </span><span class="p">(</span><span class="nx">regex</span><span class="p">,</span> <span class="nx">index</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="nx">unless</span> <span class="nv">m: </span><span class="nx">@chunk</span><span class="p">.</span><span class="nx">match</span> <span class="nx">regex</span>
|
||||
<span class="k">if</span> <span class="nx">m</span> <span class="k">then</span> <span class="nx">m</span><span class="p">[</span><span class="nx">index</span><span class="p">]</span> <span class="k">else</span> <span class="kc">false</span></pre></div> </td> </tr> <tr id="section-39"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-39">#</a> </div> <p>Are we in the midst of an unfinished expression?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">unfinished: </span><span class="o">-></span>
|
||||
<span class="nv">prev: </span><span class="nx">@prev</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
|
||||
<span class="nx">@value</span><span class="p">()</span> <span class="o">and</span> <span class="nx">@value</span><span class="p">().</span><span class="nx">match</span> <span class="o">and</span> <span class="nx">@value</span><span class="p">().</span><span class="nx">match</span><span class="p">(</span><span class="nx">NO_NEWLINE</span><span class="p">)</span> <span class="o">and</span>
|
||||
<span class="nx">prev</span> <span class="o">and</span> <span class="p">(</span><span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'.'</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@value</span><span class="p">().</span><span class="nx">match</span><span class="p">(</span><span class="nx">CODE</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-40">#</a> </div> <h2>Lexer Properties</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-41">#</a> </div> <p>There are no exensions to the core lexer by default.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="vi">@extensions: </span><span class="p">[]</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-42">#</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-43">#</a> </div> <p>Keywords that CoffeeScript shares in common with JavaScript.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">JS_KEYWORDS: </span><span class="p">[</span>
|
||||
<span class="s2">"if"</span><span class="p">,</span> <span class="s2">"else"</span><span class="p">,</span>
|
||||
<span class="s2">"true"</span><span class="p">,</span> <span class="s2">"false"</span><span class="p">,</span>
|
||||
<span class="s2">"new"</span><span class="p">,</span> <span class="s2">"return"</span><span class="p">,</span>
|
||||
<span class="s2">"try"</span><span class="p">,</span> <span class="s2">"catch"</span><span class="p">,</span> <span class="s2">"finally"</span><span class="p">,</span> <span class="s2">"throw"</span><span class="p">,</span>
|
||||
<span class="s2">"break"</span><span class="p">,</span> <span class="s2">"continue"</span><span class="p">,</span>
|
||||
<span class="s2">"for"</span><span class="p">,</span> <span class="s2">"in"</span><span class="p">,</span> <span class="s2">"while"</span><span class="p">,</span>
|
||||
<span class="s2">"delete"</span><span class="p">,</span> <span class="s2">"instanceof"</span><span class="p">,</span> <span class="s2">"typeof"</span><span class="p">,</span>
|
||||
<span class="s2">"switch"</span><span class="p">,</span> <span class="s2">"super"</span><span class="p">,</span> <span class="s2">"extends"</span><span class="p">,</span> <span class="s2">"class"</span><span class="p">,</span>
|
||||
<span class="s2">"this"</span><span class="p">,</span> <span class="s2">"null"</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-44">#</a> </div> <p>CoffeeScript-only keywords, which we're more relaxed about allowing. They can't
|
||||
be used standalone, but you can reference them as an attached property.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">COFFEE_ALIASES: </span> <span class="p">[</span><span class="s2">"and"</span><span class="p">,</span> <span class="s2">"or"</span><span class="p">,</span> <span class="s2">"is"</span><span class="p">,</span> <span class="s2">"isnt"</span><span class="p">,</span> <span class="s2">"not"</span><span class="p">]</span>
|
||||
<span class="nv">COFFEE_KEYWORDS: </span><span class="nx">COFFEE_ALIASES</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[</span>
|
||||
<span class="s2">"then"</span><span class="p">,</span> <span class="s2">"unless"</span><span class="p">,</span> <span class="s2">"until"</span><span class="p">,</span>
|
||||
<span class="s2">"yes"</span><span class="p">,</span> <span class="s2">"no"</span><span class="p">,</span> <span class="s2">"on"</span><span class="p">,</span> <span class="s2">"off"</span><span class="p">,</span>
|
||||
<span class="s2">"of"</span><span class="p">,</span> <span class="s2">"by"</span><span class="p">,</span> <span class="s2">"where"</span><span class="p">,</span> <span class="s2">"when"</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-45"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-45">#</a> </div> <p>The combined list of keywords is the superset that gets passed verbatim to
|
||||
the parser.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">KEYWORDS: </span><span class="nx">JS_KEYWORDS</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">COFFEE_KEYWORDS</span></pre></div> </td> </tr> <tr id="section-46"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-46">#</a> </div> <p>The list of keywords that are reserved by JavaScript, but not used, or are
|
||||
used by CoffeeScript internally. We throw an error when these are encountered,
|
||||
to avoid having a JavaScript error at runtime.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">RESERVED: </span><span class="p">[</span>
|
||||
<span class="s2">"case"</span><span class="p">,</span> <span class="s2">"default"</span><span class="p">,</span> <span class="s2">"do"</span><span class="p">,</span> <span class="s2">"function"</span><span class="p">,</span> <span class="s2">"var"</span><span class="p">,</span> <span class="s2">"void"</span><span class="p">,</span> <span class="s2">"with"</span>
|
||||
<span class="s2">"const"</span><span class="p">,</span> <span class="s2">"let"</span><span class="p">,</span> <span class="s2">"enum"</span><span class="p">,</span> <span class="s2">"export"</span><span class="p">,</span> <span class="s2">"import"</span><span class="p">,</span> <span class="s2">"native"</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-47">#</a> </div> <p>The superset of both JavaScript keywords and reserved words, none of which may
|
||||
be used as identifiers or properties.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">JS_FORBIDDEN: </span><span class="nx">JS_KEYWORDS</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">RESERVED</span></pre></div> </td> </tr> <tr id="section-48"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-48">#</a> </div> <p>Token matching regexes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IDENTIFIER : </span><span class="sr">/^([a-zA-Z\$_](\w|\$)*)/</span>
|
||||
<span class="nv">NUMBER : </span><span class="sr">/^(\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?(e[+\-]?[0-9]+)?)))\b/i</span>
|
||||
<span class="nv">HEREDOC : </span><span class="sr">/^("{6}|'{6}|"{3}\n?([\s\S]*?)\n?([ \t]*)"{3}|'{3}\n?([\s\S]*?)\n?([ \t]*)'{3})/</span>
|
||||
<span class="nv">INTERPOLATION : </span><span class="sr">/^\$([a-zA-Z_@]\w*(\.\w+)*)/</span>
|
||||
<span class="nv">OPERATOR : </span><span class="sr">/^([+\*&|\/\-%=<>:!?]+)([ \t]*)/</span>
|
||||
<span class="nv">WHITESPACE : </span><span class="sr">/^([ \t]+)/</span>
|
||||
<span class="nv">COMMENT : </span><span class="sr">/^((\n?[ \t]*)?#{3}(?!#)\n*([\s\S]*?)\n*([ \t]*)#{3}|((\n?[ \t]*)?#[^\n]*)+)/</span>
|
||||
<span class="nv">CODE : </span><span class="sr">/^((-|=)>)/</span>
|
||||
<span class="nv">MULTI_DENT : </span><span class="sr">/^((\n([ \t]*))+)(\.)?/</span>
|
||||
<span class="nv">LAST_DENTS : </span><span class="sr">/\n([ \t]*)/g</span>
|
||||
<span class="nv">LAST_DENT : </span><span class="sr">/\n([ \t]*)/</span>
|
||||
<span class="nv">ASSIGNMENT : </span><span class="sr">/^(:|=)$/</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-49">#</a> </div> <p>Regex-matching-regexes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">REGEX_START : </span><span class="sr">/^\/[^\/ ]/</span>
|
||||
<span class="nv">REGEX_INTERPOLATION: </span><span class="sr">/([^\\]\$[a-zA-Z_@]|[^\\]\$\{.*[^\\]\})/</span>
|
||||
<span class="nv">REGEX_END : </span><span class="sr">/^(([imgy]{1,4})\b|\W)/</span>
|
||||
<span class="nv">REGEX_ESCAPE : </span><span class="sr">/\\[^\$]/g</span></pre></div> </td> </tr> <tr id="section-50"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-50">#</a> </div> <p>Token cleaning regexes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">JS_CLEANER : </span><span class="sr">/(^`|`$)/g</span>
|
||||
<span class="nv">MULTILINER : </span><span class="sr">/\n/g</span>
|
||||
<span class="nv">STRING_NEWLINES : </span><span class="sr">/\n[ \t]*/g</span>
|
||||
<span class="nv">COMMENT_CLEANER : </span><span class="sr">/(^[ \t]*#|\n[ \t]*$)/mg</span>
|
||||
<span class="nv">NO_NEWLINE : </span><span class="sr">/^([+\*&|\/\-%=<>:!.\\][<>=&|]*|and|or|is|isnt|not|delete|typeof|instanceof)$/</span>
|
||||
<span class="nv">HEREDOC_INDENT : </span><span class="sr">/(\n+([ \t]*)|^([ \t]+))/g</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-51">#</a> </div> <p>Tokens which a regular expression will never immediately follow, but which
|
||||
a division operator might.</p>
|
||||
|
||||
<p>See: http://www.mozilla.org/js/language/js20-2002-04/rationale/syntax.html#regular-expressions</p>
|
||||
|
||||
<p>Our list is shorter, due to sans-parentheses method calls.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">NOT_REGEX: </span><span class="p">[</span>
|
||||
<span class="s1">'NUMBER'</span><span class="p">,</span> <span class="s1">'REGEX'</span><span class="p">,</span> <span class="s1">'++'</span><span class="p">,</span> <span class="s1">'--'</span><span class="p">,</span> <span class="s1">'FALSE'</span><span class="p">,</span> <span class="s1">'NULL'</span><span class="p">,</span> <span class="s1">'TRUE'</span><span class="p">,</span> <span class="s1">']'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-52">#</a> </div> <p>Tokens which could legitimately be invoked or indexed. A opening
|
||||
parentheses or bracket following these tokens will be recorded as the start
|
||||
of a function invocation or indexing operation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CALLABLE: </span><span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'SUPER'</span><span class="p">,</span> <span class="s1">')'</span><span class="p">,</span> <span class="s1">']'</span><span class="p">,</span> <span class="s1">'}'</span><span class="p">,</span> <span class="s1">'STRING'</span><span class="p">,</span> <span class="s1">'@'</span><span class="p">,</span> <span class="s1">'THIS'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-53"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-53">#</a> </div> <p>Tokens that indicate an access -- keywords immediately following will be
|
||||
treated as identifiers.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">ACCESSORS: </span><span class="p">[</span><span class="s1">'PROPERTY_ACCESS'</span><span class="p">,</span> <span class="s1">'PROTOTYPE_ACCESS'</span><span class="p">,</span> <span class="s1">'SOAK_ACCESS'</span><span class="p">,</span> <span class="s1">'@'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-54">#</a> </div> <p>Tokens that, when immediately preceding a <code>WHEN</code>, indicate that the <code>WHEN</code>
|
||||
occurs at the start of a line. We disambiguate these from trailing whens to
|
||||
avoid an ambiguity in the grammar.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">LINE_BREAK: </span><span class="p">[</span><span class="s1">'INDENT'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="s1">'TERMINATOR'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-55">#</a> </div> <p>Half-assignments...</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">HALF_ASSIGNMENTS: </span><span class="p">[</span><span class="s1">'-'</span><span class="p">,</span> <span class="s1">'+'</span><span class="p">,</span> <span class="s1">'/'</span><span class="p">,</span> <span class="s1">'*'</span><span class="p">,</span> <span class="s1">'%'</span><span class="p">,</span> <span class="s1">'||'</span><span class="p">,</span> <span class="s1">'&&'</span><span class="p">,</span> <span class="s1">'?'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-56">#</a> </div> <p>Conversions from CoffeeScript operators into JavaScript ones.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CONVERSIONS: </span><span class="p">{</span>
|
||||
<span class="s1">'and'</span><span class="o">:</span> <span class="s1">'&&'</span>
|
||||
<span class="s1">'or'</span><span class="o">:</span> <span class="s1">'||'</span>
|
||||
<span class="s1">'is'</span><span class="o">:</span> <span class="s1">'=='</span>
|
||||
<span class="s1">'isnt'</span><span class="o">:</span> <span class="s1">'!='</span>
|
||||
<span class="s1">'not'</span><span class="o">:</span> <span class="s1">'!'</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
1026
documentation/docs/nodes.html
Normal file
1026
documentation/docs/nodes.html
Normal file
File diff suppressed because it is too large
Load Diff
67
documentation/docs/optparse.html
Normal file
67
documentation/docs/optparse.html
Normal file
@@ -0,0 +1,67 @@
|
||||
<!DOCTYPE html> <html> <head> <title>optparse.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> optparse.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>A simple <strong>OptionParser</strong> class to parse option flags from the command-line.
|
||||
Use it like so:</p>
|
||||
|
||||
<pre><code>parser: new OptionParser switches, help_banner
|
||||
options: parser.parse process.argv
|
||||
</code></pre> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.OptionParser: </span><span class="nx">class</span> <span class="nx">OptionParser</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-2">#</a> </div> <p>Initialize with a list of valid options, in the form:</p>
|
||||
|
||||
<pre><code>[short-flag, long-flag, description]
|
||||
</code></pre>
|
||||
|
||||
<p>Along with an an optional banner for the usage help.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">rules</span><span class="p">,</span> <span class="nx">banner</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="vi">@banner: </span> <span class="nx">banner</span>
|
||||
<span class="vi">@rules: </span> <span class="nx">build_rules</span><span class="p">(</span><span class="nx">rules</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>Parse the list of arguments, populating an <code>options</code> object with all of the
|
||||
specified options, and returning it. <code>options.arguments</code> will be an array
|
||||
containing the remaning non-option arguments. This is a simpler API than
|
||||
many option parsers that allow you to attach callback actions for every
|
||||
flag. Instead, you're responsible for interpreting the options object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">parse: </span><span class="p">(</span><span class="nx">args</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">options: </span><span class="p">{</span><span class="nv">arguments: </span><span class="p">[]}</span>
|
||||
<span class="nv">args: </span><span class="nx">normalize_arguments</span> <span class="nx">args</span>
|
||||
<span class="k">while</span> <span class="p">(</span><span class="nv">arg: </span><span class="nx">args</span><span class="p">.</span><span class="nx">shift</span><span class="p">())</span>
|
||||
<span class="nv">is_option: </span><span class="o">!!</span><span class="p">(</span><span class="nx">arg</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">LONG_FLAG</span><span class="p">)</span> <span class="o">or</span> <span class="nx">arg</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">SHORT_FLAG</span><span class="p">))</span>
|
||||
<span class="nv">matched_rule: </span><span class="kc">no</span>
|
||||
<span class="k">for</span> <span class="nx">rule</span> <span class="k">in</span> <span class="nx">@rules</span>
|
||||
<span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">short_flag</span> <span class="o">is</span> <span class="nx">arg</span> <span class="o">or</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">long_flag</span> <span class="o">is</span> <span class="nx">arg</span>
|
||||
<span class="nx">options</span><span class="p">[</span><span class="nx">rule</span><span class="p">.</span><span class="nx">name</span><span class="p">]</span><span class="o">:</span> <span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">has_argument</span> <span class="k">then</span> <span class="nx">args</span><span class="p">.</span><span class="nx">shift</span><span class="p">()</span> <span class="k">else</span> <span class="kc">true</span>
|
||||
<span class="nv">matched_rule: </span><span class="kc">yes</span>
|
||||
<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">is_option</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">matched_rule</span>
|
||||
<span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span><span class="p">.</span><span class="nx">push</span> <span class="nx">arg</span> <span class="nx">unless</span> <span class="nx">is_option</span>
|
||||
<span class="nx">options</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Return the help text for this <strong>OptionParser</strong>, listing and describing all
|
||||
of the valid options, for <code>--help</code> and such.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">help: </span><span class="o">-></span>
|
||||
<span class="nv">lines: </span><span class="p">[</span><span class="s1">'Available options:'</span><span class="p">]</span>
|
||||
<span class="nx">lines</span><span class="p">.</span><span class="nx">unshift</span> <span class="s2">"$@banner\n"</span> <span class="k">if</span> <span class="nx">@banner</span>
|
||||
<span class="k">for</span> <span class="nx">rule</span> <span class="k">in</span> <span class="nx">@rules</span>
|
||||
<span class="nv">spaces: </span> <span class="mi">15</span> <span class="o">-</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">long_flag</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">spaces: </span> <span class="k">if</span> <span class="nx">spaces</span> <span class="o">></span> <span class="mi">0</span> <span class="k">then</span> <span class="p">(</span><span class="s1">' '</span> <span class="k">for</span> <span class="nx">i</span> <span class="k">in</span> <span class="p">[</span><span class="mi">0</span><span class="p">..</span><span class="nx">spaces</span><span class="p">]).</span><span class="nx">join</span><span class="p">(</span><span class="s1">''</span><span class="p">)</span> <span class="k">else</span> <span class="s1">''</span>
|
||||
<span class="nv">let_part: </span><span class="k">if</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">short_flag</span> <span class="k">then</span> <span class="nx">rule</span><span class="p">.</span><span class="nx">short_flag</span> <span class="o">+</span> <span class="s1">', '</span> <span class="k">else</span> <span class="s1">' '</span>
|
||||
<span class="nx">lines</span><span class="p">.</span><span class="nx">push</span> <span class="s2">" $let_part$rule.long_flag$spaces$rule.description"</span>
|
||||
<span class="s2">"\n${ lines.join('\n') }\n"</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <h2>Helpers</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Regex matchers for option flags.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">LONG_FLAG: </span> <span class="sr">/^(--\w[\w\-]+)/</span>
|
||||
<span class="nv">SHORT_FLAG: </span><span class="sr">/^(-\w)/</span>
|
||||
<span class="nv">MULTI_FLAG: </span><span class="sr">/^-(\w{2,})/</span>
|
||||
<span class="nv">OPTIONAL: </span> <span class="sr">/\[(.+)\]/</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Build and return the list of option rules. If the optional <em>short-flag</em> is
|
||||
unspecified, leave it out by padding with <code>null</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">build_rules: </span><span class="p">(</span><span class="nx">rules</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">for</span> <span class="nx">tuple</span> <span class="k">in</span> <span class="nx">rules</span>
|
||||
<span class="nx">tuple</span><span class="p">.</span><span class="nx">unshift</span> <span class="kc">null</span> <span class="k">if</span> <span class="nx">tuple</span><span class="p">.</span><span class="nx">length</span> <span class="o"><</span> <span class="mi">3</span>
|
||||
<span class="nx">build_rule</span> <span class="nx">tuple</span><span class="p">...</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Build a rule from a <code>-o</code> short flag, a <code>--output [DIR]</code> long flag, and the
|
||||
description of what the option does.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">build_rule: </span><span class="p">(</span><span class="nx">short_flag</span><span class="p">,</span> <span class="nx">long_flag</span><span class="p">,</span> <span class="nx">description</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">match: </span> <span class="nx">long_flag</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">long_flag: </span> <span class="nx">long_flag</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">LONG_FLAG</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="p">{</span>
|
||||
<span class="nv">name: </span> <span class="nx">long_flag</span><span class="p">.</span><span class="nx">substr</span> <span class="mi">2</span>
|
||||
<span class="nv">short_flag: </span> <span class="nx">short_flag</span>
|
||||
<span class="nv">long_flag: </span> <span class="nx">long_flag</span>
|
||||
<span class="nv">description: </span> <span class="nx">description</span>
|
||||
<span class="nv">has_argument: </span><span class="o">!!</span><span class="p">(</span><span class="nx">match</span> <span class="o">and</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Normalize arguments by expanding merged flags into multiple flags. This allows
|
||||
you to have <code>-wl</code> be the same as <code>--watch --lint</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">normalize_arguments: </span><span class="p">(</span><span class="nx">args</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">args: </span><span class="nx">args</span><span class="p">.</span><span class="nx">slice</span> <span class="mi">0</span>
|
||||
<span class="nv">result: </span><span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="nx">arg</span> <span class="k">in</span> <span class="nx">args</span>
|
||||
<span class="k">if</span> <span class="nv">match: </span><span class="nx">arg</span><span class="p">.</span><span class="nx">match</span> <span class="nx">MULTI_FLAG</span>
|
||||
<span class="nx">result</span><span class="p">.</span><span class="nx">push</span> <span class="s1">'-'</span> <span class="o">+</span> <span class="nx">l</span> <span class="k">for</span> <span class="nx">l</span> <span class="k">in</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">split</span> <span class="s1">''</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">result</span><span class="p">.</span><span class="nx">push</span> <span class="nx">arg</span>
|
||||
<span class="nx">result</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
21
documentation/docs/repl.html
Normal file
21
documentation/docs/repl.html
Normal file
@@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html> <html> <head> <title>repl.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> repl.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>A very simple Read-Eval-Print-Loop. Compiles one line at a time to JavaScript
|
||||
and evaluates it. Good for simple tests, or poking around the <strong>Node.js</strong> API.
|
||||
Using it looks like this:</p>
|
||||
|
||||
<pre><code>coffee> puts "$num bottles of beer" for num in [99..1]
|
||||
</code></pre> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-2">#</a> </div> <p>Require the <strong>coffee-script</strong> module to get access to the compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript: </span><span class="nx">require</span> <span class="s1">'./coffee-script'</span>
|
||||
<span class="nv">helpers: </span> <span class="nx">require</span><span class="p">(</span><span class="s1">'./helpers'</span><span class="p">).</span><span class="nx">helpers</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>Our prompt.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">prompt: </span><span class="s1">'coffee> '</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Quick alias for quitting the REPL.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">helpers</span><span class="p">.</span><span class="nx">extend</span> <span class="nx">global</span><span class="p">,</span> <span class="p">{</span>
|
||||
<span class="nv">quit: </span><span class="o">-></span> <span class="nx">process</span><span class="p">.</span><span class="nx">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
|
||||
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>The main REPL function. <strong>run</strong> is called every time a line of code is entered.
|
||||
Attempt to evaluate the command. If there's an exception, print it out instead
|
||||
of exiting.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">run: </span><span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">try</span>
|
||||
<span class="nv">val: </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">(),</span> <span class="p">{</span><span class="nv">no_wrap: </span><span class="kc">true</span><span class="p">,</span> <span class="nv">globals: </span><span class="kc">true</span><span class="p">,</span> <span class="nv">source: </span><span class="s1">'repl'</span><span class="p">}</span>
|
||||
<span class="nx">p</span> <span class="nx">val</span> <span class="k">if</span> <span class="nx">val</span> <span class="o">isnt</span> <span class="kc">undefined</span>
|
||||
<span class="k">catch</span> <span class="nx">err</span>
|
||||
<span class="nx">puts</span> <span class="nx">err</span><span class="p">.</span><span class="nx">stack</span> <span class="o">or</span> <span class="nx">err</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span>
|
||||
<span class="nx">print</span> <span class="nx">prompt</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Start up the REPL by opening <strong>stdin</strong> and listening for input.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">stdin: </span><span class="nx">process</span><span class="p">.</span><span class="nx">openStdin</span><span class="p">()</span>
|
||||
<span class="nx">stdin</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">'data'</span><span class="p">,</span> <span class="nx">run</span>
|
||||
<span class="nx">print</span> <span class="nx">prompt</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
228
documentation/docs/rewriter.html
Normal file
228
documentation/docs/rewriter.html
Normal file
@@ -0,0 +1,228 @@
|
||||
<!DOCTYPE html> <html> <head> <title>rewriter.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> rewriter.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>The CoffeeScript language has a good deal of optional syntax, implicit syntax,
|
||||
and shorthand syntax. This can greatly complicate a grammar and bloat
|
||||
the resulting parse table. Instead of making the parser handle it all, we take
|
||||
a series of passes over the token stream, using this <strong>Rewriter</strong> to convert
|
||||
shorthand into the unambiguous long form, add implicit indentation and
|
||||
parentheses, balance incorrect nestings, and generally clean things up.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-2">#</a> </div> <p>Set up exported variables for both Node.js and the browser.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nx">process</span><span class="o">?</span>
|
||||
<span class="p">{</span><span class="nx">helpers</span><span class="p">}</span><span class="o">:</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'./helpers'</span><span class="p">)</span>
|
||||
<span class="k">else</span>
|
||||
<span class="k">this</span><span class="p">.</span><span class="nv">exports: </span><span class="k">this</span>
|
||||
<span class="nv">helpers: </span> <span class="k">this</span><span class="p">.</span><span class="nx">helpers</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>Import the helpers we need.</p> </td> <td class="code"> <div class="highlight"><pre><span class="p">{</span><span class="nx">include</span><span class="p">}</span><span class="o">:</span> <span class="nx">helpers</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>The <strong>Rewriter</strong> class is used by the <a href="lexer.html">Lexer</a>, directly against
|
||||
its internal array of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Rewriter: </span><span class="nx">class</span> <span class="nx">Rewriter</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Rewrite the token stream in multiple passes, one logical filter at
|
||||
a time. This could certainly be changed into a single pass through the
|
||||
stream, with a big ol' efficient switch, but it's much nicer to work with
|
||||
like this. The order of these passes matters -- indentation must be
|
||||
corrected before implicit parentheses can be wrapped around blocks of code.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">rewrite: </span><span class="p">(</span><span class="nx">tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="vi">@tokens: </span><span class="nx">tokens</span>
|
||||
<span class="nx">@adjust_comments</span><span class="p">()</span>
|
||||
<span class="nx">@remove_leading_newlines</span><span class="p">()</span>
|
||||
<span class="nx">@remove_mid_expression_newlines</span><span class="p">()</span>
|
||||
<span class="nx">@close_open_calls_and_indexes</span><span class="p">()</span>
|
||||
<span class="nx">@add_implicit_indentation</span><span class="p">()</span>
|
||||
<span class="nx">@add_implicit_parentheses</span><span class="p">()</span>
|
||||
<span class="nx">@ensure_balance</span> <span class="nx">BALANCED_PAIRS</span>
|
||||
<span class="nx">@rewrite_closing_parens</span><span class="p">()</span>
|
||||
<span class="nx">@tokens</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Rewrite the token stream, looking one token ahead and behind.
|
||||
Allow the return value of the block to tell us how many tokens to move
|
||||
forwards (or backwards) in the stream, to make sure we don't miss anything
|
||||
as tokens are inserted and removed, and the stream changes length under
|
||||
our feet.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">scan_tokens: </span><span class="p">(</span><span class="nx">block</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">i: </span><span class="mi">0</span>
|
||||
<span class="k">while</span> <span class="kc">true</span>
|
||||
<span class="k">break</span> <span class="nx">unless</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>
|
||||
<span class="nv">move: </span><span class="nx">block</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">],</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">],</span> <span class="nx">i</span>
|
||||
<span class="nv">i: </span><span class="o">+</span> <span class="nx">move</span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Massage newlines and indentations so that comments don't have to be
|
||||
correctly indented, or appear on a line of their own.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">adjust_comments: </span><span class="o">-></span>
|
||||
<span class="nx">@scan_tokens</span> <span class="p">(</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">post</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=></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">'COMMENT'</span>
|
||||
<span class="p">[</span><span class="nx">before</span><span class="p">,</span> <span class="nx">after</span><span class="p">]</span><span class="o">:</span> <span class="p">[</span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">],</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="k">if</span> <span class="nx">after</span> <span class="o">and</span> <span class="nx">after</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'INDENT'</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="k">if</span> <span class="nx">before</span> <span class="o">and</span> <span class="nx">before</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'OUTDENT'</span> <span class="o">and</span> <span class="nx">post</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="nx">post</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">after</span>
|
||||
<span class="k">return</span> <span class="mi">1</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">prev</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'TERMINATOR'</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'INDENT'</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'OUTDENT'</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s2">"\n"</span><span class="p">,</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="k">return</span> <span class="mi">2</span>
|
||||
<span class="k">else</span>
|
||||
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Leading newlines would introduce an ambiguity in the grammar, so we
|
||||
dispatch them here.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">remove_leading_newlines: </span><span class="o">-></span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">shift</span><span class="p">()</span> <span class="k">while</span> <span class="nx">@tokens</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">and</span> <span class="nx">@tokens</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Some blocks occur in the middle of expressions -- when we're expecting
|
||||
this, remove their trailing newlines.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">remove_mid_expression_newlines: </span><span class="o">-></span>
|
||||
<span class="nx">@scan_tokens</span> <span class="p">(</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">post</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=></span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">post</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">EXPRESSION_CLOSE</span><span class="p">,</span> <span class="nx">post</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">and</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="k">return</span> <span class="mi">0</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>The lexer has tagged the opening parenthesis of a method call, and the
|
||||
opening bracket of an indexing operation. Match them with their paired
|
||||
close.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">close_open_calls_and_indexes: </span><span class="o">-></span>
|
||||
<span class="nv">parens: </span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nv">brackets: </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nx">@scan_tokens</span> <span class="p">(</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">post</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=></span>
|
||||
<span class="k">switch</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="k">when</span> <span class="s1">'CALL_START'</span> <span class="k">then</span> <span class="nx">parens</span><span class="p">.</span><span class="nx">push</span> <span class="mi">0</span>
|
||||
<span class="k">when</span> <span class="s1">'INDEX_START'</span> <span class="k">then</span> <span class="nx">brackets</span><span class="p">.</span><span class="nx">push</span> <span class="mi">0</span>
|
||||
<span class="k">when</span> <span class="s1">'('</span> <span class="k">then</span> <span class="nx">parens</span><span class="p">[</span><span class="nx">parens</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span><span class="o">:</span> <span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="k">when</span> <span class="s1">'['</span> <span class="k">then</span> <span class="nx">brackets</span><span class="p">[</span><span class="nx">brackets</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span><span class="o">:</span> <span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="k">when</span> <span class="s1">')'</span>
|
||||
<span class="k">if</span> <span class="nx">parens</span><span class="p">[</span><span class="nx">parens</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">is</span> <span class="mi">0</span>
|
||||
<span class="nx">parens</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">:</span> <span class="s1">'CALL_END'</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">parens</span><span class="p">[</span><span class="nx">parens</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span><span class="o">:</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="k">when</span> <span class="s1">']'</span>
|
||||
<span class="k">if</span> <span class="nx">brackets</span><span class="p">[</span><span class="nx">brackets</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span>
|
||||
<span class="nx">brackets</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">:</span> <span class="s1">'INDEX_END'</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">brackets</span><span class="p">[</span><span class="nx">brackets</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span><span class="o">:</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Methods may be optionally called without parentheses, for simple cases.
|
||||
Insert the implicit parentheses here, so that the parser doesn't have to
|
||||
deal with them.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">add_implicit_parentheses: </span><span class="o">-></span>
|
||||
<span class="nv">stack: </span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nv">close_calls: </span><span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="o">=></span>
|
||||
<span class="k">for</span> <span class="nx">tmp</span> <span class="k">in</span> <span class="p">[</span><span class="mi">0</span><span class="p">...</span><span class="nx">stack</span><span class="p">[</span><span class="nx">stack</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]]</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">'CALL_END'</span><span class="p">,</span> <span class="s1">')'</span><span class="p">,</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">][</span><span class="mi">2</span><span class="p">]])</span>
|
||||
<span class="nv">size: </span><span class="nx">stack</span><span class="p">[</span><span class="nx">stack</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="nx">stack</span><span class="p">[</span><span class="nx">stack</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span><span class="o">:</span> <span class="mi">0</span>
|
||||
<span class="nx">size</span>
|
||||
<span class="nx">@scan_tokens</span> <span class="p">(</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">post</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=></span>
|
||||
<span class="nv">tag: </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nx">stack</span><span class="p">[</span><span class="nx">stack</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">2</span><span class="p">]</span><span class="o">:</span> <span class="o">+</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'OUTDENT'</span>
|
||||
<span class="nv">open: </span><span class="nx">stack</span><span class="p">[</span><span class="nx">stack</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">></span> <span class="mi">0</span>
|
||||
<span class="k">if</span> <span class="nx">prev</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_FUNC</span><span class="p">,</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_CALL</span><span class="p">,</span> <span class="nx">tag</span><span class="p">)</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">'CALL_START'</span><span class="p">,</span> <span class="s1">'('</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="nx">stack</span><span class="p">[</span><span class="nx">stack</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span><span class="o">:</span> <span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="mi">0</span> <span class="k">if</span> <span class="nx">include</span><span class="p">(</span><span class="nx">EXPRESSION_START</span><span class="p">,</span> <span class="nx">tag</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="mi">2</span>
|
||||
<span class="k">if</span> <span class="nx">include</span><span class="p">(</span><span class="nx">EXPRESSION_START</span><span class="p">,</span> <span class="nx">tag</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'INDENT'</span> <span class="o">and</span> <span class="o">!</span><span class="nx">token</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">open</span> <span class="o">and</span> <span class="o">not</span> <span class="p">(</span><span class="nx">prev</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_BLOCK</span><span class="p">,</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span>
|
||||
<span class="nv">size: </span><span class="nx">close_calls</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="mi">0</span>
|
||||
<span class="k">return</span> <span class="nx">size</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="mi">0</span>
|
||||
<span class="k">return</span> <span class="mi">1</span>
|
||||
<span class="k">if</span> <span class="nx">open</span> <span class="o">and</span> <span class="o">!</span><span class="nx">token</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="p">(</span><span class="o">!</span><span class="nx">post</span> <span class="o">or</span> <span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_END</span><span class="p">,</span> <span class="nx">tag</span><span class="p">))</span>
|
||||
<span class="nv">j: </span><span class="mi">1</span><span class="p">;</span> <span class="nx">j</span><span class="o">++</span> <span class="k">while</span> <span class="p">(</span><span class="nv">nx: </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="nx">j</span><span class="p">])</span><span class="o">?</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_END</span><span class="p">,</span> <span class="nx">nx</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
|
||||
<span class="k">if</span> <span class="nx">nx</span><span class="o">?</span> <span class="o">and</span> <span class="nx">nx</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">','</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'TERMINATOR'</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">size: </span><span class="nx">close_calls</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">isnt</span> <span class="s1">'OUTDENT'</span> <span class="o">and</span> <span class="nx">include</span> <span class="nx">EXPRESSION_END</span><span class="p">,</span> <span class="nx">tag</span>
|
||||
<span class="k">return</span> <span class="nx">size</span>
|
||||
<span class="k">if</span> <span class="nx">tag</span> <span class="o">isnt</span> <span class="s1">'OUTDENT'</span> <span class="o">and</span> <span class="nx">include</span> <span class="nx">EXPRESSION_END</span><span class="p">,</span> <span class="nx">tag</span>
|
||||
<span class="nx">stack</span><span class="p">[</span><span class="nx">stack</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">2</span><span class="p">]</span><span class="o">:</span> <span class="o">+</span> <span class="nx">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="mi">1</span>
|
||||
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>Because our grammar is LALR(1), it can't handle some single-line
|
||||
expressions that lack ending delimiters. The <strong>Rewriter</strong> adds the implicit
|
||||
blocks, so it doesn't need to. ')' can close a single-line block,
|
||||
but we need to make sure it's balanced.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">add_implicit_indentation: </span><span class="o">-></span>
|
||||
<span class="nx">@scan_tokens</span> <span class="p">(</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">post</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=></span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">include</span><span class="p">(</span><span class="nx">SINGLE_LINERS</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">and</span>
|
||||
<span class="nx">post</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'INDENT'</span> <span class="o">and</span>
|
||||
<span class="o">not</span> <span class="p">(</span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'ELSE'</span> <span class="o">and</span> <span class="nx">post</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'IF'</span><span class="p">)</span>
|
||||
<span class="nv">starter: </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nv">indent: </span><span class="p">[</span><span class="s1">'INDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="nv">indent.generated: </span><span class="kc">true</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">indent</span>
|
||||
<span class="nv">idx: </span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="nv">parens: </span><span class="mi">0</span>
|
||||
<span class="k">while</span> <span class="kc">true</span>
|
||||
<span class="nv">idx: </span><span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="nv">tok: </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">idx</span><span class="p">]</span>
|
||||
<span class="nv">pre: </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">idx</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="o">not</span> <span class="nx">tok</span> <span class="o">or</span>
|
||||
<span class="p">(</span><span class="nx">include</span><span class="p">(</span><span class="nx">SINGLE_CLOSERS</span><span class="p">,</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">and</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">';'</span><span class="p">)</span> <span class="o">or</span>
|
||||
<span class="p">(</span><span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">')'</span> <span class="o">and</span> <span class="nx">parens</span> <span class="o">is</span> <span class="mi">0</span><span class="p">))</span> <span class="o">and</span>
|
||||
<span class="o">not</span> <span class="p">(</span><span class="nx">starter</span> <span class="o">is</span> <span class="s1">'ELSE'</span> <span class="o">and</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'ELSE'</span><span class="p">)</span>
|
||||
<span class="nv">insertion: </span><span class="k">if</span> <span class="nx">pre</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s2">","</span> <span class="k">then</span> <span class="nx">idx</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">else</span> <span class="nx">idx</span>
|
||||
<span class="nv">outdent: </span><span class="p">[</span><span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="nv">outdent.generated: </span><span class="kc">true</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">insertion</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">outdent</span>
|
||||
<span class="k">break</span>
|
||||
<span class="nv">parens: </span><span class="o">+</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'('</span>
|
||||
<span class="nv">parens: </span><span class="o">-</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">')'</span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'THEN'</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="k">return</span> <span class="mi">0</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>Ensure that all listed pairs of tokens are correctly balanced throughout
|
||||
the course of the token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ensure_balance: </span><span class="p">(</span><span class="nx">pairs</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">levels: </span><span class="p">{}</span>
|
||||
<span class="nv">open_line: </span><span class="p">{}</span>
|
||||
<span class="nx">@scan_tokens</span> <span class="p">(</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">post</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=></span>
|
||||
<span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">pairs</span>
|
||||
<span class="p">[</span><span class="nx">open</span><span class="p">,</span> <span class="nx">close</span><span class="p">]</span><span class="o">:</span> <span class="nx">pair</span>
|
||||
<span class="nx">levels</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span><span class="o">:</span> <span class="o">or</span> <span class="mi">0</span>
|
||||
<span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="nx">open</span>
|
||||
<span class="nx">open_line</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span><span class="o">:</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="k">if</span> <span class="nx">levels</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span>
|
||||
<span class="nx">levels</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span><span class="o">:</span> <span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="nx">levels</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span><span class="o">:</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="nx">close</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s2">"too many ${token[1]} on line ${token[2] + 1}"</span><span class="p">)</span> <span class="k">if</span> <span class="nx">levels</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span> <span class="o"><</span> <span class="mi">0</span>
|
||||
<span class="k">return</span> <span class="mi">1</span>
|
||||
<span class="nv">unclosed: </span><span class="nx">key</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">value</span> <span class="k">of</span> <span class="nx">levels</span> <span class="k">when</span> <span class="nx">value</span> <span class="o">></span> <span class="mi">0</span>
|
||||
<span class="k">if</span> <span class="nx">unclosed</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">open: </span><span class="nx">unclosed</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nv">line: </span><span class="nx">open_line</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">"unclosed $open on line $line"</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</a> </div> <p>We'd like to support syntax like this:</p>
|
||||
|
||||
<pre><code>el.click((event) ->
|
||||
el.hide())
|
||||
</code></pre>
|
||||
|
||||
<p>In order to accomplish this, move outdents that follow closing parens
|
||||
inwards, safely. The steps to accomplish this are:</p>
|
||||
|
||||
<ol>
|
||||
<li>Check that all paired tokens are balanced and in order.</li>
|
||||
<li>Rewrite the stream with a stack: if you see an <code>EXPRESSION_START</code>, add it
|
||||
to the stack. If you see an <code>EXPRESSION_END</code>, pop the stack and replace
|
||||
it with the inverse of what we've just popped.</li>
|
||||
<li>Keep track of "debt" for tokens that we manufacture, to make sure we end
|
||||
up balanced in the end.</li>
|
||||
<li>Be careful not to alter array or parentheses delimiters with overzealous
|
||||
rewriting.</li>
|
||||
</ol> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">rewrite_closing_parens: </span><span class="o">-></span>
|
||||
<span class="nv">stack: </span><span class="p">[]</span>
|
||||
<span class="nv">debt: </span> <span class="p">{}</span>
|
||||
<span class="p">(</span><span class="nx">debt</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span><span class="o">:</span> <span class="mi">0</span><span class="p">)</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">INVERSES</span>
|
||||
<span class="nx">@scan_tokens</span> <span class="p">(</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">token</span><span class="p">,</span> <span class="nx">post</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=></span>
|
||||
<span class="nv">tag: </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nv">inv: </span><span class="nx">INVERSES</span><span class="p">[</span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span>
|
||||
<span class="k">if</span> <span class="nx">include</span> <span class="nx">EXPRESSION_START</span><span class="p">,</span> <span class="nx">tag</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="nx">token</span>
|
||||
<span class="k">return</span> <span class="mi">1</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">include</span> <span class="nx">EXPRESSION_END</span><span class="p">,</span> <span class="nx">tag</span>
|
||||
<span class="k">if</span> <span class="nx">debt</span><span class="p">[</span><span class="nx">inv</span><span class="p">]</span> <span class="o">></span> <span class="mi">0</span>
|
||||
<span class="nx">debt</span><span class="p">[</span><span class="nx">inv</span><span class="p">]</span><span class="o">:</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">1</span>
|
||||
<span class="k">return</span> <span class="mi">0</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">match: </span><span class="nx">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="nv">mtag: </span> <span class="nx">match</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nv">oppos: </span><span class="nx">INVERSES</span><span class="p">[</span><span class="nx">mtag</span><span class="p">]</span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="nx">oppos</span>
|
||||
<span class="nx">debt</span><span class="p">[</span><span class="nx">mtag</span><span class="p">]</span><span class="o">:</span> <span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="nv">val: </span><span class="p">[</span><span class="nx">oppos</span><span class="p">,</span> <span class="k">if</span> <span class="nx">mtag</span> <span class="o">is</span> <span class="s1">'INDENT'</span> <span class="k">then</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">else</span> <span class="nx">oppos</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="nx">mtag</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">val</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">match</span><span class="p">)</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">val</span>
|
||||
<span class="k">return</span> <span class="mi">1</span>
|
||||
<span class="k">else</span>
|
||||
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</a> </div> <p>List of the token pairs that must be balanced.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BALANCED_PAIRS: </span><span class="p">[[</span><span class="s1">'('</span><span class="p">,</span> <span class="s1">')'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'['</span><span class="p">,</span> <span class="s1">']'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'{'</span><span class="p">,</span> <span class="s1">'}'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'INDENT'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">],</span>
|
||||
<span class="p">[</span><span class="s1">'PARAM_START'</span><span class="p">,</span> <span class="s1">'PARAM_END'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'CALL_START'</span><span class="p">,</span> <span class="s1">'CALL_END'</span><span class="p">],</span>
|
||||
<span class="p">[</span><span class="s1">'INDEX_START'</span><span class="p">,</span> <span class="s1">'INDEX_END'</span><span class="p">],</span> <span class="p">[</span><span class="s1">'SOAKED_INDEX_START'</span><span class="p">,</span> <span class="s1">'SOAKED_INDEX_END'</span><span class="p">]]</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>The inverse mappings of <code>BALANCED_PAIRS</code> we're trying to fix up, so we can
|
||||
look things up from either end.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">INVERSES: </span><span class="p">{}</span>
|
||||
<span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span>
|
||||
<span class="nx">INVERSES</span><span class="p">[</span><span class="nx">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span><span class="o">:</span> <span class="nx">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nx">INVERSES</span><span class="p">[</span><span class="nx">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]]</span><span class="o">:</span> <span class="nx">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-18">#</a> </div> <p>The tokens that signal the start of a balanced pair.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_START: </span><span class="nx">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-19">#</a> </div> <p>The tokens that signal the end of a balanced pair.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_END: </span> <span class="nx">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-20">#</a> </div> <p>Tokens that indicate the close of a clause of an expression.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_CLOSE: </span><span class="p">[</span><span class="s1">'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="octowrap"> <a class="octothorpe" href="#section-21">#</a> </div> <p>Tokens that, if followed by an <code>IMPLICIT_CALL</code>, indicate a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_FUNC: </span> <span class="p">[</span><span class="s1">'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">'@'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-22">#</a> </div> <p>If preceded by an <code>IMPLICIT_FUNC</code>, indicates a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_CALL: </span> <span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'NUMBER'</span><span class="p">,</span> <span class="s1">'STRING'</span><span class="p">,</span> <span class="s1">'JS'</span><span class="p">,</span> <span class="s1">'REGEX'</span><span class="p">,</span> <span class="s1">'NEW'</span><span class="p">,</span> <span class="s1">'PARAM_START'</span><span class="p">,</span>
|
||||
<span class="s1">'TRY'</span><span class="p">,</span> <span class="s1">'DELETE'</span><span class="p">,</span> <span class="s1">'TYPEOF'</span><span class="p">,</span> <span class="s1">'SWITCH'</span><span class="p">,</span> <span class="s1">'EXTENSION'</span><span class="p">,</span>
|
||||
<span class="s1">'TRUE'</span><span class="p">,</span> <span class="s1">'FALSE'</span><span class="p">,</span> <span class="s1">'YES'</span><span class="p">,</span> <span class="s1">'NO'</span><span class="p">,</span> <span class="s1">'ON'</span><span class="p">,</span> <span class="s1">'OFF'</span><span class="p">,</span> <span class="s1">'!'</span><span class="p">,</span> <span class="s1">'!!'</span><span class="p">,</span> <span class="s1">'NOT'</span><span class="p">,</span>
|
||||
<span class="s1">'THIS'</span><span class="p">,</span> <span class="s1">'NULL'</span><span class="p">,</span>
|
||||
<span class="s1">'@'</span><span class="p">,</span> <span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">,</span> <span class="s1">'['</span><span class="p">,</span> <span class="s1">'('</span><span class="p">,</span> <span class="s1">'{'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-23">#</a> </div> <p>Tokens indicating that the implicit call must enclose a block of expressions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_BLOCK: </span><span class="p">[</span><span class="s1">'->'</span><span class="p">,</span> <span class="s1">'=>'</span><span class="p">,</span> <span class="s1">'{'</span><span class="p">,</span> <span class="s1">'['</span><span class="p">,</span> <span class="s1">','</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-24">#</a> </div> <p>Tokens that always mark the end of an implicit call for single-liners.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_END: </span> <span class="p">[</span><span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'UNLESS'</span><span class="p">,</span> <span class="s1">'FOR'</span><span class="p">,</span> <span class="s1">'WHILE'</span><span class="p">,</span> <span class="s1">'UNTIL'</span><span class="p">,</span> <span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'INDENT'</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">EXPRESSION_END</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-25">#</a> </div> <p>Single-line flavors of block expressions that have unclosed endings.
|
||||
The grammar can't disambiguate them, so we insert the implicit indentation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">SINGLE_LINERS: </span><span class="p">[</span><span class="s1">'ELSE'</span><span class="p">,</span> <span class="s2">"->"</span><span class="p">,</span> <span class="s2">"=>"</span><span class="p">,</span> <span class="s1">'TRY'</span><span class="p">,</span> <span class="s1">'FINALLY'</span><span class="p">,</span> <span class="s1">'THEN'</span><span class="p">]</span>
|
||||
<span class="nv">SINGLE_CLOSERS: </span><span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'CATCH'</span><span class="p">,</span> <span class="s1">'FINALLY'</span><span class="p">,</span> <span class="s1">'ELSE'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="s1">'LEADING_WHEN'</span><span class="p">]</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
48
documentation/docs/scope.html
Normal file
48
documentation/docs/scope.html
Normal file
@@ -0,0 +1,48 @@
|
||||
<!DOCTYPE html> <html> <head> <title>scope.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To … <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="scope.html"> scope.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> scope.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-1">#</a> </div> <p>The <strong>Scope</strong> class regulates lexical scoping within CoffeeScript. As you
|
||||
generate code, you create a tree of scopes in the same shape as the nested
|
||||
function bodies. Each scope knows about the variables declared within it,
|
||||
and has a reference to its parent enclosing scope. In this way, we know which
|
||||
variables are new and need to be declared with <code>var</code>, and which are shared
|
||||
with the outside.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-2">#</a> </div> <p>Set up exported variables for both <strong>Node.js</strong> and the browser.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">this</span><span class="p">.</span><span class="nv">exports: </span><span class="k">this</span> <span class="nx">unless</span> <span class="nx">process</span><span class="o">?</span>
|
||||
|
||||
<span class="nv">exports.Scope: </span><span class="nx">class</span> <span class="nx">Scope</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>The top-level <strong>Scope</strong> object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="vi">@root: </span><span class="kc">null</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Initialize a scope with its parent, for lookups up the chain,
|
||||
as well as a reference to the <strong>Expressions</strong> node is belongs to, which is
|
||||
where it should declare its variables, and a reference to the function that
|
||||
it wraps.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">parent</span><span class="p">,</span> <span class="nx">expressions</span><span class="p">,</span> <span class="nx">method</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="p">[</span><span class="nx">@parent</span><span class="p">,</span> <span class="nx">@expressions</span><span class="p">,</span> <span class="nx">@method</span><span class="p">]</span><span class="o">:</span> <span class="p">[</span><span class="nx">parent</span><span class="p">,</span> <span class="nx">expressions</span><span class="p">,</span> <span class="nx">method</span><span class="p">]</span>
|
||||
<span class="vi">@variables: </span><span class="p">{}</span>
|
||||
<span class="k">if</span> <span class="nx">@parent</span>
|
||||
<span class="vi">@temp_var: </span><span class="nx">@parent</span><span class="p">.</span><span class="nx">temp_var</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">Scope.root: </span><span class="k">this</span>
|
||||
<span class="vi">@temp_var: </span><span class="s1">'_a'</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Look up a variable name in lexical scope, and declare it if it does not
|
||||
already exist.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">find: </span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">true</span> <span class="k">if</span> <span class="nx">@check</span> <span class="nx">name</span>
|
||||
<span class="nx">@variables</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span><span class="o">:</span> <span class="s1">'var'</span>
|
||||
<span class="kc">false</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Test variables and return true the first time fn(v, k) returns true</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">any: </span><span class="p">(</span><span class="nx">fn</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">for</span> <span class="nx">v</span><span class="p">,</span> <span class="nx">k</span> <span class="k">of</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">fn</span><span class="p">(</span><span class="nx">v</span><span class="p">,</span> <span class="nx">k</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="kc">true</span>
|
||||
<span class="k">return</span> <span class="kc">false</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Reserve a variable name as originating from a function parameter for this
|
||||
scope. No <code>var</code> required for internal references.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">parameter: </span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@variables</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span><span class="o">:</span> <span class="s1">'param'</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Just check to see if a variable has already been declared, without reserving.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">check: </span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">true</span> <span class="k">if</span> <span class="nx">@variables</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span>
|
||||
<span class="o">!!</span><span class="p">(</span><span class="nx">@parent</span> <span class="o">and</span> <span class="nx">@parent</span><span class="p">.</span><span class="nx">check</span><span class="p">(</span><span class="nx">name</span><span class="p">))</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>If we need to store an intermediate result, find an available name for a
|
||||
compiler-generated variable. <code>_a</code>, <code>_b</code>, and so on...</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">free_variable: </span><span class="o">-></span>
|
||||
<span class="k">while</span> <span class="nx">@check</span> <span class="nx">@temp_var</span>
|
||||
<span class="nv">ordinal: </span><span class="mi">1</span> <span class="o">+</span> <span class="nb">parseInt</span> <span class="nx">@temp_var</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span> <span class="mi">36</span>
|
||||
<span class="vi">@temp_var: </span><span class="s1">'_'</span> <span class="o">+</span> <span class="nx">ordinal</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="mi">36</span><span class="p">).</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\d/g</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">)</span>
|
||||
<span class="nx">@variables</span><span class="p">[</span><span class="nx">@temp_var</span><span class="p">]</span><span class="o">:</span> <span class="s1">'var'</span>
|
||||
<span class="nx">@temp_var</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Ensure that an assignment is made at the top of this scope
|
||||
(or at the top-level scope, if requested).</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">assign: </span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@variables</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span><span class="o">:</span> <span class="p">{</span><span class="nv">value: </span><span class="nx">value</span><span class="p">,</span> <span class="nv">assigned: </span><span class="kc">true</span><span class="p">}</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Does this scope reference any variables that need to be declared in the
|
||||
given function body?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">has_declarations: </span><span class="p">(</span><span class="nx">body</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">body</span> <span class="o">is</span> <span class="nx">@expressions</span> <span class="o">and</span> <span class="nx">@any</span> <span class="p">(</span><span class="nx">k</span><span class="p">,</span> <span class="nx">val</span><span class="p">)</span> <span class="o">-></span> <span class="nx">val</span> <span class="o">is</span> <span class="s1">'var'</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>Does this scope reference any assignments that need to be declared at the
|
||||
top of the given function body?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">has_assignments: </span><span class="p">(</span><span class="nx">body</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">body</span> <span class="o">is</span> <span class="nx">@expressions</span> <span class="o">and</span> <span class="nx">@any</span> <span class="p">(</span><span class="nx">k</span><span class="p">,</span> <span class="nx">val</span><span class="p">)</span> <span class="o">-></span> <span class="nx">val</span><span class="p">.</span><span class="nx">assigned</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>Return the list of variables first declared in this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">declared_variables: </span><span class="o">-></span>
|
||||
<span class="p">(</span><span class="nx">key</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">val</span> <span class="o">is</span> <span class="s1">'var'</span><span class="p">).</span><span class="nx">sort</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</a> </div> <p>Return the list of assignments that are supposed to be made at the top
|
||||
of this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">assigned_variables: </span><span class="o">-></span>
|
||||
<span class="s2">"$key = $val.value"</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">val</span><span class="p">.</span><span class="nx">assigned</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>Compile the JavaScript for all of the variable declarations in this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compiled_declarations: </span><span class="o">-></span>
|
||||
<span class="nx">@declared_variables</span><span class="p">().</span><span class="nx">join</span> <span class="s1">', '</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</a> </div> <p>Compile the JavaScript for all of the variable assignments in this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compiled_assignments: </span><span class="o">-></span>
|
||||
<span class="nx">@assigned_variables</span><span class="p">().</span><span class="nx">join</span> <span class="s1">', '</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
282
documentation/docs/underscore.html
Normal file
282
documentation/docs/underscore.html
Normal file
File diff suppressed because one or more lines are too long
BIN
documentation/images/favicon.ico
Normal file
BIN
documentation/images/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
BIN
documentation/images/logo.png
Normal file
BIN
documentation/images/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.9 KiB |
File diff suppressed because it is too large
Load Diff
@@ -11,4 +11,4 @@
|
||||
}
|
||||
car.speed < speed_limit ? accelerate() : null;
|
||||
print("My name is " + this.name);
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
(function(){
|
||||
var backwards;
|
||||
backwards = function backwards() {
|
||||
var arguments = Array.prototype.slice.call(arguments, 0);
|
||||
return alert(arguments.reverse());
|
||||
};
|
||||
backwards("stairway", "to", "heaven");
|
||||
})();
|
||||
@@ -1,21 +1,21 @@
|
||||
(function(){
|
||||
var __a, __b, __c, __d, __e, __f, __g, food, lunch, roid, roid2;
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, food, lunch, roid, roid2;
|
||||
// Eat lunch.
|
||||
lunch = (function() {
|
||||
__a = []; __b = ['toast', 'cheese', 'wine'];
|
||||
for (__c = 0; __c < __b.length; __c++) {
|
||||
food = __b[__c];
|
||||
__a.push(eat(food));
|
||||
_a = []; _c = ['toast', 'cheese', 'wine'];
|
||||
for (_b = 0, _d = _c.length; _b < _d; _b++) {
|
||||
food = _c[_b];
|
||||
_a.push(eat(food));
|
||||
}
|
||||
return __a;
|
||||
}).call(this);
|
||||
return _a;
|
||||
})();
|
||||
// Naive collision detection.
|
||||
__d = asteroids;
|
||||
for (__e = 0; __e < __d.length; __e++) {
|
||||
roid = __d[__e];
|
||||
__f = asteroids;
|
||||
for (__g = 0; __g < __f.length; __g++) {
|
||||
roid2 = __f[__g];
|
||||
_f = asteroids;
|
||||
for (_e = 0, _g = _f.length; _e < _g; _e++) {
|
||||
roid = _f[_e];
|
||||
_i = asteroids;
|
||||
for (_h = 0, _j = _i.length; _h < _j; _h++) {
|
||||
roid2 = _i[_h];
|
||||
if (roid !== roid2) {
|
||||
if (roid.overlaps(roid2)) {
|
||||
roid.explode();
|
||||
@@ -23,4 +23,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
var difficulty, greeting;
|
||||
greeting = "Hello CoffeeScript";
|
||||
difficulty = 0.5;
|
||||
})();
|
||||
})();
|
||||
|
||||
13
documentation/js/binding.js
Normal file
13
documentation/js/binding.js
Normal file
@@ -0,0 +1,13 @@
|
||||
(function(){
|
||||
var get_source, url;
|
||||
var __slice = Array.prototype.slice, __bind = function(func, obj, args) {
|
||||
return function() {
|
||||
return func.apply(obj || {}, args ? args.concat(__slice.call(arguments, 0)) : arguments);
|
||||
};
|
||||
};
|
||||
url = "documentation/coffee/binding.coffee";
|
||||
get_source = __bind(jQuery.get, jQuery, [url]);
|
||||
get_source(function(response) {
|
||||
return alert(response);
|
||||
});
|
||||
})();
|
||||
13
documentation/js/cake_tasks.js
Normal file
13
documentation/js/cake_tasks.js
Normal file
@@ -0,0 +1,13 @@
|
||||
(function(){
|
||||
task('test', 'run each of the unit tests', function() {
|
||||
var _a, _b, _c, _d, test;
|
||||
_a = []; _c = test_files;
|
||||
for (_b = 0, _d = _c.length; _b < _d; _b++) {
|
||||
test = _c[_b];
|
||||
_a.push(fs.readFile(test, function(err, code) {
|
||||
return eval(coffee.compile(code));
|
||||
}));
|
||||
}
|
||||
return _a;
|
||||
});
|
||||
})();
|
||||
39
documentation/js/classes.js
Normal file
39
documentation/js/classes.js
Normal file
@@ -0,0 +1,39 @@
|
||||
(function(){
|
||||
var Animal, Horse, Snake, sam, tom;
|
||||
var __extends = function(child, parent) {
|
||||
var ctor = function(){ };
|
||||
ctor.prototype = parent.prototype;
|
||||
child.__superClass__ = parent.prototype;
|
||||
child.prototype = new ctor();
|
||||
child.prototype.constructor = child;
|
||||
};
|
||||
Animal = function() { };
|
||||
Animal.prototype.move = function(meters) {
|
||||
return alert(this.name + " moved " + meters + "m.");
|
||||
};
|
||||
|
||||
Snake = function(name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
};
|
||||
__extends(Snake, Animal);
|
||||
Snake.prototype.move = function() {
|
||||
alert("Slithering...");
|
||||
return Snake.__superClass__.move.call(this, 5);
|
||||
};
|
||||
|
||||
Horse = function(name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
};
|
||||
__extends(Horse, Animal);
|
||||
Horse.prototype.move = function() {
|
||||
alert("Galloping...");
|
||||
return Horse.__superClass__.move.call(this, 45);
|
||||
};
|
||||
|
||||
sam = new Snake("Sammy the Python");
|
||||
tom = new Horse("Tommy the Palomino");
|
||||
sam.move();
|
||||
tom.move();
|
||||
})();
|
||||
@@ -2,4 +2,4 @@
|
||||
var cholesterol, healthy;
|
||||
cholesterol = 127;
|
||||
healthy = (200 > cholesterol) && (cholesterol > 60);
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -9,4 +9,4 @@
|
||||
}
|
||||
date = friday ? sue : jill;
|
||||
expensive = expensive || do_the_math();
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
hi = function() {
|
||||
return [document.title, "Hello JavaScript"].join(": ");
|
||||
};
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(function(){
|
||||
var 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;
|
||||
}
|
||||
speed = (typeof speed !== "undefined" && speed !== null) ? speed : 140;
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
(function(){
|
||||
var eldest, grade;
|
||||
grade = function grade(student) {
|
||||
grade = function(student) {
|
||||
if (student.excellent_work) {
|
||||
return "A+";
|
||||
} else if (student.okay_stuff) {
|
||||
return student.tried_hard ? "B" : "B-";
|
||||
if (student.tried_hard) {
|
||||
return "B";
|
||||
} else {
|
||||
return "B-";
|
||||
}
|
||||
} else {
|
||||
return "C";
|
||||
}
|
||||
};
|
||||
eldest = 24 > 21 ? "Liz" : "Ike";
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
(function(){
|
||||
var one, six, three, two;
|
||||
six = ((one = 1)) + ((two = 2)) + ((three = 3));
|
||||
})();
|
||||
six = (one = 1) + (two = 2) + (three = 3);
|
||||
})();
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
(function(){
|
||||
var __a, __b, globals, name;
|
||||
var _a, _b, globals, name;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
// The first ten global properties.
|
||||
globals = ((function() {
|
||||
__a = []; __b = window;
|
||||
for (name in __b) {
|
||||
if (__hasProp.call(__b, name)) {
|
||||
__a.push(name);
|
||||
}
|
||||
}
|
||||
return __a;
|
||||
}).call(this)).slice(0, 10);
|
||||
})();
|
||||
globals = (function() {
|
||||
_a = []; _b = window;
|
||||
for (name in _b) { if (__hasProp.call(_b, name)) {
|
||||
_a.push(name);
|
||||
}}
|
||||
return _a;
|
||||
})().slice(0, 10);
|
||||
})();
|
||||
|
||||
@@ -5,5 +5,5 @@
|
||||
} catch (error) {
|
||||
return "And the error is ... " + error;
|
||||
}
|
||||
}).call(this));
|
||||
})();
|
||||
})());
|
||||
})();
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
(function(){
|
||||
var Account;
|
||||
Account = function Account(customer, cart) {
|
||||
var __a;
|
||||
var __slice = Array.prototype.slice, __bind = function(func, obj, args) {
|
||||
return function() {
|
||||
return func.apply(obj || {}, args ? args.concat(__slice.call(arguments, 0)) : arguments);
|
||||
};
|
||||
};
|
||||
Account = function(customer, cart) {
|
||||
this.customer = customer;
|
||||
this.cart = cart;
|
||||
__a = $('.shopping_cart').bind('click', (function(__this) {
|
||||
var __func = function(event) {
|
||||
return $('.shopping_cart').bind('click', __bind(function(event) {
|
||||
return this.customer.purchase(this.cart);
|
||||
};
|
||||
return (function() {
|
||||
return __func.apply(__this, arguments);
|
||||
});
|
||||
})(this));
|
||||
return Account === this.constructor ? this : __a;
|
||||
}, this));
|
||||
};
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
(function(){
|
||||
var cube, square;
|
||||
square = function square(x) {
|
||||
square = function(x) {
|
||||
return x * x;
|
||||
};
|
||||
cube = function cube(x) {
|
||||
cube = function(x) {
|
||||
return square(x) * x;
|
||||
};
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
(function(){
|
||||
var html;
|
||||
html = "<strong>\n cup of coffeescript\n</strong>";
|
||||
})();
|
||||
html = '<strong>\n cup of coffeescript\n</strong>';
|
||||
})();
|
||||
|
||||
5
documentation/js/interpolation.js
Normal file
5
documentation/js/interpolation.js
Normal file
@@ -0,0 +1,5 @@
|
||||
(function(){
|
||||
var author, quote;
|
||||
author = "Wittgenstein";
|
||||
quote = ("A picture is a fact. -- " + author);
|
||||
})();
|
||||
6
documentation/js/interpolation_expression.js
Normal file
6
documentation/js/interpolation_expression.js
Normal file
@@ -0,0 +1,6 @@
|
||||
(function(){
|
||||
var dates, sentence, sep;
|
||||
sentence = ("" + (22 / 7) + " is a decent approximation of π");
|
||||
sep = "[.\\/\\- ]";
|
||||
dates = (new RegExp(("\\d+" + sep + "\\d+" + sep + "\\d+"), "g"));
|
||||
})();
|
||||
@@ -1,11 +1,11 @@
|
||||
(function(){
|
||||
var __a, city, forecast, temp, weather_report;
|
||||
weather_report = function weather_report(location) {
|
||||
var _a, city, forecast, temp, weather_report;
|
||||
weather_report = function(location) {
|
||||
// Make an Ajax request to fetch the weather...
|
||||
return [location, 72, "Mostly Sunny"];
|
||||
};
|
||||
__a = weather_report("Berkeley, CA");
|
||||
city = __a[0];
|
||||
temp = __a[1];
|
||||
forecast = __a[2];
|
||||
})();
|
||||
_a = weather_report("Berkeley, CA");
|
||||
city = _a[0];
|
||||
temp = _a[1];
|
||||
forecast = _a[2];
|
||||
})();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(function(){
|
||||
var __a, __b, age, ages, child, years_old;
|
||||
var _a, _b, age, ages, child, years_old;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
years_old = {
|
||||
max: 10,
|
||||
@@ -7,13 +7,11 @@
|
||||
tim: 11
|
||||
};
|
||||
ages = (function() {
|
||||
__a = []; __b = years_old;
|
||||
for (child in __b) {
|
||||
age = __b[child];
|
||||
if (__hasProp.call(__b, child)) {
|
||||
__a.push(child + " is " + age);
|
||||
}
|
||||
}
|
||||
return __a;
|
||||
}).call(this);
|
||||
})();
|
||||
_a = []; _b = years_old;
|
||||
for (child in _b) { if (__hasProp.call(_b, child)) {
|
||||
age = _b[child];
|
||||
_a.push(child + " is " + age);
|
||||
}}
|
||||
return _a;
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
(function(){
|
||||
var __a, __b, __c, city, futurists, poet, street;
|
||||
var _a, _b, _c, city, futurists, name, street;
|
||||
futurists = {
|
||||
sculptor: "Umberto Boccioni",
|
||||
painter: "Vladimir Burliuk",
|
||||
@@ -8,10 +8,10 @@
|
||||
address: ["Via Roma 42R", "Bellagio, Italy 22021"]
|
||||
}
|
||||
};
|
||||
__a = futurists;
|
||||
__b = __a.poet;
|
||||
poet = __b.name;
|
||||
__c = __b.address;
|
||||
street = __c[0];
|
||||
city = __c[1];
|
||||
})();
|
||||
_a = futurists;
|
||||
_b = _a.poet;
|
||||
name = _b.name;
|
||||
_c = _b.address;
|
||||
street = _c[0];
|
||||
city = _c[1];
|
||||
})();
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
tim: 11
|
||||
};
|
||||
matrix = [1, 0, 1, 0, 0, 1, 1, 1, 0];
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
(function(){
|
||||
var __a, __b, __c, cubed_list, list, math, num, number, opposite_day, race, square;
|
||||
var _a, _b, _c, _d, cubed_list, list, math, num, number, opposite_day, race, square;
|
||||
var __slice = Array.prototype.slice;
|
||||
// Assignment:
|
||||
number = 42;
|
||||
opposite_day = true;
|
||||
@@ -8,7 +9,7 @@
|
||||
number = -42;
|
||||
}
|
||||
// Functions:
|
||||
square = function square(x) {
|
||||
square = function(x) {
|
||||
return x * x;
|
||||
};
|
||||
// Arrays:
|
||||
@@ -17,14 +18,15 @@
|
||||
math = {
|
||||
root: Math.sqrt,
|
||||
square: square,
|
||||
cube: function cube(x) {
|
||||
cube: function(x) {
|
||||
return x * square(x);
|
||||
}
|
||||
};
|
||||
// Splats:
|
||||
race = function race(winner) {
|
||||
race = function(winner) {
|
||||
var runners;
|
||||
runners = Array.prototype.slice.call(arguments, 1);
|
||||
var _a = arguments.length, _b = _a >= 2;
|
||||
runners = __slice.call(arguments, 1, _a - 0);
|
||||
return print(winner, runners);
|
||||
};
|
||||
// Existence:
|
||||
@@ -33,11 +35,11 @@
|
||||
}
|
||||
// Array comprehensions:
|
||||
cubed_list = (function() {
|
||||
__a = []; __b = list;
|
||||
for (__c = 0; __c < __b.length; __c++) {
|
||||
num = __b[__c];
|
||||
__a.push(math.cube(num));
|
||||
_a = []; _c = list;
|
||||
for (_b = 0, _d = _c.length; _b < _d; _b++) {
|
||||
num = _c[_b];
|
||||
_a.push(math.cube(num));
|
||||
}
|
||||
return __a;
|
||||
}).call(this);
|
||||
})();
|
||||
return _a;
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
(function(){
|
||||
var __a, and_switch, bait;
|
||||
var _a, and_switch, bait;
|
||||
bait = 1000;
|
||||
and_switch = 0;
|
||||
__a = [and_switch, bait];
|
||||
bait = __a[0];
|
||||
and_switch = __a[1];
|
||||
})();
|
||||
_a = [and_switch, bait];
|
||||
bait = _a[0];
|
||||
and_switch = _a[1];
|
||||
})();
|
||||
|
||||
9
documentation/js/patterns_and_splats.js
Normal file
9
documentation/js/patterns_and_splats.js
Normal file
@@ -0,0 +1,9 @@
|
||||
(function(){
|
||||
var _a, close, contents, open, tag;
|
||||
var __slice = Array.prototype.slice;
|
||||
tag = "<impossible>";
|
||||
_a = tag.split("");
|
||||
open = _a[0];
|
||||
contents = __slice.call(_a, 1, _a.length - 1);
|
||||
close = _a[_a.length - 1];
|
||||
})();
|
||||
5
documentation/js/prototypes.js
vendored
Normal file
5
documentation/js/prototypes.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
(function(){
|
||||
String.prototype.dasherize = function() {
|
||||
return this.replace(/_/g, "-");
|
||||
};
|
||||
})();
|
||||
@@ -1,21 +1,21 @@
|
||||
(function(){
|
||||
var __a, __b, __c, __d, __e, countdown, egg_delivery, num;
|
||||
var _a, _b, _c, countdown, egg_delivery, num;
|
||||
countdown = (function() {
|
||||
__a = []; __d = 10; __e = 1;
|
||||
for (__c=0, num=__d; (__d <= __e ? num <= __e : num >= __e); (__d <= __e ? num += 1 : num -= 1), __c++) {
|
||||
__a.push(num);
|
||||
_a = []; _b = 10; _c = 1;
|
||||
for (num = _b; (_b <= _c ? num <= _c : num >= _c); (_b <= _c ? num += 1 : num -= 1)) {
|
||||
_a.push(num);
|
||||
}
|
||||
return __a;
|
||||
}).call(this);
|
||||
egg_delivery = function egg_delivery() {
|
||||
var __f, __g, __h, __i, __j, dozen_eggs, i;
|
||||
__f = []; __i = 0; __j = eggs.length;
|
||||
for (__h=0, i=__i; (__i <= __j ? i < __j : i > __j); (__i <= __j ? i += 12 : i -= 12), __h++) {
|
||||
__f.push((function() {
|
||||
return _a;
|
||||
})();
|
||||
egg_delivery = function() {
|
||||
var _d, _e, _f, dozen_eggs, i;
|
||||
_d = []; _e = 0; _f = eggs.length;
|
||||
for (i = _e; (_e <= _f ? i < _f : i > _f); (_e <= _f ? i += 12 : i -= 12)) {
|
||||
_d.push((function() {
|
||||
dozen_eggs = eggs.slice(i, i + 12);
|
||||
return deliver(new egg_carton(dozen));
|
||||
}).call(this));
|
||||
})());
|
||||
}
|
||||
return __f;
|
||||
return _d;
|
||||
};
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
(function(){
|
||||
var change_numbers, new_num, num;
|
||||
num = 1;
|
||||
change_numbers = function change_numbers() {
|
||||
change_numbers = function() {
|
||||
var new_num;
|
||||
new_num = -1;
|
||||
return num = 10;
|
||||
num = 10;
|
||||
return num;
|
||||
};
|
||||
new_num = change_numbers();
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
three_to_six = numbers.slice(3, 6 + 1);
|
||||
numbers_copy = numbers.slice(0, numbers.length);
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
(function(){
|
||||
var __a;
|
||||
((__a = lottery.draw_winner()) == undefined ? undefined : __a.address == undefined ? undefined : __a.address.zipcode);
|
||||
})();
|
||||
var _a;
|
||||
typeof (_a = (lottery.draw_winner())) === "undefined" || _a == undefined ? undefined : _a.address == undefined ? undefined : _a.address.zipcode;
|
||||
})();
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
(function(){
|
||||
var award_medals, contenders, gold, silver, the_field;
|
||||
var __slice = Array.prototype.slice;
|
||||
gold = (silver = (the_field = "unknown"));
|
||||
award_medals = function award_medals(first, second) {
|
||||
award_medals = function(first, second) {
|
||||
var rest;
|
||||
rest = Array.prototype.slice.call(arguments, 2);
|
||||
var _a = arguments.length, _b = _a >= 3;
|
||||
rest = __slice.call(arguments, 2, _a - 0);
|
||||
gold = first;
|
||||
silver = second;
|
||||
return the_field = rest;
|
||||
the_field = rest;
|
||||
return the_field;
|
||||
};
|
||||
contenders = ["Michael Phelps", "Liu Xiang", "Yao Ming", "Allyson Felix", "Shawn Johnson", "Roman Sebrle", "Guo Jingjing", "Tyson Gay", "Asafa Powell", "Usain Bolt"];
|
||||
award_medals.apply(this, contenders);
|
||||
alert("Gold: " + gold);
|
||||
alert("Silver: " + silver);
|
||||
alert("The Field: " + the_field);
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
var numbers;
|
||||
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
numbers.splice.apply(numbers, [3, 6 - 3 + 1].concat([-3, -4, -5, -6]));
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -6,4 +6,4 @@ 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,39 +0,0 @@
|
||||
(function(){
|
||||
var Animal, Horse, Snake, __a, __b, sam, tom;
|
||||
Animal = function Animal() { };
|
||||
Animal.prototype.move = function move(meters) {
|
||||
return alert(this.name + " moved " + meters + "m.");
|
||||
};
|
||||
Snake = function Snake(name) {
|
||||
var __a;
|
||||
__a = this.name = name;
|
||||
return Snake === this.constructor ? this : __a;
|
||||
};
|
||||
__a = function(){};
|
||||
__a.prototype = Animal.prototype;
|
||||
Snake.__superClass__ = Animal.prototype;
|
||||
Snake.prototype = new __a();
|
||||
Snake.prototype.constructor = Snake;
|
||||
Snake.prototype.move = function move() {
|
||||
alert("Slithering...");
|
||||
return Snake.__superClass__.move.call(this, 5);
|
||||
};
|
||||
Horse = function Horse(name) {
|
||||
var __b;
|
||||
__b = this.name = name;
|
||||
return Horse === this.constructor ? this : __b;
|
||||
};
|
||||
__b = function(){};
|
||||
__b.prototype = Animal.prototype;
|
||||
Horse.__superClass__ = Animal.prototype;
|
||||
Horse.prototype = new __b();
|
||||
Horse.prototype.constructor = Horse;
|
||||
Horse.prototype.move = function move() {
|
||||
alert("Galloping...");
|
||||
return Horse.__superClass__.move.call(this, 45);
|
||||
};
|
||||
sam = new Snake("Sammy the Python");
|
||||
tom = new Horse("Tommy the Palomino");
|
||||
sam.move();
|
||||
tom.move();
|
||||
})();
|
||||
@@ -15,4 +15,4 @@
|
||||
} else {
|
||||
go_to_work();
|
||||
}
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
} finally {
|
||||
clean_up();
|
||||
}
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
(function(){
|
||||
var __a, lyrics, num;
|
||||
var _a, lyrics, num;
|
||||
// Econ 101
|
||||
if (this.studying_economics) {
|
||||
while (supply > demand) {
|
||||
buy();
|
||||
}
|
||||
while (supply < demand) {
|
||||
while (!(supply > demand)) {
|
||||
sell();
|
||||
}
|
||||
}
|
||||
// Nursery Rhyme
|
||||
num = 6;
|
||||
lyrics = (function() {
|
||||
__a = [];
|
||||
_a = [];
|
||||
while (num -= 1) {
|
||||
__a.push(num + " little monkeys, jumping on the bed. \
|
||||
_a.push(num + " little monkeys, jumping on the bed. \
|
||||
One fell out and bumped his head.");
|
||||
}
|
||||
return __a;
|
||||
}).call(this);
|
||||
})();
|
||||
return _a;
|
||||
})();
|
||||
})();
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
|
||||
<title>Quickie CoffeeScript Speed Tests</title>
|
||||
<script type="text/javascript" src="http://www.broofa.com/Tools/JSLitmus/JSLitmus.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Quickie CoffeeScript Speed Tests</h1>
|
||||
|
||||
<script type="text/javascript">
|
||||
var num = 1000;
|
||||
var arr = [];
|
||||
while (num--) arr.push(num);
|
||||
|
||||
var f1 = function f1() {
|
||||
return arr;
|
||||
};
|
||||
|
||||
JSLitmus.test('regular function', function() {
|
||||
f1();
|
||||
});
|
||||
|
||||
var __this = this;
|
||||
|
||||
var f2 = function f2() {
|
||||
return (function() {
|
||||
return arr;
|
||||
}).apply(__this, arguments);
|
||||
};
|
||||
|
||||
JSLitmus.test('bound function', function() {
|
||||
f2();
|
||||
});
|
||||
|
||||
var f3 = (function() {
|
||||
__b = function() {
|
||||
return arr;
|
||||
};
|
||||
return (function f2() {
|
||||
return __b.apply(__this, arguments);
|
||||
});
|
||||
})();
|
||||
|
||||
JSLitmus.test('prebound function', function() {
|
||||
f3();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,636 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
|
||||
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
||||
<link rel="stylesheet" type="text/css" media="screen,projection,print" href="css/idle.css" />
|
||||
<title>Underscore.coffee</title>
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin: 0; padding: 0;
|
||||
}
|
||||
pre.idle {
|
||||
font-family: "Monaco", "Consolas", monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<pre class="idle"><span class="line-numbers"> 1 </span>
|
||||
<span class="line-numbers"> 2 </span> <span class="Comment"><span class="Comment">#</span> Underscore.coffee</span>
|
||||
<span class="line-numbers"> 3 </span> <span class="Comment"><span class="Comment">#</span> (c) 2010 Jeremy Ashkenas, DocumentCloud Inc.</span>
|
||||
<span class="line-numbers"> 4 </span> <span class="Comment"><span class="Comment">#</span> Underscore is freely distributable under the terms of the MIT license.</span>
|
||||
<span class="line-numbers"> 5 </span> <span class="Comment"><span class="Comment">#</span> Portions of Underscore are inspired by or borrowed from Prototype.js,</span>
|
||||
<span class="line-numbers"> 6 </span> <span class="Comment"><span class="Comment">#</span> Oliver Steele's Functional, and John Resig's Micro-Templating.</span>
|
||||
<span class="line-numbers"> 7 </span> <span class="Comment"><span class="Comment">#</span> For all details and documentation:</span>
|
||||
<span class="line-numbers"> 8 </span> <span class="Comment"><span class="Comment">#</span> http://documentcloud.github.com/underscore/</span>
|
||||
<span class="line-numbers"> 9 </span>
|
||||
<span class="line-numbers"> 10 </span>
|
||||
<span class="line-numbers"> 11 </span> <span class="Comment"><span class="Comment">#</span> ------------------------- Baseline setup ---------------------------------</span>
|
||||
<span class="line-numbers"> 12 </span>
|
||||
<span class="line-numbers"> 13 </span> <span class="Comment"><span class="Comment">#</span> Establish the root object, "window" in the browser, or "global" on the server.</span>
|
||||
<span class="line-numbers"> 14 </span> <span class="FunctionName">root</span><span class="Keyword">:</span> <span class="Variable">this</span>
|
||||
<span class="line-numbers"> 15 </span>
|
||||
<span class="line-numbers"> 16 </span>
|
||||
<span class="line-numbers"> 17 </span> <span class="Comment"><span class="Comment">#</span> Save the previous value of the "_" variable.</span>
|
||||
<span class="line-numbers"> 18 </span> <span class="FunctionName">previousUnderscore</span><span class="Keyword">:</span> root._
|
||||
<span class="line-numbers"> 19 </span>
|
||||
<span class="line-numbers"> 20 </span>
|
||||
<span class="line-numbers"> 21 </span> <span class="Comment"><span class="Comment">#</span> If Underscore is called as a function, it returns a wrapped object that</span>
|
||||
<span class="line-numbers"> 22 </span> <span class="Comment"><span class="Comment">#</span> can be used OO-style. This wrapper holds altered versions of all the</span>
|
||||
<span class="line-numbers"> 23 </span> <span class="Comment"><span class="Comment">#</span> underscore functions. Wrapped objects may be chained.</span>
|
||||
<span class="line-numbers"> 24 </span> <span class="FunctionName">wrapper</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 25 </span> <span class="FunctionName">this._wrapped</span><span class="Keyword">:</span> obj
|
||||
<span class="line-numbers"> 26 </span> <span class="Variable">this</span>
|
||||
<span class="line-numbers"> 27 </span>
|
||||
<span class="line-numbers"> 28 </span>
|
||||
<span class="line-numbers"> 29 </span> <span class="Comment"><span class="Comment">#</span> Establish the object that gets thrown to break out of a loop iteration.</span>
|
||||
<span class="line-numbers"> 30 </span> <span class="FunctionName">breaker</span><span class="Keyword">:</span> <span class="Keyword">if</span> <span class="Keyword">typeof</span>(StopIteration) <span class="Keyword">is</span> <span class="String"><span class="String">'</span>undefined<span class="String">'</span></span> <span class="Keyword">then</span> <span class="String"><span class="String">'</span>__break__<span class="String">'</span></span> <span class="Keyword">else</span> StopIteration
|
||||
<span class="line-numbers"> 31 </span>
|
||||
<span class="line-numbers"> 32 </span>
|
||||
<span class="line-numbers"> 33 </span> <span class="Comment"><span class="Comment">#</span> Create a safe reference to the Underscore object forreference below.</span>
|
||||
<span class="line-numbers"> 34 </span> <span class="FunctionName">_</span><span class="Keyword">:</span> <span class="FunctionName">root._</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> <span class="Keyword">new</span> <span class="TypeName">wrapper</span>(obj)
|
||||
<span class="line-numbers"> 35 </span>
|
||||
<span class="line-numbers"> 36 </span>
|
||||
<span class="line-numbers"> 37 </span> <span class="Comment"><span class="Comment">#</span> Export the Underscore object for CommonJS.</span>
|
||||
<span class="line-numbers"> 38 </span> <span class="Keyword">if</span> <span class="Keyword">typeof</span>(exports) <span class="Keyword">!</span><span class="Keyword">=</span> <span class="String"><span class="String">'</span>undefined<span class="String">'</span></span> <span class="Keyword">then</span> <span class="FunctionName">exports._</span><span class="Keyword">:</span> _
|
||||
<span class="line-numbers"> 39 </span>
|
||||
<span class="line-numbers"> 40 </span>
|
||||
<span class="line-numbers"> 41 </span> <span class="Comment"><span class="Comment">#</span> Create quick reference variables for speed access to core prototypes.</span>
|
||||
<span class="line-numbers"> 42 </span> <span class="FunctionName">slice</span><span class="Keyword">:</span> <span class="FunctionName">Array:</span><span class="Keyword">:</span>slice
|
||||
<span class="line-numbers"> 43 </span> <span class="FunctionName">unshift</span><span class="Keyword">:</span> <span class="FunctionName">Array:</span><span class="Keyword">:</span>unshift
|
||||
<span class="line-numbers"> 44 </span> <span class="FunctionName">toString</span><span class="Keyword">:</span> <span class="FunctionName">Object:</span><span class="Keyword">:</span>toString
|
||||
<span class="line-numbers"> 45 </span> <span class="FunctionName">hasOwnProperty</span><span class="Keyword">:</span> <span class="FunctionName">Object:</span><span class="Keyword">:</span>hasOwnProperty
|
||||
<span class="line-numbers"> 46 </span> <span class="FunctionName">propertyIsEnumerable</span><span class="Keyword">:</span> <span class="FunctionName">Object:</span><span class="Keyword">:</span>propertyIsEnumerable
|
||||
<span class="line-numbers"> 47 </span>
|
||||
<span class="line-numbers"> 48 </span>
|
||||
<span class="line-numbers"> 49 </span> <span class="Comment"><span class="Comment">#</span> Current version.</span>
|
||||
<span class="line-numbers"> 50 </span> <span class="FunctionName">_.VERSION</span><span class="Keyword">:</span> <span class="String"><span class="String">'</span>0.5.7<span class="String">'</span></span>
|
||||
<span class="line-numbers"> 51 </span>
|
||||
<span class="line-numbers"> 52 </span>
|
||||
<span class="line-numbers"> 53 </span> <span class="Comment"><span class="Comment">#</span> ------------------------ Collection Functions: ---------------------------</span>
|
||||
<span class="line-numbers"> 54 </span>
|
||||
<span class="line-numbers"> 55 </span> <span class="Comment"><span class="Comment">#</span> The cornerstone, an each implementation.</span>
|
||||
<span class="line-numbers"> 56 </span> <span class="Comment"><span class="Comment">#</span> Handles objects implementing forEach, arrays, and raw objects.</span>
|
||||
<span class="line-numbers"> 57 </span> <span class="FunctionName">_.each</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 58 </span> <span class="FunctionName">index</span><span class="Keyword">:</span> <span class="Number">0</span>
|
||||
<span class="line-numbers"> 59 </span> <span class="Keyword">try</span>
|
||||
<span class="line-numbers"> 60 </span> <span class="Keyword">return</span> obj.forEach(iterator, context) <span class="Keyword">if</span> obj.forEach
|
||||
<span class="line-numbers"> 61 </span> <span class="Keyword">if</span> _.isArray(obj) <span class="Keyword">or</span> _.isArguments(obj)
|
||||
<span class="line-numbers"> 62 </span> <span class="Keyword">return</span> iterator.call(context, obj[i], i, obj) <span class="Keyword">for</span> i <span class="Keyword">in</span> [<span class="Number">0</span>...obj.length]
|
||||
<span class="line-numbers"> 63 </span> iterator.call(context, val, key, obj) <span class="Keyword">for</span> key, val <span class="Keyword">of</span> obj
|
||||
<span class="line-numbers"> 64 </span> <span class="Keyword">catch</span> e
|
||||
<span class="line-numbers"> 65 </span> <span class="Keyword">throw</span> e <span class="Keyword">if</span> e <span class="Keyword">isnt</span> breaker
|
||||
<span class="line-numbers"> 66 </span> obj
|
||||
<span class="line-numbers"> 67 </span>
|
||||
<span class="line-numbers"> 68 </span>
|
||||
<span class="line-numbers"> 69 </span> <span class="Comment"><span class="Comment">#</span> Return the results of applying the iterator to each element. Use JavaScript</span>
|
||||
<span class="line-numbers"> 70 </span> <span class="Comment"><span class="Comment">#</span> 1.6's version of map, if possible.</span>
|
||||
<span class="line-numbers"> 71 </span> <span class="FunctionName">_.map</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 72 </span> <span class="Keyword">return</span> obj.map(iterator, context) <span class="Keyword">if</span> (obj <span class="Keyword">and</span> _.isFunction(obj.map))
|
||||
<span class="line-numbers"> 73 </span> <span class="FunctionName">results</span><span class="Keyword">:</span> []
|
||||
<span class="line-numbers"> 74 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 75 </span> results.push(iterator.call(context, value, index, list))
|
||||
<span class="line-numbers"> 76 </span> results
|
||||
<span class="line-numbers"> 77 </span>
|
||||
<span class="line-numbers"> 78 </span>
|
||||
<span class="line-numbers"> 79 </span> <span class="Comment"><span class="Comment">#</span> Reduce builds up a single result from a list of values. Also known as</span>
|
||||
<span class="line-numbers"> 80 </span> <span class="Comment"><span class="Comment">#</span> inject, or foldl. Uses JavaScript 1.8's version of reduce, if possible.</span>
|
||||
<span class="line-numbers"> 81 </span> <span class="FunctionName">_.reduce</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, memo, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 82 </span> <span class="Keyword">return</span> obj.reduce(_.bind(iterator, context), memo) <span class="Keyword">if</span> (obj <span class="Keyword">and</span> _.isFunction(obj.reduce))
|
||||
<span class="line-numbers"> 83 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 84 </span> <span class="FunctionName">memo</span><span class="Keyword">:</span> iterator.call(context, memo, value, index, list)
|
||||
<span class="line-numbers"> 85 </span> memo
|
||||
<span class="line-numbers"> 86 </span>
|
||||
<span class="line-numbers"> 87 </span>
|
||||
<span class="line-numbers"> 88 </span> <span class="Comment"><span class="Comment">#</span> The right-associative version of reduce, also known as foldr. Uses</span>
|
||||
<span class="line-numbers"> 89 </span> <span class="Comment"><span class="Comment">#</span> JavaScript 1.8's version of reduceRight, if available.</span>
|
||||
<span class="line-numbers"> 90 </span> <span class="FunctionName">_.reduceRight</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, memo, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 91 </span> <span class="Keyword">return</span> obj.reduceRight(_.bind(iterator, context), memo) <span class="Keyword">if</span> (obj <span class="Keyword">and</span> _.isFunction(obj.reduceRight))
|
||||
<span class="line-numbers"> 92 </span> _.each _.clone(_.toArray(obj)).reverse(), <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 93 </span> <span class="FunctionName">memo</span><span class="Keyword">:</span> iterator.call(context, memo, value, index, obj)
|
||||
<span class="line-numbers"> 94 </span> memo
|
||||
<span class="line-numbers"> 95 </span>
|
||||
<span class="line-numbers"> 96 </span>
|
||||
<span class="line-numbers"> 97 </span> <span class="Comment"><span class="Comment">#</span> Return the first value which passes a truth test.</span>
|
||||
<span class="line-numbers"> 98 </span> <span class="FunctionName">_.detect</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 99 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> <span class="BuiltInConstant">null</span>
|
||||
<span class="line-numbers"> 100 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 101 </span> <span class="Keyword">if</span> iterator.call(context, value, index, list)
|
||||
<span class="line-numbers"> 102 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> value
|
||||
<span class="line-numbers"> 103 </span> _.breakLoop()
|
||||
<span class="line-numbers"> 104 </span> result
|
||||
<span class="line-numbers"> 105 </span>
|
||||
<span class="line-numbers"> 106 </span>
|
||||
<span class="line-numbers"> 107 </span> <span class="Comment"><span class="Comment">#</span> Return all the elements that pass a truth test. Use JavaScript 1.6's</span>
|
||||
<span class="line-numbers"> 108 </span> <span class="Comment"><span class="Comment">#</span> filter(), if it exists.</span>
|
||||
<span class="line-numbers"> 109 </span> <span class="FunctionName">_.select</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 110 </span> <span class="Keyword">if</span> obj <span class="Keyword">and</span> _.isFunction(obj.filter) <span class="Keyword">then</span> <span class="Keyword">return</span> obj.filter(iterator, context)
|
||||
<span class="line-numbers"> 111 </span> <span class="FunctionName">results</span><span class="Keyword">:</span> []
|
||||
<span class="line-numbers"> 112 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 113 </span> results.push(value) <span class="Keyword">if</span> iterator.call(context, value, index, list)
|
||||
<span class="line-numbers"> 114 </span> results
|
||||
<span class="line-numbers"> 115 </span>
|
||||
<span class="line-numbers"> 116 </span>
|
||||
<span class="line-numbers"> 117 </span> <span class="Comment"><span class="Comment">#</span> Return all the elements for which a truth test fails.</span>
|
||||
<span class="line-numbers"> 118 </span> <span class="FunctionName">_.reject</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 119 </span> <span class="FunctionName">results</span><span class="Keyword">:</span> []
|
||||
<span class="line-numbers"> 120 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 121 </span> results.push(value) <span class="Keyword">if</span> <span class="Keyword">not</span> iterator.call(context, value, index, list)
|
||||
<span class="line-numbers"> 122 </span> results
|
||||
<span class="line-numbers"> 123 </span>
|
||||
<span class="line-numbers"> 124 </span>
|
||||
<span class="line-numbers"> 125 </span> <span class="Comment"><span class="Comment">#</span> Determine whether all of the elements match a truth test. Delegate to</span>
|
||||
<span class="line-numbers"> 126 </span> <span class="Comment"><span class="Comment">#</span> JavaScript 1.6's every(), if it is present.</span>
|
||||
<span class="line-numbers"> 127 </span> <span class="FunctionName">_.all</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 128 </span> iterator <span class="Keyword">||</span><span class="Keyword">=</span> _.identity
|
||||
<span class="line-numbers"> 129 </span> <span class="Keyword">return</span> obj.every(iterator, context) <span class="Keyword">if</span> obj <span class="Keyword">and</span> _.isFunction(obj.every)
|
||||
<span class="line-numbers"> 130 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> <span class="BuiltInConstant">true</span>
|
||||
<span class="line-numbers"> 131 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 132 </span> _.breakLoop() <span class="Keyword">unless</span> (<span class="FunctionName">result</span><span class="Keyword">:</span> result <span class="Keyword">and</span> iterator.call(context, value, index, list))
|
||||
<span class="line-numbers"> 133 </span> result
|
||||
<span class="line-numbers"> 134 </span>
|
||||
<span class="line-numbers"> 135 </span>
|
||||
<span class="line-numbers"> 136 </span> <span class="Comment"><span class="Comment">#</span> Determine if at least one element in the object matches a truth test. Use</span>
|
||||
<span class="line-numbers"> 137 </span> <span class="Comment"><span class="Comment">#</span> JavaScript 1.6's some(), if it exists.</span>
|
||||
<span class="line-numbers"> 138 </span> <span class="FunctionName">_.any</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 139 </span> iterator <span class="Keyword">||</span><span class="Keyword">=</span> _.identity
|
||||
<span class="line-numbers"> 140 </span> <span class="Keyword">return</span> obj.some(iterator, context) <span class="Keyword">if</span> obj <span class="Keyword">and</span> _.isFunction(obj.some)
|
||||
<span class="line-numbers"> 141 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> <span class="BuiltInConstant">false</span>
|
||||
<span class="line-numbers"> 142 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 143 </span> _.breakLoop() <span class="Keyword">if</span> (<span class="FunctionName">result</span><span class="Keyword">:</span> iterator.call(context, value, index, list))
|
||||
<span class="line-numbers"> 144 </span> result
|
||||
<span class="line-numbers"> 145 </span>
|
||||
<span class="line-numbers"> 146 </span>
|
||||
<span class="line-numbers"> 147 </span> <span class="Comment"><span class="Comment">#</span> Determine if a given value is included in the array or object,</span>
|
||||
<span class="line-numbers"> 148 </span> <span class="Comment"><span class="Comment">#</span> based on '==='.</span>
|
||||
<span class="line-numbers"> 149 </span> <span class="FunctionName">_.include</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, target</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 150 </span> <span class="Keyword">return</span> _.indexOf(obj, target) <span class="Keyword">isnt</span> <span class="Keyword">-</span><span class="Number">1</span> <span class="Keyword">if</span> _.isArray(obj)
|
||||
<span class="line-numbers"> 151 </span> <span class="Keyword">for</span> key, val <span class="Keyword">of</span> obj
|
||||
<span class="line-numbers"> 152 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">true</span> <span class="Keyword">if</span> val <span class="Keyword">is</span> target
|
||||
<span class="line-numbers"> 153 </span> <span class="BuiltInConstant">false</span>
|
||||
<span class="line-numbers"> 154 </span>
|
||||
<span class="line-numbers"> 155 </span>
|
||||
<span class="line-numbers"> 156 </span> <span class="Comment"><span class="Comment">#</span> Invoke a method with arguments on every item in a collection.</span>
|
||||
<span class="line-numbers"> 157 </span> <span class="FunctionName">_.invoke</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, method</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 158 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> _.rest(arguments, <span class="Number">2</span>)
|
||||
<span class="line-numbers"> 159 </span> (<span class="Keyword">if</span> method <span class="Keyword">then</span> val[method] <span class="Keyword">else</span> val).apply(val, args) <span class="Keyword">for</span> val <span class="Keyword">in</span> obj
|
||||
<span class="line-numbers"> 160 </span>
|
||||
<span class="line-numbers"> 161 </span>
|
||||
<span class="line-numbers"> 162 </span> <span class="Comment"><span class="Comment">#</span> Convenience version of a common use case of map: fetching a property.</span>
|
||||
<span class="line-numbers"> 163 </span> <span class="FunctionName">_.pluck</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, key</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 164 </span> _.map(obj, (<span class="FunctionArgument">(</span><span class="FunctionArgument">val</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> val[key]))
|
||||
<span class="line-numbers"> 165 </span>
|
||||
<span class="line-numbers"> 166 </span>
|
||||
<span class="line-numbers"> 167 </span> <span class="Comment"><span class="Comment">#</span> Return the maximum item or (item-based computation).</span>
|
||||
<span class="line-numbers"> 168 </span> <span class="FunctionName">_.max</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 169 </span> <span class="Keyword">return</span> Math.max.apply(Math, obj) <span class="Keyword">if</span> <span class="Keyword">not</span> iterator <span class="Keyword">and</span> _.isArray(obj)
|
||||
<span class="line-numbers"> 170 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> {<span class="FunctionName">computed</span><span class="Keyword">:</span> <span class="Keyword">-</span><span class="BuiltInConstant">Infinity</span>}
|
||||
<span class="line-numbers"> 171 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 172 </span> <span class="FunctionName">computed</span><span class="Keyword">:</span> <span class="Keyword">if</span> iterator <span class="Keyword">then</span> iterator.call(context, value, index, list) <span class="Keyword">else</span> value
|
||||
<span class="line-numbers"> 173 </span> computed <span class="Keyword">>=</span> result.computed <span class="Keyword">and</span> (<span class="FunctionName">result</span><span class="Keyword">:</span> {<span class="FunctionName">value</span><span class="Keyword">:</span> value, <span class="FunctionName">computed</span><span class="Keyword">:</span> computed})
|
||||
<span class="line-numbers"> 174 </span> result.value
|
||||
<span class="line-numbers"> 175 </span>
|
||||
<span class="line-numbers"> 176 </span>
|
||||
<span class="line-numbers"> 177 </span> <span class="Comment"><span class="Comment">#</span> Return the minimum element (or element-based computation).</span>
|
||||
<span class="line-numbers"> 178 </span> <span class="FunctionName">_.min</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 179 </span> <span class="Keyword">return</span> Math.min.apply(Math, obj) <span class="Keyword">if</span> <span class="Keyword">not</span> iterator <span class="Keyword">and</span> _.isArray(obj)
|
||||
<span class="line-numbers"> 180 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> {<span class="FunctionName">computed</span><span class="Keyword">:</span> <span class="BuiltInConstant">Infinity</span>}
|
||||
<span class="line-numbers"> 181 </span> _.each obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 182 </span> <span class="FunctionName">computed</span><span class="Keyword">:</span> <span class="Keyword">if</span> iterator <span class="Keyword">then</span> iterator.call(context, value, index, list) <span class="Keyword">else</span> value
|
||||
<span class="line-numbers"> 183 </span> computed <span class="Keyword"><</span> result.computed <span class="Keyword">and</span> (<span class="FunctionName">result</span><span class="Keyword">:</span> {<span class="FunctionName">value</span><span class="Keyword">:</span> value, <span class="FunctionName">computed</span><span class="Keyword">:</span> computed})
|
||||
<span class="line-numbers"> 184 </span> result.value
|
||||
<span class="line-numbers"> 185 </span>
|
||||
<span class="line-numbers"> 186 </span>
|
||||
<span class="line-numbers"> 187 </span> <span class="Comment"><span class="Comment">#</span> Sort the object's values by a criteria produced by an iterator.</span>
|
||||
<span class="line-numbers"> 188 </span> <span class="FunctionName">_.sortBy</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, iterator, context</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 189 </span> _.pluck(((_.map obj, <span class="FunctionArgument">(</span><span class="FunctionArgument">value, index, list</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 190 </span> {<span class="FunctionName">value</span><span class="Keyword">:</span> value, <span class="FunctionName">criteria</span><span class="Keyword">:</span> iterator.call(context, value, index, list)}
|
||||
<span class="line-numbers"> 191 </span> ).sort(<span class="FunctionArgument">(</span><span class="FunctionArgument">left, right</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 192 </span> <span class="FunctionName">a</span><span class="Keyword">:</span> left.criteria; <span class="FunctionName">b</span><span class="Keyword">:</span> right.criteria
|
||||
<span class="line-numbers"> 193 </span> <span class="Keyword">if</span> a <span class="Keyword"><</span> b <span class="Keyword">then</span> <span class="Keyword">-</span><span class="Number">1</span> <span class="Keyword">else</span> <span class="Keyword">if</span> a <span class="Keyword">></span> b <span class="Keyword">then</span> <span class="Number">1</span> <span class="Keyword">else</span> <span class="Number">0</span>
|
||||
<span class="line-numbers"> 194 </span> )), <span class="String"><span class="String">'</span>value<span class="String">'</span></span>)
|
||||
<span class="line-numbers"> 195 </span>
|
||||
<span class="line-numbers"> 196 </span>
|
||||
<span class="line-numbers"> 197 </span> <span class="Comment"><span class="Comment">#</span> Use a comparator function to figure out at what index an object should</span>
|
||||
<span class="line-numbers"> 198 </span> <span class="Comment"><span class="Comment">#</span> be inserted so as to maintain order. Uses binary search.</span>
|
||||
<span class="line-numbers"> 199 </span> <span class="FunctionName">_.sortedIndex</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array, obj, iterator</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 200 </span> iterator <span class="Keyword">||</span><span class="Keyword">=</span> _.identity
|
||||
<span class="line-numbers"> 201 </span> <span class="FunctionName">low</span><span class="Keyword">:</span> <span class="Number">0</span>; <span class="FunctionName">high</span><span class="Keyword">:</span> array.length
|
||||
<span class="line-numbers"> 202 </span> <span class="Keyword">while</span> low <span class="Keyword"><</span> high
|
||||
<span class="line-numbers"> 203 </span> <span class="FunctionName">mid</span><span class="Keyword">:</span> (low <span class="Keyword">+</span> high) <span class="Keyword">></span><span class="Keyword">></span> <span class="Number">1</span>
|
||||
<span class="line-numbers"> 204 </span> <span class="Keyword">if</span> iterator(array[mid]) <span class="Keyword"><</span> iterator(obj) <span class="Keyword">then</span> <span class="FunctionName">low</span><span class="Keyword">:</span> mid <span class="Keyword">+</span> <span class="Number">1</span> <span class="Keyword">else</span> <span class="FunctionName">high</span><span class="Keyword">:</span> mid
|
||||
<span class="line-numbers"> 205 </span> low
|
||||
<span class="line-numbers"> 206 </span>
|
||||
<span class="line-numbers"> 207 </span>
|
||||
<span class="line-numbers"> 208 </span> <span class="Comment"><span class="Comment">#</span> Convert anything iterable into a real, live array.</span>
|
||||
<span class="line-numbers"> 209 </span> <span class="FunctionName">_.toArray</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">iterable</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 210 </span> <span class="Keyword">return</span> [] <span class="Keyword">if</span> (<span class="Keyword">!</span>iterable)
|
||||
<span class="line-numbers"> 211 </span> <span class="Keyword">return</span> iterable.toArray() <span class="Keyword">if</span> (iterable.toArray)
|
||||
<span class="line-numbers"> 212 </span> <span class="Keyword">return</span> iterable <span class="Keyword">if</span> (_.isArray(iterable))
|
||||
<span class="line-numbers"> 213 </span> <span class="Keyword">return</span> slice.call(iterable) <span class="Keyword">if</span> (_.isArguments(iterable))
|
||||
<span class="line-numbers"> 214 </span> _.values(iterable)
|
||||
<span class="line-numbers"> 215 </span>
|
||||
<span class="line-numbers"> 216 </span>
|
||||
<span class="line-numbers"> 217 </span> <span class="Comment"><span class="Comment">#</span> Return the number of elements in an object.</span>
|
||||
<span class="line-numbers"> 218 </span> <span class="FunctionName">_.size</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> _.toArray(obj).length
|
||||
<span class="line-numbers"> 219 </span>
|
||||
<span class="line-numbers"> 220 </span>
|
||||
<span class="line-numbers"> 221 </span> <span class="Comment"><span class="Comment">#</span> -------------------------- Array Functions: ------------------------------</span>
|
||||
<span class="line-numbers"> 222 </span>
|
||||
<span class="line-numbers"> 223 </span> <span class="Comment"><span class="Comment">#</span> Get the first element of an array. Passing "n" will return the first N</span>
|
||||
<span class="line-numbers"> 224 </span> <span class="Comment"><span class="Comment">#</span> values in the array. Aliased as "head". The "guard" check allows it to work</span>
|
||||
<span class="line-numbers"> 225 </span> <span class="Comment"><span class="Comment">#</span> with _.map.</span>
|
||||
<span class="line-numbers"> 226 </span> <span class="FunctionName">_.first</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array, n, guard</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 227 </span> <span class="Keyword">if</span> n <span class="Keyword">and</span> <span class="Keyword">not</span> guard <span class="Keyword">then</span> slice.call(array, <span class="Number">0</span>, n) <span class="Keyword">else</span> array[<span class="Number">0</span>]
|
||||
<span class="line-numbers"> 228 </span>
|
||||
<span class="line-numbers"> 229 </span>
|
||||
<span class="line-numbers"> 230 </span> <span class="Comment"><span class="Comment">#</span> Returns everything but the first entry of the array. Aliased as "tail".</span>
|
||||
<span class="line-numbers"> 231 </span> <span class="Comment"><span class="Comment">#</span> Especially useful on the arguments object. Passing an "index" will return</span>
|
||||
<span class="line-numbers"> 232 </span> <span class="Comment"><span class="Comment">#</span> the rest of the values in the array from that index onward. The "guard"</span>
|
||||
<span class="line-numbers"> 233 </span> <span class="Comment"><span class="Comment">#</span> check allows it to work with _.map.</span>
|
||||
<span class="line-numbers"> 234 </span> <span class="FunctionName">_.rest</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array, index, guard</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 235 </span> slice.call(array, <span class="Keyword">if</span> _.isUndefined(index) <span class="Keyword">or</span> guard <span class="Keyword">then</span> <span class="Number">1</span> <span class="Keyword">else</span> index)
|
||||
<span class="line-numbers"> 236 </span>
|
||||
<span class="line-numbers"> 237 </span>
|
||||
<span class="line-numbers"> 238 </span> <span class="Comment"><span class="Comment">#</span> Get the last element of an array.</span>
|
||||
<span class="line-numbers"> 239 </span> <span class="FunctionName">_.last</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> array[array.length <span class="Keyword">-</span> <span class="Number">1</span>]
|
||||
<span class="line-numbers"> 240 </span>
|
||||
<span class="line-numbers"> 241 </span>
|
||||
<span class="line-numbers"> 242 </span> <span class="Comment"><span class="Comment">#</span> Trim out all falsy values from an array.</span>
|
||||
<span class="line-numbers"> 243 </span> <span class="FunctionName">_.compact</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> array[i] <span class="Keyword">for</span> i <span class="Keyword">in</span> [<span class="Number">0</span>...array.length] <span class="Keyword">when</span> array[i]
|
||||
<span class="line-numbers"> 244 </span>
|
||||
<span class="line-numbers"> 245 </span>
|
||||
<span class="line-numbers"> 246 </span> <span class="Comment"><span class="Comment">#</span> Return a completely flattened version of an array.</span>
|
||||
<span class="line-numbers"> 247 </span> <span class="FunctionName">_.flatten</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 248 </span> _.reduce array, [], <span class="FunctionArgument">(</span><span class="FunctionArgument">memo, value</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 249 </span> <span class="Keyword">return</span> memo.concat(_.flatten(value)) <span class="Keyword">if</span> _.isArray(value)
|
||||
<span class="line-numbers"> 250 </span> memo.push(value)
|
||||
<span class="line-numbers"> 251 </span> memo
|
||||
<span class="line-numbers"> 252 </span>
|
||||
<span class="line-numbers"> 253 </span>
|
||||
<span class="line-numbers"> 254 </span> <span class="Comment"><span class="Comment">#</span> Return a version of the array that does not contain the specified value(s).</span>
|
||||
<span class="line-numbers"> 255 </span> <span class="FunctionName">_.without</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 256 </span> <span class="FunctionName">values</span><span class="Keyword">:</span> _.rest(arguments)
|
||||
<span class="line-numbers"> 257 </span> val <span class="Keyword">for</span> val <span class="Keyword">in</span> _.toArray(array) <span class="Keyword">when</span> <span class="Keyword">not</span> _.include(values, val)
|
||||
<span class="line-numbers"> 258 </span>
|
||||
<span class="line-numbers"> 259 </span>
|
||||
<span class="line-numbers"> 260 </span> <span class="Comment"><span class="Comment">#</span> Produce a duplicate-free version of the array. If the array has already</span>
|
||||
<span class="line-numbers"> 261 </span> <span class="Comment"><span class="Comment">#</span> been sorted, you have the option of using a faster algorithm.</span>
|
||||
<span class="line-numbers"> 262 </span> <span class="FunctionName">_.uniq</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array, isSorted</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 263 </span> <span class="FunctionName">memo</span><span class="Keyword">:</span> []
|
||||
<span class="line-numbers"> 264 </span> <span class="Keyword">for</span> el, i <span class="Keyword">in</span> _.toArray(array)
|
||||
<span class="line-numbers"> 265 </span> memo.push(el) <span class="Keyword">if</span> i <span class="Keyword">is</span> <span class="Number">0</span> <span class="Keyword">||</span> (<span class="Keyword">if</span> isSorted <span class="Keyword">is</span> <span class="BuiltInConstant">true</span> <span class="Keyword">then</span> _.last(memo) <span class="Keyword">isnt</span> el <span class="Keyword">else</span> <span class="Keyword">not</span> _.include(memo, el))
|
||||
<span class="line-numbers"> 266 </span> memo
|
||||
<span class="line-numbers"> 267 </span>
|
||||
<span class="line-numbers"> 268 </span>
|
||||
<span class="line-numbers"> 269 </span> <span class="Comment"><span class="Comment">#</span> Produce an array that contains every item shared between all the</span>
|
||||
<span class="line-numbers"> 270 </span> <span class="Comment"><span class="Comment">#</span> passed-in arrays.</span>
|
||||
<span class="line-numbers"> 271 </span> <span class="FunctionName">_.intersect</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 272 </span> <span class="FunctionName">rest</span><span class="Keyword">:</span> _.rest(arguments)
|
||||
<span class="line-numbers"> 273 </span> _.select _.uniq(array), <span class="FunctionArgument">(</span><span class="FunctionArgument">item</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 274 </span> _.all rest, <span class="FunctionArgument">(</span><span class="FunctionArgument">other</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 275 </span> _.indexOf(other, item) <span class="Keyword">>=</span> <span class="Number">0</span>
|
||||
<span class="line-numbers"> 276 </span>
|
||||
<span class="line-numbers"> 277 </span>
|
||||
<span class="line-numbers"> 278 </span> <span class="Comment"><span class="Comment">#</span> Zip together multiple lists into a single array -- elements that share</span>
|
||||
<span class="line-numbers"> 279 </span> <span class="Comment"><span class="Comment">#</span> an index go together.</span>
|
||||
<span class="line-numbers"> 280 </span> <span class="FunctionName">_.zip</span><span class="Keyword">:</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 281 </span> <span class="FunctionName">length</span><span class="Keyword">:</span> _.max(_.pluck(arguments, <span class="String"><span class="String">'</span>length<span class="String">'</span></span>))
|
||||
<span class="line-numbers"> 282 </span> <span class="FunctionName">results</span><span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Array</span>(length)
|
||||
<span class="line-numbers"> 283 </span> <span class="Keyword">for</span> i <span class="Keyword">in</span> [<span class="Number">0</span>...length]
|
||||
<span class="line-numbers"> 284 </span> results[i]<span class="Keyword">:</span> _.pluck(arguments, String(i))
|
||||
<span class="line-numbers"> 285 </span> results
|
||||
<span class="line-numbers"> 286 </span>
|
||||
<span class="line-numbers"> 287 </span>
|
||||
<span class="line-numbers"> 288 </span> <span class="Comment"><span class="Comment">#</span> If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),</span>
|
||||
<span class="line-numbers"> 289 </span> <span class="Comment"><span class="Comment">#</span> we need this function. Return the position of the first occurence of an</span>
|
||||
<span class="line-numbers"> 290 </span> <span class="Comment"><span class="Comment">#</span> item in an array, or -1 if the item is not included in the array.</span>
|
||||
<span class="line-numbers"> 291 </span> <span class="FunctionName">_.indexOf</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array, item</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 292 </span> <span class="Keyword">return</span> array.indexOf(item) <span class="Keyword">if</span> array.indexOf
|
||||
<span class="line-numbers"> 293 </span> <span class="FunctionName">i</span><span class="Keyword">:</span> <span class="Number">0</span>; <span class="FunctionName">l</span><span class="Keyword">:</span> array.length
|
||||
<span class="line-numbers"> 294 </span> <span class="Keyword">while</span> l <span class="Keyword">-</span> i
|
||||
<span class="line-numbers"> 295 </span> <span class="Keyword">if</span> array[i] <span class="Keyword">is</span> item <span class="Keyword">then</span> <span class="Keyword">return</span> i <span class="Keyword">else</span> i<span class="Keyword">++</span>
|
||||
<span class="line-numbers"> 296 </span> <span class="Keyword">-</span><span class="Number">1</span>
|
||||
<span class="line-numbers"> 297 </span>
|
||||
<span class="line-numbers"> 298 </span>
|
||||
<span class="line-numbers"> 299 </span> <span class="Comment"><span class="Comment">#</span> Provide JavaScript 1.6's lastIndexOf, delegating to the native function,</span>
|
||||
<span class="line-numbers"> 300 </span> <span class="Comment"><span class="Comment">#</span> if possible.</span>
|
||||
<span class="line-numbers"> 301 </span> <span class="FunctionName">_.lastIndexOf</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">array, item</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 302 </span> <span class="Keyword">return</span> array.lastIndexOf(item) <span class="Keyword">if</span> array.lastIndexOf
|
||||
<span class="line-numbers"> 303 </span> <span class="FunctionName">i</span><span class="Keyword">:</span> array.length
|
||||
<span class="line-numbers"> 304 </span> <span class="Keyword">while</span> i
|
||||
<span class="line-numbers"> 305 </span> <span class="Keyword">if</span> array[i] <span class="Keyword">is</span> item <span class="Keyword">then</span> <span class="Keyword">return</span> i <span class="Keyword">else</span> i<span class="Keyword">--</span>
|
||||
<span class="line-numbers"> 306 </span> <span class="Keyword">-</span><span class="Number">1</span>
|
||||
<span class="line-numbers"> 307 </span>
|
||||
<span class="line-numbers"> 308 </span>
|
||||
<span class="line-numbers"> 309 </span> <span class="Comment"><span class="Comment">#</span> Generate an integer Array containing an arithmetic progression. A port of</span>
|
||||
<span class="line-numbers"> 310 </span> <span class="Comment"><span class="Comment">#</span> the native Python range() function. See:</span>
|
||||
<span class="line-numbers"> 311 </span> <span class="Comment"><span class="Comment">#</span> http://docs.python.org/library/functions.html#range</span>
|
||||
<span class="line-numbers"> 312 </span> <span class="FunctionName">_.range</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">start, stop, step</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 313 </span> <span class="FunctionName">a</span><span class="Keyword">:</span> arguments
|
||||
<span class="line-numbers"> 314 </span> <span class="FunctionName">solo</span><span class="Keyword">:</span> a.length <span class="Keyword"><=</span> <span class="Number">1</span>
|
||||
<span class="line-numbers"> 315 </span> <span class="FunctionName">i</span><span class="Keyword">:</span> <span class="FunctionName">start</span><span class="Keyword">:</span> <span class="Keyword">if</span> solo <span class="Keyword">then</span> <span class="Number">0</span> <span class="Keyword">else</span> a[<span class="Number">0</span>];
|
||||
<span class="line-numbers"> 316 </span> <span class="FunctionName">stop</span><span class="Keyword">:</span> <span class="Keyword">if</span> solo <span class="Keyword">then</span> a[<span class="Number">0</span>] <span class="Keyword">else</span> a[<span class="Number">1</span>];
|
||||
<span class="line-numbers"> 317 </span> <span class="FunctionName">step</span><span class="Keyword">:</span> a[<span class="Number">2</span>] <span class="Keyword">or</span> <span class="Number">1</span>
|
||||
<span class="line-numbers"> 318 </span> <span class="FunctionName">len</span><span class="Keyword">:</span> Math.ceil((stop <span class="Keyword">-</span> start) <span class="Keyword">/</span> step)
|
||||
<span class="line-numbers"> 319 </span> <span class="Keyword">return</span> [] <span class="Keyword">if</span> len <span class="Keyword"><=</span> <span class="Number">0</span>
|
||||
<span class="line-numbers"> 320 </span> <span class="FunctionName">range</span><span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Array</span>(len)
|
||||
<span class="line-numbers"> 321 </span> <span class="FunctionName">idx</span><span class="Keyword">:</span> <span class="Number">0</span>
|
||||
<span class="line-numbers"> 322 </span> <span class="Keyword">while</span> <span class="BuiltInConstant">true</span>
|
||||
<span class="line-numbers"> 323 </span> <span class="Keyword">return</span> range <span class="Keyword">if</span> (<span class="Keyword">if</span> step <span class="Keyword">></span> <span class="Number">0</span> <span class="Keyword">then</span> i <span class="Keyword">-</span> stop <span class="Keyword">else</span> stop <span class="Keyword">-</span> i) <span class="Keyword">>=</span> <span class="Number">0</span>
|
||||
<span class="line-numbers"> 324 </span> range[idx]<span class="Keyword">:</span> i
|
||||
<span class="line-numbers"> 325 </span> idx<span class="Keyword">++</span>
|
||||
<span class="line-numbers"> 326 </span> i<span class="Keyword">+</span><span class="Keyword">=</span> step
|
||||
<span class="line-numbers"> 327 </span>
|
||||
<span class="line-numbers"> 328 </span>
|
||||
<span class="line-numbers"> 329 </span> <span class="Comment"><span class="Comment">#</span> ----------------------- Function Functions: -----------------------------</span>
|
||||
<span class="line-numbers"> 330 </span>
|
||||
<span class="line-numbers"> 331 </span> <span class="Comment"><span class="Comment">#</span> Create a function bound to a given object (assigning 'this', and arguments,</span>
|
||||
<span class="line-numbers"> 332 </span> <span class="Comment"><span class="Comment">#</span> optionally). Binding with arguments is also known as 'curry'.</span>
|
||||
<span class="line-numbers"> 333 </span> <span class="FunctionName">_.bind</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">func, obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 334 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> _.rest(arguments, <span class="Number">2</span>)
|
||||
<span class="line-numbers"> 335 </span> <span class="Storage">-></span> func.apply(obj <span class="Keyword">or</span> root, args.concat(arguments))
|
||||
<span class="line-numbers"> 336 </span>
|
||||
<span class="line-numbers"> 337 </span>
|
||||
<span class="line-numbers"> 338 </span> <span class="Comment"><span class="Comment">#</span> Bind all of an object's methods to that object. Useful for ensuring that</span>
|
||||
<span class="line-numbers"> 339 </span> <span class="Comment"><span class="Comment">#</span> all callbacks defined on an object belong to it.</span>
|
||||
<span class="line-numbers"> 340 </span> <span class="FunctionName">_.bindAll</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 341 </span> <span class="FunctionName">funcs</span><span class="Keyword">:</span> <span class="Keyword">if</span> arguments.length <span class="Keyword">></span> <span class="Number">1</span> <span class="Keyword">then</span> _.rest(arguments) <span class="Keyword">else</span> _.functions(obj)
|
||||
<span class="line-numbers"> 342 </span> _.each(funcs, <span class="FunctionArgument">(</span><span class="FunctionArgument">f</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> obj[f]<span class="Keyword">:</span> _.bind(obj[f], obj))
|
||||
<span class="line-numbers"> 343 </span> obj
|
||||
<span class="line-numbers"> 344 </span>
|
||||
<span class="line-numbers"> 345 </span>
|
||||
<span class="line-numbers"> 346 </span> <span class="Comment"><span class="Comment">#</span> Delays a function for the given number of milliseconds, and then calls</span>
|
||||
<span class="line-numbers"> 347 </span> <span class="Comment"><span class="Comment">#</span> it with the arguments supplied.</span>
|
||||
<span class="line-numbers"> 348 </span> <span class="FunctionName">_.delay</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">func, wait</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 349 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> _.rest(arguments, <span class="Number">2</span>)
|
||||
<span class="line-numbers"> 350 </span> setTimeout((<span class="Storage">-></span> func.apply(func, args)), wait)
|
||||
<span class="line-numbers"> 351 </span>
|
||||
<span class="line-numbers"> 352 </span>
|
||||
<span class="line-numbers"> 353 </span> <span class="Comment"><span class="Comment">#</span> Defers a function, scheduling it to run after the current call stack has</span>
|
||||
<span class="line-numbers"> 354 </span> <span class="Comment"><span class="Comment">#</span> cleared.</span>
|
||||
<span class="line-numbers"> 355 </span> <span class="FunctionName">_.defer</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">func</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 356 </span> _.delay.apply(_, [func, <span class="Number">1</span>].concat(_.rest(arguments)))
|
||||
<span class="line-numbers"> 357 </span>
|
||||
<span class="line-numbers"> 358 </span>
|
||||
<span class="line-numbers"> 359 </span> <span class="Comment"><span class="Comment">#</span> Returns the first function passed as an argument to the second,</span>
|
||||
<span class="line-numbers"> 360 </span> <span class="Comment"><span class="Comment">#</span> allowing you to adjust arguments, run code before and after, and</span>
|
||||
<span class="line-numbers"> 361 </span> <span class="Comment"><span class="Comment">#</span> conditionally execute the original function.</span>
|
||||
<span class="line-numbers"> 362 </span> <span class="FunctionName">_.wrap</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">func, wrapper</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 363 </span> <span class="Storage">-></span> wrapper.apply(wrapper, [func].concat(arguments))
|
||||
<span class="line-numbers"> 364 </span>
|
||||
<span class="line-numbers"> 365 </span>
|
||||
<span class="line-numbers"> 366 </span> <span class="Comment"><span class="Comment">#</span> Returns a function that is the composition of a list of functions, each</span>
|
||||
<span class="line-numbers"> 367 </span> <span class="Comment"><span class="Comment">#</span> consuming the return value of the function that follows.</span>
|
||||
<span class="line-numbers"> 368 </span> <span class="FunctionName">_.compose</span><span class="Keyword">:</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 369 </span> <span class="FunctionName">funcs</span><span class="Keyword">:</span> arguments
|
||||
<span class="line-numbers"> 370 </span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 371 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> arguments
|
||||
<span class="line-numbers"> 372 </span> <span class="Keyword">for</span> i <span class="Keyword">in</span> [(funcs.length <span class="Keyword">-</span> <span class="Number">1</span>)..<span class="Number">0</span>]
|
||||
<span class="line-numbers"> 373 </span> <span class="FunctionName">args</span><span class="Keyword">:</span> [funcs[i].apply(<span class="Variable">this</span>, args)]
|
||||
<span class="line-numbers"> 374 </span> args[<span class="Number">0</span>]
|
||||
<span class="line-numbers"> 375 </span>
|
||||
<span class="line-numbers"> 376 </span>
|
||||
<span class="line-numbers"> 377 </span> <span class="Comment"><span class="Comment">#</span> ------------------------- Object Functions: ----------------------------</span>
|
||||
<span class="line-numbers"> 378 </span>
|
||||
<span class="line-numbers"> 379 </span> <span class="Comment"><span class="Comment">#</span> Retrieve the names of an object's properties.</span>
|
||||
<span class="line-numbers"> 380 </span> <span class="FunctionName">_.keys</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 381 </span> <span class="Keyword">return</span> _.range(<span class="Number">0</span>, obj.length) <span class="Keyword">if</span> _.isArray(obj)
|
||||
<span class="line-numbers"> 382 </span> key <span class="Keyword">for</span> key, val <span class="Keyword">of</span> obj
|
||||
<span class="line-numbers"> 383 </span>
|
||||
<span class="line-numbers"> 384 </span>
|
||||
<span class="line-numbers"> 385 </span> <span class="Comment"><span class="Comment">#</span> Retrieve the values of an object's properties.</span>
|
||||
<span class="line-numbers"> 386 </span> <span class="FunctionName">_.values</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 387 </span> _.map(obj, _.identity)
|
||||
<span class="line-numbers"> 388 </span>
|
||||
<span class="line-numbers"> 389 </span>
|
||||
<span class="line-numbers"> 390 </span> <span class="Comment"><span class="Comment">#</span> Return a sorted list of the function names available in Underscore.</span>
|
||||
<span class="line-numbers"> 391 </span> <span class="FunctionName">_.functions</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 392 </span> _.select(_.keys(obj), <span class="FunctionArgument">(</span><span class="FunctionArgument">key</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> _.isFunction(obj[key])).sort()
|
||||
<span class="line-numbers"> 393 </span>
|
||||
<span class="line-numbers"> 394 </span>
|
||||
<span class="line-numbers"> 395 </span> <span class="Comment"><span class="Comment">#</span> Extend a given object with all of the properties in a source object.</span>
|
||||
<span class="line-numbers"> 396 </span> <span class="FunctionName">_.extend</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">destination, source</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 397 </span> <span class="Keyword">for</span> key, val <span class="Keyword">of</span> source
|
||||
<span class="line-numbers"> 398 </span> destination[key]<span class="Keyword">:</span> val
|
||||
<span class="line-numbers"> 399 </span> destination
|
||||
<span class="line-numbers"> 400 </span>
|
||||
<span class="line-numbers"> 401 </span>
|
||||
<span class="line-numbers"> 402 </span> <span class="Comment"><span class="Comment">#</span> Create a (shallow-cloned) duplicate of an object.</span>
|
||||
<span class="line-numbers"> 403 </span> <span class="FunctionName">_.clone</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 404 </span> <span class="Keyword">return</span> obj.slice(<span class="Number">0</span>) <span class="Keyword">if</span> _.isArray(obj)
|
||||
<span class="line-numbers"> 405 </span> _.extend({}, obj)
|
||||
<span class="line-numbers"> 406 </span>
|
||||
<span class="line-numbers"> 407 </span>
|
||||
<span class="line-numbers"> 408 </span> <span class="Comment"><span class="Comment">#</span> Invokes interceptor with the obj, and then returns obj.</span>
|
||||
<span class="line-numbers"> 409 </span> <span class="Comment"><span class="Comment">#</span> The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain.</span>
|
||||
<span class="line-numbers"> 410 </span> <span class="FunctionName">_.tap</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, interceptor</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 411 </span> interceptor(obj)
|
||||
<span class="line-numbers"> 412 </span> obj
|
||||
<span class="line-numbers"> 413 </span>
|
||||
<span class="line-numbers"> 414 </span>
|
||||
<span class="line-numbers"> 415 </span> <span class="Comment"><span class="Comment">#</span> Perform a deep comparison to check if two objects are equal.</span>
|
||||
<span class="line-numbers"> 416 </span> <span class="FunctionName">_.isEqual</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">a, b</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 417 </span> <span class="Comment"><span class="Comment">#</span> Check object identity.</span>
|
||||
<span class="line-numbers"> 418 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">true</span> <span class="Keyword">if</span> a <span class="Keyword">is</span> b
|
||||
<span class="line-numbers"> 419 </span> <span class="Comment"><span class="Comment">#</span> Different types?</span>
|
||||
<span class="line-numbers"> 420 </span> <span class="FunctionName">atype</span><span class="Keyword">:</span> <span class="Keyword">typeof</span>(a); <span class="FunctionName">btype</span><span class="Keyword">:</span> <span class="Keyword">typeof</span>(b)
|
||||
<span class="line-numbers"> 421 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">false</span> <span class="Keyword">if</span> atype <span class="Keyword">isnt</span> btype
|
||||
<span class="line-numbers"> 422 </span> <span class="Comment"><span class="Comment">#</span> Basic equality test (watch out for coercions).</span>
|
||||
<span class="line-numbers"> 423 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">true</span> <span class="Keyword">if</span> <span class="String"><span class="String">`</span>a == b<span class="String">`</span></span>
|
||||
<span class="line-numbers"> 424 </span> <span class="Comment"><span class="Comment">#</span> One is falsy and the other truthy.</span>
|
||||
<span class="line-numbers"> 425 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">false</span> <span class="Keyword">if</span> (<span class="Keyword">!</span>a <span class="Keyword">and</span> b) <span class="Keyword">or</span> (a <span class="Keyword">and</span> <span class="Keyword">!</span>b)
|
||||
<span class="line-numbers"> 426 </span> <span class="Comment"><span class="Comment">#</span> One of them implements an isEqual()?</span>
|
||||
<span class="line-numbers"> 427 </span> <span class="Keyword">return</span> a.isEqual(b) <span class="Keyword">if</span> a.isEqual
|
||||
<span class="line-numbers"> 428 </span> <span class="Comment"><span class="Comment">#</span> Check dates' integer values.</span>
|
||||
<span class="line-numbers"> 429 </span> <span class="Keyword">return</span> a.getTime() <span class="Keyword">is</span> b.getTime() <span class="Keyword">if</span> _.isDate(a) <span class="Keyword">and</span> _.isDate(b)
|
||||
<span class="line-numbers"> 430 </span> <span class="Comment"><span class="Comment">#</span> Both are NaN?</span>
|
||||
<span class="line-numbers"> 431 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">true</span> <span class="Keyword">if</span> _.isNaN(a) <span class="Keyword">and</span> _.isNaN(b)
|
||||
<span class="line-numbers"> 432 </span> <span class="Comment"><span class="Comment">#</span> Compare regular expressions.</span>
|
||||
<span class="line-numbers"> 433 </span> <span class="Keyword">if</span> _.isRegExp(a) <span class="Keyword">and</span> _.isRegExp(b)
|
||||
<span class="line-numbers"> 434 </span> <span class="Keyword">return</span> a.source <span class="Keyword">is</span> b.source <span class="Keyword">and</span>
|
||||
<span class="line-numbers"> 435 </span> a.global <span class="Keyword">is</span> b.global <span class="Keyword">and</span>
|
||||
<span class="line-numbers"> 436 </span> a.ignoreCase <span class="Keyword">is</span> b.ignoreCase <span class="Keyword">and</span>
|
||||
<span class="line-numbers"> 437 </span> a.multiline <span class="Keyword">is</span> b.multiline
|
||||
<span class="line-numbers"> 438 </span> <span class="Comment"><span class="Comment">#</span> If a is not an object by this point, we can't handle it.</span>
|
||||
<span class="line-numbers"> 439 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">false</span> <span class="Keyword">if</span> atype <span class="Keyword">isnt</span> <span class="String"><span class="String">'</span>object<span class="String">'</span></span>
|
||||
<span class="line-numbers"> 440 </span> <span class="Comment"><span class="Comment">#</span> Check for different array lengths before comparing contents.</span>
|
||||
<span class="line-numbers"> 441 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">false</span> <span class="Keyword">if</span> a.length <span class="Keyword">and</span> (a.length <span class="Keyword">isnt</span> b.length)
|
||||
<span class="line-numbers"> 442 </span> <span class="Comment"><span class="Comment">#</span> Nothing else worked, deep compare the contents.</span>
|
||||
<span class="line-numbers"> 443 </span> <span class="FunctionName">aKeys</span><span class="Keyword">:</span> _.keys(a); <span class="FunctionName">bKeys</span><span class="Keyword">:</span> _.keys(b)
|
||||
<span class="line-numbers"> 444 </span> <span class="Comment"><span class="Comment">#</span> Different object sizes?</span>
|
||||
<span class="line-numbers"> 445 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">false</span> <span class="Keyword">if</span> aKeys.length <span class="Keyword">isnt</span> bKeys.length
|
||||
<span class="line-numbers"> 446 </span> <span class="Comment"><span class="Comment">#</span> Recursive comparison of contents.</span>
|
||||
<span class="line-numbers"> 447 </span> <span class="Comment"><span class="Comment">#</span> for (var key in a) if (!_.isEqual(a[key], b[key])) return false;</span>
|
||||
<span class="line-numbers"> 448 </span> <span class="Keyword">return</span> <span class="BuiltInConstant">true</span>
|
||||
<span class="line-numbers"> 449 </span>
|
||||
<span class="line-numbers"> 450 </span>
|
||||
<span class="line-numbers"> 451 </span> <span class="Comment"><span class="Comment">#</span> Is a given array or object empty?</span>
|
||||
<span class="line-numbers"> 452 </span> <span class="FunctionName">_.isEmpty</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> _.keys(obj).length <span class="Keyword">is</span> <span class="Number">0</span>
|
||||
<span class="line-numbers"> 453 </span>
|
||||
<span class="line-numbers"> 454 </span>
|
||||
<span class="line-numbers"> 455 </span> <span class="Comment"><span class="Comment">#</span> Is a given value a DOM element?</span>
|
||||
<span class="line-numbers"> 456 </span> <span class="FunctionName">_.isElement</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> obj <span class="Keyword">and</span> obj.nodeType <span class="Keyword">is</span> <span class="Number">1</span>
|
||||
<span class="line-numbers"> 457 </span>
|
||||
<span class="line-numbers"> 458 </span>
|
||||
<span class="line-numbers"> 459 </span> <span class="Comment"><span class="Comment">#</span> Is a given value an array?</span>
|
||||
<span class="line-numbers"> 460 </span> <span class="FunctionName">_.isArray</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">and</span> obj.concat <span class="Keyword">and</span> obj.unshift)
|
||||
<span class="line-numbers"> 461 </span>
|
||||
<span class="line-numbers"> 462 </span>
|
||||
<span class="line-numbers"> 463 </span> <span class="Comment"><span class="Comment">#</span> Is a given variable an arguments object?</span>
|
||||
<span class="line-numbers"> 464 </span> <span class="FunctionName">_.isArguments</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> obj <span class="Keyword">and</span> _.isNumber(obj.length) <span class="Keyword">and</span> <span class="Keyword">not</span> obj.concat <span class="Keyword">and</span>
|
||||
<span class="line-numbers"> 465 </span> <span class="Keyword">not</span> obj.substr <span class="Keyword">and</span> <span class="Keyword">not</span> obj.apply <span class="Keyword">and</span> <span class="Keyword">not</span> propertyIsEnumerable.call(obj, <span class="String"><span class="String">'</span>length<span class="String">'</span></span>)
|
||||
<span class="line-numbers"> 466 </span>
|
||||
<span class="line-numbers"> 467 </span>
|
||||
<span class="line-numbers"> 468 </span> <span class="Comment"><span class="Comment">#</span> Is the given value a function?</span>
|
||||
<span class="line-numbers"> 469 </span> <span class="FunctionName">_.isFunction</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">and</span> obj.constructor <span class="Keyword">and</span> obj.call <span class="Keyword">and</span> obj.apply)
|
||||
<span class="line-numbers"> 470 </span>
|
||||
<span class="line-numbers"> 471 </span>
|
||||
<span class="line-numbers"> 472 </span> <span class="Comment"><span class="Comment">#</span> Is the given value a string?</span>
|
||||
<span class="line-numbers"> 473 </span> <span class="FunctionName">_.isString</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">is</span> <span class="String"><span class="String">'</span><span class="String">'</span></span> <span class="Keyword">or</span> (obj <span class="Keyword">and</span> obj.charCodeAt <span class="Keyword">and</span> obj.substr))
|
||||
<span class="line-numbers"> 474 </span>
|
||||
<span class="line-numbers"> 475 </span>
|
||||
<span class="line-numbers"> 476 </span> <span class="Comment"><span class="Comment">#</span> Is a given value a number?</span>
|
||||
<span class="line-numbers"> 477 </span> <span class="FunctionName">_.isNumber</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> (obj <span class="Keyword">is</span> <span class="Keyword">+</span>obj) <span class="Keyword">or</span> toString.call(obj) <span class="Keyword">is</span> <span class="String"><span class="String">'</span>[object Number]<span class="String">'</span></span>
|
||||
<span class="line-numbers"> 478 </span>
|
||||
<span class="line-numbers"> 479 </span>
|
||||
<span class="line-numbers"> 480 </span> <span class="Comment"><span class="Comment">#</span> Is a given value a Date?</span>
|
||||
<span class="line-numbers"> 481 </span> <span class="FunctionName">_.isDate</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">and</span> obj.getTimezoneOffset <span class="Keyword">and</span> obj.setUTCFullYear)
|
||||
<span class="line-numbers"> 482 </span>
|
||||
<span class="line-numbers"> 483 </span>
|
||||
<span class="line-numbers"> 484 </span> <span class="Comment"><span class="Comment">#</span> Is the given value a regular expression?</span>
|
||||
<span class="line-numbers"> 485 </span> <span class="FunctionName">_.isRegExp</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> <span class="Keyword">!</span><span class="Keyword">!</span>(obj <span class="Keyword">and</span> obj.exec <span class="Keyword">and</span> (obj.ignoreCase <span class="Keyword">or</span> obj.ignoreCase <span class="Keyword">is</span> <span class="BuiltInConstant">false</span>))
|
||||
<span class="line-numbers"> 486 </span>
|
||||
<span class="line-numbers"> 487 </span>
|
||||
<span class="line-numbers"> 488 </span> <span class="Comment"><span class="Comment">#</span> Is the given value NaN -- this one is interesting. NaN != NaN, and</span>
|
||||
<span class="line-numbers"> 489 </span> <span class="Comment"><span class="Comment">#</span> isNaN(undefined) == true, so we make sure it's a number first.</span>
|
||||
<span class="line-numbers"> 490 </span> <span class="FunctionName">_.isNaN</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> _.isNumber(obj) <span class="Keyword">and</span> window.isNaN(obj)
|
||||
<span class="line-numbers"> 491 </span>
|
||||
<span class="line-numbers"> 492 </span>
|
||||
<span class="line-numbers"> 493 </span> <span class="Comment"><span class="Comment">#</span> Is a given value equal to null?</span>
|
||||
<span class="line-numbers"> 494 </span> <span class="FunctionName">_.isNull</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> obj <span class="Keyword">is</span> <span class="BuiltInConstant">null</span>
|
||||
<span class="line-numbers"> 495 </span>
|
||||
<span class="line-numbers"> 496 </span>
|
||||
<span class="line-numbers"> 497 </span> <span class="Comment"><span class="Comment">#</span> Is a given variable undefined?</span>
|
||||
<span class="line-numbers"> 498 </span> <span class="FunctionName">_.isUndefined</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> <span class="Keyword">typeof</span> obj <span class="Keyword">is</span> <span class="String"><span class="String">'</span>undefined<span class="String">'</span></span>
|
||||
<span class="line-numbers"> 499 </span>
|
||||
<span class="line-numbers"> 500 </span>
|
||||
<span class="line-numbers"> 501 </span> <span class="Comment"><span class="Comment">#</span> -------------------------- Utility Functions: --------------------------</span>
|
||||
<span class="line-numbers"> 502 </span>
|
||||
<span class="line-numbers"> 503 </span> <span class="Comment"><span class="Comment">#</span> Run Underscore.js in noConflict mode, returning the '_' variable to its</span>
|
||||
<span class="line-numbers"> 504 </span> <span class="Comment"><span class="Comment">#</span> previous owner. Returns a reference to the Underscore object.</span>
|
||||
<span class="line-numbers"> 505 </span> <span class="FunctionName">_.noConflict</span><span class="Keyword">:</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 506 </span> <span class="FunctionName">root._</span><span class="Keyword">:</span> previousUnderscore
|
||||
<span class="line-numbers"> 507 </span> <span class="Variable">this</span>
|
||||
<span class="line-numbers"> 508 </span>
|
||||
<span class="line-numbers"> 509 </span>
|
||||
<span class="line-numbers"> 510 </span> <span class="Comment"><span class="Comment">#</span> Keep the identity function around for default iterators.</span>
|
||||
<span class="line-numbers"> 511 </span> <span class="FunctionName">_.identity</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">value</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> value
|
||||
<span class="line-numbers"> 512 </span>
|
||||
<span class="line-numbers"> 513 </span>
|
||||
<span class="line-numbers"> 514 </span> <span class="Comment"><span class="Comment">#</span> Break out of the middle of an iteration.</span>
|
||||
<span class="line-numbers"> 515 </span> <span class="FunctionName">_.breakLoop</span><span class="Keyword">:</span> <span class="Storage">-></span> <span class="Keyword">throw</span> breaker
|
||||
<span class="line-numbers"> 516 </span>
|
||||
<span class="line-numbers"> 517 </span>
|
||||
<span class="line-numbers"> 518 </span> <span class="Comment"><span class="Comment">#</span> Generate a unique integer id (unique within the entire client session).</span>
|
||||
<span class="line-numbers"> 519 </span> <span class="Comment"><span class="Comment">#</span> Useful for temporary DOM ids.</span>
|
||||
<span class="line-numbers"> 520 </span> <span class="FunctionName">idCounter</span><span class="Keyword">:</span> <span class="Number">0</span>
|
||||
<span class="line-numbers"> 521 </span> <span class="FunctionName">_.uniqueId</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">prefix</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 522 </span> (prefix <span class="Keyword">or</span> <span class="String"><span class="String">'</span><span class="String">'</span></span>) <span class="Keyword">+</span> idCounter<span class="Keyword">++</span>
|
||||
<span class="line-numbers"> 523 </span>
|
||||
<span class="line-numbers"> 524 </span>
|
||||
<span class="line-numbers"> 525 </span> <span class="Comment"><span class="Comment">#</span> By default, Underscore uses ERB-style template delimiters, change the</span>
|
||||
<span class="line-numbers"> 526 </span> <span class="Comment"><span class="Comment">#</span> following template settings to use alternative delimiters.</span>
|
||||
<span class="line-numbers"> 527 </span> <span class="FunctionName">_.templateSettings</span><span class="Keyword">:</span> {
|
||||
<span class="line-numbers"> 528 </span> <span class="FunctionName">start</span><span class="Keyword">:</span> <span class="String"><span class="String">'</span><%<span class="String">'</span></span>
|
||||
<span class="line-numbers"> 529 </span> <span class="FunctionName">end</span><span class="Keyword">:</span> <span class="String"><span class="String">'</span>%><span class="String">'</span></span>
|
||||
<span class="line-numbers"> 530 </span> <span class="FunctionName">interpolate</span><span class="Keyword">:</span><span class="String"> <span class="String">/</span><%=(.+?)%><span class="String">/</span>g</span>
|
||||
<span class="line-numbers"> 531 </span> }
|
||||
<span class="line-numbers"> 532 </span>
|
||||
<span class="line-numbers"> 533 </span>
|
||||
<span class="line-numbers"> 534 </span> <span class="Comment"><span class="Comment">#</span> JavaScript templating a-la ERB, pilfered from John Resig's</span>
|
||||
<span class="line-numbers"> 535 </span> <span class="Comment"><span class="Comment">#</span> "Secrets of the JavaScript Ninja", page 83.</span>
|
||||
<span class="line-numbers"> 536 </span> <span class="Comment"><span class="Comment">#</span> Single-quotea fix from Rick Strahl's version.</span>
|
||||
<span class="line-numbers"> 537 </span> <span class="FunctionName">_.template</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">str, data</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 538 </span> <span class="FunctionName">c</span><span class="Keyword">:</span> _.templateSettings
|
||||
<span class="line-numbers"> 539 </span> <span class="FunctionName">fn</span><span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Function</span> <span class="String"><span class="String">'</span>obj<span class="String">'</span></span>,
|
||||
<span class="line-numbers"> 540 </span> <span class="String"><span class="String">'</span>var p=[],print=function(){p.push.apply(p,arguments);};<span class="String">'</span></span> <span class="Keyword">+</span>
|
||||
<span class="line-numbers"> 541 </span> <span class="String"><span class="String">'</span>with(obj){p.push(<span class="UserDefinedConstant">\'</span><span class="String">'</span></span> <span class="Keyword">+</span>
|
||||
<span class="line-numbers"> 542 </span> str.replace(<span class="String"><span class="String">/</span>[<span class="UserDefinedConstant">\r</span><span class="UserDefinedConstant">\t</span><span class="UserDefinedConstant">\n</span>]<span class="String">/</span>g</span>, <span class="String"><span class="String">"</span> <span class="String">"</span></span>)
|
||||
<span class="line-numbers"> 543 </span> .replace(<span class="Keyword">new</span> <span class="TypeName">RegExp</span>(<span class="String"><span class="String">"</span>'(?=[^<span class="String">"</span></span><span class="Keyword">+</span>c.end[<span class="Number">0</span>]<span class="Keyword">+</span><span class="String"><span class="String">"</span>]*<span class="String">"</span></span><span class="Keyword">+</span>c.end<span class="Keyword">+</span><span class="String"><span class="String">"</span>)<span class="String">"</span></span>,<span class="String"><span class="String">"</span>g<span class="String">"</span></span>),<span class="String"><span class="String">"</span><span class="UserDefinedConstant">\t</span><span class="String">"</span></span>)
|
||||
<span class="line-numbers"> 544 </span> .split(<span class="String"><span class="String">"</span>'<span class="String">"</span></span>).join(<span class="String"><span class="String">"</span><span class="UserDefinedConstant">\\</span>'<span class="String">"</span></span>)
|
||||
<span class="line-numbers"> 545 </span> .split(<span class="String"><span class="String">"</span><span class="UserDefinedConstant">\t</span><span class="String">"</span></span>).join(<span class="String"><span class="String">"</span>'<span class="String">"</span></span>)
|
||||
<span class="line-numbers"> 546 </span> .replace(c.interpolate, <span class="String"><span class="String">"</span>',$1,'<span class="String">"</span></span>)
|
||||
<span class="line-numbers"> 547 </span> .split(c.start).join(<span class="String"><span class="String">"</span>');<span class="String">"</span></span>)
|
||||
<span class="line-numbers"> 548 </span> .split(c.end).join(<span class="String"><span class="String">"</span>p.push('<span class="String">"</span></span>) <span class="Keyword">+</span>
|
||||
<span class="line-numbers"> 549 </span> <span class="String"><span class="String">"</span>');}return p.join('');<span class="String">"</span></span>
|
||||
<span class="line-numbers"> 550 </span> <span class="Keyword">if</span> data <span class="Keyword">then</span> fn(data) <span class="Keyword">else</span> fn
|
||||
<span class="line-numbers"> 551 </span>
|
||||
<span class="line-numbers"> 552 </span>
|
||||
<span class="line-numbers"> 553 </span> <span class="Comment"><span class="Comment">#</span> ------------------------------- Aliases ----------------------------------</span>
|
||||
<span class="line-numbers"> 554 </span>
|
||||
<span class="line-numbers"> 555 </span> <span class="FunctionName">_.forEach</span><span class="Keyword">:</span> _.each
|
||||
<span class="line-numbers"> 556 </span> <span class="FunctionName">_.foldl</span><span class="Keyword">:</span> <span class="FunctionName">_.inject</span><span class="Keyword">:</span> _.reduce
|
||||
<span class="line-numbers"> 557 </span> <span class="FunctionName">_.foldr</span><span class="Keyword">:</span> _.reduceRight
|
||||
<span class="line-numbers"> 558 </span> <span class="FunctionName">_.filter</span><span class="Keyword">:</span> _.select
|
||||
<span class="line-numbers"> 559 </span> <span class="FunctionName">_.every</span><span class="Keyword">:</span> _.all
|
||||
<span class="line-numbers"> 560 </span> <span class="FunctionName">_.some</span><span class="Keyword">:</span> _.any
|
||||
<span class="line-numbers"> 561 </span> <span class="FunctionName">_.head</span><span class="Keyword">:</span> _.first
|
||||
<span class="line-numbers"> 562 </span> <span class="FunctionName">_.tail</span><span class="Keyword">:</span> _.rest
|
||||
<span class="line-numbers"> 563 </span> <span class="FunctionName">_.methods</span><span class="Keyword">:</span> _.functions
|
||||
<span class="line-numbers"> 564 </span>
|
||||
<span class="line-numbers"> 565 </span>
|
||||
<span class="line-numbers"> 566 </span> <span class="Comment"><span class="Comment">#</span> /*------------------------ Setup the OOP Wrapper: --------------------------*/</span>
|
||||
<span class="line-numbers"> 567 </span>
|
||||
<span class="line-numbers"> 568 </span> <span class="Comment"><span class="Comment">#</span> Helper function to continue chaining intermediate results.</span>
|
||||
<span class="line-numbers"> 569 </span> <span class="FunctionName">result</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">obj, chain</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 570 </span> <span class="Keyword">if</span> chain <span class="Keyword">then</span> _(obj).chain() <span class="Keyword">else</span> obj
|
||||
<span class="line-numbers"> 571 </span>
|
||||
<span class="line-numbers"> 572 </span>
|
||||
<span class="line-numbers"> 573 </span> <span class="Comment"><span class="Comment">#</span> Add all of the Underscore functions to the wrapper object.</span>
|
||||
<span class="line-numbers"> 574 </span> _.each _.functions(_), <span class="FunctionArgument">(</span><span class="FunctionArgument">name</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 575 </span> <span class="FunctionName">method</span><span class="Keyword">:</span> _[name]
|
||||
<span class="line-numbers"> 576 </span> wrapper.prototype[name]<span class="Keyword">:</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 577 </span> unshift.call(arguments, <span class="Variable">this</span>._wrapped)
|
||||
<span class="line-numbers"> 578 </span> result(method.apply(_, arguments), <span class="Variable">this</span>._chain)
|
||||
<span class="line-numbers"> 579 </span>
|
||||
<span class="line-numbers"> 580 </span>
|
||||
<span class="line-numbers"> 581 </span> <span class="Comment"><span class="Comment">#</span> Add all mutator Array functions to the wrapper.</span>
|
||||
<span class="line-numbers"> 582 </span> _.each [<span class="String"><span class="String">'</span>pop<span class="String">'</span></span>, <span class="String"><span class="String">'</span>push<span class="String">'</span></span>, <span class="String"><span class="String">'</span>reverse<span class="String">'</span></span>, <span class="String"><span class="String">'</span>shift<span class="String">'</span></span>, <span class="String"><span class="String">'</span>sort<span class="String">'</span></span>, <span class="String"><span class="String">'</span>splice<span class="String">'</span></span>, <span class="String"><span class="String">'</span>unshift<span class="String">'</span></span>], <span class="FunctionArgument">(</span><span class="FunctionArgument">name</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 583 </span> <span class="FunctionName">method</span><span class="Keyword">:</span> Array.prototype[name]
|
||||
<span class="line-numbers"> 584 </span> wrapper.prototype[name]<span class="Keyword">:</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 585 </span> method.apply(<span class="Variable">this</span>._wrapped, arguments)
|
||||
<span class="line-numbers"> 586 </span> result(<span class="Variable">this</span>._wrapped, <span class="Variable">this</span>._chain)
|
||||
<span class="line-numbers"> 587 </span>
|
||||
<span class="line-numbers"> 588 </span>
|
||||
<span class="line-numbers"> 589 </span> <span class="Comment"><span class="Comment">#</span> Add all accessor Array functions to the wrapper.</span>
|
||||
<span class="line-numbers"> 590 </span> _.each [<span class="String"><span class="String">'</span>concat<span class="String">'</span></span>, <span class="String"><span class="String">'</span>join<span class="String">'</span></span>, <span class="String"><span class="String">'</span>slice<span class="String">'</span></span>], <span class="FunctionArgument">(</span><span class="FunctionArgument">name</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 591 </span> <span class="FunctionName">method</span><span class="Keyword">:</span> Array.prototype[name]
|
||||
<span class="line-numbers"> 592 </span> wrapper.prototype[name]<span class="Keyword">:</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 593 </span> result(method.apply(<span class="Variable">this</span>._wrapped, arguments), <span class="Variable">this</span>._chain)
|
||||
<span class="line-numbers"> 594 </span>
|
||||
<span class="line-numbers"> 595 </span>
|
||||
<span class="line-numbers"> 596 </span> <span class="Comment"><span class="Comment">#</span> Start chaining a wrapped Underscore object.</span>
|
||||
<span class="line-numbers"> 597 </span> <span class="FunctionName">wrapper::chain</span><span class="Keyword">:</span> <span class="Storage">-></span>
|
||||
<span class="line-numbers"> 598 </span> <span class="FunctionName">this._chain</span><span class="Keyword">:</span> <span class="BuiltInConstant">true</span>
|
||||
<span class="line-numbers"> 599 </span> <span class="Variable">this</span>
|
||||
<span class="line-numbers"> 600 </span>
|
||||
<span class="line-numbers"> 601 </span>
|
||||
<span class="line-numbers"> 602 </span> <span class="Comment"><span class="Comment">#</span> Extracts the result from a wrapped and chained object.</span>
|
||||
<span class="line-numbers"> 603 </span> <span class="FunctionName">wrapper::value</span><span class="Keyword">:</span> <span class="Storage">-></span> <span class="Variable">this</span>._wrapped
|
||||
</pre> <p>
|
||||
<a href="http://validator.w3.org/check?uri=referer">
|
||||
<img style="border:0"
|
||||
src="http://www.w3.org/Icons/valid-xhtml10"
|
||||
alt="Valid XHTML 1.0 Strict" height="31" width="88" />
|
||||
</a>
|
||||
<a href="http://jigsaw.w3.org/css-validator/check?uri=referer">
|
||||
<img style="border:0;width:88px;height:31px"
|
||||
src="http://jigsaw.w3.org/css-validator/images/vcss"
|
||||
alt="Valid CSS!" />
|
||||
</a>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -8,7 +8,7 @@ get '/hello', ->
|
||||
# Append.
|
||||
append: (location, data) ->
|
||||
path: new Pathname location
|
||||
throw "Location does not exist" unless path.exists()
|
||||
throw new Error("Location does not exist") unless path.exists()
|
||||
|
||||
File.open path, 'a', (file) ->
|
||||
file.puts YAML.dump data
|
||||
|
||||
@@ -140,24 +140,28 @@ sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna
|
||||
aliquam erat volutpat. Ut wisi enim ad."
|
||||
|
||||
# Inheritance and calling super.
|
||||
Animal: ->
|
||||
Animal::move: (meters) ->
|
||||
alert(this.name + " moved " + meters + "m.")
|
||||
class Animal
|
||||
move: (meters) ->
|
||||
alert this.name + " moved " + meters + "m."
|
||||
|
||||
Snake: (name) -> this.name: name
|
||||
Snake extends Animal
|
||||
Snake::move: ->
|
||||
alert('Slithering...')
|
||||
super(5)
|
||||
class Snake extends Animal
|
||||
constructor: (name) ->
|
||||
@name: name
|
||||
|
||||
Horse: (name) -> this.name: name
|
||||
Horse extends Animal
|
||||
Horse::move: ->
|
||||
alert('Galloping...')
|
||||
super(45)
|
||||
move: ->
|
||||
alert 'Slithering...'
|
||||
super 5
|
||||
|
||||
sam: new Snake("Sammy the Snake")
|
||||
tom: new Horse("Tommy the Horse")
|
||||
class Horse extends Animal
|
||||
constructor: (name) ->
|
||||
@name: name
|
||||
|
||||
move: ->
|
||||
alert 'Galloping...'
|
||||
super 45
|
||||
|
||||
sam: new Snake "Sammy the Snake"
|
||||
tom: new Horse "Tommy the Horse"
|
||||
|
||||
sam.move()
|
||||
tom.move()
|
||||
|
||||
@@ -1,90 +1,92 @@
|
||||
# "Classic" linked list implementation that doesn't keep track of its size.
|
||||
LinkedList: ->
|
||||
this._head: null # Pointer to the first item in the list.
|
||||
class LinkedList
|
||||
|
||||
constructor: ->
|
||||
this._head: null # Pointer to the first item in the list.
|
||||
|
||||
|
||||
# Appends some data to the end of the list. This method traverses the existing
|
||||
# list and places the value at the end in a new node.
|
||||
LinkedList::add: (data) ->
|
||||
# Appends some data to the end of the list. This method traverses the existing
|
||||
# list and places the value at the end in a new node.
|
||||
add: (data) ->
|
||||
|
||||
# Create a new node object to wrap the data.
|
||||
node: {data: data, next: null}
|
||||
# Create a new node object to wrap the data.
|
||||
node: {data: data, next: null}
|
||||
|
||||
current: this._head ||= node
|
||||
current: this._head ||= node
|
||||
|
||||
if this._head isnt node
|
||||
current: current.next while current.next
|
||||
current.next: node
|
||||
if this._head isnt node
|
||||
current: current.next while current.next
|
||||
current.next: node
|
||||
|
||||
this
|
||||
this
|
||||
|
||||
|
||||
# Retrieves the data at the given position in the list.
|
||||
LinkedList::item: (index) ->
|
||||
# Retrieves the data at the given position in the list.
|
||||
item: (index) ->
|
||||
|
||||
# Check for out-of-bounds values.
|
||||
return null if index < 0
|
||||
# Check for out-of-bounds values.
|
||||
return null if index < 0
|
||||
|
||||
current: this._head or null
|
||||
i: -1
|
||||
current: this._head or null
|
||||
i: -1
|
||||
|
||||
# Advance through the list.
|
||||
current: current.next while current and index > (i += 1)
|
||||
# Advance through the list.
|
||||
current: current.next while current and index > (i += 1)
|
||||
|
||||
# Return null if we've reached the end.
|
||||
current and current.data
|
||||
# Return null if we've reached the end.
|
||||
current and current.data
|
||||
|
||||
|
||||
# Remove the item from the given location in the list.
|
||||
LinkedList::remove: (index) ->
|
||||
# Remove the item from the given location in the list.
|
||||
remove: (index) ->
|
||||
|
||||
# Check for out-of-bounds values.
|
||||
return null if index < 0
|
||||
# Check for out-of-bounds values.
|
||||
return null if index < 0
|
||||
|
||||
current: this._head or null
|
||||
i: -1
|
||||
current: this._head or null
|
||||
i: -1
|
||||
|
||||
# Special case: removing the first item.
|
||||
if index is 0
|
||||
this._head: current.next
|
||||
else
|
||||
# Special case: removing the first item.
|
||||
if index is 0
|
||||
this._head: current.next
|
||||
else
|
||||
|
||||
# Find the right location.
|
||||
[previous, current]: [current, current.next] while index > (i += 1)
|
||||
# Find the right location.
|
||||
[previous, current]: [current, current.next] while index > (i += 1)
|
||||
|
||||
# Skip over the item to remove.
|
||||
previous.next: current.next
|
||||
# Skip over the item to remove.
|
||||
previous.next: current.next
|
||||
|
||||
# Return the value.
|
||||
current and current.data
|
||||
# Return the value.
|
||||
current and current.data
|
||||
|
||||
|
||||
# Calculate the number of items in the list.
|
||||
LinkedList::size: ->
|
||||
current: this._head
|
||||
count: 0
|
||||
# Calculate the number of items in the list.
|
||||
size: ->
|
||||
current: this._head
|
||||
count: 0
|
||||
|
||||
while current
|
||||
count += 1
|
||||
current: current.next
|
||||
while current
|
||||
count += 1
|
||||
current: current.next
|
||||
|
||||
count
|
||||
count
|
||||
|
||||
|
||||
# Convert the list into an array.
|
||||
LinkedList::toArray: ->
|
||||
result: []
|
||||
current: this._head
|
||||
# Convert the list into an array.
|
||||
toArray: ->
|
||||
result: []
|
||||
current: this._head
|
||||
|
||||
while current
|
||||
result.push(current.data)
|
||||
current: current.next
|
||||
while current
|
||||
result.push(current.data)
|
||||
current: current.next
|
||||
|
||||
result
|
||||
result
|
||||
|
||||
|
||||
# The string representation of the linked list.
|
||||
LinkedList::toString: -> this.toArray().toString()
|
||||
# The string representation of the linked list.
|
||||
toString: -> this.toArray().toString()
|
||||
|
||||
|
||||
# Tests.
|
||||
|
||||
@@ -53,16 +53,16 @@ for key, val of {dog: 'canine', cat: 'feline', fox: 'vulpine'}
|
||||
# Person print = ():
|
||||
# ('My name is ', /name, '.') join print.
|
||||
|
||||
Person: ->
|
||||
Person::print: ->
|
||||
print('My name is ' + this.name + '.')
|
||||
class Person
|
||||
print: ->
|
||||
print 'My name is ' + this.name + '.'
|
||||
|
||||
|
||||
# p = Person ()
|
||||
# p /name string print
|
||||
|
||||
p: new Person()
|
||||
print(p.name)
|
||||
print p.name
|
||||
|
||||
|
||||
# Policeman = Person class (rank): /rank = rank.
|
||||
@@ -71,12 +71,13 @@ print(p.name)
|
||||
#
|
||||
# Policeman ('Constable') print
|
||||
|
||||
Policeman: (rank) -> this.rank: rank
|
||||
Policeman extends Person
|
||||
Policeman::print: ->
|
||||
print('My name is ' + this.name + " and I'm a " + this.rank + '.')
|
||||
class Policeman extends Person
|
||||
constructor: (rank) ->
|
||||
@rank: rank
|
||||
print: ->
|
||||
print 'My name is ' + this.name + " and I'm a " + this.rank + '.'
|
||||
|
||||
print(new Policeman('Constable'))
|
||||
print new Policeman 'Constable'
|
||||
|
||||
|
||||
# app = [window (width=200, height=400)
|
||||
|
||||
@@ -1,96 +1,122 @@
|
||||
|
||||
# Underscore.coffee
|
||||
# (c) 2010 Jeremy Ashkenas, DocumentCloud Inc.
|
||||
# Underscore is freely distributable under the terms of the MIT license.
|
||||
# Portions of Underscore are inspired by or borrowed from Prototype.js,
|
||||
# Oliver Steele's Functional, and John Resig's Micro-Templating.
|
||||
# **Underscore.coffee
|
||||
# (c) 2010 Jeremy Ashkenas, DocumentCloud Inc.**
|
||||
# Underscore is freely distributable under the terms of the
|
||||
# [MIT license](http://en.wikipedia.org/wiki/MIT_License).
|
||||
# Portions of Underscore are inspired by or borrowed from
|
||||
# [Prototype.js](http://prototypejs.org/api), Oliver Steele's
|
||||
# [Functional](http://osteele.com), and John Resig's
|
||||
# [Micro-Templating](http://ejohn.com).
|
||||
# For all details and documentation:
|
||||
# http://documentcloud.github.com/underscore/
|
||||
|
||||
|
||||
# ------------------------- Baseline setup ---------------------------------
|
||||
# Baseline setup
|
||||
# --------------
|
||||
|
||||
# Establish the root object, "window" in the browser, or "global" on the server.
|
||||
# Establish the root object, `window` in the browser, or `global` on the server.
|
||||
root: this
|
||||
|
||||
|
||||
# Save the previous value of the "_" variable.
|
||||
# Save the previous value of the `_` variable.
|
||||
previousUnderscore: root._
|
||||
|
||||
|
||||
# If Underscore is called as a function, it returns a wrapped object that
|
||||
# can be used OO-style. This wrapper holds altered versions of all the
|
||||
# underscore functions. Wrapped objects may be chained.
|
||||
wrapper: (obj) ->
|
||||
this._wrapped: obj
|
||||
this
|
||||
|
||||
|
||||
# Establish the object that gets thrown to break out of a loop iteration.
|
||||
# `StopIteration` is SOP on Mozilla.
|
||||
breaker: if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration
|
||||
|
||||
|
||||
# Create a safe reference to the Underscore object forreference below.
|
||||
_: root._: (obj) -> new wrapper(obj)
|
||||
# Helper function to escape **RegExp** contents, because JS doesn't have one.
|
||||
escapeRegExp: (string) -> string.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1')
|
||||
|
||||
|
||||
# Export the Underscore object for CommonJS.
|
||||
if typeof(exports) != 'undefined' then exports._: _
|
||||
# Save bytes in the minified (but not gzipped) version:
|
||||
ArrayProto: Array.prototype
|
||||
ObjProto: Object.prototype
|
||||
|
||||
|
||||
# Create quick reference variables for speed access to core prototypes.
|
||||
slice: Array::slice
|
||||
unshift: Array::unshift
|
||||
toString: Object::toString
|
||||
hasOwnProperty: Object::hasOwnProperty
|
||||
propertyIsEnumerable: Object::propertyIsEnumerable
|
||||
slice: ArrayProto.slice
|
||||
unshift: ArrayProto.unshift
|
||||
toString: ObjProto.toString
|
||||
hasOwnProperty: ObjProto.hasOwnProperty
|
||||
propertyIsEnumerable: ObjProto.propertyIsEnumerable
|
||||
|
||||
|
||||
# All **ECMA5** native implementations we hope to use are declared here.
|
||||
nativeForEach: ArrayProto.forEach
|
||||
nativeMap: ArrayProto.map
|
||||
nativeReduce: ArrayProto.reduce
|
||||
nativeReduceRight: ArrayProto.reduceRight
|
||||
nativeFilter: ArrayProto.filter
|
||||
nativeEvery: ArrayProto.every
|
||||
nativeSome: ArrayProto.some
|
||||
nativeIndexOf: ArrayProto.indexOf
|
||||
nativeLastIndexOf: ArrayProto.lastIndexOf
|
||||
nativeIsArray: Array.isArray
|
||||
nativeKeys: Object.keys
|
||||
|
||||
|
||||
# Create a safe reference to the Underscore object for use below.
|
||||
_: (obj) -> new wrapper(obj)
|
||||
|
||||
|
||||
# Export the Underscore object for **CommonJS**.
|
||||
if typeof(exports) != 'undefined' then exports._: _
|
||||
|
||||
|
||||
# Export Underscore to global scope.
|
||||
root._: _
|
||||
|
||||
|
||||
# Current version.
|
||||
_.VERSION: '0.5.7'
|
||||
_.VERSION: '1.0.2'
|
||||
|
||||
|
||||
# ------------------------ Collection Functions: ---------------------------
|
||||
# Collection Functions
|
||||
# --------------------
|
||||
|
||||
# The cornerstone, an each implementation.
|
||||
# Handles objects implementing forEach, arrays, and raw objects.
|
||||
# The cornerstone, an **each** implementation.
|
||||
# Handles objects implementing **forEach**, arrays, and raw objects.
|
||||
_.each: (obj, iterator, context) ->
|
||||
index: 0
|
||||
try
|
||||
return obj.forEach(iterator, context) if obj.forEach
|
||||
if _.isArray(obj) or _.isArguments(obj)
|
||||
return iterator.call(context, obj[i], i, obj) for i in [0...obj.length]
|
||||
iterator.call(context, val, key, obj) for key, val of obj
|
||||
if nativeForEach and obj.forEach is nativeForEach
|
||||
obj.forEach iterator, context
|
||||
else if _.isNumber obj.length
|
||||
iterator.call(context, obj[i], i, obj) for i in [0...obj.length]
|
||||
else
|
||||
iterator.call(context, val, key, obj) for key, val of obj
|
||||
catch e
|
||||
throw e if e isnt breaker
|
||||
obj
|
||||
|
||||
|
||||
# Return the results of applying the iterator to each element. Use JavaScript
|
||||
# 1.6's version of map, if possible.
|
||||
# 1.6's version of **map**, if possible.
|
||||
_.map: (obj, iterator, context) ->
|
||||
return obj.map(iterator, context) if (obj and _.isFunction(obj.map))
|
||||
return obj.map(iterator, context) if nativeMap and obj.map is nativeMap
|
||||
results: []
|
||||
_.each obj, (value, index, list) ->
|
||||
results.push(iterator.call(context, value, index, list))
|
||||
results.push iterator.call context, value, index, list
|
||||
results
|
||||
|
||||
|
||||
# Reduce builds up a single result from a list of values. Also known as
|
||||
# inject, or foldl. Uses JavaScript 1.8's version of reduce, if possible.
|
||||
# **Reduce** builds up a single result from a list of values. Also known as
|
||||
# **inject**, or **foldl**. Uses JavaScript 1.8's version of **reduce**, if possible.
|
||||
_.reduce: (obj, memo, iterator, context) ->
|
||||
return obj.reduce(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduce))
|
||||
return obj.reduce(_.bind(iterator, context), memo) if nativeReduce and obj.reduce is nativeReduce
|
||||
_.each obj, (value, index, list) ->
|
||||
memo: iterator.call(context, memo, value, index, list)
|
||||
memo: iterator.call context, memo, value, index, list
|
||||
memo
|
||||
|
||||
|
||||
# The right-associative version of reduce, also known as foldr. Uses
|
||||
# JavaScript 1.8's version of reduceRight, if available.
|
||||
# The right-associative version of **reduce**, also known as **foldr**. Uses
|
||||
# JavaScript 1.8's version of **reduceRight**, if available.
|
||||
_.reduceRight: (obj, memo, iterator, context) ->
|
||||
return obj.reduceRight(_.bind(iterator, context), memo) if (obj and _.isFunction(obj.reduceRight))
|
||||
return obj.reduceRight(_.bind(iterator, context), memo) if nativeReduceRight and obj.reduceRight is nativeReduceRight
|
||||
_.each _.clone(_.toArray(obj)).reverse(), (value, index) ->
|
||||
memo: iterator.call(context, memo, value, index, obj)
|
||||
memo: iterator.call context, memo, value, index, obj
|
||||
memo
|
||||
|
||||
|
||||
@@ -98,19 +124,19 @@
|
||||
_.detect: (obj, iterator, context) ->
|
||||
result: null
|
||||
_.each obj, (value, index, list) ->
|
||||
if iterator.call(context, value, index, list)
|
||||
if iterator.call context, value, index, list
|
||||
result: value
|
||||
_.breakLoop()
|
||||
result
|
||||
|
||||
|
||||
# Return all the elements that pass a truth test. Use JavaScript 1.6's
|
||||
# filter(), if it exists.
|
||||
_.select: (obj, iterator, context) ->
|
||||
if obj and _.isFunction(obj.filter) then return obj.filter(iterator, context)
|
||||
# **filter**, if it exists.
|
||||
_.filter: (obj, iterator, context) ->
|
||||
return obj.filter iterator, context if nativeFilter and obj.filter is nativeFilter
|
||||
results: []
|
||||
_.each obj, (value, index, list) ->
|
||||
results.push(value) if iterator.call(context, value, index, list)
|
||||
results.push value if iterator.call context, value, index, list
|
||||
results
|
||||
|
||||
|
||||
@@ -118,15 +144,15 @@
|
||||
_.reject: (obj, iterator, context) ->
|
||||
results: []
|
||||
_.each obj, (value, index, list) ->
|
||||
results.push(value) if not iterator.call(context, value, index, list)
|
||||
results.push value if not iterator.call context, value, index, list
|
||||
results
|
||||
|
||||
|
||||
# Determine whether all of the elements match a truth test. Delegate to
|
||||
# JavaScript 1.6's every(), if it is present.
|
||||
_.all: (obj, iterator, context) ->
|
||||
# JavaScript 1.6's **every**, if it is present.
|
||||
_.every: (obj, iterator, context) ->
|
||||
iterator ||= _.identity
|
||||
return obj.every(iterator, context) if obj and _.isFunction(obj.every)
|
||||
return obj.every iterator, context if nativeEvery and obj.every is nativeEvery
|
||||
result: true
|
||||
_.each obj, (value, index, list) ->
|
||||
_.breakLoop() unless (result: result and iterator.call(context, value, index, list))
|
||||
@@ -134,10 +160,10 @@
|
||||
|
||||
|
||||
# Determine if at least one element in the object matches a truth test. Use
|
||||
# JavaScript 1.6's some(), if it exists.
|
||||
_.any: (obj, iterator, context) ->
|
||||
# JavaScript 1.6's **some**, if it exists.
|
||||
_.some: (obj, iterator, context) ->
|
||||
iterator ||= _.identity
|
||||
return obj.some(iterator, context) if obj and _.isFunction(obj.some)
|
||||
return obj.some iterator, context if nativeSome and obj.some is nativeSome
|
||||
result: false
|
||||
_.each obj, (value, index, list) ->
|
||||
_.breakLoop() if (result: iterator.call(context, value, index, list))
|
||||
@@ -145,9 +171,9 @@
|
||||
|
||||
|
||||
# Determine if a given value is included in the array or object,
|
||||
# based on '==='.
|
||||
# based on `===`.
|
||||
_.include: (obj, target) ->
|
||||
return _.indexOf(obj, target) isnt -1 if _.isArray(obj)
|
||||
return _.indexOf(obj, target) isnt -1 if nativeIndexOf and obj.indexOf is nativeIndexOf
|
||||
for key, val of obj
|
||||
return true if val is target
|
||||
false
|
||||
@@ -155,13 +181,13 @@
|
||||
|
||||
# Invoke a method with arguments on every item in a collection.
|
||||
_.invoke: (obj, method) ->
|
||||
args: _.rest(arguments, 2)
|
||||
args: _.rest arguments, 2
|
||||
(if method then val[method] else val).apply(val, args) for val in obj
|
||||
|
||||
|
||||
# Convenience version of a common use case of map: fetching a property.
|
||||
# Convenience version of a common use case of **map**: fetching a property.
|
||||
_.pluck: (obj, key) ->
|
||||
_.map(obj, ((val) -> val[key]))
|
||||
_.map(obj, (val) -> val[key])
|
||||
|
||||
|
||||
# Return the maximum item or (item-based computation).
|
||||
@@ -184,7 +210,7 @@
|
||||
result.value
|
||||
|
||||
|
||||
# Sort the object's values by a criteria produced by an iterator.
|
||||
# Sort the object's values by a criterion produced by an iterator.
|
||||
_.sortBy: (obj, iterator, context) ->
|
||||
_.pluck(((_.map obj, (value, index, list) ->
|
||||
{value: value, criteria: iterator.call(context, value, index, list)}
|
||||
@@ -198,7 +224,8 @@
|
||||
# be inserted so as to maintain order. Uses binary search.
|
||||
_.sortedIndex: (array, obj, iterator) ->
|
||||
iterator ||= _.identity
|
||||
low: 0; high: array.length
|
||||
low: 0
|
||||
high: array.length
|
||||
while low < high
|
||||
mid: (low + high) >> 1
|
||||
if iterator(array[mid]) < iterator(obj) then low: mid + 1 else high: mid
|
||||
@@ -218,19 +245,20 @@
|
||||
_.size: (obj) -> _.toArray(obj).length
|
||||
|
||||
|
||||
# -------------------------- Array Functions: ------------------------------
|
||||
# Array Functions
|
||||
# ---------------
|
||||
|
||||
# Get the first element of an array. Passing "n" will return the first N
|
||||
# values in the array. Aliased as "head". The "guard" check allows it to work
|
||||
# with _.map.
|
||||
# Get the first element of an array. Passing `n` will return the first N
|
||||
# values in the array. Aliased as **head**. The `guard` check allows it to work
|
||||
# with **map**.
|
||||
_.first: (array, n, guard) ->
|
||||
if n and not guard then slice.call(array, 0, n) else array[0]
|
||||
|
||||
|
||||
# Returns everything but the first entry of the array. Aliased as "tail".
|
||||
# Especially useful on the arguments object. Passing an "index" will return
|
||||
# the rest of the values in the array from that index onward. The "guard"
|
||||
# check allows it to work with _.map.
|
||||
# Returns everything but the first entry of the array. Aliased as **tail**.
|
||||
# Especially useful on the arguments object. Passing an `index` will return
|
||||
# the rest of the values in the array from that index onward. The `guard`
|
||||
# check allows it to work with **map**.
|
||||
_.rest: (array, index, guard) ->
|
||||
slice.call(array, if _.isUndefined(index) or guard then 1 else index)
|
||||
|
||||
@@ -240,36 +268,36 @@
|
||||
|
||||
|
||||
# Trim out all falsy values from an array.
|
||||
_.compact: (array) -> array[i] for i in [0...array.length] when array[i]
|
||||
_.compact: (array) -> item for item in array when item
|
||||
|
||||
|
||||
# Return a completely flattened version of an array.
|
||||
_.flatten: (array) ->
|
||||
_.reduce array, [], (memo, value) ->
|
||||
return memo.concat(_.flatten(value)) if _.isArray(value)
|
||||
memo.push(value)
|
||||
return memo.concat(_.flatten(value)) if _.isArray value
|
||||
memo.push value
|
||||
memo
|
||||
|
||||
|
||||
# Return a version of the array that does not contain the specified value(s).
|
||||
_.without: (array) ->
|
||||
values: _.rest(arguments)
|
||||
val for val in _.toArray(array) when not _.include(values, val)
|
||||
values: _.rest arguments
|
||||
val for val in _.toArray(array) when not _.include values, val
|
||||
|
||||
|
||||
# Produce a duplicate-free version of the array. If the array has already
|
||||
# been sorted, you have the option of using a faster algorithm.
|
||||
_.uniq: (array, isSorted) ->
|
||||
memo: []
|
||||
for el, i in _.toArray(array)
|
||||
memo.push(el) if i is 0 || (if isSorted is true then _.last(memo) isnt el else not _.include(memo, el))
|
||||
for el, i in _.toArray array
|
||||
memo.push el if i is 0 || (if isSorted is true then _.last(memo) isnt el else not _.include(memo, el))
|
||||
memo
|
||||
|
||||
|
||||
# Produce an array that contains every item shared between all the
|
||||
# passed-in arrays.
|
||||
_.intersect: (array) ->
|
||||
rest: _.rest(arguments)
|
||||
rest: _.rest arguments
|
||||
_.select _.uniq(array), (item) ->
|
||||
_.all rest, (other) ->
|
||||
_.indexOf(other, item) >= 0
|
||||
@@ -278,28 +306,28 @@
|
||||
# Zip together multiple lists into a single array -- elements that share
|
||||
# an index go together.
|
||||
_.zip: ->
|
||||
length: _.max(_.pluck(arguments, 'length'))
|
||||
results: new Array(length)
|
||||
length: _.max _.pluck arguments, 'length'
|
||||
results: new Array length
|
||||
for i in [0...length]
|
||||
results[i]: _.pluck(arguments, String(i))
|
||||
results[i]: _.pluck arguments, String i
|
||||
results
|
||||
|
||||
|
||||
# If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),
|
||||
# If the browser doesn't supply us with **indexOf** (I'm looking at you, MSIE),
|
||||
# we need this function. Return the position of the first occurence of an
|
||||
# item in an array, or -1 if the item is not included in the array.
|
||||
_.indexOf: (array, item) ->
|
||||
return array.indexOf(item) if array.indexOf
|
||||
return array.indexOf item if nativeIndexOf and array.indexOf is nativeIndexOf
|
||||
i: 0; l: array.length
|
||||
while l - i
|
||||
if array[i] is item then return i else i++
|
||||
-1
|
||||
|
||||
|
||||
# Provide JavaScript 1.6's lastIndexOf, delegating to the native function,
|
||||
# Provide JavaScript 1.6's **lastIndexOf**, delegating to the native function,
|
||||
# if possible.
|
||||
_.lastIndexOf: (array, item) ->
|
||||
return array.lastIndexOf(item) if array.lastIndexOf
|
||||
return array.lastIndexOf(item) if nativeLastIndexOf and array.lastIndexOf is nativeLastIndexOf
|
||||
i: array.length
|
||||
while i
|
||||
if array[i] is item then return i else i--
|
||||
@@ -307,17 +335,16 @@
|
||||
|
||||
|
||||
# Generate an integer Array containing an arithmetic progression. A port of
|
||||
# the native Python range() function. See:
|
||||
# http://docs.python.org/library/functions.html#range
|
||||
# [the native Python **range** function](http://docs.python.org/library/functions.html#range).
|
||||
_.range: (start, stop, step) ->
|
||||
a: arguments
|
||||
solo: a.length <= 1
|
||||
i: start: if solo then 0 else a[0];
|
||||
stop: if solo then a[0] else a[1];
|
||||
i: start: if solo then 0 else a[0]
|
||||
stop: if solo then a[0] else a[1]
|
||||
step: a[2] or 1
|
||||
len: Math.ceil((stop - start) / step)
|
||||
return [] if len <= 0
|
||||
range: new Array(len)
|
||||
range: new Array len
|
||||
idx: 0
|
||||
while true
|
||||
return range if (if step > 0 then i - stop else stop - i) >= 0
|
||||
@@ -326,41 +353,42 @@
|
||||
i+= step
|
||||
|
||||
|
||||
# ----------------------- Function Functions: -----------------------------
|
||||
# Function Functions
|
||||
# ------------------
|
||||
|
||||
# Create a function bound to a given object (assigning 'this', and arguments,
|
||||
# optionally). Binding with arguments is also known as 'curry'.
|
||||
# Create a function bound to a given object (assigning `this`, and arguments,
|
||||
# optionally). Binding with arguments is also known as **curry**.
|
||||
_.bind: (func, obj) ->
|
||||
args: _.rest(arguments, 2)
|
||||
-> func.apply(obj or root, args.concat(arguments))
|
||||
args: _.rest arguments, 2
|
||||
-> func.apply obj or root, args.concat arguments
|
||||
|
||||
|
||||
# Bind all of an object's methods to that object. Useful for ensuring that
|
||||
# all callbacks defined on an object belong to it.
|
||||
_.bindAll: (obj) ->
|
||||
funcs: if arguments.length > 1 then _.rest(arguments) else _.functions(obj)
|
||||
_.each(funcs, (f) -> obj[f]: _.bind(obj[f], obj))
|
||||
_.each funcs, (f) -> obj[f]: _.bind obj[f], obj
|
||||
obj
|
||||
|
||||
|
||||
# Delays a function for the given number of milliseconds, and then calls
|
||||
# it with the arguments supplied.
|
||||
_.delay: (func, wait) ->
|
||||
args: _.rest(arguments, 2)
|
||||
args: _.rest arguments, 2
|
||||
setTimeout((-> func.apply(func, args)), wait)
|
||||
|
||||
|
||||
# Defers a function, scheduling it to run after the current call stack has
|
||||
# cleared.
|
||||
_.defer: (func) ->
|
||||
_.delay.apply(_, [func, 1].concat(_.rest(arguments)))
|
||||
_.delay.apply _, [func, 1].concat _.rest arguments
|
||||
|
||||
|
||||
# Returns the first function passed as an argument to the second,
|
||||
# allowing you to adjust arguments, run code before and after, and
|
||||
# conditionally execute the original function.
|
||||
_.wrap: (func, wrapper) ->
|
||||
-> wrapper.apply(wrapper, [func].concat(arguments))
|
||||
-> wrapper.apply wrapper, [func].concat arguments
|
||||
|
||||
|
||||
# Returns a function that is the composition of a list of functions, each
|
||||
@@ -374,41 +402,42 @@
|
||||
args[0]
|
||||
|
||||
|
||||
# ------------------------- Object Functions: ----------------------------
|
||||
# Object Functions
|
||||
# ----------------
|
||||
|
||||
# Retrieve the names of an object's properties.
|
||||
_.keys: (obj) ->
|
||||
return _.range(0, obj.length) if _.isArray(obj)
|
||||
_.keys: nativeKeys or (obj) ->
|
||||
return _.range 0, obj.length if _.isArray(obj)
|
||||
key for key, val of obj
|
||||
|
||||
|
||||
# Retrieve the values of an object's properties.
|
||||
_.values: (obj) ->
|
||||
_.map(obj, _.identity)
|
||||
_.map obj, _.identity
|
||||
|
||||
|
||||
# Return a sorted list of the function names available in Underscore.
|
||||
_.functions: (obj) ->
|
||||
_.select(_.keys(obj), (key) -> _.isFunction(obj[key])).sort()
|
||||
_.filter(_.keys(obj), (key) -> _.isFunction(obj[key])).sort()
|
||||
|
||||
|
||||
# Extend a given object with all of the properties in a source object.
|
||||
_.extend: (destination, source) ->
|
||||
for key, val of source
|
||||
destination[key]: val
|
||||
destination
|
||||
_.extend: (obj) ->
|
||||
for source in _.rest(arguments)
|
||||
(obj[key]: val) for key, val of source
|
||||
obj
|
||||
|
||||
|
||||
# Create a (shallow-cloned) duplicate of an object.
|
||||
_.clone: (obj) ->
|
||||
return obj.slice(0) if _.isArray(obj)
|
||||
_.extend({}, obj)
|
||||
return obj.slice 0 if _.isArray obj
|
||||
_.extend {}, obj
|
||||
|
||||
|
||||
# Invokes interceptor with the obj, and then returns obj.
|
||||
# The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain.
|
||||
_.tap: (obj, interceptor) ->
|
||||
interceptor(obj)
|
||||
interceptor obj
|
||||
obj
|
||||
|
||||
|
||||
@@ -423,7 +452,7 @@
|
||||
return true if `a == b`
|
||||
# One is falsy and the other truthy.
|
||||
return false if (!a and b) or (a and !b)
|
||||
# One of them implements an isEqual()?
|
||||
# One of them implements an `isEqual()`?
|
||||
return a.isEqual(b) if a.isEqual
|
||||
# Check dates' integer values.
|
||||
return a.getTime() is b.getTime() if _.isDate(a) and _.isDate(b)
|
||||
@@ -444,12 +473,15 @@
|
||||
# Different object sizes?
|
||||
return false if aKeys.length isnt bKeys.length
|
||||
# Recursive comparison of contents.
|
||||
# for (var key in a) if (!_.isEqual(a[key], b[key])) return false;
|
||||
return true
|
||||
(return false) for key, val of a when !(key in b) or !_.isEqual(val, b[key])
|
||||
true
|
||||
|
||||
|
||||
# Is a given array or object empty?
|
||||
_.isEmpty: (obj) -> _.keys(obj).length is 0
|
||||
_.isEmpty: (obj) ->
|
||||
return obj.length is 0 if _.isArray obj
|
||||
(return false) for key of obj when hasOwnProperty.call(obj, key)
|
||||
true
|
||||
|
||||
|
||||
# Is a given value a DOM element?
|
||||
@@ -457,12 +489,11 @@
|
||||
|
||||
|
||||
# Is a given value an array?
|
||||
_.isArray: (obj) -> !!(obj and obj.concat and obj.unshift)
|
||||
_.isArray: nativeIsArray or (obj) -> !!(obj and obj.concat and obj.unshift and not obj.callee)
|
||||
|
||||
|
||||
# Is a given variable an arguments object?
|
||||
_.isArguments: (obj) -> obj and _.isNumber(obj.length) and not obj.concat and
|
||||
not obj.substr and not obj.apply and not propertyIsEnumerable.call(obj, 'length')
|
||||
_.isArguments: (obj) -> obj and obj.callee
|
||||
|
||||
|
||||
# Is the given value a function?
|
||||
@@ -477,6 +508,10 @@
|
||||
_.isNumber: (obj) -> (obj is +obj) or toString.call(obj) is '[object Number]'
|
||||
|
||||
|
||||
# Is a given value a boolean?
|
||||
_.isBoolean: (obj) -> obj is true or obj is false
|
||||
|
||||
|
||||
# Is a given value a Date?
|
||||
_.isDate: (obj) -> !!(obj and obj.getTimezoneOffset and obj.setUTCFullYear)
|
||||
|
||||
@@ -485,8 +520,8 @@
|
||||
_.isRegExp: (obj) -> !!(obj and obj.exec and (obj.ignoreCase or obj.ignoreCase is false))
|
||||
|
||||
|
||||
# Is the given value NaN -- this one is interesting. NaN != NaN, and
|
||||
# isNaN(undefined) == true, so we make sure it's a number first.
|
||||
# Is the given value NaN -- this one is interesting. `NaN != NaN`, and
|
||||
# `isNaN(undefined) == true`, so we make sure it's a number first.
|
||||
_.isNaN: (obj) -> _.isNumber(obj) and window.isNaN(obj)
|
||||
|
||||
|
||||
@@ -498,9 +533,10 @@
|
||||
_.isUndefined: (obj) -> typeof obj is 'undefined'
|
||||
|
||||
|
||||
# -------------------------- Utility Functions: --------------------------
|
||||
# Utility Functions
|
||||
# -----------------
|
||||
|
||||
# Run Underscore.js in noConflict mode, returning the '_' variable to its
|
||||
# Run Underscore.js in noConflict mode, returning the `_` variable to its
|
||||
# previous owner. Returns a reference to the Underscore object.
|
||||
_.noConflict: ->
|
||||
root._: previousUnderscore
|
||||
@@ -511,10 +547,22 @@
|
||||
_.identity: (value) -> value
|
||||
|
||||
|
||||
# Run a function `n` times.
|
||||
_.times: (n, iterator, context) ->
|
||||
iterator.call(context, i) for i in [0...n]
|
||||
|
||||
|
||||
# Break out of the middle of an iteration.
|
||||
_.breakLoop: -> throw breaker
|
||||
|
||||
|
||||
# Add your own custom functions to the Underscore object, ensuring that
|
||||
# they're correctly added to the OOP wrapper as well.
|
||||
_.mixin: (obj) ->
|
||||
for name in _.functions(obj)
|
||||
addToWrapper name, _[name]: obj[name]
|
||||
|
||||
|
||||
# Generate a unique integer id (unique within the entire client session).
|
||||
# Useful for temporary DOM ids.
|
||||
idCounter: 0
|
||||
@@ -522,7 +570,7 @@
|
||||
(prefix or '') + idCounter++
|
||||
|
||||
|
||||
# By default, Underscore uses ERB-style template delimiters, change the
|
||||
# By default, Underscore uses **ERB**-style template delimiters, change the
|
||||
# following template settings to use alternative delimiters.
|
||||
_.templateSettings: {
|
||||
start: '<%'
|
||||
@@ -531,16 +579,17 @@
|
||||
}
|
||||
|
||||
|
||||
# JavaScript templating a-la ERB, pilfered from John Resig's
|
||||
# "Secrets of the JavaScript Ninja", page 83.
|
||||
# Single-quotea fix from Rick Strahl's version.
|
||||
# JavaScript templating a-la **ERB**, pilfered from John Resig's
|
||||
# *Secrets of the JavaScript Ninja*, page 83.
|
||||
# Single-quote fix from Rick Strahl.
|
||||
_.template: (str, data) ->
|
||||
c: _.templateSettings
|
||||
endMatch: new RegExp("'(?=[^"+c.end.substr(0, 1)+"]*"+escapeRegExp(c.end)+")","g")
|
||||
fn: new Function 'obj',
|
||||
'var p=[],print=function(){p.push.apply(p,arguments);};' +
|
||||
'with(obj){p.push(\'' +
|
||||
str.replace(/[\r\t\n]/g, " ")
|
||||
.replace(new RegExp("'(?=[^"+c.end[0]+"]*"+c.end+")","g"),"\t")
|
||||
.replace(endMatch,"\t")
|
||||
.split("'").join("\\'")
|
||||
.split("\t").join("'")
|
||||
.replace(c.interpolate, "',$1,'")
|
||||
@@ -550,32 +599,46 @@
|
||||
if data then fn(data) else fn
|
||||
|
||||
|
||||
# ------------------------------- Aliases ----------------------------------
|
||||
# Aliases
|
||||
# -------
|
||||
|
||||
_.forEach: _.each
|
||||
_.foldl: _.inject: _.reduce
|
||||
_.foldr: _.reduceRight
|
||||
_.filter: _.select
|
||||
_.every: _.all
|
||||
_.some: _.any
|
||||
_.select: _.filter
|
||||
_.all: _.every
|
||||
_.any: _.some
|
||||
_.head: _.first
|
||||
_.tail: _.rest
|
||||
_.methods: _.functions
|
||||
|
||||
|
||||
# /*------------------------ Setup the OOP Wrapper: --------------------------*/
|
||||
# Setup the OOP Wrapper
|
||||
# ---------------------
|
||||
|
||||
# If Underscore is called as a function, it returns a wrapped object that
|
||||
# can be used OO-style. This wrapper holds altered versions of all the
|
||||
# underscore functions. Wrapped objects may be chained.
|
||||
wrapper: (obj) ->
|
||||
this._wrapped: obj
|
||||
this
|
||||
|
||||
|
||||
# Helper function to continue chaining intermediate results.
|
||||
result: (obj, chain) ->
|
||||
if chain then _(obj).chain() else obj
|
||||
|
||||
|
||||
# Add all of the Underscore functions to the wrapper object.
|
||||
_.each _.functions(_), (name) ->
|
||||
method: _[name]
|
||||
# A method to easily add functions to the OOP wrapper.
|
||||
addToWrapper: (name, func) ->
|
||||
wrapper.prototype[name]: ->
|
||||
unshift.call(arguments, this._wrapped)
|
||||
result(method.apply(_, arguments), this._chain)
|
||||
args: _.toArray arguments
|
||||
unshift.call args, this._wrapped
|
||||
result func.apply(_, args), this._chain
|
||||
|
||||
|
||||
# Add all of the Underscore functions to the wrapper object.
|
||||
_.mixin _
|
||||
|
||||
|
||||
# Add all mutator Array functions to the wrapper.
|
||||
|
||||
13
examples/web_server.coffee
Normal file
13
examples/web_server.coffee
Normal file
@@ -0,0 +1,13 @@
|
||||
# Contributed by Jason Huggins
|
||||
|
||||
sys: require 'sys'
|
||||
http: require 'http'
|
||||
|
||||
server: http.createServer (req, res) ->
|
||||
res.writeHeader 200, {'Content-Type': 'text/plain'}
|
||||
res.write 'Hello, World!'
|
||||
res.end()
|
||||
|
||||
server.listen 3000
|
||||
|
||||
sys.puts "Server running at http://localhost:3000/"
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>comments</string>
|
||||
<key>scope</key>
|
||||
<string>source.coffee</string>
|
||||
<key>settings</key>
|
||||
<dict>
|
||||
<key>shellVariables</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>TM_COMMENT_START</string>
|
||||
<key>value</key>
|
||||
<string># </string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<key>uuid</key>
|
||||
<string>0A92C6F6-4D73-4859-B38C-4CC19CBC191F</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,361 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>CoffeeScript Syntax: version 1</string>
|
||||
<key>fileTypes</key>
|
||||
<array>
|
||||
<string>coffee</string>
|
||||
</array>
|
||||
<key>name</key>
|
||||
<string>CoffeeScript</string>
|
||||
<key>foldingStartMarker</key>
|
||||
<string>^.*[:=] \{[^\}]*$</string>
|
||||
<key>foldingStopMarker</key>
|
||||
<string>\s*\}</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>variable.parameter.function.coffee</string>
|
||||
</dict>
|
||||
<key>2</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>variable.parameter.function.coffee</string>
|
||||
</dict>
|
||||
<key>4</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>variable.parameter.function.coffee</string>
|
||||
</dict>
|
||||
<key>5</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>storage.type.function.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>comment</key>
|
||||
<string>match stuff like: a -> … </string>
|
||||
<key>match</key>
|
||||
<string>(\()([a-zA-Z0-9_?.$]*(,\s*[a-zA-Z0-9_?.$]+)*)(\))\s*((=|-)>)</string>
|
||||
<key>name</key>
|
||||
<string>meta.inline.function.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.operator.new.coffee</string>
|
||||
</dict>
|
||||
<key>2</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>entity.name.type.instance.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>match</key>
|
||||
<string>(new)\s+(\w+(?:\.\w*)?)</string>
|
||||
<key>name</key>
|
||||
<string>meta.class.instance.constructor</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?(e[+\-]?[0-9]+)?))\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.numeric.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(@)[a-zA-Z_$]\w*</string>
|
||||
<key>name</key>
|
||||
<string>variable.other.readwrite.instance.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>string.quoted.heredoc.coffee</string>
|
||||
<key>begin</key>
|
||||
<string>("""|''')</string>
|
||||
<key>end</key>
|
||||
<string>("""|''')</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>'</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>'</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>string.quoted.single.coffee</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)</string>
|
||||
<key>name</key>
|
||||
<string>constant.character.escape.coffee</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>"</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>"</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>string.quoted.double.coffee</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)</string>
|
||||
<key>name</key>
|
||||
<string>constant.character.escape.coffee</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>`</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>`</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>string.quoted.script.coffee</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)</string>
|
||||
<key>name</key>
|
||||
<string>constant.character.escape.coffee</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.comment.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>match</key>
|
||||
<string>(#).*$\n?</string>
|
||||
<key>name</key>
|
||||
<string>comment.line.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>(?<=[=(:]|^|return)\s*(/)(?![/*+{}?])</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>(/)[igm]*</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>string.regexp.coffee</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\\.</string>
|
||||
<key>name</key>
|
||||
<string>constant.character.escape.coffee</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(break|by|catch|continue|else|finally|for|in|of|if|return|switch|then|throw|try|unless|when|while)\b</string>
|
||||
<key>name</key>
|
||||
<string>keyword.control.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b([a-zA-Z$_](\w|\$|:|\.)*\s*(?=\:))</string>
|
||||
<key>name</key>
|
||||
<string>variable.assignment.coffee</string>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>entity.name.function.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(true|on|yes)\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.language.boolean.true.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(false|off|no)\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.language.boolean.false.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\bnull\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.language.null.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(super|this|extends)\b</string>
|
||||
<key>name</key>
|
||||
<string>variable.language.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(debugger|\\)\b</string>
|
||||
<key>name</key>
|
||||
<string>keyword.other.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(=|-)></string>
|
||||
<key>name</key>
|
||||
<string>storage.type.function.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>!|%|&|\*|\/|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\?|\|\||\:|\*=|(?<!\()/=|%=|\+=|\-=|&=|\^=|\b(instanceof|new|delete|typeof|and|or|is|isnt|not)\b</string>
|
||||
<key>name</key>
|
||||
<string>keyword.operator.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(Infinity|NaN|undefined)\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.language.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\;</string>
|
||||
<key>name</key>
|
||||
<string>punctuation.terminator.statement.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>,[ |\t]*</string>
|
||||
<key>name</key>
|
||||
<string>meta.delimiter.object.comma.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\.</string>
|
||||
<key>name</key>
|
||||
<string>meta.delimiter.method.period.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\{|\}</string>
|
||||
<key>name</key>
|
||||
<string>meta.brace.curly.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\(|\)</string>
|
||||
<key>name</key>
|
||||
<string>meta.brace.round.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\[|\]</string>
|
||||
<key>name</key>
|
||||
<string>meta.brace.square.coffee</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>scopeName</key>
|
||||
<string>source.coffee</string>
|
||||
<key>uuid</key>
|
||||
<string>5B520980-A7D5-4E10-8582-1A4C889A8DE5</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>CoffeeScript</string>
|
||||
<key>uuid</key>
|
||||
<string>A46E4382-F1AC-405B-8F22-65FF470F34D7</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,20 +1,7 @@
|
||||
This folder includes rough cuts of CoffeeScript syntax highlighters for
|
||||
TextMate and Vim. Improvements to their lexing ability are always welcome.
|
||||
EXTRAS:
|
||||
|
||||
To install the TextMate bundle, run `bin/coffee --install-bundle`, or drop it
|
||||
into "~/Library/Application Support/TextMate/Bundles".
|
||||
"extras/coffee-script.js" is a concatenated and compressed version of the
|
||||
CoffeeScript compiler. To use it in the browser, include the script after any
|
||||
inline script tags of type "text/coffeescript" on the page. It will compile
|
||||
and evaluate all of the scripts in order.
|
||||
|
||||
To install the Vim highlighter, copy "coffee.vim" into the "syntax" directory of
|
||||
your vim72, and enable it in either of the following two ways:
|
||||
|
||||
* Manually, by running `:set syntax=coffee`
|
||||
|
||||
* Or automatically, by creating a "filetype.vim" file within "~/.vim", which
|
||||
contains something along these lines:
|
||||
|
||||
if exists("did_load_filetypes")
|
||||
finish
|
||||
end
|
||||
augroup filetypedetect
|
||||
au! BufRead,BufNewFile *.coffee setfiletype coffee
|
||||
augroup END
|
||||
|
||||
1
extras/coffee-script.js
Normal file
1
extras/coffee-script.js
Normal file
File diff suppressed because one or more lines are too long
@@ -1,111 +0,0 @@
|
||||
" Vim syntax file
|
||||
" Language: CoffeeScript
|
||||
" Maintainer: Jeff Olson <olson.jeffery@gmail.com>
|
||||
" URL: http://github.com/olsonjeffery
|
||||
" Changes: (jro) initial port from javascript
|
||||
" Last Change: 2006 Jun 19
|
||||
" Adaptation of javascript.vim syntax file (distro'd w/ vim72),
|
||||
" maintained by Claudio Fleiner <claudio@fleiner.com>
|
||||
" with updates from Scott Shattuck (ss) <ss@technicalpursuit.com>
|
||||
|
||||
if !exists("main_syntax")
|
||||
if version < 600
|
||||
syntax clear
|
||||
elseif exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
let main_syntax = 'coffee'
|
||||
endif
|
||||
|
||||
syn case ignore
|
||||
|
||||
syn match coffeeLineComment "#.*" contains=@Spell,CoffeeCommentTodo
|
||||
syn match coffeeSpecial "\\\d\d\d\|\\."
|
||||
syn region coffeeStringD start=+"+ skip=+\\\\\|\\"+ end=+"\|$+ contains=coffeeSpecial,@htmlPreproc
|
||||
syn region coffeeStringS start=+'+ skip=+\\\\\|\\'+ end=+'\|$+ contains=coffeeSpecial,@htmlPreproc
|
||||
|
||||
syn match coffeeSpecialCharacter "'\\.'"
|
||||
syn match coffeeNumber "-\=\<\d\+L\=\>\|0[xX][0-9a-fA-F]\+\>"
|
||||
syn region coffeeRegexpString start=+/[^/*]+me=e-1 skip=+\\\\\|\\/+ end=+/[gi]\{0,2\}\s*$+ end=+/[gi]\{0,2\}\s*[;.,)\]}]+me=e-1 contains=@htmlPreproc oneline
|
||||
|
||||
syn match coffeePrototypeAccess "::"
|
||||
syn match coffeeFunction "->"
|
||||
|
||||
syn keyword coffeeExtends extends
|
||||
syn keyword coffeeConditional if else switch then
|
||||
syn keyword coffeeRepeat while for in of
|
||||
syn keyword coffeeBranch break continue
|
||||
syn keyword coffeeOperator delete instanceof typeof
|
||||
syn keyword coffeeType Array Boolean Date Function Number Object String RegExp
|
||||
syn keyword coffeeStatement return with
|
||||
syn keyword coffeeBoolean true false
|
||||
syn keyword coffeeNull null undefined
|
||||
syn keyword coffeeIdentifier arguments this var
|
||||
syn keyword coffeeLabel case default
|
||||
syn keyword coffeeException try catch finally throw
|
||||
syn keyword coffeeMessage alert confirm prompt status
|
||||
syn keyword coffeeGlobal self window top parent
|
||||
syn keyword coffeeMember document event location
|
||||
syn keyword coffeeDeprecated escape unescape
|
||||
syn keyword coffeeReserved abstract boolean byte char class const debugger double enum export final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile
|
||||
|
||||
syn sync fromstart
|
||||
syn sync maxlines=100
|
||||
|
||||
if main_syntax == "coffee"
|
||||
syn sync ccomment coffeeComment
|
||||
endif
|
||||
|
||||
" Define the default highlighting.
|
||||
" For version 5.7 and earlier: only when not done already
|
||||
" For version 5.8 and later: only when an item doesn't have highlighting yet
|
||||
if version >= 508 || !exists("did_coffee_syn_inits")
|
||||
if version < 508
|
||||
let did_coffee_syn_inits = 1
|
||||
command -nargs=+ HiLink hi link <args>
|
||||
else
|
||||
command -nargs=+ HiLink hi def link <args>
|
||||
endif
|
||||
HiLink coffeePrototypeAccess Keyword
|
||||
HiLink coffeeExtends Keyword
|
||||
HiLink coffeeLineComment Comment
|
||||
HiLink coffeeSpecial Special
|
||||
HiLink coffeeStringS String
|
||||
HiLink coffeeStringD String
|
||||
HiLink coffeeCharacter Character
|
||||
HiLink coffeeSpecialCharacter coffeeSpecial
|
||||
HiLink coffeeNumber coffeeValue
|
||||
HiLink coffeeConditional Conditional
|
||||
HiLink coffeeRepeat Repeat
|
||||
HiLink coffeeBranch Conditional
|
||||
HiLink coffeeOperator Operator
|
||||
HiLink coffeeType Type
|
||||
HiLink coffeeStatement Statement
|
||||
HiLink coffeeFunction Function
|
||||
HiLink coffeeBraces Function
|
||||
HiLink coffeeError Error
|
||||
HiLink coffeeScrParenError coffeeError
|
||||
HiLink coffeeNull Keyword
|
||||
HiLink coffeeBoolean Boolean
|
||||
HiLink coffeeRegexpString String
|
||||
|
||||
HiLink coffeeIdentifier Identifier
|
||||
HiLink coffeeLabel Label
|
||||
HiLink coffeeException Exception
|
||||
HiLink coffeeMessage Keyword
|
||||
HiLink coffeeGlobal Keyword
|
||||
HiLink coffeeMember Keyword
|
||||
HiLink coffeeDeprecated Exception
|
||||
HiLink coffeeReserved Keyword
|
||||
HiLink coffeeDebug Debug
|
||||
HiLink coffeeConstant Label
|
||||
|
||||
delcommand HiLink
|
||||
endif
|
||||
|
||||
let b:current_syntax = "coffee"
|
||||
if main_syntax == 'coffee'
|
||||
unlet main_syntax
|
||||
endif
|
||||
|
||||
" vim: ts=8
|
||||
1454
index.html
1454
index.html
File diff suppressed because it is too large
Load Diff
106
lib/cake.js
Executable file
106
lib/cake.js
Executable file
@@ -0,0 +1,106 @@
|
||||
(function(){
|
||||
var CoffeeScript, fs, helpers, no_such_task, oparse, options, optparse, path, print_tasks, switches, tasks;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
// `cake` is a simplified version of [Make](http://www.gnu.org/software/make/)
|
||||
// ([Rake](http://rake.rubyforge.org/), [Jake](http://github.com/280north/jake))
|
||||
// for CoffeeScript. You define tasks with names and descriptions in a Cakefile,
|
||||
// and can call them from the command line, or invoke them from other tasks.
|
||||
// Running `cake` with no arguments will print out a list of all the tasks in the
|
||||
// current directory's Cakefile.
|
||||
// External dependencies.
|
||||
fs = require('fs');
|
||||
path = require('path');
|
||||
helpers = require('./helpers').helpers;
|
||||
optparse = require('./optparse');
|
||||
CoffeeScript = require('./coffee-script');
|
||||
// Keep track of the list of defined tasks, the accepted options, and so on.
|
||||
tasks = {};
|
||||
options = {};
|
||||
switches = [];
|
||||
oparse = null;
|
||||
// Mixin the top-level Cake functions for Cakefiles to use directly.
|
||||
helpers.extend(global, {
|
||||
// Define a Cake task with a short name, an optional sentence description,
|
||||
// and the function to run as the action itself.
|
||||
task: function(name, description, action) {
|
||||
var _a;
|
||||
if (!(action)) {
|
||||
_a = [description, action];
|
||||
action = _a[0];
|
||||
description = _a[1];
|
||||
}
|
||||
tasks[name] = {
|
||||
name: name,
|
||||
description: description,
|
||||
action: action
|
||||
};
|
||||
return tasks[name];
|
||||
},
|
||||
// Define an option that the Cakefile accepts. The parsed options hash,
|
||||
// containing all of the command-line options passed, will be made available
|
||||
// as the first argument to the action.
|
||||
option: function(letter, flag, description) {
|
||||
return switches.push([letter, flag, description]);
|
||||
},
|
||||
// Invoke another task in the current Cakefile.
|
||||
invoke: function(name) {
|
||||
if (!(tasks[name])) {
|
||||
no_such_task(name);
|
||||
}
|
||||
return tasks[name].action(options);
|
||||
}
|
||||
});
|
||||
// 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.
|
||||
exports.run = function() {
|
||||
return path.exists('Cakefile', function(exists) {
|
||||
var _a, _b, _c, _d, arg, args;
|
||||
if (!(exists)) {
|
||||
throw new Error(("Cakefile not found in " + (process.cwd())));
|
||||
}
|
||||
args = process.argv.slice(2, process.argv.length);
|
||||
CoffeeScript.run(fs.readFileSync('Cakefile').toString(), {
|
||||
source: 'Cakefile'
|
||||
});
|
||||
oparse = new optparse.OptionParser(switches);
|
||||
if (!(args.length)) {
|
||||
return print_tasks();
|
||||
}
|
||||
options = oparse.parse(args);
|
||||
_a = []; _c = options.arguments;
|
||||
for (_b = 0, _d = _c.length; _b < _d; _b++) {
|
||||
arg = _c[_b];
|
||||
_a.push(invoke(arg));
|
||||
}
|
||||
return _a;
|
||||
});
|
||||
};
|
||||
// Display the list of Cake tasks in a format similar to `rake -T`
|
||||
print_tasks = function() {
|
||||
var _a, _b, _c, _d, desc, i, name, spaces, task;
|
||||
puts('');
|
||||
_a = tasks;
|
||||
for (name in _a) { if (__hasProp.call(_a, name)) {
|
||||
task = _a[name];
|
||||
spaces = 20 - name.length;
|
||||
spaces = spaces > 0 ? (function() {
|
||||
_b = []; _c = 0; _d = spaces;
|
||||
for (i = _c; (_c <= _d ? i <= _d : i >= _d); (_c <= _d ? i += 1 : i -= 1)) {
|
||||
_b.push(' ');
|
||||
}
|
||||
return _b;
|
||||
})().join('') : '';
|
||||
desc = task.description ? ("# " + task.description) : '';
|
||||
puts(("cake " + name + spaces + " " + desc));
|
||||
}}
|
||||
if (switches.length) {
|
||||
return puts(oparse.help());
|
||||
}
|
||||
};
|
||||
// Print an error and exit when attempting to all an undefined task.
|
||||
no_such_task = function(task) {
|
||||
puts(("No such task: \"" + task + "\""));
|
||||
return process.exit(1);
|
||||
};
|
||||
})();
|
||||
111
lib/coffee-script.js
Normal file
111
lib/coffee-script.js
Normal file
@@ -0,0 +1,111 @@
|
||||
(function(){
|
||||
var Lexer, compile, helpers, lexer, parser, path, process_scripts;
|
||||
// CoffeeScript can be used both on the server, as a command-line compiler based
|
||||
// on Node.js/V8, or to run CoffeeScripts directly in the browser. This module
|
||||
// contains the main entry functions for tokenzing, parsing, and compiling source
|
||||
// CoffeeScript into JavaScript.
|
||||
// If included on a webpage, it will automatically sniff out, compile, and
|
||||
// execute all scripts present in `text/coffeescript` tags.
|
||||
// Set up dependencies correctly for both the server and the browser.
|
||||
if ((typeof process !== "undefined" && process !== null)) {
|
||||
path = require('path');
|
||||
Lexer = require('./lexer').Lexer;
|
||||
parser = require('./parser').parser;
|
||||
helpers = require('./helpers').helpers;
|
||||
helpers.extend(global, require('./nodes'));
|
||||
require.registerExtension ? require.registerExtension('.coffee', function(content) {
|
||||
return compile(content);
|
||||
}) : null;
|
||||
} else {
|
||||
this.exports = (this.CoffeeScript = {});
|
||||
Lexer = this.Lexer;
|
||||
parser = this.parser;
|
||||
helpers = this.helpers;
|
||||
}
|
||||
// The current CoffeeScript version number.
|
||||
exports.VERSION = '0.6.2';
|
||||
// Instantiate a Lexer for our use here.
|
||||
lexer = new Lexer();
|
||||
// Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
|
||||
// compiler.
|
||||
exports.compile = (compile = function(code, options) {
|
||||
options = options || {};
|
||||
try {
|
||||
return (parser.parse(lexer.tokenize(code))).compile(options);
|
||||
} catch (err) {
|
||||
if (options.source) {
|
||||
err.message = ("In " + options.source + ", " + err.message);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
// Tokenize a string of CoffeeScript code, and return the array of tokens.
|
||||
exports.tokens = function(code) {
|
||||
return lexer.tokenize(code);
|
||||
};
|
||||
// Tokenize and parse a string of CoffeeScript code, and return the AST. You can
|
||||
// then compile it by calling `.compile()` on the root, or traverse it by using
|
||||
// `.traverse()` with a callback.
|
||||
exports.nodes = function(code) {
|
||||
return parser.parse(lexer.tokenize(code));
|
||||
};
|
||||
// Compile and execute a string of CoffeeScript (on the server), correctly
|
||||
// setting `__filename`, `__dirname`, and relative `require()`.
|
||||
exports.run = (function(code, options) {
|
||||
var __dirname, __filename;
|
||||
module.filename = (__filename = options.source);
|
||||
__dirname = path.dirname(__filename);
|
||||
return eval(exports.compile(code, options));
|
||||
});
|
||||
// Extend CoffeeScript with a custom language extension. It should hook in to
|
||||
// the **Lexer** (as a peer of any of the lexer's tokenizing methods), and
|
||||
// push a token on to the stack that contains a **Node** as the value (as a
|
||||
// peer of the nodes in [nodes.coffee](nodes.html)).
|
||||
exports.extend = function(func) {
|
||||
return Lexer.extensions.push(func);
|
||||
};
|
||||
// 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".
|
||||
parser.lexer = {
|
||||
lex: function() {
|
||||
var token;
|
||||
token = this.tokens[this.pos] || [""];
|
||||
this.pos += 1;
|
||||
this.yylineno = token[2];
|
||||
this.yytext = token[1];
|
||||
return token[0];
|
||||
},
|
||||
setInput: function(tokens) {
|
||||
this.tokens = tokens;
|
||||
this.pos = 0;
|
||||
return this.pos;
|
||||
},
|
||||
upcomingInput: function() {
|
||||
return "";
|
||||
},
|
||||
showPosition: function() {
|
||||
return this.pos;
|
||||
}
|
||||
};
|
||||
// Activate CoffeeScript in the browser by having it compile and evaluate
|
||||
// all script tags with a content-type of `text/coffeescript`. This happens
|
||||
// on page load. Unfortunately, the text contents of remote scripts cannot be
|
||||
// accessed from the browser, so only inline script tags will work.
|
||||
if ((typeof document !== "undefined" && document !== null) && document.getElementsByTagName) {
|
||||
process_scripts = function() {
|
||||
var _a, _b, _c, _d, tag;
|
||||
_a = []; _c = document.getElementsByTagName('script');
|
||||
for (_b = 0, _d = _c.length; _b < _d; _b++) {
|
||||
tag = _c[_b];
|
||||
tag.type === 'text/coffeescript' ? _a.push(eval(exports.compile(tag.innerHTML))) : null;
|
||||
}
|
||||
return _a;
|
||||
};
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener('load', process_scripts, false);
|
||||
} else if (window.attachEvent) {
|
||||
window.attachEvent('onload', process_scripts);
|
||||
}
|
||||
}
|
||||
})();
|
||||
@@ -1,21 +0,0 @@
|
||||
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
||||
require "coffee_script/lexer"
|
||||
require "coffee_script/parser"
|
||||
require "coffee_script/nodes"
|
||||
require "coffee_script/value"
|
||||
require "coffee_script/scope"
|
||||
require "coffee_script/rewriter"
|
||||
require "coffee_script/parse_error"
|
||||
|
||||
# Namespace for all CoffeeScript internal classes.
|
||||
module CoffeeScript
|
||||
|
||||
VERSION = '0.3.2' # Keep in sync with the gemspec.
|
||||
|
||||
# Compile a script (String or IO) to JavaScript.
|
||||
def self.compile(script, options={})
|
||||
script = script.read if script.respond_to?(:read)
|
||||
Parser.new.parse(script).compile(options)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,50 +0,0 @@
|
||||
(function(){
|
||||
var compiler, path;
|
||||
// Executes the `coffee` Ruby program to convert from CoffeeScript to JavaScript.
|
||||
path = require('path');
|
||||
// The path to the CoffeeScript executable.
|
||||
compiler = path.normalize(path.dirname(__filename) + '/../../bin/coffee');
|
||||
// Compile a string over stdin, with global variables, for the REPL.
|
||||
exports.compile = function compile(code, callback) {
|
||||
var coffee, js;
|
||||
js = '';
|
||||
coffee = process.createChildProcess(compiler, ['--eval', '--no-wrap', '--globals']);
|
||||
coffee.addListener('output', function(results) {
|
||||
if ((typeof results !== "undefined" && results !== null)) {
|
||||
return js += results;
|
||||
}
|
||||
});
|
||||
coffee.addListener('exit', function() {
|
||||
return callback(js);
|
||||
});
|
||||
coffee.write(code);
|
||||
return coffee.close();
|
||||
};
|
||||
// Compile a list of CoffeeScript files on disk.
|
||||
exports.compile_files = function compile_files(paths, callback) {
|
||||
var coffee, exit_ran, js;
|
||||
js = '';
|
||||
coffee = process.createChildProcess(compiler, ['--print'].concat(paths));
|
||||
coffee.addListener('output', function(results) {
|
||||
if ((typeof results !== "undefined" && results !== null)) {
|
||||
return js += results;
|
||||
}
|
||||
});
|
||||
// NB: we have to add a mutex to make sure it doesn't get called twice.
|
||||
exit_ran = false;
|
||||
coffee.addListener('exit', function() {
|
||||
if (exit_ran) {
|
||||
return null;
|
||||
}
|
||||
exit_ran = true;
|
||||
return callback(js);
|
||||
});
|
||||
return coffee.addListener('error', function(message) {
|
||||
if (!(message)) {
|
||||
return null;
|
||||
}
|
||||
puts(message);
|
||||
throw new Error("CoffeeScript compile error");
|
||||
});
|
||||
};
|
||||
})();
|
||||
@@ -1,235 +0,0 @@
|
||||
require 'optparse'
|
||||
require 'fileutils'
|
||||
require 'open3'
|
||||
begin
|
||||
require File.expand_path(File.dirname(__FILE__) + '/../coffee-script')
|
||||
rescue LoadError => e
|
||||
puts(e.message)
|
||||
puts("use \"rake build:parser\" to regenerate parser.rb")
|
||||
exit(1)
|
||||
end
|
||||
|
||||
module CoffeeScript
|
||||
|
||||
# The CommandLine handles all of the functionality of the `coffee`
|
||||
# utility.
|
||||
class CommandLine
|
||||
|
||||
BANNER = <<-EOS
|
||||
coffee compiles CoffeeScript source files into JavaScript.
|
||||
|
||||
Usage:
|
||||
coffee path/to/script.coffee
|
||||
EOS
|
||||
|
||||
# Seconds to pause between checks for changed source files.
|
||||
WATCH_INTERVAL = 0.5
|
||||
|
||||
# Path to the root of the CoffeeScript install.
|
||||
ROOT = File.expand_path(File.dirname(__FILE__) + '/../..')
|
||||
|
||||
# Commands to execute CoffeeScripts.
|
||||
RUNNERS = {
|
||||
:node => "node #{ROOT}/lib/coffee_script/runner.js",
|
||||
:narwhal => "narwhal -p #{ROOT} -e 'require(\"coffee-script\").run(system.args);'"
|
||||
}
|
||||
|
||||
# Run the CommandLine off the contents of ARGV.
|
||||
def initialize
|
||||
@mtimes = {}
|
||||
parse_options
|
||||
return launch_repl if @options[:interactive]
|
||||
return eval_scriptlet if @options[:eval]
|
||||
check_sources
|
||||
return run_scripts if @options[:run]
|
||||
@sources.each {|source| compile_javascript(source) }
|
||||
watch_coffee_scripts if @options[:watch]
|
||||
end
|
||||
|
||||
# The "--help" usage message.
|
||||
def usage
|
||||
puts "\n#{@option_parser}\n"
|
||||
exit
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
# Compiles (or partially compiles) the source CoffeeScript file, returning
|
||||
# the desired JS, tokens, or lint results.
|
||||
def compile_javascript(source)
|
||||
script = File.read(source)
|
||||
return tokens(script) if @options[:tokens]
|
||||
js = compile(script, source)
|
||||
return unless js
|
||||
return puts(js) if @options[:print]
|
||||
return lint(js) if @options[:lint]
|
||||
File.open(path_for(source), 'w+') {|f| f.write(js) }
|
||||
end
|
||||
|
||||
# Spins up a watcher thread to keep track of the modification times of the
|
||||
# source files, recompiling them whenever they're saved.
|
||||
def watch_coffee_scripts
|
||||
watch_thread = Thread.start do
|
||||
loop do
|
||||
@sources.each do |source|
|
||||
mtime = File.stat(source).mtime
|
||||
@mtimes[source] ||= mtime
|
||||
if mtime > @mtimes[source]
|
||||
@mtimes[source] = mtime
|
||||
compile_javascript(source)
|
||||
end
|
||||
end
|
||||
sleep WATCH_INTERVAL
|
||||
end
|
||||
end
|
||||
Signal.trap("INT") { watch_thread.kill }
|
||||
watch_thread.join
|
||||
end
|
||||
|
||||
# Ensure that all of the source files exist.
|
||||
def check_sources
|
||||
usage if @sources.empty?
|
||||
missing = @sources.detect {|s| !File.exists?(s) }
|
||||
if missing
|
||||
STDERR.puts("File not found: '#{missing}'")
|
||||
exit(1)
|
||||
end
|
||||
end
|
||||
|
||||
# Pipe compiled JS through JSLint (requires a working 'jsl' command).
|
||||
def lint(js)
|
||||
stdin, stdout, stderr = Open3.popen3('jsl -nologo -stdin')
|
||||
stdin.write(js)
|
||||
stdin.close
|
||||
puts stdout.read.tr("\n", '')
|
||||
errs = stderr.read.chomp
|
||||
puts errs unless errs.empty?
|
||||
stdout.close and stderr.close
|
||||
end
|
||||
|
||||
# Eval a little piece of CoffeeScript directly from the command line.
|
||||
def eval_scriptlet
|
||||
script = STDIN.tty? ? @sources.join(' ') : STDIN.read
|
||||
return tokens(script) if @options[:tokens]
|
||||
js = compile(script)
|
||||
return lint(js) if @options[:lint]
|
||||
puts js
|
||||
end
|
||||
|
||||
# Use Node.js or Narwhal to run an interactive CoffeeScript session.
|
||||
def launch_repl
|
||||
exec "#{RUNNERS[@options[:runner]]}"
|
||||
rescue Errno::ENOENT
|
||||
puts "Error: #{@options[:runner]} must be installed to use the interactive REPL."
|
||||
exit(1)
|
||||
end
|
||||
|
||||
# Use Node.js or Narwhal to compile and execute CoffeeScripts.
|
||||
def run_scripts
|
||||
sources = @sources.join(' ')
|
||||
exec "#{RUNNERS[@options[:runner]]} #{sources}"
|
||||
rescue Errno::ENOENT
|
||||
puts "Error: #{@options[:runner]} must be installed in order to execute scripts."
|
||||
exit(1)
|
||||
end
|
||||
|
||||
# Print the tokens that the lexer generates from a source script.
|
||||
def tokens(script)
|
||||
puts Lexer.new.tokenize(script).inspect
|
||||
end
|
||||
|
||||
# Compile a single source file to JavaScript.
|
||||
def compile(script, source='error')
|
||||
begin
|
||||
options = {}
|
||||
options[:no_wrap] = true if @options[:no_wrap]
|
||||
options[:globals] = true if @options[:globals]
|
||||
CoffeeScript.compile(script, options)
|
||||
rescue CoffeeScript::ParseError => e
|
||||
STDERR.puts "#{source}: #{e.message}"
|
||||
exit(1) unless @options[:watch]
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Write out JavaScript alongside CoffeeScript unless an output directory
|
||||
# is specified.
|
||||
def path_for(source)
|
||||
filename = File.basename(source, File.extname(source)) + '.js'
|
||||
dir = @options[:output] || File.dirname(source)
|
||||
File.join(dir, filename)
|
||||
end
|
||||
|
||||
# Install the CoffeeScript TextMate bundle to ~/Library.
|
||||
def install_bundle
|
||||
bundle_dir = File.expand_path('~/Library/Application Support/TextMate/Bundles/')
|
||||
FileUtils.cp_r("#{ROOT}/extras/CoffeeScript.tmbundle", bundle_dir)
|
||||
end
|
||||
|
||||
# Use OptionParser for all the options.
|
||||
def parse_options
|
||||
@options = {:runner => :node}
|
||||
@option_parser = OptionParser.new do |opts|
|
||||
opts.on('-i', '--interactive', 'run an interactive CoffeeScript REPL') do |i|
|
||||
@options[:interactive] = true
|
||||
end
|
||||
opts.on('-r', '--run', 'compile and run a CoffeeScript') do |r|
|
||||
@options[:run] = true
|
||||
end
|
||||
opts.on('-o', '--output [DIR]', 'set the directory for compiled JavaScript') do |d|
|
||||
@options[:output] = d
|
||||
FileUtils.mkdir_p(d) unless File.exists?(d)
|
||||
end
|
||||
opts.on('-w', '--watch', 'watch scripts for changes, and recompile') do |w|
|
||||
@options[:watch] = true
|
||||
end
|
||||
opts.on('-p', '--print', 'print the compiled JavaScript to stdout') do |d|
|
||||
@options[:print] = true
|
||||
end
|
||||
opts.on('-l', '--lint', 'pipe the compiled JavaScript through JSLint') do |l|
|
||||
@options[:lint] = true
|
||||
end
|
||||
opts.on('-e', '--eval', 'compile a cli scriptlet or read from stdin') do |e|
|
||||
@options[:eval] = true
|
||||
end
|
||||
opts.on('-t', '--tokens', 'print the tokens that the lexer produces') do |t|
|
||||
@options[:tokens] = true
|
||||
end
|
||||
opts.on('-v', '--verbose', 'print at every step of code generation') do |v|
|
||||
ENV['VERBOSE'] = 'true'
|
||||
end
|
||||
opts.on('-n', '--no-wrap', 'raw output, no function safety wrapper') do |n|
|
||||
@options[:no_wrap] = true
|
||||
end
|
||||
opts.on('-g', '--globals', 'attach all top-level variable as globals') do |n|
|
||||
@options[:globals] = true
|
||||
end
|
||||
opts.on_tail('--narwhal', 'use Narwhal instead of Node.js') do |n|
|
||||
@options[:runner] = :narwhal
|
||||
end
|
||||
opts.on_tail('--install-bundle', 'install the CoffeeScript TextMate bundle') do |i|
|
||||
install_bundle
|
||||
exit
|
||||
end
|
||||
opts.on_tail('--version', 'display CoffeeScript version') do
|
||||
puts "CoffeeScript version #{CoffeeScript::VERSION}"
|
||||
exit
|
||||
end
|
||||
opts.on_tail('-h', '--help', 'display this help message') do
|
||||
usage
|
||||
end
|
||||
end
|
||||
@option_parser.banner = BANNER
|
||||
begin
|
||||
@option_parser.parse!(ARGV)
|
||||
rescue OptionParser::InvalidOption => e
|
||||
puts e.message
|
||||
exit(1)
|
||||
end
|
||||
@sources = ARGV
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,481 +0,0 @@
|
||||
class Parser
|
||||
|
||||
# Declare terminal tokens produced by the lexer.
|
||||
token IF ELSE UNLESS
|
||||
token NUMBER STRING REGEX
|
||||
token TRUE FALSE YES NO ON OFF
|
||||
token IDENTIFIER PROPERTY_ACCESS PROTOTYPE_ACCESS SOAK_ACCESS
|
||||
token CODE PARAM_START PARAM PARAM_END NEW RETURN
|
||||
token CALL_START CALL_END INDEX_START INDEX_END
|
||||
token TRY CATCH FINALLY THROW
|
||||
token BREAK CONTINUE
|
||||
token FOR IN OF BY WHEN WHILE
|
||||
token SWITCH LEADING_WHEN
|
||||
token DELETE INSTANCEOF TYPEOF
|
||||
token SUPER EXTENDS
|
||||
token ASSIGN RETURN
|
||||
token NEWLINE
|
||||
token COMMENT
|
||||
token JS
|
||||
token INDENT OUTDENT
|
||||
|
||||
# Declare order of operations.
|
||||
prechigh
|
||||
nonassoc UMINUS UPLUS NOT '!' '!!' '~' '++' '--'
|
||||
left '*' '/' '%' '?' '.'
|
||||
left '+' '-'
|
||||
left '<<' '>>' '>>>' '&' '|' '^'
|
||||
left '<=' '<' '>' '>='
|
||||
right '==' '!=' IS ISNT
|
||||
left '&&' '||' AND OR
|
||||
right '-=' '+=' '/=' '*=' '%=' '||=' '&&=' '?='
|
||||
right DELETE INSTANCEOF TYPEOF
|
||||
right INDENT
|
||||
left OUTDENT
|
||||
right WHEN LEADING_WHEN IN OF BY
|
||||
right THROW FOR NEW SUPER
|
||||
left EXTENDS
|
||||
right ASSIGN RETURN
|
||||
right '->' '=>' UNLESS IF ELSE WHILE
|
||||
preclow
|
||||
|
||||
rule
|
||||
|
||||
# All parsing will end in this rule, being the trunk of the AST.
|
||||
Root:
|
||||
/* nothing */ { result = Expressions.new }
|
||||
| Terminator { result = Expressions.new }
|
||||
| Expressions { result = val[0] }
|
||||
| Block Terminator { result = val[0] }
|
||||
;
|
||||
|
||||
# Any list of expressions or method body, seperated by line breaks or semis.
|
||||
Expressions:
|
||||
Expression { result = Expressions.wrap(val) }
|
||||
| Expressions Terminator Expression { result = val[0] << val[2] }
|
||||
| Expressions Terminator { result = val[0] }
|
||||
;
|
||||
|
||||
# All types of expressions in our language. The basic unit of CoffeeScript
|
||||
# is the expression.
|
||||
Expression:
|
||||
Value
|
||||
| Call
|
||||
| Code
|
||||
| Operation
|
||||
| Assign
|
||||
| If
|
||||
| Try
|
||||
| Throw
|
||||
| Return
|
||||
| While
|
||||
| For
|
||||
| Switch
|
||||
| Extends
|
||||
| Splat
|
||||
| Existence
|
||||
| Comment
|
||||
;
|
||||
|
||||
# A block of expressions. Note that the Rewriter will convert some postfix
|
||||
# forms into blocks for us, by altering the token stream.
|
||||
Block:
|
||||
INDENT Expressions OUTDENT { result = val[1] }
|
||||
| INDENT OUTDENT { result = Expressions.new }
|
||||
;
|
||||
|
||||
# Tokens that can terminate an expression.
|
||||
Terminator:
|
||||
"\n"
|
||||
| ";"
|
||||
;
|
||||
|
||||
# All hard-coded values. These can be printed straight to JavaScript.
|
||||
Literal:
|
||||
NUMBER { result = LiteralNode.new(val[0]) }
|
||||
| STRING { result = LiteralNode.new(val[0]) }
|
||||
| JS { result = LiteralNode.new(val[0]) }
|
||||
| REGEX { result = LiteralNode.new(val[0]) }
|
||||
| BREAK { result = LiteralNode.new(val[0]) }
|
||||
| CONTINUE { result = LiteralNode.new(val[0]) }
|
||||
| TRUE { result = LiteralNode.new(Value.new(true)) }
|
||||
| FALSE { result = LiteralNode.new(Value.new(false)) }
|
||||
| YES { result = LiteralNode.new(Value.new(true)) }
|
||||
| NO { result = LiteralNode.new(Value.new(false)) }
|
||||
| ON { result = LiteralNode.new(Value.new(true)) }
|
||||
| OFF { result = LiteralNode.new(Value.new(false)) }
|
||||
;
|
||||
|
||||
# Assignment to a variable (or index).
|
||||
Assign:
|
||||
Value ASSIGN Expression { result = AssignNode.new(val[0], val[2]) }
|
||||
;
|
||||
|
||||
# Assignment within an object literal (can be quoted).
|
||||
AssignObj:
|
||||
IDENTIFIER ASSIGN Expression { result = AssignNode.new(ValueNode.new(val[0]), val[2], :object) }
|
||||
| STRING ASSIGN Expression { result = AssignNode.new(ValueNode.new(LiteralNode.new(val[0])), val[2], :object) }
|
||||
| Comment { result = val[0] }
|
||||
;
|
||||
|
||||
# A return statement.
|
||||
Return:
|
||||
RETURN Expression { result = ReturnNode.new(val[1]) }
|
||||
| RETURN { result = ReturnNode.new(ValueNode.new(Value.new('null'))) }
|
||||
;
|
||||
|
||||
# A comment.
|
||||
Comment:
|
||||
COMMENT { result = CommentNode.new(val[0]) }
|
||||
;
|
||||
|
||||
# Arithmetic and logical operators
|
||||
# For Ruby's Operator precedence, see:
|
||||
# https://www.cs.auckland.ac.nz/references/ruby/ProgrammingRuby/language.html
|
||||
Operation:
|
||||
'!' Expression { result = OpNode.new(val[0], val[1]) }
|
||||
| '!!' Expression { result = OpNode.new(val[0], val[1]) }
|
||||
| '-' Expression = UMINUS { result = OpNode.new(val[0], val[1]) }
|
||||
| '+' Expression = UPLUS { result = OpNode.new(val[0], val[1]) }
|
||||
| NOT Expression { result = OpNode.new(val[0], val[1]) }
|
||||
| '~' Expression { result = OpNode.new(val[0], val[1]) }
|
||||
| '--' Expression { result = OpNode.new(val[0], val[1]) }
|
||||
| '++' Expression { result = OpNode.new(val[0], val[1]) }
|
||||
| DELETE Expression { result = OpNode.new(val[0], val[1]) }
|
||||
| TYPEOF Expression { result = OpNode.new(val[0], val[1]) }
|
||||
| Expression '--' { result = OpNode.new(val[1], val[0], nil, true) }
|
||||
| Expression '++' { result = OpNode.new(val[1], val[0], nil, true) }
|
||||
|
||||
| Expression '*' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression '/' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression '%' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
|
||||
| Expression '+' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression '-' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
|
||||
| Expression '<<' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression '>>' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression '>>>' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
|
||||
| Expression '&' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression '|' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression '^' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
|
||||
| Expression '<=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression '<' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression '>' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression '>=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
|
||||
| Expression '==' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression '!=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression IS Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression ISNT Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
|
||||
| Expression '&&' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression '||' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression AND Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression OR Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression '?' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
|
||||
| Expression '-=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression '+=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression '/=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression '*=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression '%=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression '||=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression '&&=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression '?=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
|
||||
| Expression INSTANCEOF Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
| Expression IN Expression { result = OpNode.new(val[1], val[0], val[2]) }
|
||||
;
|
||||
|
||||
# The existence operator.
|
||||
Existence:
|
||||
Expression '?' { result = ExistenceNode.new(val[0]) }
|
||||
;
|
||||
|
||||
# Function definition.
|
||||
Code:
|
||||
PARAM_START ParamList PARAM_END
|
||||
FuncGlyph Block { result = CodeNode.new(val[1], val[4], val[3]) }
|
||||
| FuncGlyph Block { result = CodeNode.new([], val[1], val[0]) }
|
||||
;
|
||||
|
||||
# The symbols to signify functions, and bound functions.
|
||||
FuncGlyph:
|
||||
'->' { result = :func }
|
||||
| '=>' { result = :boundfunc }
|
||||
;
|
||||
|
||||
# The parameters to a function definition.
|
||||
ParamList:
|
||||
Param { result = val }
|
||||
| ParamList "," Param { result = val[0] << val[2] }
|
||||
;
|
||||
|
||||
# A Parameter (or ParamSplat) in a function definition.
|
||||
Param:
|
||||
PARAM
|
||||
| PARAM "." "." "." { result = SplatNode.new(val[0]) }
|
||||
;
|
||||
|
||||
# A regular splat.
|
||||
Splat:
|
||||
Expression "." "." "." { result = SplatNode.new(val[0]) }
|
||||
;
|
||||
|
||||
# Expressions that can be treated as values.
|
||||
Value:
|
||||
IDENTIFIER { result = ValueNode.new(val[0]) }
|
||||
| Literal { result = ValueNode.new(val[0]) }
|
||||
| Array { result = ValueNode.new(val[0]) }
|
||||
| Object { result = ValueNode.new(val[0]) }
|
||||
| Parenthetical { result = ValueNode.new(val[0]) }
|
||||
| Range { result = ValueNode.new(val[0]) }
|
||||
| This { result = ValueNode.new(val[0]) }
|
||||
| Value Accessor { result = val[0] << val[1] }
|
||||
| Invocation Accessor { result = ValueNode.new(val[0], [val[1]]) }
|
||||
;
|
||||
|
||||
# Accessing into an object or array, through dot or index notation.
|
||||
Accessor:
|
||||
PROPERTY_ACCESS IDENTIFIER { result = AccessorNode.new(val[1]) }
|
||||
| PROTOTYPE_ACCESS IDENTIFIER { result = AccessorNode.new(val[1], :prototype) }
|
||||
| SOAK_ACCESS IDENTIFIER { result = AccessorNode.new(val[1], :soak) }
|
||||
| Index { result = val[0] }
|
||||
| Slice { result = SliceNode.new(val[0]) }
|
||||
;
|
||||
|
||||
# Indexing into an object or array.
|
||||
Index:
|
||||
INDEX_START Expression INDEX_END { result = IndexNode.new(val[1]) }
|
||||
;
|
||||
|
||||
# An object literal.
|
||||
Object:
|
||||
"{" AssignList "}" { result = ObjectNode.new(val[1]) }
|
||||
;
|
||||
|
||||
# Assignment within an object literal (comma or newline separated).
|
||||
AssignList:
|
||||
/* nothing */ { result = [] }
|
||||
| AssignObj { result = val }
|
||||
| AssignList "," AssignObj { result = val[0] << val[2] }
|
||||
| AssignList Terminator AssignObj { result = val[0] << val[2] }
|
||||
| AssignList ","
|
||||
Terminator AssignObj { result = val[0] << val[3] }
|
||||
| INDENT AssignList OUTDENT { result = val[1] }
|
||||
;
|
||||
|
||||
# All flavors of function call (instantiation, super, and regular).
|
||||
Call:
|
||||
Invocation { result = val[0] }
|
||||
| NEW Invocation { result = val[1].new_instance }
|
||||
| Super { result = val[0] }
|
||||
;
|
||||
|
||||
# Extending an object's prototype.
|
||||
Extends:
|
||||
Value EXTENDS Value { result = ExtendsNode.new(val[0], val[2]) }
|
||||
;
|
||||
|
||||
# A generic function invocation.
|
||||
Invocation:
|
||||
Value Arguments { result = CallNode.new(val[0], val[1]) }
|
||||
| Invocation Arguments { result = CallNode.new(val[0], val[1]) }
|
||||
;
|
||||
|
||||
# The list of arguments to a function invocation.
|
||||
Arguments:
|
||||
CALL_START ArgList CALL_END { result = val[1] }
|
||||
;
|
||||
|
||||
# Calling super.
|
||||
Super:
|
||||
SUPER CALL_START ArgList CALL_END { result = CallNode.new(Value.new('super'), val[2]) }
|
||||
;
|
||||
|
||||
# This references, either naked or to a property.
|
||||
This:
|
||||
'@' { result = ThisNode.new }
|
||||
| '@' IDENTIFIER { result = ThisNode.new(val[1]) }
|
||||
;
|
||||
|
||||
# The range literal.
|
||||
Range:
|
||||
"[" Expression
|
||||
"." "." Expression "]" { result = RangeNode.new(val[1], val[4]) }
|
||||
| "[" Expression
|
||||
"." "." "." Expression "]" { result = RangeNode.new(val[1], val[5], true) }
|
||||
;
|
||||
|
||||
# The slice literal.
|
||||
Slice:
|
||||
INDEX_START Expression "." "."
|
||||
Expression INDEX_END { result = RangeNode.new(val[1], val[4]) }
|
||||
| INDEX_START Expression "." "." "."
|
||||
Expression INDEX_END { result = RangeNode.new(val[1], val[5], true) }
|
||||
;
|
||||
|
||||
# The array literal.
|
||||
Array:
|
||||
"[" ArgList "]" { result = ArrayNode.new(val[1]) }
|
||||
;
|
||||
|
||||
# A list of arguments to a method call, or as the contents of an array.
|
||||
ArgList:
|
||||
/* nothing */ { result = [] }
|
||||
| Expression { result = val }
|
||||
| INDENT Expression { result = [val[1]] }
|
||||
| ArgList "," Expression { result = val[0] << val[2] }
|
||||
| ArgList Terminator Expression { result = val[0] << val[2] }
|
||||
| ArgList "," Terminator Expression { result = val[0] << val[3] }
|
||||
| ArgList "," INDENT Expression { result = val[0] << val[3] }
|
||||
| ArgList OUTDENT { result = val[0] }
|
||||
;
|
||||
|
||||
# Just simple, comma-separated, required arguments (no fancy syntax).
|
||||
SimpleArgs:
|
||||
Expression { result = val[0] }
|
||||
| SimpleArgs "," Expression { result = ([val[0]] << val[2]).flatten }
|
||||
;
|
||||
|
||||
# Try/catch/finally exception handling blocks.
|
||||
Try:
|
||||
TRY Block Catch { result = TryNode.new(val[1], val[2][0], val[2][1]) }
|
||||
| TRY Block FINALLY Block { result = TryNode.new(val[1], nil, nil, val[3]) }
|
||||
| TRY Block Catch
|
||||
FINALLY Block { result = TryNode.new(val[1], val[2][0], val[2][1], val[4]) }
|
||||
;
|
||||
|
||||
# A catch clause.
|
||||
Catch:
|
||||
CATCH IDENTIFIER Block { result = [val[1], val[2]] }
|
||||
;
|
||||
|
||||
# Throw an exception.
|
||||
Throw:
|
||||
THROW Expression { result = ThrowNode.new(val[1]) }
|
||||
;
|
||||
|
||||
# Parenthetical expressions.
|
||||
Parenthetical:
|
||||
"(" Expression ")" { result = ParentheticalNode.new(val[1], val[0].line) }
|
||||
;
|
||||
|
||||
# The while loop. (there is no do..while).
|
||||
While:
|
||||
WHILE Expression Block { result = WhileNode.new(val[1], val[2]) }
|
||||
| WHILE Expression { result = WhileNode.new(val[1], nil) }
|
||||
| Expression WHILE Expression { result = WhileNode.new(val[2], Expressions.wrap(val[0])) }
|
||||
;
|
||||
|
||||
# Array comprehensions, including guard and current index.
|
||||
# Looks a little confusing, check nodes.rb for the arguments to ForNode.
|
||||
For:
|
||||
Expression FOR
|
||||
ForVariables ForSource { result = ForNode.new(val[0], val[3], val[2][0], val[2][1]) }
|
||||
| FOR ForVariables ForSource Block { result = ForNode.new(val[3], val[2], val[1][0], val[1][1]) }
|
||||
;
|
||||
|
||||
# An array comprehension has variables for the current element and index.
|
||||
ForVariables:
|
||||
IDENTIFIER { result = val }
|
||||
| IDENTIFIER "," IDENTIFIER { result = [val[0], val[2]] }
|
||||
;
|
||||
|
||||
# The source of the array comprehension can optionally be filtered.
|
||||
ForSource:
|
||||
IN Expression { result = {:source => val[1]} }
|
||||
| OF Expression { result = {:source => val[1], :object => true} }
|
||||
| ForSource
|
||||
WHEN Expression { result = val[0].merge(:filter => val[2]) }
|
||||
| ForSource
|
||||
BY Expression { result = val[0].merge(:step => val[2]) }
|
||||
;
|
||||
|
||||
# Switch/When blocks.
|
||||
Switch:
|
||||
SWITCH Expression INDENT
|
||||
Whens OUTDENT { result = val[3].rewrite_condition(val[1]) }
|
||||
| SWITCH Expression INDENT
|
||||
Whens ELSE Block OUTDENT { result = val[3].rewrite_condition(val[1]).add_else(val[5]) }
|
||||
;
|
||||
|
||||
# The inner list of whens.
|
||||
Whens:
|
||||
When { result = val[0] }
|
||||
| Whens When { result = val[0] << val[1] }
|
||||
;
|
||||
|
||||
# An individual when.
|
||||
When:
|
||||
LEADING_WHEN SimpleArgs Block { result = IfNode.new(val[1], val[2], nil, {:statement => true}) }
|
||||
| LEADING_WHEN SimpleArgs Block
|
||||
Terminator { result = IfNode.new(val[1], val[2], nil, {:statement => true}) }
|
||||
| Comment Terminator When { result = val[2].add_comment(val[0]) }
|
||||
;
|
||||
|
||||
# The most basic form of "if".
|
||||
IfBlock:
|
||||
IF Expression Block { result = IfNode.new(val[1], val[2]) }
|
||||
;
|
||||
|
||||
# An elsif portion of an if-else block.
|
||||
ElsIf:
|
||||
ELSE IfBlock { result = val[1].force_statement }
|
||||
;
|
||||
|
||||
# Multiple elsifs can be chained together.
|
||||
ElsIfs:
|
||||
ElsIf { result = val[0] }
|
||||
| ElsIfs ElsIf { result = val[0].add_else(val[1]) }
|
||||
;
|
||||
|
||||
# Terminating else bodies are strictly optional.
|
||||
ElseBody
|
||||
/* nothing */ { result = nil }
|
||||
| ELSE Block { result = val[1] }
|
||||
;
|
||||
|
||||
# All the alternatives for ending an if-else block.
|
||||
IfEnd:
|
||||
ElseBody { result = val[0] }
|
||||
| ElsIfs ElseBody { result = val[0].add_else(val[1]) }
|
||||
;
|
||||
|
||||
# The full complement of if blocks, including postfix one-liner ifs and unlesses.
|
||||
If:
|
||||
IfBlock IfEnd { result = val[0].add_else(val[1]) }
|
||||
| Expression IF Expression { result = IfNode.new(val[2], Expressions.wrap(val[0]), nil, {:statement => true}) }
|
||||
| Expression UNLESS Expression { result = IfNode.new(val[2], Expressions.wrap(val[0]), nil, {:statement => true, :invert => true}) }
|
||||
;
|
||||
|
||||
end
|
||||
|
||||
---- header
|
||||
module CoffeeScript
|
||||
|
||||
---- inner
|
||||
# Lex and parse a CoffeeScript.
|
||||
def parse(code)
|
||||
# Uncomment the following line to enable grammar debugging, in combination
|
||||
# with the -g flag in the Rake build task.
|
||||
# @yydebug = true
|
||||
@tokens = Lexer.new.tokenize(code)
|
||||
do_parse
|
||||
end
|
||||
|
||||
# Retrieve the next token from the list.
|
||||
def next_token
|
||||
@tokens.shift
|
||||
end
|
||||
|
||||
# Raise a custom error class that knows about line numbers.
|
||||
def on_error(error_token_id, error_value, value_stack)
|
||||
raise ParseError.new(token_to_str(error_token_id), error_value, value_stack)
|
||||
end
|
||||
|
||||
---- footer
|
||||
end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user