haml-more 0.4.0.a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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]