opal 0.3.11 → 0.3.15

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 (282) hide show
  1. data/.gitignore +13 -0
  2. data/Gemfile +10 -0
  3. data/LICENSE +20 -0
  4. data/README.md +11 -116
  5. data/Rakefile +126 -0
  6. data/bin/opal +1 -2
  7. data/docs/spec_runner.html +16 -0
  8. data/index.html +434 -0
  9. data/lib/opal.rb +14 -15
  10. data/lib/opal/builder.rb +46 -148
  11. data/lib/opal/command.rb +45 -115
  12. data/lib/opal/context.rb +139 -78
  13. data/lib/opal/dependency_builder.rb +34 -0
  14. data/lib/opal/environment.rb +92 -0
  15. data/lib/opal/parser/grammar.rb +4915 -0
  16. data/lib/opal/{parser.y → parser/grammar.y} +430 -284
  17. data/lib/opal/parser/lexer.rb +1329 -0
  18. data/lib/opal/parser/parser.rb +1460 -0
  19. data/lib/opal/parser/scope.rb +140 -0
  20. data/lib/opal/parser/sexp.rb +17 -0
  21. data/lib/opal/version.rb +2 -1
  22. data/opal.gemspec +23 -0
  23. data/opal.js +3149 -4162
  24. data/runtime/README.md +25 -0
  25. data/runtime/corelib/alpha.rb +10 -0
  26. data/runtime/corelib/array.rb +962 -0
  27. data/runtime/corelib/basic_object.rb +66 -0
  28. data/runtime/corelib/boolean.rb +44 -0
  29. data/runtime/corelib/class.rb +43 -0
  30. data/runtime/corelib/comparable.rb +25 -0
  31. data/runtime/corelib/complex.rb +2 -0
  32. data/runtime/corelib/dir.rb +29 -0
  33. data/runtime/corelib/enumerable.rb +316 -0
  34. data/runtime/corelib/enumerator.rb +80 -0
  35. data/runtime/corelib/error.rb +25 -0
  36. data/runtime/corelib/file.rb +80 -0
  37. data/runtime/corelib/hash.rb +503 -0
  38. data/runtime/corelib/io.rb +44 -0
  39. data/runtime/corelib/kernel.rb +237 -0
  40. data/runtime/corelib/load_order +29 -0
  41. data/runtime/corelib/match_data.rb +37 -0
  42. data/runtime/corelib/module.rb +171 -0
  43. data/runtime/corelib/native.rb +50 -0
  44. data/runtime/corelib/nil_class.rb +47 -0
  45. data/runtime/corelib/numeric.rb +219 -0
  46. data/runtime/corelib/object.rb +21 -0
  47. data/runtime/corelib/proc.rb +42 -0
  48. data/runtime/corelib/range.rb +38 -0
  49. data/runtime/corelib/rational.rb +16 -0
  50. data/runtime/corelib/regexp.rb +63 -0
  51. data/runtime/corelib/string.rb +185 -0
  52. data/runtime/corelib/struct.rb +97 -0
  53. data/runtime/corelib/time.rb +196 -0
  54. data/runtime/corelib/top_self.rb +7 -0
  55. data/runtime/gemlib/alpha.rb +5 -0
  56. data/runtime/gemlib/kernel.rb +17 -0
  57. data/runtime/gemlib/load_order +2 -0
  58. data/runtime/kernel/class.js +256 -0
  59. data/runtime/kernel/debug.js +42 -0
  60. data/runtime/kernel/init.js +114 -0
  61. data/runtime/kernel/load_order +5 -0
  62. data/runtime/kernel/loader.js +151 -0
  63. data/runtime/kernel/runtime.js +414 -0
  64. data/runtime/spec/README.md +34 -0
  65. data/runtime/spec/core/array/allocate_spec.rb +15 -0
  66. data/runtime/spec/core/array/append_spec.rb +31 -0
  67. data/runtime/spec/core/array/assoc_spec.rb +29 -0
  68. data/runtime/spec/core/array/at_spec.rb +38 -0
  69. data/runtime/spec/core/array/clear_spec.rb +22 -0
  70. data/runtime/spec/core/array/collect_spec.rb +3 -0
  71. data/runtime/spec/core/array/compact_spec.rb +42 -0
  72. data/runtime/spec/core/array/concat_spec.rb +21 -0
  73. data/runtime/spec/core/array/constructor_spec.rb +24 -0
  74. data/runtime/spec/core/array/count_spec.rb +11 -0
  75. data/runtime/spec/core/array/delete_at_spec.rb +31 -0
  76. data/runtime/spec/core/array/delete_if_spec.rb +24 -0
  77. data/runtime/spec/core/array/delete_spec.rb +26 -0
  78. data/runtime/spec/core/array/each_index_spec.rb +33 -0
  79. data/runtime/spec/core/array/each_spec.rb +11 -0
  80. data/runtime/spec/core/array/element_reference_spec.rb +136 -0
  81. data/runtime/spec/core/array/element_set_spec.rb +7 -0
  82. data/runtime/spec/core/array/empty_spec.rb +10 -0
  83. data/runtime/spec/core/array/eql_spec.rb +3 -0
  84. data/runtime/spec/core/array/equal_value_spec.rb +3 -0
  85. data/runtime/spec/core/array/fetch_spec.rb +26 -0
  86. data/runtime/spec/core/array/first_spec.rb +54 -0
  87. data/runtime/spec/core/array/fixtures/classes.rb +8 -0
  88. data/runtime/spec/core/array/flatten_spec.rb +41 -0
  89. data/runtime/spec/core/array/include_spec.rb +20 -0
  90. data/runtime/spec/core/array/insert_spec.rb +59 -0
  91. data/runtime/spec/core/array/last_spec.rb +57 -0
  92. data/runtime/spec/core/array/length_spec.rb +3 -0
  93. data/runtime/spec/core/array/map_spec.rb +3 -0
  94. data/runtime/spec/core/array/plus_spec.rb +16 -0
  95. data/runtime/spec/core/array/pop_spec.rb +79 -0
  96. data/runtime/spec/core/array/push_spec.rb +19 -0
  97. data/runtime/spec/core/array/rassoc_spec.rb +12 -0
  98. data/runtime/spec/core/array/reject_spec.rb +54 -0
  99. data/runtime/spec/core/array/replace_spec.rb +3 -0
  100. data/runtime/spec/core/array/reverse_each_spec.rb +18 -0
  101. data/runtime/spec/core/array/reverse_spec.rb +9 -0
  102. data/runtime/spec/core/array/shared/collect.rb +53 -0
  103. data/runtime/spec/core/array/shared/eql.rb +19 -0
  104. data/runtime/spec/core/array/shared/length.rb +6 -0
  105. data/runtime/spec/core/array/shared/replace.rb +31 -0
  106. data/runtime/spec/core/class/new_spec.rb +19 -0
  107. data/runtime/spec/core/enumerable/all_spec.rb +102 -0
  108. data/runtime/spec/core/enumerable/any_spec.rb +115 -0
  109. data/runtime/spec/core/enumerable/collect_spec.rb +3 -0
  110. data/runtime/spec/core/enumerable/count_spec.rb +29 -0
  111. data/runtime/spec/core/enumerable/detect_spec.rb +3 -0
  112. data/runtime/spec/core/enumerable/find_spec.rb +3 -0
  113. data/runtime/spec/core/enumerable/fixtures/classes.rb +26 -0
  114. data/runtime/spec/core/enumerable/shared/collect.rb +12 -0
  115. data/runtime/spec/core/enumerable/shared/entries.rb +7 -0
  116. data/runtime/spec/core/enumerable/shared/find.rb +49 -0
  117. data/runtime/spec/core/enumerable/to_a_spec.rb +7 -0
  118. data/runtime/spec/core/false/and_spec.rb +11 -0
  119. data/runtime/spec/core/false/inspect_spec.rb +7 -0
  120. data/runtime/spec/core/false/or_spec.rb +11 -0
  121. data/runtime/spec/core/false/to_s_spec.rb +7 -0
  122. data/runtime/spec/core/false/xor_spec.rb +11 -0
  123. data/runtime/spec/core/hash/allocate_spec.rb +15 -0
  124. data/runtime/spec/core/hash/assoc_spec.rb +29 -0
  125. data/runtime/spec/core/hash/clear_spec.rb +21 -0
  126. data/runtime/spec/core/hash/clone_spec.rb +12 -0
  127. data/runtime/spec/core/hash/default_spec.rb +6 -0
  128. data/runtime/spec/core/hash/delete_if_spec.rb +15 -0
  129. data/runtime/spec/core/hash/element_reference_spec.rb +16 -0
  130. data/runtime/spec/core/hash/element_set_spec.rb +8 -0
  131. data/runtime/spec/core/hash/new_spec.rb +13 -0
  132. data/runtime/spec/core/matchdata/to_a_spec.rb +7 -0
  133. data/runtime/spec/core/nil/and_spec.rb +12 -0
  134. data/runtime/spec/core/nil/inspect_spec.rb +8 -0
  135. data/runtime/spec/core/nil/nil_spec.rb +8 -0
  136. data/runtime/spec/core/nil/or_spec.rb +12 -0
  137. data/runtime/spec/core/nil/to_a_spec.rb +8 -0
  138. data/runtime/spec/core/nil/to_f_spec.rb +12 -0
  139. data/runtime/spec/core/nil/to_i_spec.rb +12 -0
  140. data/runtime/spec/core/nil/to_s_spec.rb +8 -0
  141. data/runtime/spec/core/nil/xor_spec.rb +12 -0
  142. data/runtime/spec/core/numeric/equal_value_spec.rb +11 -0
  143. data/runtime/spec/core/object/is_a_spec.rb +2 -0
  144. data/runtime/spec/core/object/shared/kind_of.rb +0 -0
  145. data/runtime/spec/core/regexp/match_spec.rb +23 -0
  146. data/runtime/spec/core/regexp/shared/match.rb +11 -0
  147. data/runtime/spec/core/symbol/to_proc_spec.rb +8 -0
  148. data/runtime/spec/core/true/and_spec.rb +11 -0
  149. data/runtime/spec/core/true/inspect_spec.rb +7 -0
  150. data/runtime/spec/core/true/or_spec.rb +11 -0
  151. data/runtime/spec/core/true/to_s_spec.rb +7 -0
  152. data/runtime/spec/core/true/xor_spec.rb +11 -0
  153. data/runtime/spec/language/alias_spec.rb +25 -0
  154. data/runtime/spec/language/and_spec.rb +62 -0
  155. data/runtime/spec/language/array_spec.rb +68 -0
  156. data/runtime/spec/language/block_spec.rb +105 -0
  157. data/runtime/spec/language/break_spec.rb +49 -0
  158. data/runtime/spec/language/case_spec.rb +165 -0
  159. data/runtime/spec/language/defined_spec.rb +80 -0
  160. data/runtime/spec/language/ensure_spec.rb +82 -0
  161. data/runtime/spec/language/fixtures/block.rb +19 -0
  162. data/runtime/spec/language/fixtures/break.rb +39 -0
  163. data/runtime/spec/language/fixtures/defined.rb +9 -0
  164. data/runtime/spec/language/fixtures/ensure.rb +37 -0
  165. data/runtime/spec/language/fixtures/next.rb +46 -0
  166. data/runtime/spec/language/fixtures/send.rb +36 -0
  167. data/runtime/spec/language/fixtures/super.rb +43 -0
  168. data/runtime/spec/language/hash_spec.rb +43 -0
  169. data/runtime/spec/language/if_spec.rb +278 -0
  170. data/runtime/spec/language/loop_spec.rb +32 -0
  171. data/runtime/spec/language/next_spec.rb +128 -0
  172. data/runtime/spec/language/or_spec.rb +65 -0
  173. data/runtime/spec/language/predefined_spec.rb +21 -0
  174. data/runtime/spec/language/regexp/interpolation_spec.rb +9 -0
  175. data/runtime/spec/language/regexp_spec.rb +7 -0
  176. data/runtime/spec/language/send_spec.rb +105 -0
  177. data/runtime/spec/language/string_spec.rb +4 -0
  178. data/runtime/spec/language/super_spec.rb +18 -0
  179. data/runtime/spec/language/symbol_spec.rb +41 -0
  180. data/runtime/spec/language/undef_spec.rb +16 -0
  181. data/runtime/spec/language/unless_spec.rb +44 -0
  182. data/runtime/spec/language/until_spec.rb +137 -0
  183. data/runtime/spec/language/variables_spec.rb +28 -0
  184. data/runtime/spec/language/versions/hash_1.9.rb +20 -0
  185. data/runtime/spec/language/while_spec.rb +175 -0
  186. data/runtime/spec/library/stringscanner/scan_spec.rb +36 -0
  187. data/runtime/spec/opal/forwardable/def_instance_delegator_spec.rb +49 -0
  188. data/runtime/spec/opal/opal/defined_spec.rb +15 -0
  189. data/runtime/spec/opal/opal/function_spec.rb +11 -0
  190. data/runtime/spec/opal/opal/native_spec.rb +16 -0
  191. data/runtime/spec/opal/opal/null_spec.rb +10 -0
  192. data/runtime/spec/opal/opal/number_spec.rb +11 -0
  193. data/runtime/spec/opal/opal/object_spec.rb +16 -0
  194. data/runtime/spec/opal/opal/string_spec.rb +11 -0
  195. data/runtime/spec/opal/opal/typeof_spec.rb +9 -0
  196. data/runtime/spec/opal/opal/undefined_spec.rb +10 -0
  197. data/runtime/spec/opal/true/case_compare_spec.rb +12 -0
  198. data/runtime/spec/opal/true/class_spec.rb +10 -0
  199. data/runtime/spec/spec_helper.rb +25 -0
  200. data/runtime/stdlib/base64.rb +91 -0
  201. data/runtime/stdlib/date.rb +4 -0
  202. data/{stdlib → runtime/stdlib}/dev.rb +0 -0
  203. data/runtime/stdlib/forwardable.rb +33 -0
  204. data/runtime/stdlib/optparse.rb +0 -0
  205. data/runtime/stdlib/pp.rb +6 -0
  206. data/{stdlib → runtime/stdlib}/racc/parser.rb +0 -0
  207. data/runtime/stdlib/rbconfig.rb +0 -0
  208. data/runtime/stdlib/si.rb +17 -0
  209. data/runtime/stdlib/strscan.rb +53 -0
  210. data/runtime/stdlib/uri.rb +111 -0
  211. data/runtime/stdlib/uri/common.rb +1014 -0
  212. data/runtime/stdlib/uri/ftp.rb +261 -0
  213. data/runtime/stdlib/uri/generic.rb +1599 -0
  214. data/runtime/stdlib/uri/http.rb +106 -0
  215. data/runtime/stdlib/uri/https.rb +22 -0
  216. data/runtime/stdlib/uri/ldap.rb +260 -0
  217. data/runtime/stdlib/uri/ldaps.rb +20 -0
  218. data/runtime/stdlib/uri/mailto.rb +280 -0
  219. data/spec/builder/build_source_spec.rb +52 -0
  220. data/spec/builder/fixtures/build_source/adam.rb +0 -0
  221. data/spec/builder/fixtures/build_source/bar/a.rb +0 -0
  222. data/spec/builder/fixtures/build_source/bar/wow/b.rb +0 -0
  223. data/spec/builder/fixtures/build_source/bar/wow/cow/c.rb +0 -0
  224. data/spec/builder/fixtures/build_source/beynon.rb +0 -0
  225. data/spec/builder/fixtures/build_source/charles.js +0 -0
  226. data/spec/builder/fixtures/build_source/foo/a.rb +0 -0
  227. data/spec/builder/fixtures/build_source/foo/b.rb +0 -0
  228. data/spec/builder/fixtures/build_source/foo/x.js +0 -0
  229. data/spec/builder/fixtures/build_source/foo/y.js +0 -0
  230. data/spec/builder/output_path_spec.rb +50 -0
  231. data/spec/grammar/alias_spec.rb +26 -0
  232. data/spec/grammar/and_spec.rb +13 -0
  233. data/spec/grammar/array_spec.rb +22 -0
  234. data/spec/grammar/attrasgn_spec.rb +28 -0
  235. data/spec/grammar/begin_spec.rb +38 -0
  236. data/spec/grammar/block_spec.rb +12 -0
  237. data/spec/grammar/break_spec.rb +17 -0
  238. data/spec/grammar/call_spec.rb +58 -0
  239. data/spec/grammar/class_spec.rb +35 -0
  240. data/spec/grammar/const_spec.rb +13 -0
  241. data/spec/grammar/cvar_spec.rb +11 -0
  242. data/spec/grammar/def_spec.rb +60 -0
  243. data/spec/grammar/false_spec.rb +17 -0
  244. data/spec/grammar/file_spec.rb +7 -0
  245. data/spec/grammar/gvar_spec.rb +13 -0
  246. data/spec/grammar/hash_spec.rb +17 -0
  247. data/spec/grammar/iasgn_spec.rb +9 -0
  248. data/spec/grammar/if_spec.rb +26 -0
  249. data/spec/grammar/iter_spec.rb +59 -0
  250. data/spec/grammar/ivar_spec.rb +9 -0
  251. data/spec/grammar/lasgn_spec.rb +8 -0
  252. data/spec/grammar/line_spec.rb +8 -0
  253. data/spec/grammar/lvar_spec.rb +38 -0
  254. data/spec/grammar/module_spec.rb +27 -0
  255. data/spec/grammar/nil_spec.rb +17 -0
  256. data/spec/grammar/not_spec.rb +27 -0
  257. data/spec/grammar/op_asgn1_spec.rb +23 -0
  258. data/spec/grammar/op_asgn2_spec.rb +23 -0
  259. data/spec/grammar/or_spec.rb +13 -0
  260. data/spec/grammar/return_spec.rb +17 -0
  261. data/spec/grammar/sclass_spec.rb +20 -0
  262. data/spec/grammar/self_spec.rb +17 -0
  263. data/spec/grammar/str_spec.rb +96 -0
  264. data/spec/grammar/super_spec.rb +20 -0
  265. data/spec/grammar/true_spec.rb +17 -0
  266. data/spec/grammar/undef_spec.rb +15 -0
  267. data/spec/grammar/unless_spec.rb +13 -0
  268. data/spec/grammar/while_spec.rb +15 -0
  269. data/spec/grammar/xstr_spec.rb +116 -0
  270. data/spec/grammar/yield_spec.rb +20 -0
  271. data/spec/spec_helper.rb +9 -0
  272. metadata +346 -21
  273. data/lib/opal/bundle.rb +0 -34
  274. data/lib/opal/lexer.rb +0 -902
  275. data/lib/opal/nodes.rb +0 -2150
  276. data/lib/opal/parser.rb +0 -4894
  277. data/lib/opal/rake/bundle_task.rb +0 -63
  278. data/opal-parser.js +0 -8343
  279. data/stdlib/strscan.rb +0 -52
  280. data/templates/init/Rakefile +0 -7
  281. data/templates/init/index.html +0 -17
  282. data/templates/init/lib/__NAME__.rb +0 -2
