haml-more 0.4.0.a

Sign up to get free protection for your applications and to get access to all the features.
Files changed (225) hide show
  1. data/README.md +79 -0
  2. data/lib/haml/more/coffee_script.rb +137 -0
  3. data/lib/haml/more/content_for.rb +25 -0
  4. data/lib/haml/more.rb +45 -0
  5. data/lib/haml-more.rb +1 -0
  6. data/lib/sass/more.rb +16 -0
  7. data/lib/sass-more.rb +1 -0
  8. data/spec/sass/more_spec.rb +21 -0
  9. data/vendor/coffee-script/Cakefile +57 -0
  10. data/vendor/coffee-script/LICENSE +22 -0
  11. data/vendor/coffee-script/README +41 -0
  12. data/vendor/coffee-script/Rakefile +20 -0
  13. data/vendor/coffee-script/bin/cake +7 -0
  14. data/vendor/coffee-script/bin/coffee +7 -0
  15. data/vendor/coffee-script/documentation/coffee/aliases.coffee +9 -0
  16. data/vendor/coffee-script/documentation/coffee/arguments.coffee +4 -0
  17. data/vendor/coffee-script/documentation/coffee/array_comprehensions.coffee +7 -0
  18. data/vendor/coffee-script/documentation/coffee/assignment.coffee +2 -0
  19. data/vendor/coffee-script/documentation/coffee/cake_tasks.coffee +5 -0
  20. data/vendor/coffee-script/documentation/coffee/comparisons.coffee +5 -0
  21. data/vendor/coffee-script/documentation/coffee/conditionals.coffee +9 -0
  22. data/vendor/coffee-script/documentation/coffee/embedded.coffee +5 -0
  23. data/vendor/coffee-script/documentation/coffee/existence.coffee +8 -0
  24. data/vendor/coffee-script/documentation/coffee/expressions.coffee +9 -0
  25. data/vendor/coffee-script/documentation/coffee/expressions_assignment.coffee +1 -0
  26. data/vendor/coffee-script/documentation/coffee/expressions_comprehension.coffee +3 -0
  27. data/vendor/coffee-script/documentation/coffee/expressions_try.coffee +6 -0
  28. data/vendor/coffee-script/documentation/coffee/fat_arrow.coffee +6 -0
  29. data/vendor/coffee-script/documentation/coffee/functions.coffee +2 -0
  30. data/vendor/coffee-script/documentation/coffee/heredocs.coffee +5 -0
  31. data/vendor/coffee-script/documentation/coffee/multiple_return_values.coffee +5 -0
  32. data/vendor/coffee-script/documentation/coffee/object_comprehensions.coffee +4 -0
  33. data/vendor/coffee-script/documentation/coffee/object_extraction.coffee +13 -0
  34. data/vendor/coffee-script/documentation/coffee/objects_and_arrays.coffee +13 -0
  35. data/vendor/coffee-script/documentation/coffee/overview.coffee +29 -0
  36. data/vendor/coffee-script/documentation/coffee/parallel_assignment.coffee +4 -0
  37. data/vendor/coffee-script/documentation/coffee/range_comprehensions.coffee +6 -0
  38. data/vendor/coffee-script/documentation/coffee/scope.coffee +5 -0
  39. data/vendor/coffee-script/documentation/coffee/slices.coffee +6 -0
  40. data/vendor/coffee-script/documentation/coffee/soaks.coffee +1 -0
  41. data/vendor/coffee-script/documentation/coffee/splats.coffee +25 -0
  42. data/vendor/coffee-script/documentation/coffee/splices.coffee +5 -0
  43. data/vendor/coffee-script/documentation/coffee/strings.coffee +8 -0
  44. data/vendor/coffee-script/documentation/coffee/super.coffee +34 -0
  45. data/vendor/coffee-script/documentation/coffee/switch.coffee +10 -0
  46. data/vendor/coffee-script/documentation/coffee/try.coffee +7 -0
  47. data/vendor/coffee-script/documentation/coffee/while.coffee +10 -0
  48. data/vendor/coffee-script/documentation/css/docs.css +213 -0
  49. data/vendor/coffee-script/documentation/css/idle.css +63 -0
  50. data/vendor/coffee-script/documentation/css/logo.png +0 -0
  51. data/vendor/coffee-script/documentation/index.html.erb +967 -0
  52. data/vendor/coffee-script/documentation/js/aliases.js +14 -0
  53. data/vendor/coffee-script/documentation/js/arguments.js +8 -0
  54. data/vendor/coffee-script/documentation/js/array_comprehensions.js +26 -0
  55. data/vendor/coffee-script/documentation/js/assignment.js +5 -0
  56. data/vendor/coffee-script/documentation/js/cake_tasks.js +14 -0
  57. data/vendor/coffee-script/documentation/js/comparisons.js +5 -0
  58. data/vendor/coffee-script/documentation/js/conditionals.js +12 -0
  59. data/vendor/coffee-script/documentation/js/embedded.js +6 -0
  60. data/vendor/coffee-script/documentation/js/existence.js +7 -0
  61. data/vendor/coffee-script/documentation/js/expressions.js +13 -0
  62. data/vendor/coffee-script/documentation/js/expressions_assignment.js +4 -0
  63. data/vendor/coffee-script/documentation/js/expressions_comprehension.js +12 -0
  64. data/vendor/coffee-script/documentation/js/expressions_try.js +9 -0
  65. data/vendor/coffee-script/documentation/js/fat_arrow.js +15 -0
  66. data/vendor/coffee-script/documentation/js/functions.js +9 -0
  67. data/vendor/coffee-script/documentation/js/heredocs.js +4 -0
  68. data/vendor/coffee-script/documentation/js/intro.js +7 -0
  69. data/vendor/coffee-script/documentation/js/multiple_return_values.js +11 -0
  70. data/vendor/coffee-script/documentation/js/object_comprehensions.js +17 -0
  71. data/vendor/coffee-script/documentation/js/object_extraction.js +17 -0
  72. data/vendor/coffee-script/documentation/js/objects_and_arrays.js +10 -0
  73. data/vendor/coffee-script/documentation/js/overview.js +43 -0
  74. data/vendor/coffee-script/documentation/js/parallel_assignment.js +8 -0
  75. data/vendor/coffee-script/documentation/js/punctuation.js +8 -0
  76. data/vendor/coffee-script/documentation/js/range_comprehensions.js +21 -0
  77. data/vendor/coffee-script/documentation/js/scope.js +10 -0
  78. data/vendor/coffee-script/documentation/js/slices.js +6 -0
  79. data/vendor/coffee-script/documentation/js/soaks.js +4 -0
  80. data/vendor/coffee-script/documentation/js/splats.js +16 -0
  81. data/vendor/coffee-script/documentation/js/splices.js +5 -0
  82. data/vendor/coffee-script/documentation/js/strings.js +9 -0
  83. data/vendor/coffee-script/documentation/js/super.js +37 -0
  84. data/vendor/coffee-script/documentation/js/switch.js +18 -0
  85. data/vendor/coffee-script/documentation/js/try.js +10 -0
  86. data/vendor/coffee-script/documentation/js/while.js +22 -0
  87. data/vendor/coffee-script/documentation/underscore.html +627 -0
  88. data/vendor/coffee-script/examples/beautiful_code/binary_search.coffee +16 -0
  89. data/vendor/coffee-script/examples/beautiful_code/quicksort_runtime.coffee +13 -0
  90. data/vendor/coffee-script/examples/beautiful_code/regular_expression_matcher.coffee +34 -0
  91. data/vendor/coffee-script/examples/blocks.coffee +57 -0
  92. data/vendor/coffee-script/examples/code.coffee +173 -0
  93. data/vendor/coffee-script/examples/computer_science/README +4 -0
  94. data/vendor/coffee-script/examples/computer_science/binary_search.coffee +25 -0
  95. data/vendor/coffee-script/examples/computer_science/bubble_sort.coffee +11 -0
  96. data/vendor/coffee-script/examples/computer_science/linked_list.coffee +106 -0
  97. data/vendor/coffee-script/examples/computer_science/luhn_algorithm.coffee +36 -0
  98. data/vendor/coffee-script/examples/computer_science/merge_sort.coffee +19 -0
  99. data/vendor/coffee-script/examples/computer_science/selection_sort.coffee +23 -0
  100. data/vendor/coffee-script/examples/poignant.coffee +186 -0
  101. data/vendor/coffee-script/examples/potion.coffee +205 -0
  102. data/vendor/coffee-script/examples/underscore.coffee +603 -0
  103. data/vendor/coffee-script/examples/web_server.coffee +12 -0
  104. data/vendor/coffee-script/extras/CoffeeScript.tmbundle/Preferences/CoffeeScript.tmPreferences +24 -0
  105. data/vendor/coffee-script/extras/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage +361 -0
  106. data/vendor/coffee-script/extras/CoffeeScript.tmbundle/info.plist +10 -0
  107. data/vendor/coffee-script/extras/EXTRAS +20 -0
  108. data/vendor/coffee-script/extras/coffee.vim +117 -0
  109. data/vendor/coffee-script/index.html +1847 -0
  110. data/vendor/coffee-script/lib/bin/cake +7 -0
  111. data/vendor/coffee-script/lib/bin/coffee +7 -0
  112. data/vendor/coffee-script/lib/cake.js +80 -0
  113. data/vendor/coffee-script/lib/coffee-script.js +61 -0
  114. data/vendor/coffee-script/lib/command_line.js +201 -0
  115. data/vendor/coffee-script/lib/grammar.js +564 -0
  116. data/vendor/coffee-script/lib/lexer.js +405 -0
  117. data/vendor/coffee-script/lib/narwhal.js +44 -0
  118. data/vendor/coffee-script/lib/nodes.js +1328 -0
  119. data/vendor/coffee-script/lib/optparse.js +117 -0
  120. data/vendor/coffee-script/lib/parser.js +536 -0
  121. data/vendor/coffee-script/lib/repl.js +32 -0
  122. data/vendor/coffee-script/lib/rewriter.js +383 -0
  123. data/vendor/coffee-script/lib/scope.js +114 -0
  124. data/vendor/coffee-script/package.json +7 -0
  125. data/vendor/coffee-script/src/cake.coffee +45 -0
  126. data/vendor/coffee-script/src/coffee-script.coffee +45 -0
  127. data/vendor/coffee-script/src/command_line.coffee +130 -0
  128. data/vendor/coffee-script/src/grammar.coffee +456 -0
  129. data/vendor/coffee-script/src/lexer.coffee +327 -0
  130. data/vendor/coffee-script/src/narwhal.coffee +42 -0
  131. data/vendor/coffee-script/src/nodes.coffee +1045 -0
  132. data/vendor/coffee-script/src/optparse.coffee +79 -0
  133. data/vendor/coffee-script/src/repl.coffee +23 -0
  134. data/vendor/coffee-script/src/rewriter.coffee +253 -0
  135. data/vendor/coffee-script/src/scope.coffee +75 -0
  136. data/vendor/coffee-script/test/test_arguments.coffee +34 -0
  137. data/vendor/coffee-script/test/test_array_comprehension.coffee +42 -0
  138. data/vendor/coffee-script/test/test_assignment.coffee +26 -0
  139. data/vendor/coffee-script/test/test_blocks.coffee +4 -0
  140. data/vendor/coffee-script/test/test_calling_super.coffee +42 -0
  141. data/vendor/coffee-script/test/test_chained_calls.coffee +25 -0
  142. data/vendor/coffee-script/test/test_destructuring_assignment.coffee +62 -0
  143. data/vendor/coffee-script/test/test_everything.coffee +29 -0
  144. data/vendor/coffee-script/test/test_exceptions.coffee +2 -0
  145. data/vendor/coffee-script/test/test_existence.coffee +81 -0
  146. data/vendor/coffee-script/test/test_expressions.coffee +30 -0
  147. data/vendor/coffee-script/test/test_fancy_if_statement.coffee +26 -0
  148. data/vendor/coffee-script/test/test_functions.coffee +80 -0
  149. data/vendor/coffee-script/test/test_funky_comments.coffee +25 -0
  150. data/vendor/coffee-script/test/test_heredocs.coffee +46 -0
  151. data/vendor/coffee-script/test/test_lexical_scope.coffee +10 -0
  152. data/vendor/coffee-script/test/test_literals.coffee +56 -0
  153. data/vendor/coffee-script/test/test_nested_comprehensions.coffee +11 -0
  154. data/vendor/coffee-script/test/test_newline_escaping.coffee +6 -0
  155. data/vendor/coffee-script/test/test_operations.coffee +18 -0
  156. data/vendor/coffee-script/test/test_range_comprehension.coffee +20 -0
  157. data/vendor/coffee-script/test/test_ranges_and_slices.coffee +16 -0
  158. data/vendor/coffee-script/test/test_splats.coffee +47 -0
  159. data/vendor/coffee-script/test/test_splices.coffee +5 -0
  160. data/vendor/coffee-script/test/test_switch.coffee +64 -0
  161. data/vendor/coffee-script/test/test_while.coffee +30 -0
  162. data/vendor/coffee-script/vendor/jison/Jakefile +31 -0
  163. data/vendor/coffee-script/vendor/jison/README.md +347 -0
  164. data/vendor/coffee-script/vendor/jison/bin/jison +3 -0
  165. data/vendor/coffee-script/vendor/jison/bin/json2jison +3 -0
  166. data/vendor/coffee-script/vendor/jison/examples/ansic.jison +415 -0
  167. data/vendor/coffee-script/vendor/jison/examples/basic.json +8 -0
  168. data/vendor/coffee-script/vendor/jison/examples/basic2.json +9 -0
  169. data/vendor/coffee-script/vendor/jison/examples/basic2_lex.json +16 -0
  170. data/vendor/coffee-script/vendor/jison/examples/basic_lex.json +15 -0
  171. data/vendor/coffee-script/vendor/jison/examples/calculator.jison +38 -0
  172. data/vendor/coffee-script/vendor/jison/examples/calculator.jisonlex +14 -0
  173. data/vendor/coffee-script/vendor/jison/examples/calculator.json +42 -0
  174. data/vendor/coffee-script/vendor/jison/examples/classy.json +105 -0
  175. data/vendor/coffee-script/vendor/jison/examples/classy_ast.json +126 -0
  176. data/vendor/coffee-script/vendor/jison/examples/dism.json +25 -0
  177. data/vendor/coffee-script/vendor/jison/examples/dism_lr0.json +26 -0
  178. data/vendor/coffee-script/vendor/jison/examples/json.js +80 -0
  179. data/vendor/coffee-script/vendor/jison/examples/json_ast.js +83 -0
  180. data/vendor/coffee-script/vendor/jison/examples/precedence.json +26 -0
  181. data/vendor/coffee-script/vendor/jison/examples/reduce_conflict.json +13 -0
  182. data/vendor/coffee-script/vendor/jison/lib/jison/bnf.js +43 -0
  183. data/vendor/coffee-script/vendor/jison/lib/jison/jisonlex.js +18 -0
  184. data/vendor/coffee-script/vendor/jison/lib/jison/json2jison.js +146 -0
  185. data/vendor/coffee-script/vendor/jison/lib/jison/lexer.js +224 -0
  186. data/vendor/coffee-script/vendor/jison/lib/jison/util/bnf-parser.js +383 -0
  187. data/vendor/coffee-script/vendor/jison/lib/jison/util/lex-parser.js +407 -0
  188. data/vendor/coffee-script/vendor/jison/lib/jison/util/set.js +94 -0
  189. data/vendor/coffee-script/vendor/jison/lib/jison/util/typal.js +90 -0
  190. data/vendor/coffee-script/vendor/jison/lib/jison.js +1414 -0
  191. data/vendor/coffee-script/vendor/jison/package.json +14 -0
  192. data/vendor/coffee-script/vendor/jison/src/bnf.jison +110 -0
  193. data/vendor/coffee-script/vendor/jison/src/bnf.jisonlex +25 -0
  194. data/vendor/coffee-script/vendor/jison/src/bnf.lex.json +24 -0
  195. data/vendor/coffee-script/vendor/jison/src/jisonlex.jison +129 -0
  196. data/vendor/coffee-script/vendor/jison/src/jisonlex.jisonlex +31 -0
  197. data/vendor/coffee-script/vendor/jison/src/jisonlex.lex.json +30 -0
  198. data/vendor/coffee-script/vendor/jison/tests/all-tests.js +8 -0
  199. data/vendor/coffee-script/vendor/jison/tests/grammar/bnf.js +91 -0
  200. data/vendor/coffee-script/vendor/jison/tests/grammar/bnf_parse.js +65 -0
  201. data/vendor/coffee-script/vendor/jison/tests/grammar/grammar-tests.js +10 -0
  202. data/vendor/coffee-script/vendor/jison/tests/grammar/json2jison.js +24 -0
  203. data/vendor/coffee-script/vendor/jison/tests/grammar/lex/ansic.jisonlex +115 -0
  204. data/vendor/coffee-script/vendor/jison/tests/grammar/lex/bnf.jisonlex +25 -0
  205. data/vendor/coffee-script/vendor/jison/tests/grammar/lex/bnf.lex.json +24 -0
  206. data/vendor/coffee-script/vendor/jison/tests/grammar/lex/lex_grammar.jisonlex +31 -0
  207. data/vendor/coffee-script/vendor/jison/tests/grammar/lex/lex_grammar.lex.json +30 -0
  208. data/vendor/coffee-script/vendor/jison/tests/grammar/lex.jison +119 -0
  209. data/vendor/coffee-script/vendor/jison/tests/grammar/lex.js +58 -0
  210. data/vendor/coffee-script/vendor/jison/tests/grammar/lex_parse.js +117 -0
  211. data/vendor/coffee-script/vendor/jison/tests/lexer/lexer-tests.js +6 -0
  212. data/vendor/coffee-script/vendor/jison/tests/lexer/regexplexer.js +417 -0
  213. data/vendor/coffee-script/vendor/jison/tests/parser/actions.js +311 -0
  214. data/vendor/coffee-script/vendor/jison/tests/parser/api.js +236 -0
  215. data/vendor/coffee-script/vendor/jison/tests/parser/generator.js +196 -0
  216. data/vendor/coffee-script/vendor/jison/tests/parser/lalr.js +183 -0
  217. data/vendor/coffee-script/vendor/jison/tests/parser/lr0.js +72 -0
  218. data/vendor/coffee-script/vendor/jison/tests/parser/lr1.js +119 -0
  219. data/vendor/coffee-script/vendor/jison/tests/parser/parser-tests.js +14 -0
  220. data/vendor/coffee-script/vendor/jison/tests/parser/precedence.js +237 -0
  221. data/vendor/coffee-script/vendor/jison/tests/parser/slr.js +52 -0
  222. data/vendor/coffee-script/vendor/jison/tests/parser/tables.js +126 -0
  223. data/vendor/coffee-script/vendor/jison/tests/performance.js +110 -0
  224. data/vendor/coffee-script/vendor/jison/tests/setup.js +3 -0
  225. metadata +324 -0
