opal-cj 0.7.0.beta1

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 (470) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.gitmodules +27 -0
  4. data/.rspec +3 -0
  5. data/.spectator +2 -0
  6. data/.spectator-mspec +3 -0
  7. data/.travis.yml +45 -0
  8. data/CHANGELOG.md +406 -0
  9. data/CONTRIBUTING.md +41 -0
  10. data/Gemfile +27 -0
  11. data/Guardfile +77 -0
  12. data/LICENSE +19 -0
  13. data/README.md +178 -0
  14. data/Rakefile +116 -0
  15. data/benchmarks/operators.rb +11 -0
  16. data/bin/opal +22 -0
  17. data/bin/opal-build +77 -0
  18. data/bin/opal-mspec +10 -0
  19. data/bin/opal-repl +72 -0
  20. data/config.ru +14 -0
  21. data/examples/rack/Gemfile +3 -0
  22. data/examples/rack/app/application.rb +13 -0
  23. data/examples/rack/app/user.rb +21 -0
  24. data/examples/rack/config.ru +7 -0
  25. data/examples/rack/index.html.erb +10 -0
  26. data/examples/sinatra/Gemfile +4 -0
  27. data/examples/sinatra/app/application.rb +7 -0
  28. data/examples/sinatra/config.ru +28 -0
  29. data/lib/mspec/opal/main.rb.erb +9 -0
  30. data/lib/mspec/opal/rake_task.rb +278 -0
  31. data/lib/mspec/opal/runner.rb +206 -0
  32. data/lib/mspec/opal/sprockets.js +57 -0
  33. data/lib/opal.rb +11 -0
  34. data/lib/opal/builder.rb +135 -0
  35. data/lib/opal/builder_processors.rb +165 -0
  36. data/lib/opal/cli.rb +145 -0
  37. data/lib/opal/cli_options.rb +149 -0
  38. data/lib/opal/cli_runners.rb +10 -0
  39. data/lib/opal/cli_runners/nodejs.rb +56 -0
  40. data/lib/opal/cli_runners/phantom.js +35 -0
  41. data/lib/opal/cli_runners/phantomjs.rb +28 -0
  42. data/lib/opal/cli_runners/server.rb +54 -0
  43. data/lib/opal/compiler.rb +307 -0
  44. data/lib/opal/erb.rb +64 -0
  45. data/lib/opal/fragment.rb +41 -0
  46. data/lib/opal/hike_path_finder.rb +18 -0
  47. data/lib/opal/nodes.rb +26 -0
  48. data/lib/opal/nodes/arglist.rb +56 -0
  49. data/lib/opal/nodes/array.rb +54 -0
  50. data/lib/opal/nodes/base.rb +151 -0
  51. data/lib/opal/nodes/call.rb +283 -0
  52. data/lib/opal/nodes/call_special.rb +178 -0
  53. data/lib/opal/nodes/case.rb +96 -0
  54. data/lib/opal/nodes/class.rb +42 -0
  55. data/lib/opal/nodes/constants.rb +78 -0
  56. data/lib/opal/nodes/def.rb +157 -0
  57. data/lib/opal/nodes/defined.rb +113 -0
  58. data/lib/opal/nodes/definitions.rb +168 -0
  59. data/lib/opal/nodes/for.rb +35 -0
  60. data/lib/opal/nodes/hash.rb +67 -0
  61. data/lib/opal/nodes/helpers.rb +114 -0
  62. data/lib/opal/nodes/if.rb +67 -0
  63. data/lib/opal/nodes/iter.rb +131 -0
  64. data/lib/opal/nodes/literal.rb +230 -0
  65. data/lib/opal/nodes/logic.rb +217 -0
  66. data/lib/opal/nodes/masgn.rb +62 -0
  67. data/lib/opal/nodes/module.rb +46 -0
  68. data/lib/opal/nodes/rescue.rb +135 -0
  69. data/lib/opal/nodes/runtime_helpers.rb +45 -0
  70. data/lib/opal/nodes/scope.rb +293 -0
  71. data/lib/opal/nodes/singleton_class.rb +25 -0
  72. data/lib/opal/nodes/super.rb +97 -0
  73. data/lib/opal/nodes/top.rb +101 -0
  74. data/lib/opal/nodes/variables.rb +158 -0
  75. data/lib/opal/nodes/while.rb +65 -0
  76. data/lib/opal/nodes/yield.rb +95 -0
  77. data/lib/opal/parser.rb +658 -0
  78. data/lib/opal/parser/grammar.rb +5452 -0
  79. data/lib/opal/parser/grammar.y +1684 -0
  80. data/lib/opal/parser/keywords.rb +66 -0
  81. data/lib/opal/parser/lexer.rb +1208 -0
  82. data/lib/opal/parser/parser_scope.rb +25 -0
  83. data/lib/opal/parser/sexp.rb +75 -0
  84. data/lib/opal/path_reader.rb +28 -0
  85. data/lib/opal/paths.rb +38 -0
  86. data/lib/opal/source_map.rb +70 -0
  87. data/lib/opal/sprockets.rb +4 -0
  88. data/lib/opal/sprockets/cache_key_fix.rb +17 -0
  89. data/lib/opal/sprockets/environment.rb +37 -0
  90. data/lib/opal/sprockets/erb.rb +37 -0
  91. data/lib/opal/sprockets/path_reader.rb +34 -0
  92. data/lib/opal/sprockets/processor.rb +124 -0
  93. data/lib/opal/sprockets/server.rb +180 -0
  94. data/lib/opal/util.rb +64 -0
  95. data/lib/opal/version.rb +3 -0
  96. data/opal.gemspec +36 -0
  97. data/opal/README.md +6 -0
  98. data/opal/corelib/array.rb +1556 -0
  99. data/opal/corelib/array/inheritance.rb +113 -0
  100. data/opal/corelib/basic_object.rb +73 -0
  101. data/opal/corelib/boolean.rb +41 -0
  102. data/opal/corelib/class.rb +55 -0
  103. data/opal/corelib/comparable.rb +56 -0
  104. data/opal/corelib/complex.rb +3 -0
  105. data/opal/corelib/dir.rb +20 -0
  106. data/opal/corelib/enumerable.rb +1132 -0
  107. data/opal/corelib/enumerator.rb +422 -0
  108. data/opal/corelib/error.rb +63 -0
  109. data/opal/corelib/file.rb +56 -0
  110. data/opal/corelib/hash.rb +728 -0
  111. data/opal/corelib/helpers.rb +102 -0
  112. data/opal/corelib/io.rb +59 -0
  113. data/opal/corelib/kernel.rb +569 -0
  114. data/opal/corelib/main.rb +7 -0
  115. data/opal/corelib/match_data.rb +114 -0
  116. data/opal/corelib/method.rb +58 -0
  117. data/opal/corelib/module.rb +462 -0
  118. data/opal/corelib/nil_class.rb +62 -0
  119. data/opal/corelib/numeric.rb +532 -0
  120. data/opal/corelib/proc.rb +52 -0
  121. data/opal/corelib/range.rb +116 -0
  122. data/opal/corelib/rational.rb +3 -0
  123. data/opal/corelib/regexp.rb +133 -0
  124. data/opal/corelib/runtime.js +1240 -0
  125. data/opal/corelib/string.rb +1212 -0
  126. data/opal/corelib/string/inheritance.rb +78 -0
  127. data/opal/corelib/struct.rb +141 -0
  128. data/opal/corelib/time.rb +584 -0
  129. data/opal/corelib/variables.rb +24 -0
  130. data/opal/opal.rb +32 -0
  131. data/package.json +9 -0
  132. data/spec/filters/bugs/array.rb +232 -0
  133. data/spec/filters/bugs/basic_object.rb +14 -0
  134. data/spec/filters/bugs/class.rb +21 -0
  135. data/spec/filters/bugs/enumerable.rb +69 -0
  136. data/spec/filters/bugs/enumerator.rb +3 -0
  137. data/spec/filters/bugs/hash.rb +128 -0
  138. data/spec/filters/bugs/kernel.rb +10 -0
  139. data/spec/filters/bugs/language.rb +415 -0
  140. data/spec/filters/bugs/math.rb +95 -0
  141. data/spec/filters/bugs/module.rb +14 -0
  142. data/spec/filters/bugs/nil.rb +7 -0
  143. data/spec/filters/bugs/numeric.rb +20 -0
  144. data/spec/filters/bugs/opal.rb +14 -0
  145. data/spec/filters/bugs/regexp.rb +11 -0
  146. data/spec/filters/bugs/set.rb +7 -0
  147. data/spec/filters/bugs/singleton.rb +6 -0
  148. data/spec/filters/bugs/string.rb +360 -0
  149. data/spec/filters/bugs/stringscanner.rb +22 -0
  150. data/spec/filters/bugs/struct.rb +45 -0
  151. data/spec/filters/bugs/time.rb +177 -0
  152. data/spec/filters/bugs/unknown.rb +11 -0
  153. data/spec/filters/unsupported/encoding.rb +95 -0
  154. data/spec/filters/unsupported/enumerator.rb +14 -0
  155. data/spec/filters/unsupported/float.rb +5 -0
  156. data/spec/filters/unsupported/frozen.rb +90 -0
  157. data/spec/filters/unsupported/hash_compare_by_identity.rb +16 -0
  158. data/spec/filters/unsupported/integer_size.rb +7 -0
  159. data/spec/filters/unsupported/method_added.rb +10 -0
  160. data/spec/filters/unsupported/mutable_strings.rb +361 -0
  161. data/spec/filters/unsupported/private_constants.rb +30 -0
  162. data/spec/filters/unsupported/private_methods.rb +44 -0
  163. data/spec/filters/unsupported/random.rb +4 -0
  164. data/spec/filters/unsupported/ruby_exe.rb +5 -0
  165. data/spec/filters/unsupported/tainted.rb +155 -0
  166. data/spec/filters/unsupported/time.rb +21 -0
  167. data/spec/filters/unsupported/trusted.rb +80 -0
  168. data/spec/lib/builder_processors_spec.rb +27 -0
  169. data/spec/lib/builder_spec.rb +66 -0
  170. data/spec/lib/cli_spec.rb +134 -0
  171. data/spec/lib/compiler_spec.rb +197 -0
  172. data/spec/lib/dependency_resolver_spec.rb +40 -0
  173. data/spec/lib/fixtures/no_requires.rb +1 -0
  174. data/spec/lib/fixtures/opal_file.rb +2 -0
  175. data/spec/lib/fixtures/require_tree_test.rb +3 -0
  176. data/spec/lib/fixtures/required_tree_test/required_file1.rb +1 -0
  177. data/spec/lib/fixtures/required_tree_test/required_file2.rb +1 -0
  178. data/spec/lib/fixtures/requires.rb +7 -0
  179. data/spec/lib/fixtures/sprockets_file.js.rb +3 -0
  180. data/spec/lib/fixtures/sprockets_require_tree_test.rb +3 -0
  181. data/spec/lib/hike_path_finder_spec.rb +23 -0
  182. data/spec/lib/lexer_spec.rb +110 -0
  183. data/spec/lib/parser/alias_spec.rb +26 -0
  184. data/spec/lib/parser/and_spec.rb +13 -0
  185. data/spec/lib/parser/attrasgn_spec.rb +28 -0
  186. data/spec/lib/parser/begin_spec.rb +42 -0
  187. data/spec/lib/parser/block_spec.rb +12 -0
  188. data/spec/lib/parser/break_spec.rb +17 -0
  189. data/spec/lib/parser/call_spec.rb +139 -0
  190. data/spec/lib/parser/class_spec.rb +35 -0
  191. data/spec/lib/parser/comments_spec.rb +11 -0
  192. data/spec/lib/parser/def_spec.rb +61 -0
  193. data/spec/lib/parser/if_spec.rb +26 -0
  194. data/spec/lib/parser/iter_spec.rb +59 -0
  195. data/spec/lib/parser/lambda_spec.rb +64 -0
  196. data/spec/lib/parser/literal_spec.rb +118 -0
  197. data/spec/lib/parser/masgn_spec.rb +37 -0
  198. data/spec/lib/parser/module_spec.rb +27 -0
  199. data/spec/lib/parser/not_spec.rb +27 -0
  200. data/spec/lib/parser/op_asgn1_spec.rb +23 -0
  201. data/spec/lib/parser/op_asgn2_spec.rb +23 -0
  202. data/spec/lib/parser/or_spec.rb +13 -0
  203. data/spec/lib/parser/return_spec.rb +17 -0
  204. data/spec/lib/parser/sclass_spec.rb +21 -0
  205. data/spec/lib/parser/string_spec.rb +276 -0
  206. data/spec/lib/parser/super_spec.rb +20 -0
  207. data/spec/lib/parser/unary_spec.rb +48 -0
  208. data/spec/lib/parser/undef_spec.rb +15 -0
  209. data/spec/lib/parser/unless_spec.rb +13 -0
  210. data/spec/lib/parser/variables_spec.rb +92 -0
  211. data/spec/lib/parser/while_spec.rb +15 -0
  212. data/spec/lib/parser/yield_spec.rb +20 -0
  213. data/spec/lib/path_reader_spec.rb +24 -0
  214. data/spec/lib/shared/path_finder_shared.rb +19 -0
  215. data/spec/lib/shared/path_reader_shared.rb +31 -0
  216. data/spec/lib/spec_helper.rb +9 -0
  217. data/spec/lib/sprockets/environment_spec.rb +30 -0
  218. data/spec/lib/sprockets/erb_spec.rb +25 -0
  219. data/spec/lib/sprockets/path_reader_spec.rb +25 -0
  220. data/spec/lib/sprockets/processor_spec.rb +35 -0
  221. data/spec/lib/sprockets/server_spec.rb +20 -0
  222. data/spec/opal/compiler/irb_spec.rb +44 -0
  223. data/spec/opal/core/array/select_spec.rb +14 -0
  224. data/spec/opal/core/array/set_range_to_array_spec.rb +7 -0
  225. data/spec/opal/core/date_spec.rb +122 -0
  226. data/spec/opal/core/enumerable/all_break_spec.rb +5 -0
  227. data/spec/opal/core/enumerable/any_break_spec.rb +5 -0
  228. data/spec/opal/core/enumerable/collect_break_spec.rb +13 -0
  229. data/spec/opal/core/enumerable/count_break_spec.rb +5 -0
  230. data/spec/opal/core/enumerable/detect_break_spec.rb +5 -0
  231. data/spec/opal/core/enumerable/drop_while_break_spec.rb +5 -0
  232. data/spec/opal/core/enumerable/each_slice_break.rb +6 -0
  233. data/spec/opal/core/enumerable/each_with_index_break_spec.rb +5 -0
  234. data/spec/opal/core/enumerable/each_with_object_break_spec.rb +5 -0
  235. data/spec/opal/core/enumerable/find_all_break_spec.rb +5 -0
  236. data/spec/opal/core/enumerable/find_index_break_spec.rb +5 -0
  237. data/spec/opal/core/enumerable/grep_break_spec.rb +5 -0
  238. data/spec/opal/core/enumerable/max_break_spec.rb +5 -0
  239. data/spec/opal/core/enumerable/max_by_break_spec.rb +5 -0
  240. data/spec/opal/core/enumerable/min_break_spec.rb +5 -0
  241. data/spec/opal/core/enumerable/min_by_break_spec.rb +5 -0
  242. data/spec/opal/core/enumerable/none_break_spec.rb +5 -0
  243. data/spec/opal/core/enumerable/one_break_spec.rb +5 -0
  244. data/spec/opal/core/enumerable/reduce_break_spec.rb +5 -0
  245. data/spec/opal/core/enumerable/take_while_break_spec.rb +5 -0
  246. data/spec/opal/core/fixtures/class.rb +124 -0
  247. data/spec/opal/core/fixtures/class_variables.rb +0 -0
  248. data/spec/opal/core/fixtures/constants.rb +33 -0
  249. data/spec/opal/core/fixtures/require_tree_files/file 1.rb +1 -0
  250. data/spec/opal/core/fixtures/require_tree_files/file 2.rb +1 -0
  251. data/spec/opal/core/fixtures/require_tree_files/file 3.rb +1 -0
  252. data/spec/opal/core/fixtures/require_tree_files/file 4.rb +1 -0
  253. data/spec/opal/core/fixtures/require_tree_files/file 5.rb +1 -0
  254. data/spec/opal/core/kernel/Array_spec.rb +10 -0
  255. data/spec/opal/core/kernel/block_given_spec.rb +30 -0
  256. data/spec/opal/core/kernel/class_spec.rb +6 -0
  257. data/spec/opal/core/kernel/define_singleton_method_spec.rb +21 -0
  258. data/spec/opal/core/kernel/equal_value_spec.rb +12 -0
  259. data/spec/opal/core/kernel/extend_spec.rb +21 -0
  260. data/spec/opal/core/kernel/format_spec.rb +122 -0
  261. data/spec/opal/core/kernel/freeze_spec.rb +15 -0
  262. data/spec/opal/core/kernel/instance_eval_spec.rb +28 -0
  263. data/spec/opal/core/kernel/instance_variable_defined_spec.rb +15 -0
  264. data/spec/opal/core/kernel/instance_variable_get_spec.rb +14 -0
  265. data/spec/opal/core/kernel/instance_variable_set_spec.rb +10 -0
  266. data/spec/opal/core/kernel/loop_spec.rb +23 -0
  267. data/spec/opal/core/kernel/match_spec.rb +5 -0
  268. data/spec/opal/core/kernel/method_spec.rb +31 -0
  269. data/spec/opal/core/kernel/methods_spec.rb +25 -0
  270. data/spec/opal/core/kernel/nil_spec.rb +7 -0
  271. data/spec/opal/core/kernel/p_spec.rb +15 -0
  272. data/spec/opal/core/kernel/printf_spec.rb +11 -0
  273. data/spec/opal/core/kernel/proc_spec.rb +13 -0
  274. data/spec/opal/core/kernel/rand_spec.rb +23 -0
  275. data/spec/opal/core/kernel/require_tree_spec.rb +7 -0
  276. data/spec/opal/core/kernel/respond_to_spec.rb +41 -0
  277. data/spec/opal/core/kernel/send_spec.rb +56 -0
  278. data/spec/opal/core/kernel/sprintf_spec.rb +5 -0
  279. data/spec/opal/core/language/block_spec.rb +538 -0
  280. data/spec/opal/core/language/fixtures/array.rb +11 -0
  281. data/spec/opal/core/language/fixtures/block.rb +57 -0
  282. data/spec/opal/core/language/fixtures/break.rb +240 -0
  283. data/spec/opal/core/language/fixtures/ensure.rb +72 -0
  284. data/spec/opal/core/language/fixtures/literal_lambda.rb +7 -0
  285. data/spec/opal/core/language/fixtures/metaclass.rb +33 -0
  286. data/spec/opal/core/language/fixtures/module.rb +24 -0
  287. data/spec/opal/core/language/fixtures/next.rb +128 -0
  288. data/spec/opal/core/language/fixtures/return.rb +118 -0
  289. data/spec/opal/core/language/fixtures/send.rb +110 -0
  290. data/spec/opal/core/language/fixtures/send_1.9.rb +22 -0
  291. data/spec/opal/core/language/fixtures/super.rb +308 -0
  292. data/spec/opal/core/language/fixtures/variables.rb +58 -0
  293. data/spec/opal/core/language/fixtures/yield.rb +28 -0
  294. data/spec/opal/core/language/predefined_spec.rb +85 -0
  295. data/spec/opal/core/language/proc_spec.rb +263 -0
  296. data/spec/opal/core/language/regexp_spec.rb +20 -0
  297. data/spec/opal/core/language/send_spec.rb +225 -0
  298. data/spec/opal/core/language/string_spec.rb +44 -0
  299. data/spec/opal/core/language/symbol_spec.rb +40 -0
  300. data/spec/opal/core/language/variables_spec.rb +1366 -0
  301. data/spec/opal/core/language/versions/array_1.9.rb +39 -0
  302. data/spec/opal/core/language/versions/block_1.9.rb +0 -0
  303. data/spec/opal/core/language/versions/break_1.9.rb +0 -0
  304. data/spec/opal/core/language/versions/case_1.9.rb +20 -0
  305. data/spec/opal/core/language/versions/hash_1.9.rb +18 -0
  306. data/spec/opal/core/language/versions/literal_lambda_1.9.rb +143 -0
  307. data/spec/opal/core/language/versions/not_1.9.rb +22 -0
  308. data/spec/opal/core/language/versions/send_1.9.rb +241 -0
  309. data/spec/opal/core/language/versions/symbol_1.9.rb +15 -0
  310. data/spec/opal/core/language/versions/variables_1.9.rb +8 -0
  311. data/spec/opal/core/module/alias_method_spec.rb +28 -0
  312. data/spec/opal/core/module/ancestors_spec.rb +11 -0
  313. data/spec/opal/core/module/append_features_spec.rb +14 -0
  314. data/spec/opal/core/module/attr_accessor_spec.rb +26 -0
  315. data/spec/opal/core/module/const_defined_spec.rb +85 -0
  316. data/spec/opal/core/module/const_get_spec.rb +85 -0
  317. data/spec/opal/core/module/const_missing_spec.rb +17 -0
  318. data/spec/opal/core/module/const_set_spec.rb +64 -0
  319. data/spec/opal/core/module/constants_spec.rb +49 -0
  320. data/spec/opal/core/module/fixtures/classes.rb +434 -0
  321. data/spec/opal/core/module/method_defined_spec.rb +48 -0
  322. data/spec/opal/core/module/module_function_spec.rb +25 -0
  323. data/spec/opal/core/module/name_spec.rb +52 -0
  324. data/spec/opal/core/module/public_method_defined_spec.rb +18 -0
  325. data/spec/opal/core/module/remove_const_spec.rb +22 -0
  326. data/spec/opal/core/module/undef_method_spec.rb +66 -0
  327. data/spec/opal/core/numeric/bit_and_spec.rb +7 -0
  328. data/spec/opal/core/numeric/bit_or_spec.rb +8 -0
  329. data/spec/opal/core/numeric/bit_xor_spec.rb +6 -0
  330. data/spec/opal/core/numeric/ceil_spec.rb +8 -0
  331. data/spec/opal/core/numeric/chr_spec.rb +8 -0
  332. data/spec/opal/core/numeric/comparison_spec.rb +24 -0
  333. data/spec/opal/core/numeric/complement_spec.rb +8 -0
  334. data/spec/opal/core/numeric/divide_spec.rb +10 -0
  335. data/spec/opal/core/numeric/eql_spec.rb +9 -0
  336. data/spec/opal/core/numeric/exponent_spec.rb +33 -0
  337. data/spec/opal/core/numeric/floor_spec.rb +8 -0
  338. data/spec/opal/core/numeric/gt_spec.rb +11 -0
  339. data/spec/opal/core/numeric/gte_spec.rb +12 -0
  340. data/spec/opal/core/numeric/integer_spec.rb +9 -0
  341. data/spec/opal/core/numeric/left_shift_spec.rb +21 -0
  342. data/spec/opal/core/numeric/lt_spec.rb +11 -0
  343. data/spec/opal/core/numeric/lte_spec.rb +12 -0
  344. data/spec/opal/core/numeric/minus_spec.rb +8 -0
  345. data/spec/opal/core/numeric/modulo_spec.rb +19 -0
  346. data/spec/opal/core/numeric/multiply_spec.rb +9 -0
  347. data/spec/opal/core/numeric/next_spec.rb +9 -0
  348. data/spec/opal/core/numeric/ord_spec.rb +9 -0
  349. data/spec/opal/core/numeric/plus_spec.rb +8 -0
  350. data/spec/opal/core/numeric/pred_spec.rb +7 -0
  351. data/spec/opal/core/numeric/right_shift_spec.rb +25 -0
  352. data/spec/opal/core/numeric/step_spec.rb +11 -0
  353. data/spec/opal/core/numeric/succ_spec.rb +9 -0
  354. data/spec/opal/core/numeric/times_spec.rb +36 -0
  355. data/spec/opal/core/numeric/to_f_spec.rb +7 -0
  356. data/spec/opal/core/numeric/to_i_spec.rb +7 -0
  357. data/spec/opal/core/numeric/to_json_spec.rb +8 -0
  358. data/spec/opal/core/numeric/to_s_spec.rb +26 -0
  359. data/spec/opal/core/numeric/uminus_spec.rb +9 -0
  360. data/spec/opal/core/numeric/upto_spec.rb +19 -0
  361. data/spec/opal/core/numeric/zero_spec.rb +7 -0
  362. data/spec/opal/core/proc/call_spec.rb +21 -0
  363. data/spec/opal/core/proc/element_reference_spec.rb +21 -0
  364. data/spec/opal/core/proc/proc_tricks_spec.rb +7 -0
  365. data/spec/opal/core/runtime/begin_spec.rb +39 -0
  366. data/spec/opal/core/runtime/block_send_spec.rb +28 -0
  367. data/spec/opal/core/runtime/block_spec.rb +23 -0
  368. data/spec/opal/core/runtime/bridged_classes_spec.rb +64 -0
  369. data/spec/opal/core/runtime/constants_spec.rb +13 -0
  370. data/spec/opal/core/runtime/eval_spec.rb +5 -0
  371. data/spec/opal/core/runtime/main_methods_spec.rb +27 -0
  372. data/spec/opal/core/runtime/method_missing_spec.rb +62 -0
  373. data/spec/opal/core/runtime/method_spec.rb +31 -0
  374. data/spec/opal/core/runtime/operator_call_spec.rb +13 -0
  375. data/spec/opal/core/runtime/paren_spec.rb +14 -0
  376. data/spec/opal/core/runtime/rescue_spec.rb +38 -0
  377. data/spec/opal/core/runtime/return_spec.rb +38 -0
  378. data/spec/opal/core/runtime/send_spec.rb +34 -0
  379. data/spec/opal/core/runtime/singleton_class_spec.rb +13 -0
  380. data/spec/opal/core/runtime/super_spec.rb +212 -0
  381. data/spec/opal/core/runtime/truthy_spec.rb +23 -0
  382. data/spec/opal/core/runtime/variables_spec.rb +20 -0
  383. data/spec/opal/core/source_map_spec.rb +15 -0
  384. data/spec/opal/core/string_spec.rb +11 -0
  385. data/spec/opal/stdlib/erb/erb_spec.rb +30 -0
  386. data/spec/opal/stdlib/erb/inline_block.opalerb +3 -0
  387. data/spec/opal/stdlib/erb/quoted.opalerb +1 -0
  388. data/spec/opal/stdlib/erb/simple.opalerb +1 -0
  389. data/spec/opal/stdlib/json/ext_spec.rb +48 -0
  390. data/spec/opal/stdlib/json/parse_spec.rb +33 -0
  391. data/spec/opal/stdlib/native/alias_native_spec.rb +27 -0
  392. data/spec/opal/stdlib/native/each_spec.rb +13 -0
  393. data/spec/opal/stdlib/native/element_reference_spec.rb +16 -0
  394. data/spec/opal/stdlib/native/exposure_spec.rb +33 -0
  395. data/spec/opal/stdlib/native/ext_spec.rb +19 -0
  396. data/spec/opal/stdlib/native/initialize_spec.rb +17 -0
  397. data/spec/opal/stdlib/native/method_missing_spec.rb +51 -0
  398. data/spec/opal/stdlib/native/native_reader_spec.rb +22 -0
  399. data/spec/opal/stdlib/native/native_writer_spec.rb +30 -0
  400. data/spec/opal/stdlib/native/new_spec.rb +8 -0
  401. data/spec/opal/stdlib/promise/error_spec.rb +15 -0
  402. data/spec/opal/stdlib/promise/rescue_spec.rb +35 -0
  403. data/spec/opal/stdlib/promise/then_spec.rb +54 -0
  404. data/spec/opal/stdlib/promise/trace_spec.rb +35 -0
  405. data/spec/opal/stdlib/promise/value_spec.rb +15 -0
  406. data/spec/opal/stdlib/promise/when_spec.rb +34 -0
  407. data/spec/opal/stdlib/template/paths_spec.rb +10 -0
  408. data/spec/opal/stdlib/thread/mutex_spec.rb +40 -0
  409. data/spec/opal/stdlib/thread/thread_queue_spec.rb +32 -0
  410. data/spec/opal/stdlib/thread/thread_spec.rb +60 -0
  411. data/spec/rubyspecs +329 -0
  412. data/spec/spec_helper.rb +42 -0
  413. data/spec/support/mspec_rspec_adapter.rb +33 -0
  414. data/spec/support/parser_helpers.rb +37 -0
  415. data/stdlib/README.md +3 -0
  416. data/stdlib/base64.rb +152 -0
  417. data/stdlib/benchmark.rb +10 -0
  418. data/stdlib/buffer.rb +40 -0
  419. data/stdlib/buffer/array.rb +66 -0
  420. data/stdlib/buffer/view.rb +70 -0
  421. data/stdlib/date.rb +170 -0
  422. data/stdlib/delegate.rb +29 -0
  423. data/stdlib/dir.rb +1 -0
  424. data/stdlib/encoding.rb +166 -0
  425. data/stdlib/enumerator.rb +1 -0
  426. data/stdlib/erb.rb +16 -0
  427. data/stdlib/file.rb +1 -0
  428. data/stdlib/forwardable.rb +71 -0
  429. data/stdlib/json.rb +182 -0
  430. data/stdlib/math.rb +370 -0
  431. data/stdlib/native.rb +530 -0
  432. data/stdlib/nodejs.rb +5 -0
  433. data/stdlib/nodejs/dir.rb +13 -0
  434. data/stdlib/nodejs/file.rb +98 -0
  435. data/stdlib/nodejs/fileutils.rb +26 -0
  436. data/stdlib/nodejs/io.rb +2 -0
  437. data/stdlib/nodejs/irb.rb +45 -0
  438. data/stdlib/nodejs/process.rb +16 -0
  439. data/stdlib/nodejs/require.rb +32 -0
  440. data/stdlib/nodejs/rubygems.rb +68 -0
  441. data/stdlib/nodejs/runtime.rb +25 -0
  442. data/stdlib/nodejs/yaml.rb +11 -0
  443. data/stdlib/observer.rb +202 -0
  444. data/stdlib/opal-parser.rb +53 -0
  445. data/stdlib/opal-source-maps.rb +2 -0
  446. data/stdlib/ostruct.rb +69 -0
  447. data/stdlib/pathname.rb +31 -0
  448. data/stdlib/phantomjs.rb +8 -0
  449. data/stdlib/pp.rb +12 -0
  450. data/stdlib/process.rb +10 -0
  451. data/stdlib/promise.rb +300 -0
  452. data/stdlib/racc/parser.rb +215 -0
  453. data/stdlib/rbconfig.rb +20 -0
  454. data/stdlib/securerandom.rb +12 -0
  455. data/stdlib/set.rb +116 -0
  456. data/stdlib/singleton.rb +40 -0
  457. data/stdlib/source_map.rb +5 -0
  458. data/stdlib/source_map/map.rb +220 -0
  459. data/stdlib/source_map/mapping.rb +26 -0
  460. data/stdlib/source_map/offset.rb +88 -0
  461. data/stdlib/source_map/version.rb +3 -0
  462. data/stdlib/source_map/vlq.rb +98 -0
  463. data/stdlib/sourcemap.rb +1 -0
  464. data/stdlib/stringio.rb +181 -0
  465. data/stdlib/strscan.rb +155 -0
  466. data/stdlib/template.rb +46 -0
  467. data/stdlib/thread.rb +160 -0
  468. data/stdlib/time.rb +9 -0
  469. data/tasks/github.rake +19 -0
  470. metadata +690 -0