@@ -0,0 +1,1329 @@
1
+ require 'opal/parser/grammar'
2
+ require 'opal/parser/sexp'
3
+
4
+ require 'strscan'
5
+
6
+ module Opal
7
+ class Grammar < Racc::Parser
8
+
9
+ class LexingError < StandardError; end
10
+
11
+ attr_reader :line
12
+
13
+ def initialize
14
+ @lex_state = :expr_beg
15
+ @cond = 0
16
+ @cmdarg = 0
17
+ @line = 1
18
+ @scopes = []
19
+
20
+ @string_parse_stack = []
21
+ end
22
+
23
+ def s *parts
24
+ sexp = Sexp.new *parts
25
+ sexp.line = @line
26
+ sexp
27
+ end
28
+
29
+ def parse source, file = '(string)'
30
+ #puts "============"
31
+ @file = file
32
+ @scanner = StringScanner.new source
33
+ push_scope
34
+ result = do_parse
35
+ pop_scope
36
+
37
+ result
38
+ end
39
+
40
+ class LexerScope
41
+ attr_reader :locals
42
+ attr_accessor :parent
43
+
44
+ def initialize type
45
+ @block = type == :block
46
+ @locals = []
47
+ @parent = nil
48
+ end
49
+
50
+ def add_local local
51
+ @locals << local
52
+ end
53
+
54
+ def has_local? local
55
+ return true if @locals.include? local
56
+ return @parent.has_local?(local) if @parent and @block
57
+ false
58
+ end
59
+ end
60
+
61
+ def push_scope type = nil
62
+ top = @scopes.last
63
+ scope = LexerScope.new type
64
+ scope.parent = top
65
+ @scopes << scope
66
+ @scope = scope
67
+ end
68
+
69
+ def pop_scope
70
+ @scopes.pop
71
+ @scope = @scopes.last
72
+ end
73
+
74
+ def new_block stmt = nil
75
+ s = s(:block)
76
+ s << stmt if stmt
77
+ s
78
+ end
79
+
80
+ def new_compstmt block
81
+ if block.size == 1
82
+ nil
83
+ elsif block.size == 2
84
+ block[1]
85
+ else
86
+ block.line = block[1].line
87
+ block
88
+ end
89
+ end
90
+
91
+ def new_body compstmt, res, els, ens
92
+ s = compstmt || s(:block)
93
+
94
+ if compstmt
95
+ # s = s(:block, compstmt) unless compstmt[0] == :block
96
+ s.line = compstmt.line
97
+ end
98
+
99
+ if res
100
+ s = s(:rescue, s)
101
+ res.each { |r| s << r }
102
+ s << els if els
103
+ end
104
+
105
+ if ens
106
+ s = s(:ensure, s, ens)
107
+ end
108
+
109
+ s
110
+ end
111
+
112
+ def new_defn line, name, args, body
113
+ body = s(:block, body) if body[0] != :block
114
+ scope = s(:scope, body)
115
+ body << s(:nil) if body.size == 1
116
+ scope.line = body.line
117
+ args.line = line
118
+ s = s(:defn, name.intern, args, scope)
119
+ s.line = line
120
+ s.end_line = @line
121
+ s
122
+ end
123
+
124
+ def new_defs line, recv, name, args, body
125
+ scope = s(:scope, body)
126
+ scope.line = body.line
127
+ s = s(:defs, recv, name.intern, args, scope)
128
+ s.line = line
129
+ s.end_line = @line
130
+ s
131
+ end
132
+
133
+ def new_class path, sup, body
134
+ scope = s(:scope)
135
+ scope << body unless body.size == 1
136
+ scope.line = body.line
137
+ s = s(:class, path, sup, scope)
138
+ s
139
+ end
140
+
141
+ def new_sclass expr, body
142
+ scope = s(:scope)
143
+ scope << body unless body.size == 1
144
+ scope.line = body.line
145
+ s = s(:sclass, expr, scope)
146
+ s
147
+ end
148
+
149
+ def new_module path, body
150
+ scope = s(:scope)
151
+ scope << body unless body.size == 1
152
+ scope.line = body.line
153
+ s = s(:module, path, scope)
154
+ s
155
+ end
156
+
157
+ def new_iter call, args, body
158
+ s = s(:iter, call, args)
159
+ s << body if body
160
+ s.end_line = @line
161
+ s
162
+ end
163
+
164
+ def new_if expr, stmt, tail
165
+ s = s(:if, expr, stmt, tail)
166
+ s.line = expr.line
167
+ s.end_line = @line
168
+ s
169
+ end
170
+
171
+ def new_args norm, opt, rest, block
172
+ res = s(:args)
173
+
174
+ if norm
175
+ norm.each do |arg|
176
+ @scope.add_local arg
177
+ res << arg
178
+ end
179
+ end
180
+
181
+ if opt
182
+ opt[1..-1].each do |opt|
183
+ res << opt[1]
184
+ end
185
+ end
186
+
187
+ if rest
188
+ res << rest
189
+ @scope.add_local rest.to_s[1..-1].intern
190
+ end
191
+
192
+ if block
193
+ res << block
194
+ @scope.add_local block.to_s[1..-1].intern
195
+ end
196
+
197
+ res << opt if opt
198
+
199
+ res
200
+ end
201
+
202
+ def new_block_args norm, opt, rest, block
203
+ res = s(:array)
204
+
205
+ if norm
206
+ norm.each do |arg|
207
+ @scope.add_local arg
208
+ res << s(:lasgn, arg)
209
+ end
210
+ end
211
+
212
+ if opt
213
+ opt[1..-1].each do |opt|
214
+ res << s(:lasgn, opt[1])
215
+ end
216
+ end
217
+
218
+ if rest
219
+ r = rest.to_s[1..-1].intern
220
+ res << s(:splat, s(:lasgn, r))
221
+ @scope.add_local r
222
+ end
223
+
224
+ if block
225
+ b = block.to_s[1..-1].intern
226
+ res << s(:block_pass, s(:lasgn, b))
227
+ @scope.add_local r
228
+ end
229
+
230
+ res << opt if opt
231
+
232
+ res.size == 2 && norm ? res[1] : s(:masgn, res)
233
+ end
234
+
235
+ def new_call recv, meth, args = nil
236
+ call = s(:call, recv, meth)
237
+ args = s(:arglist) unless args
238
+ args[0] = :arglist if args[0] == :array
239
+ call << args
240
+
241
+ if recv
242
+ call.line = recv.line
243
+ elsif args[1]
244
+ call.line = args[1].line
245
+ end
246
+
247
+ # fix arglist spilling over into next line if no args
248
+ if args.length == 1
249
+ args.line = call.line
250
+ else
251
+ args.line = args[1].line
252
+ end
253
+
254
+ call
255
+ end
256
+
257
+ def add_block_pass arglist, block
258
+ arglist << block if block
259
+ arglist
260
+ end
261
+
262
+ def new_op_asgn op, lhs, rhs
263
+ case op
264
+ when :"||"
265
+ result = s(:op_asgn_or, new_gettable(lhs))
266
+ result << (lhs << rhs)
267
+ when :"&&"
268
+ result = s(:op_asgn_and, new_gettable(lhs))
269
+ result << (lhs << rhs)
270
+ else
271
+ result = lhs
272
+ result << new_call(new_gettable(lhs), op, s(:arglist, rhs))
273
+
274
+ end
275
+
276
+ result.line = lhs.line
277
+ result
278
+ end
279
+
280
+ def new_assign lhs, rhs
281
+ case lhs[0]
282
+ when :iasgn, :cdecl, :lasgn, :gasgn, :cvdecl
283
+ lhs << rhs
284
+ lhs
285
+ when :call, :attrasgn
286
+ lhs.last << rhs
287
+ lhs
288
+ else
289
+ raise "Bad lhs for new_assign: #{lhs[0]}"
290
+ end
291
+ end
292
+
293
+ def new_assignable ref
294
+ case ref[0]
295
+ when :ivar
296
+ ref[0] = :iasgn
297
+ when :const
298
+ ref[0] = :cdecl
299
+ when :identifier
300
+ @scope.add_local ref[1] unless @scope.has_local? ref[1]
301
+ ref[0] = :lasgn
302
+ when :gvar
303
+ ref[0] = :gasgn
304
+ when :cvar
305
+ ref[0] = :cvdecl
306
+ else
307
+ raise "Bad new_assignable type: #{ref[0]}"
308
+ end
309
+
310
+ ref
311
+ end
312
+
313
+ def new_gettable ref
314
+ res = case ref[0]
315
+ when :lasgn
316
+ s(:lvar, ref[1])
317
+ when :iasgn
318
+ s(:ivar, ref[1])
319
+ when :gasgn
320
+ s(:gvar, ref[1])
321
+ when :cvdecl
322
+ s(:cvar, ref[1])
323
+ else
324
+ raise "Bad new_gettable ref: #{ref[0]}"
325
+ end
326
+
327
+ res.line = ref.line
328
+ res
329
+ end
330
+
331
+ def new_var_ref ref
332
+ case ref[0]
333
+ when :self, :nil, :true, :false, :line, :file
334
+ ref
335
+ when :const
336
+ ref
337
+ when :ivar, :gvar, :cvar
338
+ ref
339
+ when :lit
340
+ # this is when we passed __LINE__ which is converted into :lit
341
+ ref
342
+ when :str
343
+ # returns for __FILE__ as it is converted into str
344
+ ref
345
+ when :identifier
346
+ if @scope.has_local? ref[1]
347
+ s(:lvar, ref[1])
348
+ else
349
+ s(:call, nil, ref[1], s(:arglist))
350
+ end
351
+ else
352
+ raise "Bad var_ref type: #{ref[0]}"
353
+ end
354
+ end
355
+
356
+ def new_super args
357
+ args = (args || s(:arglist))[1..-1]
358
+ s(:super, *args)
359
+ end
360
+
361
+ def new_yield args
362
+ args = (args || s(:arglist))[1..-1]
363
+ s(:yield, *args)
364
+ end
365
+
366
+ def new_xstr str
367
+ return s(:xstr, '') unless str
368
+ case str[0]
369
+ when :str then str[0] = :xstr
370
+ when :dstr then str[0] = :dxstr
371
+ when :evstr then str = s(:dxstr, '', str)
372
+ end
373
+
374
+ str
375
+ end
376
+
377
+ def new_dsym str
378
+ return s(:nil) unless str
379
+ case str[0]
380
+ when :str
381
+ str[0] = :lit
382
+ str[1] = str[1].intern
383
+ when :dstr
384
+ str[0] = :dsym
385
+ end
386
+
387
+ str
388
+ end
389
+
390
+ def new_str str
391
+ # cover empty strings
392
+ return s(:str, "") unless str
393
+ # catch s(:str, "", other_str)
394
+ if str.size == 3 and str[1] == "" and str[0] == :str
395
+ return str[2]
396
+ # catch s(:str, "content", more_content)
397
+ elsif str[0] == :str && str.size > 3
398
+ str[0] = :dstr
399
+ str
400
+ # top level evstr should be a dstr
401
+ elsif str[0] == :evstr
402
+ s(:dstr, "", str)
403
+ else
404
+ str
405
+ end
406
+ end
407
+
408
+ def new_regexp reg
409
+ return s(:lit, //) unless reg
410
+ case reg[0]
411
+ when :str
412
+ s(:lit, Regexp.new(reg[1]))
413
+ when :evstr
414
+ res = s(:dregx, "", reg)
415
+ when :dstr
416
+ reg[0] = :dregx
417
+ reg
418
+ end
419
+ end
420
+
421
+ def str_append str, str2
422
+ return str2 unless str
423
+ return str unless str2
424
+
425
+ if str.first == :evstr
426
+ str = s(:dstr, "", str)
427
+ elsif str.first == :str
428
+ str = s(:dstr, str[1])
429
+ else
430
+ #puts str.first
431
+ end
432
+ str << str2
433
+ str
434
+ end
435
+
436
+ def next_token
437
+ t = get_next_token
438
+ #puts "returning token #{t.inspect}"
439
+ #t[1] = { :value => t[1], :line => @line }
440
+ t
441
+ end
442
+
443
+ def cond_push(n)
444
+ @cond = (@cond << 1) | (n & 1)
445
+ end
446
+
447
+ def cond_pop
448
+ @cond = @cond >> 1
449
+ end
450
+
451
+ def cond_lexpop
452
+ @cond = (@cond >> 1) | (@cond & 1)
453
+ end
454
+
455
+ def cond?
456
+ (@cond & 1) != 0
457
+ end
458
+
459
+ def cmdarg_push(n)
460
+ @cmdarg = (@cmdarg << 1) | (n & 1)
461
+ end
462
+
463
+ def cmdarg_pop
464
+ @cmdarg = @cmdarg >> 1
465
+ end
466
+
467
+ def cmdarg_lexpop
468
+ @cmdarg = (@cmdarg >> 1) | (@cmdarg & 1)
469
+ end
470
+
471
+ def cmdarg?
472
+ (@cmdarg & 1) != 0
473
+ end
474
+
475
+ def next_string_token
476
+ # str_parse, scanner = current_string_parse, @scanner
477
+ str_parse = @string_parse
478
+ scanner = @scanner
479
+ space = false
480
+
481
+ # everything bar single quote and lower case bare wrds can interpolate
482
+ interpolate = str_parse[:interpolate]
483
+
484
+ words = ['w', 'W'].include? str_parse[:beg]
485
+
486
+ space = true if ['w', 'W'].include?(str_parse[:beg]) and scanner.scan(/\s+/)
487
+
488
+ # if not end of string, so we must be parsing contents
489
+ str_buffer = []
490
+
491
+ # see if we can read end of string/xstring/regecp markers
492
+ # if scanner.scan /#{str_parse[:end]}/
493
+ if scanner.scan Regexp.new(Regexp.escape(str_parse[:end]))
494
+ if words && !str_parse[:done_last_space]#&& space
495
+ str_parse[:done_last_space] = true
496
+ scanner.pos -= 1
497
+ return :SPACE, ' '
498
+ end
499
+ @string_parse = nil
500
+
501
+ # return :SPACE, ' ' if words && space
502
+
503
+ # if in %Q{, we should balance { with } before ending.
504
+ if str_parse[:balance]
505
+ if str_parse[:nesting] == 0
506
+ @lex_state = :expr_end
507
+ return :STRING_END, scanner.matched
508
+ else
509
+ #puts "nesting not 0!"
510
+ #puts str_parse[:nesting]
511
+ str_buffer << scanner.matched
512
+ str_parse[:nesting] -= 1
513
+ # make sure we carry on string parse (its set to nil above)
514
+ @string_parse = str_parse
515
+ end
516
+
517
+ elsif ['"', "'"].include? str_parse[:beg]
518
+ @lex_state = :expr_end
519
+ return :STRING_END, scanner.matched
520
+
521
+ elsif str_parse[:beg] == '`'
522
+ @lex_state = :expr_end
523
+ return :STRING_END, scanner.matched
524
+
525
+ elsif str_parse[:beg] == '/'
526
+ result = scanner.matched if scanner.scan(/\w+/)
527
+ @lex_state = :expr_end
528
+ return :REGEXP_END, result
529
+
530
+ else
531
+ @lex_state = :expr_end
532
+ return :STRING_END, scanner.matched
533
+ end
534
+ end
535
+
536
+ return :SPACE, ' ' if space
537
+
538
+ if str_parse[:balance] and scanner.scan Regexp.new(Regexp.escape(str_parse[:beg]))
539
+ #puts "matced beg balance!"
540
+ str_buffer << scanner.matched
541
+ str_parse[:nesting] += 1
542
+ elsif scanner.check(/#[$@]/)
543
+ scanner.scan(/#/)
544
+ if interpolate
545
+ return :STRING_DVAR, scanner.matched
546
+ else
547
+ str_buffer << scanner.matched
548
+ end
549
+
550
+ elsif scanner.scan(/#\{/)
551
+ if interpolate
552
+ # we are into ruby code, so stop parsing content (for now)
553
+ return :STRING_DBEG, scanner.matched
554
+ else
555
+ str_buffer << scanner.matched
556
+ end
557
+
558
+ # causes error, so we will just collect it later on with other text
559
+ elsif scanner.scan(/\#/)
560
+ str_buffer << '#'
561
+ end
562
+
563
+ add_string_content str_buffer, str_parse
564
+ complete_str = str_buffer.join ''
565
+ return :STRING_CONTENT, complete_str
566
+ end
567
+
568
+ def add_string_content(str_buffer, str_parse)
569
+ scanner = @scanner
570
+ # regexp for end of string/regexp
571
+ # end_str_re = /#{str_parse[:end]}/
572
+ end_str_re = Regexp.new(Regexp.escape(str_parse[:end]))
573
+ # can be interpolate
574
+ interpolate = str_parse[:interpolate]
575
+
576
+ words = ['W', 'w'].include? str_parse[:beg]
577
+
578
+ until scanner.eos?
579
+ c = nil
580
+ handled = true
581
+
582
+ if scanner.check end_str_re
583
+ # eos
584
+ # if its just balancing, add it ass normal content..
585
+ if str_parse[:balance] && (str_parse[:nesting] != 0)
586
+ # we only checked above, so actually scan it
587
+ scanner.scan end_str_re
588
+ c = scanner.matched
589
+ str_parse[:nesting] -= 1
590
+ else
591
+ # not balancing, so break (eos!)
592
+ break
593
+ end
594
+
595
+ elsif str_parse[:balance] and scanner.scan Regexp.new(Regexp.escape(str_parse[:beg]))
596
+ str_parse[:nesting] += 1
597
+ c = scanner.matched
598
+
599
+ elsif words && scanner.scan(/\s/)
600
+ scanner.pos -= 1
601
+ break
602
+
603
+ elsif interpolate && scanner.check(/#(?=[\@\{])/)
604
+ break
605
+
606
+ #elsif scanner.scan(/\\\\/)
607
+ #c = scanner.matched
608
+
609
+ elsif scanner.scan(/\\/)
610
+ if str_parse[:regexp]
611
+ if scanner.scan(/(.)/)
612
+ c = "\\" + scanner.matched
613
+ end
614
+ else
615
+ c = if scanner.scan(/n/)
616
+ "\n"
617
+ else
618
+ # escaped char doesnt need escaping, so just return it
619
+ scanner.scan(/./)
620
+ scanner.matched
621
+ end
622
+ end
623
+ else
624
+ handled = false
625
+ end
626
+
627
+ unless handled
628
+ reg = if words
629
+ Regexp.new("[^#{Regexp.escape str_parse[:end]}\#\0\n\ \\\\]+|.")
630
+ elsif str_parse[:balance]
631
+ #puts "using tis regexp"
632
+ Regexp.new("[^#{Regexp.escape str_parse[:end]}#{Regexp.escape str_parse[:beg]}\#\0\\\\]+|.")
633
+ else
634
+ Regexp.new("[^#{Regexp.escape str_parse[:end]}\#\0\\\\]+|.")
635
+ end
636
+
637
+ scanner.scan reg
638
+ #puts scanner.matched
639
+ c = scanner.matched
640
+ end
641
+
642
+ c ||= scanner.matched
643
+ str_buffer << c
644
+ end
645
+
646
+ raise "reached EOF while in string" if scanner.eos?
647
+ end
648
+
649
+ def get_next_token
650
+ if @string_parse
651
+ return next_string_token
652
+ end
653
+
654
+ # scanner, space_seen, cmd_start, c = @scanner, false, false, ''
655
+ scanner = @scanner
656
+ space_seen = false
657
+ cmd_start = false
658
+ c = ''
659
+
660
+ while true
661
+ if scanner.scan(/\ |\t|\r/)
662
+ space_seen = true
663
+ next
664
+
665
+ elsif scanner.scan(/(\n|#)/)
666
+ c = scanner.matched
667
+ if c == '#' then scanner.scan(/(.*)/) else @line += 1; end
668
+
669
+ scanner.scan(/(\n+)/)
670
+ @line += scanner.matched.length if scanner.matched
671
+
672
+ next if [:expr_beg, :expr_dot].include? @lex_state
673
+
674
+ cmd_start = true
675
+ @lex_state = :expr_beg
676
+ return '\\n', '\\n'
677
+
678
+ elsif scanner.scan(/\;/)
679
+ @lex_state = :expr_beg
680
+ return ';', ';'
681
+
682
+ elsif scanner.scan(/\"/)
683
+ @string_parse = { :beg => '"', :end => '"', :interpolate => true }
684
+ return :STRING_BEG, scanner.matched
685
+
686
+ elsif scanner.scan(/\'/)
687
+ @string_parse = { :beg => "'", :end => "'" }
688
+ return :STRING_BEG, scanner.matched
689
+
690
+ elsif scanner.scan(/\`/)
691
+ @string_parse = { :beg => "`", :end => "`", :interpolate => true }
692
+ return :XSTRING_BEG, scanner.matched
693
+
694
+ elsif scanner.scan(/\%W/)
695
+ start_word = scanner.scan(/./)
696
+ end_word = { '(' => ')', '[' => ']', '{' => '}' }[start_word] || start_word
697
+ @string_parse = { :beg => 'W', :end => end_word, :interpolate => true }
698
+ scanner.scan(/\s*/)
699
+ return :WORDS_BEG, scanner.matched
700
+
701
+ elsif scanner.scan(/\%w/)
702
+ start_word = scanner.scan(/./)
703
+ end_word = { '(' => ')', '[' => ']', '{' => '}' }[start_word] || start_word
704
+ @string_parse = { :beg => 'w', :end => end_word }
705
+ scanner.scan(/\s*/)
706
+ return :AWORDS_BEG, scanner.matched
707
+
708
+ elsif scanner.scan(/\%[Qq]/)
709
+ interpolate = scanner.matched.end_with? 'Q'
710
+ start_word = scanner.scan(/./)
711
+ end_word = { '(' => ')', '[' => ']', '{' => '}' }[start_word] || start_word
712
+ @string_parse = { :beg => start_word, :end => end_word, :balance => true, :nesting => 0, :interpolate => interpolate }
713
+ return :STRING_BEG, scanner.matched
714
+
715
+ elsif scanner.scan(/\%x/)
716
+ start_word = scanner.scan(/./)
717
+ end_word = { '(' => ')', '[' => ']', '{' => '}' }[start_word] || start_word
718
+ @string_parse = { :beg => start_word, :end => end_word, :balance => true, :nesting => 0, :interpolate => true }
719
+ return :XSTRING_BEG, scanner.matched
720
+
721
+ elsif scanner.scan(/\//)
722
+ if [:expr_beg, :expr_mid].include? @lex_state
723
+ @string_parse = { :beg => '/', :end => '/', :interpolate => true, :regexp => true }
724
+ return :REGEXP_BEG, scanner.matched
725
+ elsif scanner.scan(/\=/)
726
+ @lex_state = :expr_beg
727
+ return :OP_ASGN, '/'
728
+ elsif @lex_state == :expr_fname
729
+ @lex_state = :expr_end
730
+ end
731
+
732
+ return '/', '/'
733
+
734
+ elsif scanner.scan(/\%/)
735
+ if scanner.scan(/\=/)
736
+ @lex_state = :expr_beg
737
+ return :OP_ASGN, '%'
738
+ end
739
+ @lex_state = @lex_state == :expr_fname ? :expr_end : :expr_beg
740
+ return '%', '%'
741
+
742
+ elsif scanner.scan(/\(/)
743
+ result = scanner.matched
744
+ if [:expr_beg, :expr_mid].include? @lex_state
745
+ result = :PAREN_BEG
746
+ elsif space_seen
747
+ result = '('
748
+ end
749
+
750
+ @lex_state = :expr_beg
751
+ cond_push 0
752
+ cmdarg_push 0
753
+
754
+ return result, scanner.matched
755
+
756
+ elsif scanner.scan(/\)/)
757
+ cond_lexpop
758
+ cmdarg_lexpop
759
+ @lex_state = :expr_end
760
+ return ')', scanner.matched
761
+
762
+ elsif scanner.scan(/\[/)
763
+ result = scanner.matched
764
+
765
+ if [:expr_fname, :expr_dot].include? @lex_state
766
+ @lex_state = :expr_arg
767
+ if scanner.scan(/\]=/)
768
+ return '[]=', '[]='
769
+ elsif scanner.scan(/\]/)
770
+ return '[]', '[]'
771
+ else
772
+ raise "Unexpected '[' token"
773
+ end
774
+ elsif [:expr_beg, :expr_mid].include?(@lex_state) || space_seen
775
+ @lex_state = :expr_beg
776
+ cond_push 0
777
+ cmdarg_push 0
778
+ return '[', scanner.matched
779
+ else
780
+ @lex_state = :expr_beg
781
+ cond_push 0
782
+ cmdarg_push 0
783
+ return '[@', scanner.matched
784
+ end
785
+
786
+ elsif scanner.scan(/\]/)
787
+ cond_lexpop
788
+ cmdarg_lexpop
789
+ @lex_state = :expr_end
790
+ return ']', scanner.matched
791
+
792
+ elsif scanner.scan(/\}/)
793
+ cond_lexpop
794
+ cmdarg_lexpop
795
+ @lex_state = :expr_end
796
+
797
+ return '}', scanner.matched
798
+
799
+ elsif scanner.scan(/\.\.\./)
800
+ @lex_state = :expr_beg
801
+ return '...', scanner.matched
802
+
803
+ elsif scanner.scan(/\.\./)
804
+ @lex_state = :expr_beg
805
+ return '..', scanner.matched
806
+
807
+ elsif scanner.scan(/\./)
808
+ @lex_state = :expr_dot unless @lex_state == :expr_fname
809
+ return '.', scanner.matched
810
+
811
+ elsif scanner.scan(/\*\*\=/)
812
+ @lex_state = :expr_beg
813
+ return :OP_ASGN, '**'
814
+
815
+ elsif scanner.scan(/\*\*/)
816
+ return '**', '**'
817
+
818
+ elsif scanner.scan(/\*\=/)
819
+ @lex_state = :expr_beg
820
+ return :OP_ASGN, '*'
821
+
822
+ elsif scanner.scan(/\*/)
823
+ result = scanner.matched
824
+ if @lex_state == :expr_fname
825
+ @lex_state = :expr_end
826
+ return '*', result
827
+ elsif space_seen && scanner.check(/\S/)
828
+ @lex_state = :expr_beg
829
+ return :SPLAT, result
830
+ elsif [:expr_beg, :expr_mid].include? @lex_state
831
+ @lex_state = :expr_beg
832
+ return :SPLAT, result
833
+ else
834
+ @lex_state = :expr_beg
835
+ return '*', result
836
+ end
837
+
838
+ elsif scanner.scan(/\:\:/)
839
+ if [:expr_beg, :expr_mid, :expr_class].include? @lex_state
840
+ @lex_state = :expr_beg
841
+ return '::@', scanner.matched
842
+ end
843
+
844
+ @lex_state = :expr_dot
845
+ return '::', scanner.matched
846
+
847
+ elsif scanner.scan(/\:/)
848
+ if [:expr_end, :expr_endarg].include?(@lex_state) || scanner.check(/\s/)
849
+ unless scanner.check(/\w/)
850
+ @lex_state = :expr_beg
851
+ return ':', ':'
852
+ end
853
+
854
+ @lex_state = :expr_fname
855
+ return :SYMBOL_BEG, ':'
856
+ end
857
+
858
+ if scanner.scan(/\'/)
859
+ @string_parse = { :beg => "'", :end => "'" }
860
+ elsif scanner.scan(/\"/)
861
+ @string_parse = { :beg => '"', :end => '"', :interpolate => true }
862
+ end
863
+
864
+ @lex_state = :expr_fname
865
+ return :SYMBOL_BEG, ':'
866
+
867
+ elsif scanner.check(/\|/)
868
+ if scanner.scan(/\|\|\=/)
869
+ @lex_state = :expr_beg
870
+ return :OP_ASGN, '||'
871
+ elsif scanner.scan(/\|\|/)
872
+ @lex_state = :expr_beg
873
+ return '||', '||'
874
+ elsif scanner.scan(/\|\=/)
875
+ @lex_state = :expr_beg
876
+ return :OP_ASGN, '|'
877
+ elsif scanner.scan(/\|/)
878
+ if @lex_state == :expr_fname
879
+ @lex_state = :expr_end
880
+ return '|', scanner.matched
881
+ else
882
+ @lex_state = :expr_beg
883
+ return '|', scanner.matched
884
+ end
885
+ end
886
+
887
+ elsif scanner.scan(/\^\=/)
888
+ @lex_state = :exor_beg
889
+ return :OP_ASGN, '^'
890
+ elsif scanner.scan(/\^/)
891
+ if @lex_state == :expr_fname
892
+ @lex_state = :expr_end
893
+ return '^', scanner.matched
894
+ end
895
+
896
+ @lex_state = :expr_beg
897
+ return '^', scanner.matched
898
+
899
+ elsif scanner.check(/\&/)
900
+ if scanner.scan(/\&\&\=/)
901
+ @lex_state = :expr_beg
902
+ return :OP_ASGN, '&&'
903
+ elsif scanner.scan(/\&\&/)
904
+ @lex_state = :expr_beg
905
+ return '&&', scanner.matched
906
+ elsif scanner.scan(/\&\=/)
907
+ @lex_state = :expr_beg
908
+ return :OP_ASGN, '&'
909
+ elsif scanner.scan(/\&/)
910
+ if space_seen && !scanner.check(/\s/) && (@lex_state == :expr_cmdarg || @lex_state == :expr_arg)
911
+ return '&@', '&'
912
+ elsif [:expr_beg, :expr_mid].include? @lex_state
913
+ return '&@', '&'
914
+ else
915
+ return '&', '&'
916
+ end
917
+ end
918
+
919
+ elsif scanner.check(/\</)
920
+ if scanner.scan(/\<\<\=/)
921
+ @lex_state = :expr_beg
922
+ return :OP_ASGN, '<<'
923
+ elsif scanner.scan(/\<\</)
924
+ if @lex_state == :expr_fname
925
+ @lex_state = :expr_end
926
+ return '<<', '<<'
927
+ elsif ![:expr_end, :expr_dot, :expr_endarg, :expr_class].include?(@lex_state) && space_seen
928
+ @lex_state = :expr_beg
929
+ return '<<', '<<'
930
+ end
931
+ @lex_state = :expr_beg
932
+ return '<<', '<<'
933
+ elsif scanner.scan(/\<\=\>/)
934
+ if @lex_state == :expr_fname
935
+ @lex_state = :expr_end
936
+ else
937
+ @lex_state = :expr_beg
938
+ end
939
+ return '<=>', '<=>'
940
+ elsif scanner.scan(/\<\=/)
941
+ if @lex_state == :expr_fname
942
+ @lex_state = :expr_end
943
+ else
944
+ @lex_state = :expr_beg
945
+ end
946
+ return '<=', '<='
947
+ elsif scanner.scan(/\</)
948
+ if @lex_state == :expr_fname
949
+ @lex_state = :expr_end
950
+ else
951
+ @lex_state = :expr_beg
952
+ end
953
+ return '<', '<'
954
+ end
955
+
956
+ elsif scanner.check(/\>/)
957
+ if scanner.scan(/\>\>\=/)
958
+ return :OP_ASGN, '>>'
959
+ elsif scanner.scan(/\>\>/)
960
+ return '>>', '>>'
961
+ elsif scanner.scan(/\>\=/)
962
+ if @lex_state == :expr_fname
963
+ @lex_state = :expr_end
964
+ else
965
+ @lex_state = :expr_beg
966
+ end
967
+ return '>=', scanner.matched
968
+ elsif scanner.scan(/\>/)
969
+ if @lex_state == :expr_fname
970
+ @lex_state = :expr_end
971
+ else
972
+ @lex_state = :expr_beg
973
+ end
974
+ return '>', '>'
975
+ end
976
+
977
+ elsif scanner.scan(/[+-]/)
978
+ result = scanner.matched
979
+ sign = result + '@'
980
+
981
+ if @lex_state == :expr_beg || @lex_state == :expr_mid
982
+ @lex_state = :expr_mid
983
+ return [sign, sign]
984
+ elsif @lex_state == :expr_fname
985
+ @lex_state = :expr_end
986
+ return [:IDENTIFIER, result + scanner.matched] if scanner.scan(/@/)
987
+ return [result, result]
988
+ end
989
+
990
+ if scanner.scan(/\=/)
991
+ @lex_state = :expr_beg
992
+ return [:OP_ASGN, result]
993
+ end
994
+
995
+ @lex_state = :expr_beg
996
+ return [result, result]
997
+
998
+ elsif scanner.scan(/\?/)
999
+ @lex_state = :expr_beg if [:expr_end, :expr_endarg].include?(@lex_state)
1000
+ return '?', scanner.matched
1001
+
1002
+ elsif scanner.scan(/\=\=\=/)
1003
+ if @lex_state == :expr_fname
1004
+ @lex_state = :expr_end
1005
+ return '===', '==='
1006
+ end
1007
+ @lex_state = :expr_beg
1008
+ return '===', '==='
1009
+
1010
+ elsif scanner.scan(/\=\=/)
1011
+ if @lex_state == :expr_fname
1012
+ @lex_state = :expr_end
1013
+ return '==', '=='
1014
+ end
1015
+ @lex_state = :expr_beg
1016
+ return '==', '=='
1017
+
1018
+ elsif scanner.scan(/\=\~/)
1019
+ if @lex_state == :expr_fname
1020
+ @lex_state = :expr_end
1021
+ return '=~', '=~'
1022
+ end
1023
+ @lex_state = :expr_beg
1024
+ return '=~', '=~'
1025
+
1026
+ elsif scanner.scan(/\=\>/)
1027
+ @lex_state = :expr_beg
1028
+ return '=>', '=>'
1029
+
1030
+ elsif scanner.scan(/\=/)
1031
+ @lex_state = :expr_beg
1032
+ return '=', '='
1033
+
1034
+ elsif scanner.scan(/\!\=/)
1035
+ if @lex_state == :expr_fname
1036
+ @lex_state == :expr_end
1037
+ return '!=', '!='
1038
+ end
1039
+ @lex_state = :expr_beg
1040
+ return '!=', '!='
1041
+
1042
+ elsif scanner.scan(/\!\~/)
1043
+ @lex_state = :expr_beg
1044
+ return '!~', '!~'
1045
+
1046
+ elsif scanner.scan(/\!/)
1047
+ if @lex_state == :expr_fname
1048
+ @lex_state = :expr_end
1049
+ return '!', '!'
1050
+ end
1051
+ @lex_state = :expr_beg
1052
+ return '!', '!'
1053
+
1054
+ elsif scanner.scan(/\~/)
1055
+ if @lex_state == :expr_fname
1056
+ @lex_state = :expr_end
1057
+ return '~', '~'
1058
+ end
1059
+ @lex_state = :expr_beg
1060
+ return '~', '~'
1061
+
1062
+ elsif scanner.scan(/\$[\+\'\`\&!@\"~*$?\/\\:;=.,<>_]/)
1063
+ @lex_state = :expr_end
1064
+ return :GVAR, scanner.matched
1065
+
1066
+ elsif scanner.scan(/\$\w+/)
1067
+ @lex_state = :expr_end
1068
+ return :GVAR, scanner.matched
1069
+
1070
+ elsif scanner.scan(/\@\@\w*/)
1071
+ @lex_state = :expr_end
1072
+ return :CVAR, scanner.matched
1073
+
1074
+ elsif scanner.scan(/\@\w*/)
1075
+ @lex_state = :expr_end
1076
+ return :IVAR, scanner.matched
1077
+
1078
+ elsif scanner.scan(/\,/)
1079
+ @lex_state = :expr_beg
1080
+ return ',', scanner.matched
1081
+
1082
+ elsif scanner.scan(/\{/)
1083
+ if [:expr_end, :expr_arg, :expr_cmdarg].include? @lex_state
1084
+ result = :LCURLY
1085
+ elsif @lex_state == :expr_endarg
1086
+ result = :LBRACE_ARG
1087
+ else
1088
+ result = '{'
1089
+ end
1090
+
1091
+ @lex_state = :expr_beg
1092
+ cond_push 0
1093
+ cmdarg_push 0
1094
+ return result, scanner.matched
1095
+
1096
+ elsif scanner.check(/[0-9]/)
1097
+ @lex_state = :expr_end
1098
+ if scanner.scan(/[\d_]+\.[\d_]+\b/)
1099
+ return [:FLOAT, scanner.matched.gsub(/_/, '').to_f]
1100
+ elsif scanner.scan(/[\d_]+\b/)
1101
+ return [:INTEGER, scanner.matched.gsub(/_/, '').to_i]
1102
+ elsif scanner.scan(/0(x|X)(\d|[a-f]|[A-F])+/)
1103
+ return [:INTEGER, scanner.matched.to_i]
1104
+ else
1105
+ raise "Lexing error on numeric type: `#{scanner.peek 5}`"
1106
+ end
1107
+
1108
+ elsif scanner.scan(/(\w)+[\?\!]?/)
1109
+ matched = scanner.matched
1110
+ if scanner.peek(2) != '::' && scanner.scan(/:/)
1111
+ @lex_state = :expr_beg
1112
+ return :LABEL, "#{matched}"
1113
+ end
1114
+
1115
+ case matched
1116
+ when 'class'
1117
+ if @lex_state == :expr_dot
1118
+ @lex_state = :expr_end
1119
+ return :IDENTIFIER, matched
1120
+ end
1121
+ @lex_state = :expr_class
1122
+ return :CLASS, matched
1123
+
1124
+ when 'module'
1125
+ return :IDENTIFIER, matched if @lex_state == :expr_dot
1126
+ @lex_state = :expr_class
1127
+ return :MODULE, matched
1128
+
1129
+ when 'defined?'
1130
+ return :IDENTIFIER, matched if @lex_state == :expr_dot
1131
+ @lex_state = :expr_arg
1132
+ return :DEFINED, 'defined?'
1133
+
1134
+ when 'def'
1135
+ @lex_state = :expr_fname
1136
+ @scope_line = @line
1137
+ return :DEF, matched
1138
+
1139
+ when 'undef'
1140
+ @lex_state = :expr_fname
1141
+ return :UNDEF, matched
1142
+
1143
+ when 'end'
1144
+ if [:expr_dot, :expr_fname].include? @lex_state
1145
+ @lex_state = :expr_end
1146
+ return :IDENTIFIER, matched
1147
+ end
1148
+
1149
+ @lex_state = :expr_end
1150
+ return :END, matched
1151
+
1152
+ when 'do'
1153
+ #puts cond?
1154
+ #puts cmdarg?
1155
+ #nputs @lex_state
1156
+ if cond?
1157
+ @lex_state = :expr_beg
1158
+ return :DO_COND, matched
1159
+ elsif cmdarg? && @lex_state != :expr_cmdarg
1160
+ @lex_state = :expr_beg
1161
+ return :DO_BLOCK, matched
1162
+ elsif @lex_state == :expr_endarg
1163
+ return :DO_BLOCK, matched
1164
+ else
1165
+ @lex_state = :expr_beg
1166
+ return :DO, matched
1167
+ end
1168
+
1169
+ when 'if'
1170
+ return :IF, matched if @lex_state == :expr_beg
1171
+ @lex_state = :expr_beg
1172
+ return :IF_MOD, matched
1173
+
1174
+ when 'unless'
1175
+ return :UNLESS, matched if @lex_state == :expr_beg
1176
+ @lex_state = :expr_beg
1177
+ return :UNLESS_MOD, matched
1178
+
1179
+ when 'else'
1180
+ return :ELSE, matched
1181
+
1182
+ when 'elsif'
1183
+ return :ELSIF, matched
1184
+
1185
+ when 'self'
1186
+ @lex_state = :expr_end unless @lex_state == :expr_fname
1187
+ return :SELF, matched
1188
+
1189
+ when 'true'
1190
+ @lex_state = :expr_end
1191
+ return :TRUE, matched
1192
+
1193
+ when 'false'
1194
+ @lex_state = :expr_end
1195
+ return :FALSE, matched
1196
+
1197
+ when 'nil'
1198
+ @lex_state = :expr_end
1199
+ return :NIL, matched
1200
+
1201
+ when '__LINE__'
1202
+ @lex_state = :expr_end
1203
+ return :LINE, @line.to_s
1204
+
1205
+ when '__FILE__'
1206
+ @lex_state = :expr_end
1207
+ return :FILE, matched
1208
+
1209
+ when 'begin'
1210
+ if [:expr_dot, :expr_fname].include? @lex_state
1211
+ @lex_state = :expr_end
1212
+ return :IDENTIFIER, matched
1213
+ end
1214
+ @lex_state = :expr_beg
1215
+ return :BEGIN, matched
1216
+
1217
+ when 'rescue'
1218
+ return :IDENTIFIER, matched if [:expr_dot, :expr_fname].include? @lex_state
1219
+ return :RESCUE, matched if @lex_state == :expr_beg
1220
+ @lex_state = :expr_beg
1221
+ return :RESCUE_MOD, matched
1222
+
1223
+ when 'ensure'
1224
+ @lex_state = :expr_beg
1225
+ return :ENSURE, matched
1226
+
1227
+ when 'case'
1228
+ @lex_state = :expr_beg
1229
+ return :CASE, matched
1230
+
1231
+ when 'when'
1232
+ @lex_state = :expr_beg
1233
+ return :WHEN, matched
1234
+
1235
+ when 'or'
1236
+ @lex_state = :expr_beg
1237
+ return :OR, matched
1238
+
1239
+ when 'and'
1240
+ @lex_state = :expr_beg
1241
+ return :AND, matched
1242
+
1243
+ when 'not'
1244
+ @lex_state = :expr_beg
1245
+ return :NOT, matched
1246
+
1247
+ when 'return'
1248
+ @lex_state = :expr_mid
1249
+ return :RETURN, matched
1250
+
1251
+ when 'next'
1252
+ if @lex_state == :expr_dot || @lex_state == :expr_fname
1253
+ @lex_state = :expr_end
1254
+ return :IDENTIFIER, matched
1255
+ end
1256
+
1257
+ @lex_state = :expr_mid
1258
+ return :NEXT, matched
1259
+
1260
+ when 'redo'
1261
+ if @lex_state == :expr_dot || @lex_state == :expr_fname
1262
+ @lex_state = :expr_end
1263
+ return :IDENTIFIER, matched
1264
+ end
1265
+
1266
+ @lex_state = :expr_mid
1267
+ return :REDO, matched
1268
+
1269
+ when 'break'
1270
+ @lex_state = :expr_mid
1271
+ return :BREAK, matched
1272
+
1273
+ when 'super'
1274
+ @lex_state = :expr_arg
1275
+ return :SUPER, matched
1276
+
1277
+ when 'then'
1278
+ return :THEN, matched
1279
+
1280
+ when 'while'
1281
+ return :WHILE, matched if @lex_state == :expr_beg
1282
+ @lex_state = :expr_beg
1283
+ return :WHILE_MOD, matched
1284
+
1285
+ when 'until'
1286
+ return :UNTIL, matched if @lex_state == :expr_beg
1287
+ @lex_state = :expr_beg
1288
+ return :UNTIL_MOD, matched
1289
+
1290
+ when 'yield'
1291
+ @lex_state = :expr_arg
1292
+ return :YIELD, matched
1293
+
1294
+ when 'alias'
1295
+ @lex_state = :expr_arg
1296
+ return :ALIAS, matched
1297
+ end
1298
+
1299
+ matched = matched
1300
+ if scanner.peek(2) != '::' && scanner.scan(/\:/)
1301
+ return :LABEL, matched
1302
+ end
1303
+
1304
+ if @lex_state == :expr_fname
1305
+ if scanner.scan(/\=/)
1306
+ @lex_state = :expr_end
1307
+ return :IDENTIFIER, matched + scanner.matched
1308
+ end
1309
+ end
1310
+
1311
+ if [:expr_beg, :expr_dot, :expr_mid, :expr_arg, :expr_cmdarg].include? @lex_state
1312
+ # old:
1313
+ #@lex_state = :expr_cmdarg
1314
+ # new:
1315
+ @lex_state = cmd_start ? :expr_cmdarg : :expr_arg
1316
+ else
1317
+ @lex_state = :expr_end
1318
+ end
1319
+
1320
+ return [matched =~ /[A-Z]/ ? :CONSTANT : :IDENTIFIER, matched]
1321
+
1322
+ end
1323
+ return [false, false] if scanner.eos?
1324
+
1325
+ raise LexingError, "Unexpected content in parsing stream `#{scanner.peek 5}`"
1326
+ end
1327
+ end
1328
+ end
1329
+ end