@@ -0,0 +1,327 @@
1
+ if process?
2
+ Rewriter: require('./rewriter').Rewriter
3
+ else
4
+ this.exports: this
5
+ Rewriter: this.Rewriter
6
+
7
+ # The lexer reads a stream of CoffeeScript and divvys it up into tagged
8
+ # tokens. A minor bit of the ambiguity in the grammar has been avoided by
9
+ # pushing some extra smarts into the Lexer.
10
+ exports.Lexer: lex: ->
11
+
12
+ # Constants ============================================================
13
+
14
+ # Keywords that CoffeScript shares in common with JS.
15
+ JS_KEYWORDS: [
16
+ "if", "else",
17
+ "true", "false",
18
+ "new", "return",
19
+ "try", "catch", "finally", "throw",
20
+ "break", "continue",
21
+ "for", "in", "while",
22
+ "delete", "instanceof", "typeof",
23
+ "switch", "super", "extends"
24
+ ]
25
+
26
+ # CoffeeScript-only keywords -- which we're more relaxed about allowing.
27
+ COFFEE_KEYWORDS: [
28
+ "then", "unless",
29
+ "yes", "no", "on", "off",
30
+ "and", "or", "is", "isnt", "not",
31
+ "of", "by", "where", "when"
32
+ ]
33
+
34
+ # The list of keywords passed verbatim to the parser.
35
+ KEYWORDS: JS_KEYWORDS.concat COFFEE_KEYWORDS
36
+
37
+ # The list of keywords that are reserved by JavaScript, but not used, and aren't
38
+ # used by CoffeeScript. Using these will throw an error at compile time.
39
+ RESERVED: [
40
+ "case", "default", "do", "function", "var", "void", "with", "class"
41
+ "const", "let", "debugger", "enum", "export", "import", "native"
42
+ ]
43
+
44
+ # JavaScript keywords and reserved words together, excluding CoffeeScript ones.
45
+ JS_FORBIDDEN: JS_KEYWORDS.concat RESERVED
46
+
47
+ # Token matching regexes. (keep the IDENTIFIER regex in sync with AssignNode.)
48
+ IDENTIFIER : /^([a-zA-Z$_](\w|\$)*)/
49
+ NUMBER : /^(\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?(e[+\-]?[0-9]+)?)))\b/i
50
+ STRING : /^(""|''|"([\s\S]*?)([^\\]|\\\\)"|'([\s\S]*?)([^\\]|\\\\)')/
51
+ HEREDOC : /^("{6}|'{6}|"{3}\n?([\s\S]*?)\n?([ \t]*)"{3}|'{3}\n?([\s\S]*?)\n?([ \t]*)'{3})/
52
+ JS : /^(``|`([\s\S]*?)([^\\]|\\\\)`)/
53
+ OPERATOR : /^([+\*&|\/\-%=<>:!?]+)/
54
+ WHITESPACE : /^([ \t]+)/
55
+ COMMENT : /^(((\n?[ \t]*)?#[^\n]*)+)/
56
+ CODE : /^((-|=)>)/
57
+ REGEX : /^(\/(.*?)([^\\]|\\\\)\/[imgy]{0,4})/
58
+ MULTI_DENT : /^((\n([ \t]*))+)(\.)?/
59
+ LAST_DENTS : /\n([ \t]*)/g
60
+ LAST_DENT : /\n([ \t]*)/
61
+ ASSIGNMENT : /^(:|=)$/
62
+
63
+ # Token cleaning regexes.
64
+ JS_CLEANER : /(^`|`$)/g
65
+ MULTILINER : /\n/g
66
+ STRING_NEWLINES : /\n[ \t]*/g
67
+ COMMENT_CLEANER : /(^[ \t]*#|\n[ \t]*$)/mg
68
+ NO_NEWLINE : /^([+\*&|\/\-%=<>:!.\\][<>=&|]*|and|or|is|isnt|not|delete|typeof|instanceof)$/
69
+ HEREDOC_INDENT : /^[ \t]+/mg
70
+
71
+ # Tokens which a regular expression will never immediately follow, but which
72
+ # a division operator might.
73
+ # See: http://www.mozilla.org/js/language/js20-2002-04/rationale/syntax.html#regular-expressions
74
+ NOT_REGEX: [
75
+ 'IDENTIFIER', 'NUMBER', 'REGEX', 'STRING',
76
+ ')', '++', '--', ']', '}',
77
+ 'FALSE', 'NULL', 'TRUE'
78
+ ]
79
+
80
+ # Tokens which could legitimately be invoked or indexed.
81
+ CALLABLE: ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING', '@']
82
+
83
+ # Tokens that indicate an access -- keywords immediately following will be
84
+ # treated as identifiers.
85
+ ACCESSORS: ['PROPERTY_ACCESS', 'PROTOTYPE_ACCESS', 'SOAK_ACCESS', '@']
86
+
87
+ # Tokens that, when immediately preceding a 'WHEN', indicate that its leading.
88
+ BEFORE_WHEN: ['INDENT', 'OUTDENT', 'TERMINATOR']
89
+
90
+ # Scan by attempting to match tokens one character at a time. Slow and steady.
91
+ lex::tokenize: (code) ->
92
+ @code : code # Cleanup code by remove extra line breaks, TODO: chomp
93
+ @i : 0 # Current character position we're parsing
94
+ @line : 1 # The current line.
95
+ @indent : 0 # The current indent level.
96
+ @indents : [] # The stack of all indent levels we are currently within.
97
+ @tokens : [] # Collection of all parsed tokens in the form [:TOKEN_TYPE, value]
98
+ while @i < @code.length
99
+ @chunk: @code.slice(@i)
100
+ @extract_next_token()
101
+ @close_indentation()
102
+ (new Rewriter()).rewrite @tokens
103
+
104
+ # At every position, run through this list of attempted matches,
105
+ # short-circuiting if any of them succeed.
106
+ lex::extract_next_token: ->
107
+ return if @identifier_token()
108
+ return if @number_token()
109
+ return if @heredoc_token()
110
+ return if @string_token()
111
+ return if @js_token()
112
+ return if @regex_token()
113
+ return if @indent_token()
114
+ return if @comment_token()
115
+ return if @whitespace_token()
116
+ return @literal_token()
117
+
118
+ # Tokenizers ==========================================================
119
+
120
+ # Matches identifying literals: variables, keywords, method names, etc.
121
+ lex::identifier_token: ->
122
+ return false unless id: @match IDENTIFIER, 1
123
+ @tag(1, 'PROTOTYPE_ACCESS') if @value() is '::'
124
+ if @value() is '.' and not (@value(2) is '.')
125
+ if @tag(2) is '?'
126
+ @tag(1, 'SOAK_ACCESS')
127
+ @tokens.splice(-2, 1)
128
+ else
129
+ @tag(1, 'PROPERTY_ACCESS')
130
+ tag: 'IDENTIFIER'
131
+ tag: id.toUpperCase() if KEYWORDS.indexOf(id) >= 0 and
132
+ not ((ACCESSORS.indexOf(@tag()) >= 0) and not @prev().spaced)
133
+ throw new Error('SyntaxError: Reserved word "' + id + '" on line ' + @line) if RESERVED.indexOf(id) >= 0
134
+ tag: 'LEADING_WHEN' if tag is 'WHEN' and BEFORE_WHEN.indexOf(@tag()) >= 0
135
+ @token(tag, id)
136
+ @i += id.length
137
+ true
138
+
139
+ # Matches numbers, including decimals, hex, and exponential notation.
140
+ lex::number_token: ->
141
+ return false unless number: @match NUMBER, 1
142
+ @token 'NUMBER', number
143
+ @i += number.length
144
+ true
145
+
146
+ # Matches strings, including multi-line strings.
147
+ lex::string_token: ->
148
+ return false unless string: @match STRING, 1
149
+ escaped: string.replace STRING_NEWLINES, " \\\n"
150
+ @token 'STRING', escaped
151
+ @line += @count string, "\n"
152
+ @i += string.length
153
+ true
154
+
155
+ # Matches heredocs, adjusting indentation to the correct level.
156
+ lex::heredoc_token: ->
157
+ return false unless match = @chunk.match(HEREDOC)
158
+ doc: match[2] or match[4]
159
+ indent: (doc.match(HEREDOC_INDENT) or ['']).sort()[0]
160
+ doc: doc.replace(new RegExp("^" + indent, 'gm'), '')
161
+ .replace(MULTILINER, "\\n")
162
+ .replace('"', '\\"')
163
+ @token 'STRING', '"' + doc + '"'
164
+ @line += @count match[1], "\n"
165
+ @i += match[1].length
166
+ true
167
+
168
+ # Matches interpolated JavaScript.
169
+ lex::js_token: ->
170
+ return false unless script: @match JS, 1
171
+ @token 'JS', script.replace(JS_CLEANER, '')
172
+ @i += script.length
173
+ true
174
+
175
+ # Matches regular expression literals.
176
+ lex::regex_token: ->
177
+ return false unless regex: @match REGEX, 1
178
+ return false if NOT_REGEX.indexOf(@tag()) >= 0
179
+ @token 'REGEX', regex
180
+ @i += regex.length
181
+ true
182
+
183
+ # Matches and conumes comments.
184
+ lex::comment_token: ->
185
+ return false unless comment: @match COMMENT, 1
186
+ @line += (comment.match(MULTILINER) or []).length
187
+ @token 'COMMENT', comment.replace(COMMENT_CLEANER, '').split(MULTILINER)
188
+ @token 'TERMINATOR', "\n"
189
+ @i += comment.length
190
+ true
191
+
192
+ # Record tokens for indentation differing from the previous line.
193
+ lex::indent_token: ->
194
+ return false unless indent: @match MULTI_DENT, 1
195
+ @line += indent.match(MULTILINER).length
196
+ @i += indent.length
197
+ next_character: @chunk.match(MULTI_DENT)[4]
198
+ prev: @prev(2)
199
+ no_newlines: next_character is '.' or (@value() and @value().match(NO_NEWLINE) and prev and (prev[0] isnt '.') and not @value().match(CODE))
200
+ return @suppress_newlines(indent) if no_newlines
201
+ size: indent.match(LAST_DENTS).reverse()[0].match(LAST_DENT)[1].length
202
+ return @newline_token(indent) if size is @indent
203
+ if size > @indent
204
+ diff: size - @indent
205
+ @token 'INDENT', diff
206
+ @indents.push diff
207
+ else
208
+ @outdent_token @indent - size
209
+ @indent: size
210
+ true
211
+
212
+ # Record an oudent token or tokens, if we're moving back inwards past
213
+ # multiple recorded indents.
214
+ lex::outdent_token: (move_out) ->
215
+ while move_out > 0 and @indents.length
216
+ last_indent: @indents.pop()
217
+ @token 'OUTDENT', last_indent
218
+ move_out -= last_indent
219
+ @token 'TERMINATOR', "\n" unless @tag() is 'TERMINATOR'
220
+ true
221
+
222
+ # Matches and consumes non-meaningful whitespace.
223
+ lex::whitespace_token: ->
224
+ return false unless space: @match WHITESPACE, 1
225
+ prev: @prev()
226
+ prev.spaced: true if prev
227
+ @i += space.length
228
+ true
229
+
230
+ # Multiple newlines get merged together.
231
+ # Use a trailing \ to escape newlines.
232
+ lex::newline_token: (newlines) ->
233
+ @token 'TERMINATOR', "\n" unless @tag() is 'TERMINATOR'
234
+ true
235
+
236
+ # Tokens to explicitly escape newlines are removed once their job is done.
237
+ lex::suppress_newlines: (newlines) ->
238
+ @tokens.pop() if @value() is "\\"
239
+ true
240
+
241
+ # We treat all other single characters as a token. Eg.: ( ) , . !
242
+ # Multi-character operators are also literal tokens, so that Racc can assign
243
+ # the proper order of operations.
244
+ lex::literal_token: ->
245
+ match: @chunk.match(OPERATOR)
246
+ value: match and match[1]
247
+ @tag_parameters() if value and value.match(CODE)
248
+ value ||= @chunk.substr(0, 1)
249
+ not_spaced: not @prev() or not @prev().spaced
250
+ tag: value
251
+ if value.match(ASSIGNMENT)
252
+ tag: 'ASSIGN'
253
+ throw new Error('SyntaxError: Reserved word "' + @value() + '" on line ' + @line + ' can\'t be assigned') if JS_FORBIDDEN.indexOf(@value()) >= 0
254
+ else if value is ';'
255
+ tag: 'TERMINATOR'
256
+ else if value is '[' and @tag() is '?' and not_spaced
257
+ tag: 'SOAKED_INDEX_START'
258
+ @soaked_index: true
259
+ @tokens.pop()
260
+ else if value is ']' and @soaked_index
261
+ tag: 'SOAKED_INDEX_END'
262
+ @soaked_index: false
263
+ else if CALLABLE.indexOf(@tag()) >= 0 and not_spaced
264
+ tag: 'CALL_START' if value is '('
265
+ tag: 'INDEX_START' if value is '['
266
+ @token tag, value
267
+ @i += value.length
268
+ true
269
+
270
+ # Helpers =============================================================
271
+
272
+ # Add a token to the results, taking note of the line number.
273
+ lex::token: (tag, value) ->
274
+ @tokens.push([tag, value, @line])
275
+
276
+ # Look at a tag in the current token stream.
277
+ lex::tag: (index, tag) ->
278
+ return unless tok: @prev(index)
279
+ return tok[0]: tag if tag?
280
+ tok[0]
281
+
282
+ # Look at a value in the current token stream.
283
+ lex::value: (index, val) ->
284
+ return unless tok: @prev(index)
285
+ return tok[1]: val if val?
286
+ tok[1]
287
+
288
+ # Look at a previous token.
289
+ lex::prev: (index) ->
290
+ @tokens[@tokens.length - (index or 1)]
291
+
292
+ # Count the occurences of a character in a string.
293
+ lex::count: (string, letter) ->
294
+ num: 0
295
+ pos: string.indexOf(letter)
296
+ while pos isnt -1
297
+ num += 1
298
+ pos: string.indexOf(letter, pos + 1)
299
+ num
300
+
301
+ # Attempt to match a string against the current chunk, returning the indexed
302
+ # match.
303
+ lex::match: (regex, index) ->
304
+ return false unless m: @chunk.match(regex)
305
+ if m then m[index] else false
306
+
307
+ # A source of ambiguity in our grammar was parameter lists in function
308
+ # definitions (as opposed to argument lists in function calls). Tag
309
+ # parameter identifiers in order to avoid this. Also, parameter lists can
310
+ # make use of splats.
311
+ lex::tag_parameters: ->
312
+ return if @tag() isnt ')'
313
+ i: 0
314
+ while true
315
+ i += 1
316
+ tok: @prev(i)
317
+ return if not tok
318
+ switch tok[0]
319
+ when 'IDENTIFIER' then tok[0]: 'PARAM'
320
+ when ')' then tok[0]: 'PARAM_END'
321
+ when '(' then return tok[0]: 'PARAM_START'
322
+ true
323
+
324
+ # Close up all remaining open blocks. IF the first token is an indent,
325
+ # axe it.
326
+ lex::close_indentation: ->
327
+ @outdent_token(@indent)
@@ -0,0 +1,42 @@
1
+ # The Narwhal-compatibility wrapper for CoffeeScript.
2
+
3
+ # Require external dependencies.
4
+ os: require 'os'
5
+ file: require 'file'
6
+ coffee: require './coffee-script'
7
+
8
+ # Alias print to "puts", for Node.js compatibility:
9
+ puts: print
10
+
11
+ # Compile a string of CoffeeScript into JavaScript.
12
+ exports.compile: (source) ->
13
+ coffee.compile source
14
+
15
+ # Compile a given CoffeeScript file into JavaScript.
16
+ exports.compileFile: (path) ->
17
+ coffee.compile file.read path
18
+
19
+ # Make a factory for the CoffeeScript environment.
20
+ exports.makeNarwhalFactory: (path) ->
21
+ code: exports.compileFile path
22
+ factoryText: "function(require,exports,module,system,print){" + code + "/**/\n}"
23
+ if system.engine is "rhino"
24
+ Packages.org.mozilla.javascript.Context.getCurrentContext().compileFunction(global, factoryText, path, 0, null)
25
+ else
26
+ # eval requires parentheses, but parentheses break compileFunction.
27
+ eval "(" + factoryText + ")"
28
+
29
+ # The Narwhal loader for '.coffee' files.
30
+ factories: {}
31
+ loader: {}
32
+
33
+ # Reload the coffee-script environment from source.
34
+ loader.reload: (topId, path) ->
35
+ factories[topId]: ->
36
+ exports.makeNarwhalFactory path
37
+
38
+ # Ensure that the coffee-script environment is loaded.
39
+ loader.load: (topId, path) ->
40
+ factories[topId] ||= this.reload topId, path
41
+
42
+ require.loader.loaders.unshift [".coffee", loader]