@@ -0,0 +1,66 @@
1
+ module Opal
2
+ module Keywords
3
+
4
+ class KeywordTable
5
+ attr_accessor :name, :id, :state
6
+
7
+ def initialize(name, id, state)
8
+ @name = name
9
+ @id = id
10
+ @state = state
11
+ end
12
+ end
13
+
14
+ KEYWORDS = [
15
+ ["__LINE__", [:k__LINE__, :k__LINE__], :expr_end],
16
+ ["__FILE__", [:k__FILE__, :k__FILE__], :expr_end],
17
+ ["alias", [:kALIAS, :kALIAS], :expr_fname],
18
+ ["and", [:kAND, :kAND], :expr_beg],
19
+ ["begin", [:kBEGIN, :kBEGIN], :expr_beg],
20
+ ["break", [:kBREAK, :kBREAK], :expr_mid],
21
+ ["case", [:kCASE, :kCASE], :expr_beg],
22
+ ["class", [:kCLASS, :kCLASS], :expr_class],
23
+ ["def", [:kDEF, :kDEF], :expr_fname],
24
+ ["defined?", [:kDEFINED, :kDEFINED], :expr_arg],
25
+ ["do", [:kDO, :kDO], :expr_beg],
26
+ ["else", [:kELSE, :kELSE], :expr_beg],
27
+ ["elsif", [:kELSIF, :kELSIF], :expr_beg],
28
+ ["end", [:kEND, :kEND], :expr_end],
29
+ ["ensure", [:kENSURE, :kENSURE], :expr_beg],
30
+ ["false", [:kFALSE, :kFALSE], :expr_end],
31
+ ["for", [:kFOR, :kFOR], :expr_beg],
32
+ ["if", [:kIF, :kIF_MOD], :expr_beg],
33
+ ["in", [:kIN, :kIN], :expr_beg],
34
+ ["module", [:kMODULE, :kMODULE], :expr_beg],
35
+ ["nil", [:kNIL, :kNIL], :expr_end],
36
+ ["next", [:kNEXT, :kNEXT], :expr_mid],
37
+ ["not", [:kNOT, :kNOT], :expr_beg],
38
+ ["or", [:kOR, :kOR], :expr_beg],
39
+ ["redo", [:kREDO, :kREDO], :expr_end],
40
+ ["rescue", [:kRESCUE, :kRESCUE_MOD], :expr_mid],
41
+ ["return", [:kRETURN, :kRETURN], :expr_mid],
42
+ ["self", [:kSELF, :kSELF], :expr_end],
43
+ ["super", [:kSUPER, :kSUPER], :expr_arg],
44
+ ["then", [:kTHEN, :kTHEN], :expr_beg],
45
+ ["true", [:kTRUE, :kTRUE], :expr_end],
46
+ ["undef", [:kUNDEF, :kUNDEF], :expr_fname],
47
+ ["unless", [:kUNLESS, :kUNLESS_MOD], :expr_beg],
48
+ ["until", [:kUNTIL, :kUNTIL_MOD], :expr_beg],
49
+ ["when", [:kWHEN, :kWHEN], :expr_beg],
50
+ ["while", [:kWHILE, :kWHILE_MOD], :expr_beg],
51
+ ["yield", [:kYIELD, :kYIELD], :expr_arg]
52
+ ].map { |decl| KeywordTable.new(*decl) }
53
+
54
+ def self.map
55
+ unless @map
56
+ @map = {}
57
+ KEYWORDS.each { |k| @map[k.name] = k }
58
+ end
59
+ @map
60
+ end
61
+
62
+ def self.keyword(kw)
63
+ map[kw]
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,1208 @@
1
+ require 'strscan'
2
+ require 'opal/parser/keywords'
3
+
4
+ module Opal
5
+ class Lexer
6
+
7
+ STR_FUNC_ESCAPE = 0x01
8
+ STR_FUNC_EXPAND = 0x02
9
+ STR_FUNC_REGEXP = 0x04
10
+ STR_FUNC_QWORDS = 0x08
11
+ STR_FUNC_SYMBOL = 0x10
12
+ STR_FUNC_INDENT = 0x20
13
+ STR_FUNC_XQUOTE = 0x40
14
+
15
+ STR_SQUOTE = 0x00
16
+ STR_DQUOTE = STR_FUNC_EXPAND
17
+ STR_XQUOTE = STR_FUNC_EXPAND | STR_FUNC_XQUOTE
18
+ STR_REGEXP = STR_FUNC_REGEXP | STR_FUNC_ESCAPE | STR_FUNC_EXPAND
19
+ STR_SWORD = STR_FUNC_QWORDS
20
+ STR_DWORD = STR_FUNC_QWORDS | STR_FUNC_EXPAND
21
+ STR_SSYM = STR_FUNC_SYMBOL
22
+ STR_DSYM = STR_FUNC_SYMBOL | STR_FUNC_EXPAND
23
+
24
+ attr_reader :line, :column
25
+ attr_reader :scope
26
+ attr_reader :eof_content
27
+
28
+ attr_accessor :lex_state
29
+ attr_accessor :strterm
30
+ attr_accessor :scanner
31
+ attr_accessor :yylval
32
+ attr_accessor :parser
33
+
34
+ def initialize(source, file)
35
+ @lex_state = :expr_beg
36
+ @cond = 0
37
+ @cmdarg = 0
38
+ @line = 1
39
+ @tok_line = 1
40
+ @column = 0
41
+ @tok_column = 0
42
+ @file = file
43
+
44
+ @scanner = StringScanner.new(source)
45
+ @scanner_stack = [@scanner]
46
+
47
+ @case_stmt = nil
48
+ @start_of_lambda = nil
49
+ end
50
+
51
+ def has_local?(local)
52
+ parser.scope.has_local?(local.to_sym)
53
+ end
54
+
55
+ def cond_push(n)
56
+ @cond = (@cond << 1) | (n & 1)
57
+ end
58
+
59
+ def cond_pop
60
+ @cond = @cond >> 1
61
+ end
62
+
63
+ def cond_lexpop
64
+ @cond = (@cond >> 1) | (@cond & 1)
65
+ end
66
+
67
+ def cond?
68
+ (@cond & 1) != 0
69
+ end
70
+
71
+ def cmdarg_push(n)
72
+ @cmdarg = (@cmdarg << 1) | (n & 1)
73
+ end
74
+
75
+ def cmdarg_pop
76
+ @cmdarg = @cmdarg >> 1
77
+ end
78
+
79
+ def cmdarg_lexpop
80
+ @cmdarg = (@cmdarg >> 1) | (@cmdarg & 1)
81
+ end
82
+
83
+ def cmdarg?
84
+ (@cmdarg & 1) != 0
85
+ end
86
+
87
+ def arg?
88
+ [:expr_arg, :expr_cmdarg].include? @lex_state
89
+ end
90
+
91
+ def end?
92
+ [:expr_end, :expr_endarg, :expr_endfn].include? @lex_state
93
+ end
94
+
95
+ def beg?
96
+ [:expr_beg, :expr_value, :expr_mid, :expr_class].include? @lex_state
97
+ end
98
+
99
+ def after_operator?
100
+ [:expr_fname, :expr_dot].include? @lex_state
101
+ end
102
+
103
+ def spcarg?
104
+ arg? and @space_seen and !space?
105
+ end
106
+
107
+ def space?
108
+ @scanner.check(/\s/)
109
+ end
110
+
111
+ def set_arg_state
112
+ @lex_state = after_operator? ? :expr_arg : :expr_beg
113
+ end
114
+
115
+ def scan(regexp)
116
+ if result = @scanner.scan(regexp)
117
+ @column += result.length
118
+ @yylval += @scanner.matched
119
+ end
120
+
121
+ result
122
+ end
123
+
124
+ def skip(regexp)
125
+ if result = @scanner.scan(regexp)
126
+ @column += result.length
127
+ @tok_column = @column
128
+ end
129
+
130
+ result
131
+ end
132
+
133
+ def check(regexp)
134
+ @scanner.check regexp
135
+ end
136
+
137
+ def pushback(n)
138
+ @scanner.pos -= n
139
+ end
140
+
141
+ def matched
142
+ @scanner.matched
143
+ end
144
+
145
+ def line=(line)
146
+ @column = @tok_column = 0
147
+ @line = @tok_line = line
148
+ end
149
+
150
+ def next_token
151
+ token = self.yylex
152
+ value = self.yylval
153
+ location = [@tok_line, @tok_column]
154
+
155
+ # once location is stored, ensure next token starts in correct place
156
+ @tok_column = @column
157
+ @tok_line = @line
158
+
159
+ [token, [value, location]]
160
+ end
161
+
162
+ def new_strterm(func, term, paren)
163
+ { :type => :string, :func => func, :term => term, :paren => paren }
164
+ end
165
+
166
+ def new_strterm2(func, term, paren)
167
+ term = new_strterm(func, term, paren)
168
+ term.merge({ :balance => true, :nesting => 0 })
169
+ end
170
+
171
+ def new_op_asgn(value)
172
+ self.yylval = value
173
+ :tOP_ASGN
174
+ end
175
+
176
+ def process_numeric
177
+ @lex_state = :expr_end
178
+
179
+ if scan(/[\d_]+\.[\d_]+\b|[\d_]+(\.[\d_]+)?[eE][-+]?[\d_]+\b/) # FLOATS
180
+ self.yylval = scanner.matched.gsub(/_/, '').to_f
181
+ return :tFLOAT
182
+ elsif scan(/([^0][\d_]*|0)\b/) # BASE 10
183
+ self.yylval = scanner.matched.gsub(/_/, '').to_i
184
+ return :tINTEGER
185
+ elsif scan(/0[bB](0|1|_)+/) # BASE 2
186
+ self.yylval = scanner.matched.to_i(2)
187
+ return :tINTEGER
188
+ elsif scan(/0[xX](\d|[a-f]|[A-F]|_)+/) # BASE 16
189
+ self.yylval = scanner.matched.to_i(16)
190
+ return :tINTEGER
191
+ elsif scan(/0[oO]?([0-7]|_)+/) # BASE 8
192
+ self.yylval = scanner.matched.to_i(8)
193
+ return :tINTEGER
194
+ elsif scan(/0[dD]([0-9]|_)+/) # BASE 10
195
+ self.yylval = scanner.matched.gsub(/_/, '').to_i
196
+ return :tINTEGER
197
+ else
198
+ raise "Lexing error on numeric type: `#{scanner.peek 5}`"
199
+ end
200
+ end
201
+
202
+ def read_escape
203
+ if scan(/\\/)
204
+ "\\"
205
+ elsif scan(/n/)
206
+ "\n"
207
+ elsif scan(/t/)
208
+ "\t"
209
+ elsif scan(/r/)
210
+ "\r"
211
+ elsif scan(/f/)
212
+ "\f"
213
+ elsif scan(/v/)
214
+ "\v"
215
+ elsif scan(/a/)
216
+ "\a"
217
+ elsif scan(/e/)
218
+ "\e"
219
+ elsif scan(/s/)
220
+ " "
221
+ elsif scan(/[0-7]{1,3}/)
222
+ (matched.to_i(8) % 0x100).chr
223
+ elsif scan(/x([0-9a-fA-F]{1,2})/)
224
+ scanner[1].to_i(16).chr
225
+ elsif scan(/u([0-9a-zA-Z]{1,4})/)
226
+ if defined?(::Encoding)
227
+ scanner[1].to_i(16).chr(Encoding::UTF_8)
228
+ else
229
+ # FIXME: no encoding on 1.8
230
+ ""
231
+ end
232
+ else
233
+ # escaped char doesnt need escaping, so just return it
234
+ scan(/./)
235
+ end
236
+ end
237
+
238
+ def peek_variable_name
239
+ if check(/[@$]/)
240
+ :tSTRING_DVAR
241
+ elsif scan(/\{/)
242
+ :tSTRING_DBEG
243
+ end
244
+ end
245
+
246
+ def here_document(str_parse)
247
+ eos_regx = /[ \t]*#{Regexp.escape(str_parse[:term])}(\r*\n|$)/
248
+ expand = true
249
+
250
+ # Don't escape single-quoted heredoc identifiers
251
+ escape = str_parse[:func] != STR_SQUOTE
252
+
253
+ if check(eos_regx)
254
+ scan(/[ \t]*#{Regexp.escape(str_parse[:term])}/)
255
+
256
+ if str_parse[:scanner]
257
+ @scanner_stack << str_parse[:scanner]
258
+ @scanner = str_parse[:scanner]
259
+ end
260
+
261
+ return :tSTRING_END
262
+ end
263
+
264
+ str_buffer = []
265
+
266
+ if scan(/#/)
267
+ if tok = peek_variable_name
268
+ return tok
269
+ end
270
+
271
+ str_buffer << '#'
272
+ end
273
+
274
+ until check(eos_regx) && scanner.bol?
275
+ if scanner.eos?
276
+ raise "reached EOF while in heredoc"
277
+ end
278
+
279
+ if scan(/\n/)
280
+ str_buffer << scanner.matched
281
+ elsif expand && check(/#(?=[\$\@\{])/)
282
+ break
283
+ elsif scan(/\\/)
284
+ str_buffer << (escape ? self.read_escape : scanner.matched)
285
+ else
286
+ reg = Regexp.new("[^\#\0\\\\\n]+|.")
287
+
288
+ scan reg
289
+ str_buffer << scanner.matched
290
+ end
291
+ end
292
+
293
+ complete_str = str_buffer.join ''
294
+ @line += complete_str.count("\n")
295
+
296
+ self.yylval = complete_str
297
+ return :tSTRING_CONTENT
298
+ end
299
+
300
+ def parse_string
301
+ str_parse = self.strterm
302
+ func = str_parse[:func]
303
+
304
+ space = false
305
+
306
+ qwords = (func & STR_FUNC_QWORDS) != 0
307
+ expand = (func & STR_FUNC_EXPAND) != 0
308
+ regexp = (func & STR_FUNC_REGEXP) != 0
309
+
310
+ space = true if qwords and scan(/\s+/)
311
+
312
+ # if not end of string, so we must be parsing contents
313
+ str_buffer = []
314
+
315
+ if scan Regexp.new(Regexp.escape(str_parse[:term]))
316
+ if qwords && !str_parse[:done_last_space]#&& space
317
+ str_parse[:done_last_space] = true
318
+ pushback(1)
319
+ self.yylval = ' '
320
+ return :tSPACE
321
+ end
322
+
323
+ if str_parse[:balance]
324
+ if str_parse[:nesting] == 0
325
+
326
+ if regexp
327
+ self.yylval = scan(/\w+/)
328
+ return :tREGEXP_END
329
+ end
330
+ return :tSTRING_END
331
+ else
332
+ str_buffer << scanner.matched
333
+ str_parse[:nesting] -= 1
334
+ self.strterm = str_parse
335
+ end
336
+ elsif regexp
337
+ @lex_state = :expr_end
338
+ self.yylval = scan(/\w+/)
339
+ return :tREGEXP_END
340
+ else
341
+ if str_parse[:scanner]
342
+ @scanner_stack << str_parse[:scanner]
343
+ @scanner = str_parse[:scanner]
344
+ end
345
+
346
+ return :tSTRING_END
347
+ end
348
+ end
349
+
350
+ if space
351
+ self.yylval = ' '
352
+ return :tSPACE
353
+ end
354
+
355
+ if str_parse[:balance] and scan Regexp.new(Regexp.escape(str_parse[:paren]))
356
+ str_buffer << scanner.matched
357
+ str_parse[:nesting] += 1
358
+ elsif check(/#[@$]/)
359
+ scan(/#/)
360
+ if expand
361
+ return :tSTRING_DVAR
362
+ else
363
+ str_buffer << scanner.matched
364
+ end
365
+
366
+ elsif scan(/#\{/)
367
+ if expand
368
+ return :tSTRING_DBEG
369
+ else
370
+ str_buffer << scanner.matched
371
+ end
372
+
373
+ # causes error, so we will just collect it later on with other text
374
+ elsif scan(/\#/)
375
+ str_buffer << '#'
376
+ end
377
+
378
+ add_string_content str_buffer, str_parse
379
+
380
+ complete_str = str_buffer.join ''
381
+ @line += complete_str.count("\n")
382
+
383
+ self.yylval = complete_str
384
+ return :tSTRING_CONTENT
385
+ end
386
+
387
+ def add_string_content(str_buffer, str_parse)
388
+ func = str_parse[:func]
389
+
390
+ end_str_re = Regexp.new(Regexp.escape(str_parse[:term]))
391
+
392
+ qwords = (func & STR_FUNC_QWORDS) != 0
393
+ expand = (func & STR_FUNC_EXPAND) != 0
394
+ regexp = (func & STR_FUNC_REGEXP) != 0
395
+ escape = (func & STR_FUNC_ESCAPE) != 0
396
+ xquote = (func == STR_XQUOTE)
397
+
398
+ until scanner.eos?
399
+ c = nil
400
+ handled = true
401
+
402
+ if check end_str_re
403
+ # eos
404
+ # if its just balancing, add it ass normal content..
405
+ if str_parse[:balance] && (str_parse[:nesting] != 0)
406
+ # we only checked above, so actually scan it
407
+ scan end_str_re
408
+ c = scanner.matched
409
+ str_parse[:nesting] -= 1
410
+ else
411
+ # not balancing, so break (eos!)
412
+ break
413
+ end
414
+
415
+ elsif str_parse[:balance] and scan Regexp.new(Regexp.escape(str_parse[:paren]))
416
+ str_parse[:nesting] += 1
417
+ c = scanner.matched
418
+
419
+ elsif qwords && scan(/\s/)
420
+ pushback(1)
421
+ break
422
+ elsif expand && check(/#(?=[\$\@\{])/)
423
+ break
424
+ elsif qwords and scan(/\s/)
425
+ pushback(1)
426
+ break
427
+ elsif scan(/\\/)
428
+ if xquote # opal - treat xstrings as dquotes? forces us to double escape
429
+ c = "\\" + scan(/./)
430
+ elsif qwords and scan(/\n/)
431
+ str_buffer << "\n"
432
+ next
433
+ elsif expand and scan(/\n/)
434
+ next
435
+ elsif qwords and scan(/\s/)
436
+ c = ' '
437
+ elsif regexp
438
+ if scan(/(.)/)
439
+ c = "\\" + scanner.matched
440
+ end
441
+ elsif expand
442
+ c = self.read_escape
443
+ elsif scan(/\n/)
444
+ # nothing..
445
+ elsif scan(/\\/)
446
+ if escape
447
+ c = "\\\\"
448
+ else
449
+ c = scanner.matched
450
+ end
451
+ else # \\
452
+ unless scan(end_str_re)
453
+ str_buffer << "\\"
454
+ else
455
+ #c = scanner.matched
456
+ end
457
+ end
458
+ else
459
+ handled = false
460
+ end
461
+
462
+ unless handled
463
+ reg = if qwords
464
+ Regexp.new("[^#{Regexp.escape str_parse[:term]}\#\0\n\ \\\\]+|.")
465
+ elsif str_parse[:balance]
466
+ Regexp.new("[^#{Regexp.escape str_parse[:term]}#{Regexp.escape str_parse[:paren]}\#\0\\\\]+|.")
467
+ else
468
+ Regexp.new("[^#{Regexp.escape str_parse[:term]}\#\0\\\\]+|.")
469
+ end
470
+
471
+ scan reg
472
+ c = scanner.matched
473
+ end
474
+
475
+ c ||= scanner.matched
476
+ str_buffer << c
477
+ end
478
+
479
+ raise "reached EOF while in string" if scanner.eos?
480
+ end
481
+
482
+ def heredoc_identifier
483
+ if scan(/(-?)(['"])?(\w+)\2?/)
484
+ escape_method = (@scanner[2] == "'") ? STR_SQUOTE : STR_DQUOTE
485
+ heredoc = @scanner[3]
486
+
487
+ self.strterm = new_strterm(escape_method, heredoc, heredoc)
488
+ self.strterm[:type] = :heredoc
489
+
490
+ # if ruby code at end of line after heredoc, we have to store it to
491
+ # parse after heredoc is finished parsing
492
+ end_of_line = scan(/.*\n/)
493
+ self.strterm[:scanner] = StringScanner.new(end_of_line) if end_of_line != "\n"
494
+
495
+ self.line += 1
496
+ self.yylval = heredoc
497
+ return :tSTRING_BEG
498
+ end
499
+ end
500
+
501
+ def process_identifier(matched, cmd_start)
502
+ last_state = @lex_state
503
+
504
+ if !check(/::/) and scan(/:/)
505
+ @lex_state = :expr_beg
506
+ self.yylval = matched
507
+ return :tLABEL
508
+ end
509
+
510
+ if matched == 'defined?'
511
+ if after_operator?
512
+ @lex_state = :expr_end
513
+ return :tIDENTIFIER
514
+ end
515
+
516
+ @lex_state = :expr_arg
517
+ return :kDEFINED
518
+ end
519
+
520
+ if matched.end_with? '?', '!'
521
+ result = :tIDENTIFIER
522
+ else
523
+ if @lex_state == :expr_fname
524
+ if !check(/\=\>/) and scan(/\=/)
525
+ result = :tIDENTIFIER
526
+ matched += scanner.matched
527
+ end
528
+
529
+ elsif matched =~ /^[A-Z]/
530
+ result = :tCONSTANT
531
+ else
532
+ result = :tIDENTIFIER
533
+ end
534
+ end
535
+
536
+ if @lex_state != :expr_dot and kw = Keywords.keyword(matched)
537
+ old_state = @lex_state
538
+ @lex_state = kw.state
539
+
540
+ if old_state == :expr_fname
541
+ self.yylval = kw.name
542
+ return kw.id[0]
543
+ end
544
+
545
+ if @lex_state == :expr_beg
546
+ cmd_start = true
547
+ end
548
+
549
+ if matched == "do"
550
+ if after_operator?
551
+ @lex_state = :expr_end
552
+ return :tIDENTIFIER
553
+ end
554
+
555
+ if @start_of_lambda
556
+ @start_of_lambda = false
557
+ @lex_state = :expr_beg
558
+ return :kDO_LAMBDA
559
+ elsif cond?
560
+ @lex_state = :expr_beg
561
+ return :kDO_COND
562
+ elsif cmdarg? && @lex_state != :expr_cmdarg
563
+ @lex_state = :expr_beg
564
+ return :kDO_BLOCK
565
+ elsif @lex_state == :expr_endarg
566
+ return :kDO_BLOCK
567
+ else
568
+ @lex_state = :expr_beg
569
+ return :kDO
570
+ end
571
+ else
572
+ if old_state == :expr_beg or old_state == :expr_value
573
+ self.yylval = matched
574
+ return kw.id[0]
575
+ else
576
+ if kw.id[0] != kw.id[1]
577
+ @lex_state = :expr_beg
578
+ end
579
+
580
+ self.yylval = matched
581
+ return kw.id[1]
582
+ end
583
+ end
584
+ end
585
+
586
+ if [:expr_beg, :expr_dot, :expr_mid, :expr_arg, :expr_cmdarg].include? @lex_state
587
+ @lex_state = cmd_start ? :expr_cmdarg : :expr_arg
588
+ else
589
+ @lex_state = :expr_end
590
+ end
591
+
592
+ if ![:expr_dot, :expr_fname].include?(last_state) and has_local?(matched)
593
+ @lex_state = :expr_end
594
+ end
595
+
596
+ return matched =~ /^[A-Z]/ ? :tCONSTANT : :tIDENTIFIER
597
+ end
598
+
599
+ def yylex
600
+ @yylval = ''
601
+ @space_seen = false
602
+ cmd_start = false
603
+ c = ''
604
+
605
+ if self.strterm
606
+ if self.strterm[:type] == :heredoc
607
+ token = here_document(self.strterm)
608
+ else
609
+ token = parse_string
610
+ end
611
+
612
+ if token == :tSTRING_END or token == :tREGEXP_END
613
+ self.strterm = nil
614
+ @lex_state = :expr_end
615
+ end
616
+
617
+ return token
618
+ end
619
+
620
+ while true
621
+ if skip(/\ |\t|\r/)
622
+ @space_seen = true
623
+ next
624
+
625
+ elsif skip(/(\n|#)/)
626
+ c = scanner.matched
627
+ if c == '#'
628
+ skip(/(.*)/)
629
+ else
630
+ self.line += 1
631
+ end
632
+
633
+ skip(/(\n+)/)
634
+
635
+ if scanner.matched
636
+ self.line += scanner.matched.length
637
+ end
638
+
639
+ next if [:expr_beg, :expr_dot].include? @lex_state
640
+
641
+ if skip(/([\ \t\r\f\v]*)\./)
642
+ @space_seen = true unless scanner[1].empty?
643
+ pushback(1)
644
+
645
+ next unless check(/\.\./)
646
+ end
647
+
648
+ cmd_start = true
649
+ @lex_state = :expr_beg
650
+ self.yylval = '\\n'
651
+ return :tNL
652
+
653
+ elsif scan(/\;/)
654
+ @lex_state = :expr_beg
655
+ return :tSEMI
656
+
657
+ elsif check(/\*/)
658
+ if scan(/\*\*\=/)
659
+ @lex_state = :expr_beg
660
+ return new_op_asgn('**')
661
+ elsif scan(/\*\*/)
662
+ self.set_arg_state
663
+ return :tPOW
664
+ elsif scan(/\*\=/)
665
+ @lex_state = :expr_beg
666
+ return new_op_asgn('*')
667
+ else
668
+ scan(/\*/)
669
+
670
+ if after_operator?
671
+ @lex_state = :expr_arg
672
+ return :tSTAR2
673
+ elsif @space_seen && check(/\S/)
674
+ @lex_state = :expr_beg
675
+ return :tSTAR
676
+ elsif [:expr_beg, :expr_mid].include? @lex_state
677
+ @lex_state = :expr_beg
678
+ return :tSTAR
679
+ else
680
+ @lex_state = :expr_beg
681
+ return :tSTAR2
682
+ end
683
+ end
684
+
685
+ elsif scan(/\!/)
686
+ if after_operator?
687
+ @lex_state = :expr_arg
688
+ if scan(/@/)
689
+ return :tBANG, '!'
690
+ end
691
+ else
692
+ @lex_state = :expr_beg
693
+ end
694
+
695
+ if scan(/\=/)
696
+ return :tNEQ
697
+ elsif scan(/\~/)
698
+ return :tNMATCH
699
+ end
700
+
701
+ return :tBANG
702
+
703
+ elsif scan(/\=/)
704
+ if @lex_state == :expr_beg and !@space_seen
705
+ if scan(/begin/) and space?
706
+ scan(/(.*)/) # end of line
707
+ line_count = 0
708
+
709
+ while true
710
+ if scanner.eos?
711
+ raise "embedded document meets end of file"
712
+ end
713
+
714
+ if scan(/\=end/) and space?
715
+ @line += line_count
716
+ return yylex
717
+ end
718
+
719
+ if scan(/\n/)
720
+ line_count += 1
721
+ next
722
+ end
723
+
724
+ scan(/(.*)/)
725
+ end
726
+ end
727
+ end
728
+
729
+ self.set_arg_state
730
+
731
+ if scan(/\=/)
732
+ if scan(/\=/)
733
+ return :tEQQ
734
+ end
735
+
736
+ return :tEQ
737
+ end
738
+
739
+ if scan(/\~/)
740
+ return :tMATCH
741
+ elsif scan(/\>/)
742
+ return :tASSOC
743
+ end
744
+
745
+ return :tEQL
746
+
747
+ elsif scan(/\"/)
748
+ self.strterm = new_strterm(STR_DQUOTE, '"', "\0")
749
+ return :tSTRING_BEG
750
+
751
+ elsif scan(/\'/)
752
+ self.strterm = new_strterm(STR_SQUOTE, "'", "\0")
753
+ return :tSTRING_BEG
754
+
755
+ elsif scan(/\`/)
756
+ self.strterm = new_strterm(STR_XQUOTE, "`", "\0")
757
+ return :tXSTRING_BEG
758
+
759
+ elsif scan(/\&/)
760
+ if scan(/\&/)
761
+ @lex_state = :expr_beg
762
+
763
+ if scan(/\=/)
764
+ return new_op_asgn('&&')
765
+ end
766
+
767
+ return :tANDOP
768
+
769
+ elsif scan(/\=/)
770
+ @lex_state = :expr_beg
771
+ return new_op_asgn('&')
772
+ end
773
+
774
+ if spcarg?
775
+ #puts "warning: `&' interpreted as argument prefix"
776
+ result = :tAMPER
777
+ elsif beg?
778
+ result = :tAMPER
779
+ else
780
+ #puts "warn_balanced: & argument prefix"
781
+ result = :tAMPER2
782
+ end
783
+
784
+ self.set_arg_state
785
+ return result
786
+
787
+ elsif scan(/\|/)
788
+ if scan(/\|/)
789
+ @lex_state = :expr_beg
790
+ if scan(/\=/)
791
+ return new_op_asgn('||')
792
+ end
793
+
794
+ return :tOROP
795
+
796
+ elsif scan(/\=/)
797
+ return new_op_asgn('|')
798
+ end
799
+
800
+ self.set_arg_state
801
+ return :tPIPE
802
+
803
+ elsif scan(/\%[QqWwixr]/)
804
+ str_type = scanner.matched[1, 1]
805
+ paren = term = scan(/./)
806
+
807
+ case term
808
+ when '(' then term = ')'
809
+ when '[' then term = ']'
810
+ when '{' then term = '}'
811
+ when '<' then term = '>'
812
+ else paren = "\0"
813
+ end
814
+
815
+ token, func = case str_type
816
+ when 'Q'
817
+ [:tSTRING_BEG, STR_DQUOTE]
818
+ when 'q'
819
+ [:tSTRING_BEG, STR_SQUOTE]
820
+ when 'W'
821
+ skip(/\s*/)
822
+ [:tWORDS_BEG, STR_DWORD]
823
+ when 'w', 'i'
824
+ skip(/\s*/)
825
+ [:tAWORDS_BEG, STR_SWORD]
826
+ when 'x'
827
+ [:tXSTRING_BEG, STR_XQUOTE]
828
+ when 'r'
829
+ [:tREGEXP_BEG, STR_REGEXP]
830
+ end
831
+
832
+ self.strterm = new_strterm2(func, term, paren)
833
+ return token
834
+
835
+ elsif scan(/\//)
836
+ if beg?
837
+ self.strterm = new_strterm(STR_REGEXP, '/', '/')
838
+ return :tREGEXP_BEG
839
+ elsif scan(/\=/)
840
+ @lex_state = :expr_beg
841
+ return new_op_asgn('/')
842
+ elsif after_operator?
843
+ @lex_state = :expr_arg
844
+ elsif arg?
845
+ if !check(/\s/) && @space_seen
846
+ self.strterm = new_strterm(STR_REGEXP, '/', '/')
847
+ return :tREGEXP_BEG
848
+ end
849
+ else
850
+ @lex_state = :expr_beg
851
+ end
852
+
853
+ return :tDIVIDE
854
+
855
+ elsif scan(/\%/)
856
+ if scan(/\=/)
857
+ @lex_state = :expr_beg
858
+ return new_op_asgn('%')
859
+ elsif check(/[^\s]/)
860
+ if @lex_state == :expr_beg or (@lex_state == :expr_arg && @space_seen)
861
+ start_word = scan(/./)
862
+ end_word = { '(' => ')', '[' => ']', '{' => '}' }[start_word] || start_word
863
+ self.strterm = new_strterm2(STR_DQUOTE, end_word, start_word)
864
+ return :tSTRING_BEG
865
+ end
866
+ end
867
+
868
+ self.set_arg_state
869
+
870
+ return :tPERCENT
871
+
872
+ elsif scan(/\\/)
873
+ if scan(/\r?\n/)
874
+ @space_seen = true
875
+ next
876
+ end
877
+
878
+ raise SyntaxError, "backslash must appear before newline :#{@file}:#{@line}"
879
+
880
+ elsif scan(/\(/)
881
+ result = scanner.matched
882
+ if beg?
883
+ result = :tLPAREN
884
+ elsif @space_seen && arg?
885
+ result = :tLPAREN_ARG
886
+ else
887
+ result = :tLPAREN2
888
+ end
889
+
890
+ @lex_state = :expr_beg
891
+ cond_push 0
892
+ cmdarg_push 0
893
+
894
+ return result
895
+
896
+ elsif scan(/\)/)
897
+ cond_lexpop
898
+ cmdarg_lexpop
899
+ @lex_state = :expr_end
900
+ return :tRPAREN
901
+
902
+ elsif scan(/\[/)
903
+ result = scanner.matched
904
+
905
+ if after_operator?
906
+ @lex_state = :expr_arg
907
+ if scan(/\]=/)
908
+ return :tASET
909
+ elsif scan(/\]/)
910
+ return :tAREF
911
+ else
912
+ raise "Unexpected '[' token"
913
+ end
914
+ elsif beg?
915
+ result = :tLBRACK
916
+ elsif arg? && @space_seen
917
+ result = :tLBRACK
918
+ else
919
+ result = :tLBRACK2
920
+ end
921
+
922
+ @lex_state = :expr_beg
923
+ cond_push 0
924
+ cmdarg_push 0
925
+ return result
926
+
927
+ elsif scan(/\]/)
928
+ cond_lexpop
929
+ cmdarg_lexpop
930
+ @lex_state = :expr_end
931
+ return :tRBRACK
932
+
933
+ elsif scan(/\}/)
934
+ cond_lexpop
935
+ cmdarg_lexpop
936
+ @lex_state = :expr_end
937
+
938
+ return :tRCURLY
939
+
940
+ elsif scan(/\.\.\./)
941
+ @lex_state = :expr_beg
942
+ return :tDOT3
943
+
944
+ elsif scan(/\.\./)
945
+ @lex_state = :expr_beg
946
+ return :tDOT2
947
+
948
+ elsif scan(/\./)
949
+ @lex_state = :expr_dot unless @lex_state == :expr_fname
950
+ return :tDOT
951
+
952
+ elsif scan(/\:\:/)
953
+ if beg?
954
+ @lex_state = :expr_beg
955
+ return :tCOLON3
956
+ elsif spcarg?
957
+ @lex_state = :expr_beg
958
+ return :tCOLON3
959
+ end
960
+
961
+ @lex_state = :expr_dot
962
+ return :tCOLON2
963
+
964
+ elsif scan(/\:/)
965
+ if end? || check(/\s/)
966
+ unless check(/\w/)
967
+ @lex_state = :expr_beg
968
+ return :tCOLON
969
+ end
970
+
971
+ @lex_state = :expr_fname
972
+ return :tSYMBEG
973
+ end
974
+
975
+ if scan(/\'/)
976
+ self.strterm = new_strterm(STR_SSYM, "'", "\0")
977
+ elsif scan(/\"/)
978
+ self.strterm = new_strterm(STR_DSYM, '"', "\0")
979
+ end
980
+
981
+ @lex_state = :expr_fname
982
+ return :tSYMBEG
983
+
984
+ elsif scan(/\^\=/)
985
+ @lex_state = :expr_beg
986
+ return new_op_asgn('^')
987
+
988
+ elsif scan(/\^/)
989
+ self.set_arg_state
990
+ return :tCARET
991
+
992
+ elsif check(/\</)
993
+ if scan(/\<\<\=/)
994
+ @lex_state = :expr_beg
995
+ return new_op_asgn('<<')
996
+
997
+ elsif scan(/\<\</)
998
+ if after_operator?
999
+ @lex_state = :expr_arg
1000
+ return :tLSHFT
1001
+ elsif !after_operator? && !end? && (!arg? || @space_seen)
1002
+ if token = heredoc_identifier
1003
+ return token
1004
+ end
1005
+
1006
+ @lex_state = :expr_beg
1007
+ return :tLSHFT
1008
+ end
1009
+ @lex_state = :expr_beg
1010
+ return :tLSHFT
1011
+ elsif scan(/\<\=\>/)
1012
+ if after_operator?
1013
+ @lex_state = :expr_arg
1014
+ else
1015
+ if @lex_state == :expr_class
1016
+ cmd_start = true
1017
+ end
1018
+
1019
+ @lex_state = :expr_beg
1020
+ end
1021
+
1022
+ return :tCMP
1023
+ elsif scan(/\<\=/)
1024
+ self.set_arg_state
1025
+ return :tLEQ
1026
+
1027
+ elsif scan(/\</)
1028
+ self.set_arg_state
1029
+ return :tLT
1030
+ end
1031
+
1032
+ elsif check(/\>/)
1033
+ if scan(/\>\>\=/)
1034
+ return new_op_asgn('>>')
1035
+
1036
+ elsif scan(/\>\>/)
1037
+ self.set_arg_state
1038
+ return :tRSHFT
1039
+
1040
+ elsif scan(/\>\=/)
1041
+ self.set_arg_state
1042
+ return :tGEQ
1043
+
1044
+ elsif scan(/\>/)
1045
+ self.set_arg_state
1046
+ return :tGT
1047
+ end
1048
+
1049
+ elsif scan(/->/)
1050
+ # FIXME: # should be :expr_arg, but '(' breaks it...
1051
+ @lex_state = :expr_end
1052
+ @start_of_lambda = true
1053
+ return :tLAMBDA
1054
+
1055
+ elsif scan(/[+-]/)
1056
+ matched = scanner.matched
1057
+ sign, utype = if matched == '+'
1058
+ [:tPLUS, :tUPLUS]
1059
+ else
1060
+ [:tMINUS, :tUMINUS]
1061
+ end
1062
+
1063
+ if beg?
1064
+ @lex_state = :expr_mid
1065
+ self.yylval = matched
1066
+ if scanner.peek(1) =~ /\d/ and
1067
+ return utype == :tUMINUS ? '-@NUM' : '+@NUM'
1068
+ else
1069
+ return utype
1070
+ end
1071
+ elsif after_operator?
1072
+ @lex_state = :expr_arg
1073
+ if scan(/@/)
1074
+ self.yylval = matched + '@'
1075
+ return :tIDENTIFIER
1076
+ end
1077
+
1078
+ self.yylval = matched
1079
+ return sign
1080
+ end
1081
+
1082
+ if scan(/\=/)
1083
+ @lex_state = :expr_beg
1084
+ return new_op_asgn(matched)
1085
+ end
1086
+
1087
+ if spcarg?
1088
+ @lex_state = :expr_mid
1089
+ self.yylval = matched
1090
+ return utype
1091
+ end
1092
+
1093
+ @lex_state = :expr_beg
1094
+ self.yylval = matched
1095
+ return sign
1096
+
1097
+ elsif scan(/\?/)
1098
+ if end?
1099
+ @lex_state = :expr_beg
1100
+ return :tEH
1101
+ end
1102
+
1103
+ if check(/\ |\t|\r|\s/)
1104
+ @lex_state = :expr_beg
1105
+ return :tEH
1106
+ elsif scan(/\\/)
1107
+ @lex_state = :expr_end
1108
+ self.yylval = self.read_escape
1109
+ return :tSTRING
1110
+ end
1111
+
1112
+ @lex_state = :expr_end
1113
+ self.yylval = scan(/./)
1114
+ return :tSTRING
1115
+
1116
+ elsif scan(/\~/)
1117
+ self.set_arg_state
1118
+ return :tTILDE
1119
+
1120
+ elsif check(/\$/)
1121
+ if scan(/\$([1-9]\d*)/)
1122
+ @lex_state = :expr_end
1123
+ self.yylval = scanner.matched.sub('$', '')
1124
+ return :tNTH_REF
1125
+
1126
+ elsif scan(/(\$_)(\w+)/)
1127
+ @lex_state = :expr_end
1128
+ return :tGVAR
1129
+
1130
+ elsif scan(/\$[\+\'\`\&!@\"~*$?\/\\:;=.,<>_]/)
1131
+ @lex_state = :expr_end
1132
+ return :tGVAR
1133
+ elsif scan(/\$\w+/)
1134
+ @lex_state = :expr_end
1135
+ return :tGVAR
1136
+ else
1137
+ raise "Bad gvar name: #{scanner.peek(5).inspect}"
1138
+ end
1139
+
1140
+ elsif scan(/\$\w+/)
1141
+ @lex_state = :expr_end
1142
+ return :tGVAR
1143
+
1144
+ elsif scan(/\@\@\w*/)
1145
+ @lex_state = :expr_end
1146
+ return :tCVAR
1147
+
1148
+ elsif scan(/\@\w*/)
1149
+ @lex_state = :expr_end
1150
+ return :tIVAR
1151
+
1152
+ elsif scan(/\,/)
1153
+ @lex_state = :expr_beg
1154
+ return :tCOMMA
1155
+
1156
+ elsif scan(/\{/)
1157
+ if @start_of_lambda
1158
+ @start_of_lambda = false
1159
+ @lex_state = :expr_beg
1160
+ return :tLAMBEG
1161
+
1162
+ elsif arg? or @lex_state == :expr_end
1163
+ result = :tLCURLY
1164
+ elsif @lex_state == :expr_endarg
1165
+ result = :LBRACE_ARG
1166
+ else
1167
+ result = :tLBRACE
1168
+ end
1169
+
1170
+ @lex_state = :expr_beg
1171
+ cond_push 0
1172
+ cmdarg_push 0
1173
+ return result
1174
+
1175
+ elsif scanner.bol? and skip(/\__END__(\n|$)/)
1176
+ while true
1177
+ if scanner.eos?
1178
+ @eof_content = self.yylval
1179
+ return false
1180
+ end
1181
+
1182
+ scan(/(.*)/)
1183
+ scan(/\n/)
1184
+ end
1185
+
1186
+ elsif check(/[0-9]/)
1187
+ return process_numeric
1188
+
1189
+ elsif scan(/(\w)+[\?\!]?/)
1190
+ return process_identifier scanner.matched, cmd_start
1191
+ end
1192
+
1193
+ if scanner.eos?
1194
+ if @scanner_stack.size == 1 # our main scanner, we cant pop this
1195
+ self.yylval = false
1196
+ return false
1197
+ else # we were probably parsing a heredoc, so pop that parser and continue
1198
+ @scanner_stack.pop
1199
+ @scanner = @scanner_stack.last
1200
+ return yylex
1201
+ end
1202
+ end
1203
+
1204
+ raise "Unexpected content in parsing stream `#{scanner.peek 5}` :#{@file}:#{@line}"
1205
+ end
1206
+ end
1207
+ end
1208
+ end