opal 0.5.2 → 0.5.4

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -0
  3. data/lib/opal.rb +0 -5
  4. data/lib/opal/compiler.rb +24 -44
  5. data/lib/opal/nodes/base.rb +5 -8
  6. data/lib/opal/nodes/call.rb +4 -0
  7. data/lib/opal/nodes/class.rb +6 -7
  8. data/lib/opal/nodes/def.rb +4 -4
  9. data/lib/opal/nodes/definitions.rb +0 -14
  10. data/lib/opal/nodes/iter.rb +51 -38
  11. data/lib/opal/nodes/literal.rb +21 -24
  12. data/lib/opal/nodes/module.rb +4 -4
  13. data/lib/opal/nodes/runtime_helpers.rb +45 -0
  14. data/lib/opal/nodes/scope.rb +280 -0
  15. data/lib/opal/nodes/singleton_class.rb +4 -5
  16. data/lib/opal/nodes/super.rb +1 -1
  17. data/lib/opal/nodes/top.rb +9 -7
  18. data/lib/opal/nodes/yield.rb +14 -3
  19. data/lib/opal/parser.rb +4 -18
  20. data/lib/opal/parser/grammar.rb +3745 -3667
  21. data/lib/opal/parser/grammar.y +1692 -1778
  22. data/lib/opal/parser/keywords.rb +35 -35
  23. data/lib/opal/parser/lexer.rb +356 -325
  24. data/lib/opal/parser/sexp.rb +1 -1
  25. data/lib/opal/version.rb +1 -1
  26. data/opal.gemspec +1 -0
  27. data/opal/core/array.rb +320 -81
  28. data/opal/core/enumerable.rb +46 -5
  29. data/opal/core/hash.rb +6 -64
  30. data/opal/core/helpers.rb +67 -0
  31. data/opal/core/method.rb +1 -1
  32. data/opal/core/module.rb +4 -4
  33. data/opal/core/range.rb +1 -12
  34. data/opal/core/regexp.rb +2 -8
  35. data/opal/core/runtime.js +74 -3
  36. data/opal/core/string.rb +99 -74
  37. data/opal/opal.rb +3 -72
  38. data/spec/filters/bugs/array.rb +2 -30
  39. data/spec/filters/bugs/basic_object.rb +0 -1
  40. data/spec/filters/bugs/string.rb +26 -21
  41. data/spec/filters/unsupported/enumerator.rb +3 -0
  42. data/spec/filters/unsupported/float.rb +1 -0
  43. data/spec/filters/unsupported/immutable_strings.rb +15 -0
  44. data/spec/filters/unsupported/tainted.rb +58 -30
  45. data/spec/filters/unsupported/trusted.rb +35 -15
  46. data/spec/opal/parser/class_spec.rb +4 -4
  47. data/spec/opal/parser/def_spec.rb +4 -4
  48. data/spec/opal/parser/lvar_spec.rb +6 -6
  49. data/spec/opal/parser/module_spec.rb +4 -4
  50. data/spec/opal/parser/sclass_spec.rb +2 -2
  51. data/spec/stdlib/native/exposure_spec.rb +33 -0
  52. data/stdlib/buffer.rb +1 -1
  53. data/stdlib/buffer/view.rb +1 -1
  54. data/stdlib/native.rb +193 -174
  55. data/stdlib/opal-parser.rb +0 -6
  56. data/stdlib/pp.rb +9 -0
  57. data/tasks/mspec.rake +3 -1
  58. metadata +9 -9
  59. data/lib/opal/nodes/base_scope.rb +0 -11
  60. data/lib/opal/target_scope.rb +0 -281
  61. data/spec/filters/20.rb +0 -4
  62. data/spec/filters/unsupported/array_subclasses.rb +0 -37
@@ -12,41 +12,41 @@ module Opal
12
12
  end
13
13
 
14
14
  KEYWORDS = [
15
- ["__LINE__", [:LINE, :LINE], :expr_end],
16
- ["__FILE__", [:FILE, :FILE], :expr_end],
17
- ["alias", [:ALIAS, :ALIAS], :expr_fname],
18
- ["and", [:AND, :AND], :expr_beg],
19
- ["begin", [:BEGIN, :BEGIN], :expr_beg],
20
- ["break", [:BREAK, :BREAK], :expr_mid],
21
- ["case", [:CASE, :CASE], :expr_beg],
22
- ["class", [:CLASS, :CLASS], :expr_class],
23
- ["def", [:DEF, :DEF], :expr_fname],
24
- ["defined?", [:DEFINED, :DEFINED], :expr_arg],
25
- ["do", [:DO, :DO], :expr_beg],
26
- ["else", [:ELSE, :ELSE], :expr_beg],
27
- ["elsif", [:ELSIF, :ELSIF], :expr_beg],
28
- ["end", [:END, :END], :expr_end],
29
- ["ensure", [:ENSURE, :ENSURE], :expr_beg],
30
- ["false", [:FALSE, :FALSE], :expr_end],
31
- ["if", [:IF, :IF_MOD], :expr_beg],
32
- ["module", [:MODULE, :MODULE], :expr_beg],
33
- ["nil", [:NIL, :NIL], :expr_end],
34
- ["next", [:NEXT, :NEXT], :expr_mid],
35
- ["not", [:NOT, :NOT], :expr_beg],
36
- ["or", [:OR, :OR], :expr_beg],
37
- ["redo", [:REDO, :REDO], :expr_end],
38
- ["rescue", [:RESCUE, :RESCUE_MOD], :expr_mid],
39
- ["return", [:RETURN, :RETURN], :expr_mid],
40
- ["self", [:SELF, :SELF], :expr_end],
41
- ["super", [:SUPER, :SUPER], :expr_arg],
42
- ["then", [:THEN, :THEN], :expr_beg],
43
- ["true", [:TRUE, :TRUE], :expr_end],
44
- ["undef", [:UNDEF, :UNDEF], :expr_fname],
45
- ["unless", [:UNLESS, :UNLESS_MOD], :expr_beg],
46
- ["until", [:UNTIL, :UNTIL_MOD], :expr_beg],
47
- ["when", [:WHEN, :WHEN], :expr_beg],
48
- ["while", [:WHILE, :WHILE_MOD], :expr_beg],
49
- ["yield", [:YIELD, :YIELD], :expr_arg]
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
+ ["if", [:kIF, :kIF_MOD], :expr_beg],
32
+ ["module", [:kMODULE, :kMODULE], :expr_beg],
33
+ ["nil", [:kNIL, :kNIL], :expr_end],
34
+ ["next", [:kNEXT, :kNEXT], :expr_mid],
35
+ ["not", [:kNOT, :kNOT], :expr_beg],
36
+ ["or", [:kOR, :kOR], :expr_beg],
37
+ ["redo", [:kREDO, :kREDO], :expr_end],
38
+ ["rescue", [:kRESCUE, :kRESCUE_MOD], :expr_mid],
39
+ ["return", [:kRETURN, :kRETURN], :expr_mid],
40
+ ["self", [:kSELF, :kSELF], :expr_end],
41
+ ["super", [:kSUPER, :kSUPER], :expr_arg],
42
+ ["then", [:kTHEN, :kTHEN], :expr_beg],
43
+ ["true", [:kTRUE, :kTRUE], :expr_end],
44
+ ["undef", [:kUNDEF, :kUNDEF], :expr_fname],
45
+ ["unless", [:kUNLESS, :kUNLESS_MOD], :expr_beg],
46
+ ["until", [:kUNTIL, :kUNTIL_MOD], :expr_beg],
47
+ ["when", [:kWHEN, :kWHEN], :expr_beg],
48
+ ["while", [:kWHILE, :kWHILE_MOD], :expr_beg],
49
+ ["yield", [:kYIELD, :kYIELD], :expr_arg]
50
50
  ].map { |decl| KeywordTable.new(*decl) }
51
51
 
52
52
  def self.map
@@ -6,7 +6,7 @@ module Opal
6
6
 
7
7
  attr_reader :line, :scope_line, :scope
8
8
 
9
- attr_accessor :lex_state, :strterm
9
+ attr_accessor :lex_state, :strterm, :scanner
10
10
 
11
11
  def initialize(source, file)
12
12
  @lex_state = :expr_beg
@@ -75,6 +75,18 @@ module Opal
75
75
  @scanner.check(/\s/)
76
76
  end
77
77
 
78
+ def scan(regexp)
79
+ @scanner.scan regexp
80
+ end
81
+
82
+ def check(regexp)
83
+ @scanner.check regexp
84
+ end
85
+
86
+ def matched
87
+ @scanner.matched
88
+ end
89
+
78
90
  def next_token
79
91
  self.yylex
80
92
  end
@@ -85,6 +97,34 @@ module Opal
85
97
  [:dquote, :dsym, :dword, :heredoc, :xquote, :regexp].include? type
86
98
  end
87
99
 
100
+ def new_strterm(type, start, finish)
101
+ { :type => type, :beg => start, :end => finish }
102
+ end
103
+
104
+ def new_strterm2(type, start, finish)
105
+ term = new_strterm(type, start, finish)
106
+ term.merge({ :balance => true, :nesting => 0 })
107
+ end
108
+
109
+ def process_numeric
110
+ @lex_state = :expr_end
111
+ scanner = @scanner
112
+
113
+ if scan(/0b?(0|1|_)+/)
114
+ return [:tINTEGER, scanner.matched.to_i(2)]
115
+ elsif scan(/0o?([0-7]|_)+/)
116
+ return [:tINTEGER, scanner.matched.to_i(8)]
117
+ elsif scan(/[\d_]+\.[\d_]+\b|[\d_]+(\.[\d_]+)?[eE][-+]?[\d_]+\b/)
118
+ return [:tFLOAT, scanner.matched.gsub(/_/, '').to_f]
119
+ elsif scan(/[\d_]+\b/)
120
+ return [:tINTEGER, scanner.matched.gsub(/_/, '').to_i]
121
+ elsif scan(/0(x|X)(\d|[a-f]|[A-F]|_)+/)
122
+ return [:tINTEGER, scanner.matched.to_i(16)]
123
+ else
124
+ raise "Lexing error on numeric type: `#{scanner.peek 5}`"
125
+ end
126
+ end
127
+
88
128
  def next_string_token
89
129
  str_parse = self.strterm
90
130
  scanner = @scanner
@@ -94,7 +134,7 @@ module Opal
94
134
 
95
135
  words = ['w', 'W'].include? str_parse[:beg]
96
136
 
97
- space = true if ['w', 'W'].include?(str_parse[:beg]) and scanner.scan(/\s+/)
137
+ space = true if ['w', 'W'].include?(str_parse[:beg]) and scan(/\s+/)
98
138
 
99
139
  # if not end of string, so we must be parsing contents
100
140
  str_buffer = []
@@ -102,8 +142,8 @@ module Opal
102
142
  if str_parse[:type] == :heredoc
103
143
  eos_regx = /[ \t]*#{Regexp.escape(str_parse[:end])}(\r*\n|$)/
104
144
 
105
- if scanner.check(eos_regx)
106
- scanner.scan(/[ \t]*#{Regexp.escape(str_parse[:end])}/)
145
+ if check(eos_regx)
146
+ scan(/[ \t]*#{Regexp.escape(str_parse[:end])}/)
107
147
  self.strterm = nil
108
148
 
109
149
  if str_parse[:scanner]
@@ -112,17 +152,17 @@ module Opal
112
152
  end
113
153
 
114
154
  @lex_state = :expr_end
115
- return :STRING_END, scanner.matched
155
+ return :tSTRING_END, scanner.matched
116
156
  end
117
157
  end
118
158
 
119
- # see if we can read end of string/xstring/regecp markers
120
- # if scanner.scan /#{str_parse[:end]}/
121
- if scanner.scan Regexp.new(Regexp.escape(str_parse[:end]))
159
+ # see if we can read end of string/xstring/regexp markers
160
+ # if scan /#{str_parse[:end]}/
161
+ if scan Regexp.new(Regexp.escape(str_parse[:end]))
122
162
  if words && !str_parse[:done_last_space]#&& space
123
163
  str_parse[:done_last_space] = true
124
164
  scanner.pos -= 1
125
- return :SPACE, ' '
165
+ return :tSPACE, ' '
126
166
  end
127
167
  self.strterm = nil
128
168
 
@@ -130,11 +170,11 @@ module Opal
130
170
  if str_parse[:nesting] == 0
131
171
  @lex_state = :expr_end
132
172
 
133
- if str_parse[:regexp]
134
- result = scanner.scan(/\w+/)
135
- return :REGEXP_END, result
173
+ if str_parse[:type] == :regexp
174
+ result = scan(/\w+/)
175
+ return :tREGEXP_END, result
136
176
  end
137
- return :STRING_END, scanner.matched
177
+ return :tSTRING_END, scanner.matched
138
178
  else
139
179
  str_buffer << scanner.matched
140
180
  str_parse[:nesting] -= 1
@@ -143,16 +183,16 @@ module Opal
143
183
 
144
184
  elsif ['"', "'"].include? str_parse[:beg]
145
185
  @lex_state = :expr_end
146
- return :STRING_END, scanner.matched
186
+ return :tSTRING_END, scanner.matched
147
187
 
148
188
  elsif str_parse[:beg] == '`'
149
189
  @lex_state = :expr_end
150
- return :STRING_END, scanner.matched
190
+ return :tSTRING_END, scanner.matched
151
191
 
152
- elsif str_parse[:beg] == '/' || str_parse[:regexp]
153
- result = scanner.scan(/\w+/)
192
+ elsif str_parse[:beg] == '/' || str_parse[:type] == :regexp
193
+ result = scan(/\w+/)
154
194
  @lex_state = :expr_end
155
- return :REGEXP_END, result
195
+ return :tREGEXP_END, result
156
196
 
157
197
  else
158
198
  if str_parse[:scanner]
@@ -161,33 +201,33 @@ module Opal
161
201
  end
162
202
 
163
203
  @lex_state = :expr_end
164
- return :STRING_END, scanner.matched
204
+ return :tSTRING_END, scanner.matched
165
205
  end
166
206
  end
167
207
 
168
- return :SPACE, ' ' if space
208
+ return :tSPACE, ' ' if space
169
209
 
170
- if str_parse[:balance] and scanner.scan Regexp.new(Regexp.escape(str_parse[:beg]))
210
+ if str_parse[:balance] and scan Regexp.new(Regexp.escape(str_parse[:beg]))
171
211
  str_buffer << scanner.matched
172
212
  str_parse[:nesting] += 1
173
- elsif scanner.check(/#[@$]/)
174
- scanner.scan(/#/)
213
+ elsif check(/#[@$]/)
214
+ scan(/#/)
175
215
  if expand
176
- return :STRING_DVAR, scanner.matched
216
+ return :tSTRING_DVAR, scanner.matched
177
217
  else
178
218
  str_buffer << scanner.matched
179
219
  end
180
220
 
181
- elsif scanner.scan(/#\{/)
221
+ elsif scan(/#\{/)
182
222
  if expand
183
223
  # we are into ruby code, so stop parsing content (for now)
184
- return :STRING_DBEG, scanner.matched
224
+ return :tSTRING_DBEG, scanner.matched
185
225
  else
186
226
  str_buffer << scanner.matched
187
227
  end
188
228
 
189
229
  # causes error, so we will just collect it later on with other text
190
- elsif scanner.scan(/\#/)
230
+ elsif scan(/\#/)
191
231
  str_buffer << '#'
192
232
  end
193
233
 
@@ -199,7 +239,7 @@ module Opal
199
239
 
200
240
  complete_str = str_buffer.join ''
201
241
  @line += complete_str.count("\n")
202
- return :STRING_CONTENT, complete_str
242
+ return :tSTRING_CONTENT, complete_str
203
243
  end
204
244
 
205
245
  def add_heredoc_content(str_buffer, str_parse)
@@ -212,29 +252,29 @@ module Opal
212
252
  c = nil
213
253
  handled = true
214
254
 
215
- if scanner.scan(/\n/)
255
+ if scan(/\n/)
216
256
  c = scanner.matched
217
- elsif scanner.check(eos_regx) && scanner.bol?
257
+ elsif check(eos_regx) && scanner.bol?
218
258
  break # eos!
219
- elsif expand && scanner.check(/#(?=[\$\@\{])/)
259
+ elsif expand && check(/#(?=[\$\@\{])/)
220
260
  break
221
- elsif scanner.scan(/\\/)
222
- if str_parse[:regexp]
223
- if scanner.scan(/(.)/)
261
+ elsif scan(/\\/)
262
+ if str_parse[:type] == :regexp
263
+ if scan(/(.)/)
224
264
  c = "\\" + scanner.matched
225
265
  end
226
266
  else
227
- c = if scanner.scan(/n/)
267
+ c = if scan(/n/)
228
268
  "\n"
229
- elsif scanner.scan(/r/)
269
+ elsif scan(/r/)
230
270
  "\r"
231
- elsif scanner.scan(/\n/)
271
+ elsif scan(/\n/)
232
272
  "\n"
233
- elsif scanner.scan(/t/)
273
+ elsif scan(/t/)
234
274
  "\t"
235
275
  else
236
276
  # escaped char doesnt need escaping, so just return it
237
- scanner.scan(/./)
277
+ scan(/./)
238
278
  scanner.matched
239
279
  end
240
280
  end
@@ -245,7 +285,7 @@ module Opal
245
285
  unless handled
246
286
  reg = Regexp.new("[^#{Regexp.escape str_parse[:end]}\#\0\\\\\n]+|.")
247
287
 
248
- scanner.scan reg
288
+ scan reg
249
289
  c = scanner.matched
250
290
  end
251
291
 
@@ -270,12 +310,12 @@ module Opal
270
310
  c = nil
271
311
  handled = true
272
312
 
273
- if scanner.check end_str_re
313
+ if check end_str_re
274
314
  # eos
275
315
  # if its just balancing, add it ass normal content..
276
316
  if str_parse[:balance] && (str_parse[:nesting] != 0)
277
317
  # we only checked above, so actually scan it
278
- scanner.scan end_str_re
318
+ scan end_str_re
279
319
  c = scanner.matched
280
320
  str_parse[:nesting] -= 1
281
321
  else
@@ -283,37 +323,37 @@ module Opal
283
323
  break
284
324
  end
285
325
 
286
- elsif str_parse[:balance] and scanner.scan Regexp.new(Regexp.escape(str_parse[:beg]))
326
+ elsif str_parse[:balance] and scan Regexp.new(Regexp.escape(str_parse[:beg]))
287
327
  str_parse[:nesting] += 1
288
328
  c = scanner.matched
289
329
 
290
- elsif words && scanner.scan(/\s/)
330
+ elsif words && scan(/\s/)
291
331
  scanner.pos -= 1
292
332
  break
293
333
 
294
- elsif expand && scanner.check(/#(?=[\$\@\{])/)
334
+ elsif expand && check(/#(?=[\$\@\{])/)
295
335
  break
296
336
 
297
- #elsif scanner.scan(/\\\\/)
337
+ #elsif scan(/\\\\/)
298
338
  #c = scanner.matched
299
339
 
300
- elsif scanner.scan(/\\/)
301
- if str_parse[:regexp]
302
- if scanner.scan(/(.)/)
340
+ elsif scan(/\\/)
341
+ if str_parse[:type] == :regexp
342
+ if scan(/(.)/)
303
343
  c = "\\" + scanner.matched
304
344
  end
305
345
  else
306
- c = if scanner.scan(/n/)
346
+ c = if scan(/n/)
307
347
  "\n"
308
- elsif scanner.scan(/r/)
348
+ elsif scan(/r/)
309
349
  "\r"
310
- elsif scanner.scan(/\n/)
350
+ elsif scan(/\n/)
311
351
  "\n"
312
- elsif scanner.scan(/t/)
352
+ elsif scan(/t/)
313
353
  "\t"
314
354
  else
315
355
  # escaped char doesnt need escaping, so just return it
316
- scanner.scan(/./)
356
+ scan(/./)
317
357
  scanner.matched
318
358
  end
319
359
  end
@@ -330,7 +370,7 @@ module Opal
330
370
  Regexp.new("[^#{Regexp.escape str_parse[:end]}\#\0\\\\]+|.")
331
371
  end
332
372
 
333
- scanner.scan reg
373
+ scan reg
334
374
  c = scanner.matched
335
375
  end
336
376
 
@@ -344,14 +384,14 @@ module Opal
344
384
  def heredoc_identifier
345
385
  if @scanner.scan(/(-?)['"]?(\w+)['"]?/)
346
386
  heredoc = @scanner[2]
347
- self.strterm = { :type => :heredoc, :beg => heredoc, :end => heredoc }
387
+ self.strterm = new_strterm(:heredoc, heredoc, heredoc)
348
388
 
349
389
  # if ruby code at end of line after heredoc, we have to store it to
350
390
  # parse after heredoc is finished parsing
351
391
  end_of_line = @scanner.scan(/.*\n/)
352
392
  self.strterm[:scanner] = StringScanner.new(end_of_line) if end_of_line != "\n"
353
393
 
354
- return :STRING_BEG, heredoc
394
+ return :tSTRING_BEG, heredoc
355
395
  end
356
396
  end
357
397
 
@@ -359,34 +399,34 @@ module Opal
359
399
  scanner = @scanner
360
400
  matched = scanner.matched
361
401
 
362
- if scanner.peek(2) != '::' && scanner.scan(/:/)
402
+ if scanner.peek(2) != '::' && scan(/:/)
363
403
  @lex_state = :expr_beg
364
- return :LABEL, "#{matched}"
404
+ return :tLABEL, "#{matched}"
365
405
  end
366
406
 
367
407
  if matched == 'defined?'
368
408
  if after_operator?
369
409
  @lex_state = :expr_end
370
- return :IDENTIFIER, matched
410
+ return :tIDENTIFIER, matched
371
411
  end
372
412
 
373
413
  @lex_state = :expr_arg
374
- return :DEFINED, 'defined?'
414
+ return :kDEFINED, 'defined?'
375
415
  end
376
416
 
377
417
  if matched.end_with? '?', '!'
378
- result = :IDENTIFIER
418
+ result = :tIDENTIFIER
379
419
  else
380
420
  if @lex_state == :expr_fname
381
- if scanner.scan(/\=/)
382
- result = :IDENTIFIER
421
+ if scan(/\=/)
422
+ result = :tIDENTIFIER
383
423
  matched += scanner.matched
384
424
  end
385
425
 
386
426
  elsif matched =~ /^[A-Z]/
387
- result = :CONSTANT
427
+ result = :tCONSTANT
388
428
  else
389
- result = :IDENTIFIER
429
+ result = :tIDENTIFIER
390
430
  end
391
431
  end
392
432
 
@@ -405,24 +445,24 @@ module Opal
405
445
  if matched == "do"
406
446
  if after_operator?
407
447
  @lex_state = :expr_end
408
- return :IDENTIFIER, matched
448
+ return :tIDENTIFIER, matched
409
449
  end
410
450
 
411
451
  if @start_of_lambda
412
452
  @start_of_lambda = false
413
453
  @lex_state = :expr_beg
414
- return [:DO_LAMBDA, scanner.matched]
454
+ return [:kDO_LAMBDA, scanner.matched]
415
455
  elsif cond?
416
456
  @lex_state = :expr_beg
417
- return :DO_COND, matched
457
+ return :kDO_COND, matched
418
458
  elsif cmdarg? && @lex_state != :expr_cmdarg
419
459
  @lex_state = :expr_beg
420
- return :DO_BLOCK, matched
460
+ return :kDO_BLOCK, matched
421
461
  elsif @lex_state == :expr_endarg
422
- return :DO_BLOCK, matched
462
+ return :kDO_BLOCK, matched
423
463
  else
424
464
  @lex_state = :expr_beg
425
- return :DO, matched
465
+ return :kDO, matched
426
466
  end
427
467
  else
428
468
  if old_state == :expr_beg or old_state == :expr_value
@@ -443,11 +483,10 @@ module Opal
443
483
  @lex_state = :expr_end
444
484
  end
445
485
 
446
- return [matched =~ /^[A-Z]/ ? :CONSTANT : :IDENTIFIER, matched]
486
+ return [matched =~ /^[A-Z]/ ? :tCONSTANT : :tIDENTIFIER, matched]
447
487
  end
448
488
 
449
489
  def yylex
450
- scanner = @scanner
451
490
  @space_seen = false
452
491
  cmd_start = false
453
492
  c = ''
@@ -457,39 +496,39 @@ module Opal
457
496
  end
458
497
 
459
498
  while true
460
- if scanner.scan(/\ |\t|\r/)
499
+ if scan(/\ |\t|\r/)
461
500
  @space_seen = true
462
501
  next
463
502
 
464
- elsif scanner.scan(/(\n|#)/)
503
+ elsif scan(/(\n|#)/)
465
504
  c = scanner.matched
466
- if c == '#' then scanner.scan(/(.*)/) else @line += 1; end
505
+ if c == '#' then scan(/(.*)/) else @line += 1; end
467
506
 
468
- scanner.scan(/(\n+)/)
507
+ scan(/(\n+)/)
469
508
  @line += scanner.matched.length if scanner.matched
470
509
 
471
510
  next if [:expr_beg, :expr_dot].include? @lex_state
472
511
 
473
- if scanner.scan(/([\ \t\r\f\v]*)\./)
512
+ if scan(/([\ \t\r\f\v]*)\./)
474
513
  @space_seen = true unless scanner[1].empty?
475
514
  scanner.pos = scanner.pos - 1
476
515
 
477
- next unless scanner.check(/\.\./)
516
+ next unless check(/\.\./)
478
517
  end
479
518
 
480
519
  cmd_start = true
481
520
  @lex_state = :expr_beg
482
- return '\\n', '\\n'
521
+ return :tNL, '\\n'
483
522
 
484
- elsif scanner.scan(/\;/)
523
+ elsif scan(/\;/)
485
524
  @lex_state = :expr_beg
486
- return ';', ';'
525
+ return :tSEMI, ';'
487
526
 
488
- elsif scanner.scan(/\*/)
489
- if scanner.scan(/\*/)
490
- if scanner.scan(/\=/)
527
+ elsif scan(/\*/)
528
+ if scan(/\*/)
529
+ if scan(/\=/)
491
530
  @lex_state = :expr_beg
492
- return :OP_ASGN, '**'
531
+ return :tOP_ASGN, '**'
493
532
  end
494
533
 
495
534
  if @lex_state == :expr_fname or @lex_state == :expr_dot
@@ -498,74 +537,74 @@ module Opal
498
537
  @lex_state = :expr_beg
499
538
  end
500
539
 
501
- return '**', '**'
540
+ return :tPOW, '**'
502
541
 
503
542
  else
504
- if scanner.scan(/\=/)
543
+ if scan(/\=/)
505
544
  @lex_state = :expr_beg
506
- return :OP_ASGN, '*'
545
+ return :tOP_ASGN, '*'
507
546
  end
508
547
  end
509
548
 
510
- if scanner.scan(/\*\=/)
549
+ if scan(/\*\=/)
511
550
  @lex_state = :expr_beg
512
- return :OP_ASGN, '**'
551
+ return :tOP_ASGN, '**'
513
552
  end
514
553
 
515
- if scanner.scan(/\*/)
554
+ if scan(/\*/)
516
555
  if after_operator?
517
556
  @lex_state = :expr_arg
518
557
  else
519
558
  @lex_state = :expr_beg
520
559
  end
521
560
 
522
- return '**', '**'
561
+ return :tPOW, '**'
523
562
  end
524
563
 
525
- if scanner.scan(/\=/)
564
+ if scan(/\=/)
526
565
  @lex_state = :expr_beg
527
- return :OP_ASGN, '*'
566
+ return :tOP_ASGN, '*'
528
567
  else
529
568
  result = '*'
530
569
  if @lex_state == :expr_fname or @lex_state == :expr_dot
531
570
  @lex_state = :expr_arg
532
- return '*', result
533
- elsif @space_seen && scanner.check(/\S/)
571
+ return :tSTAR2, result
572
+ elsif @space_seen && check(/\S/)
534
573
  @lex_state = :expr_beg
535
- return :SPLAT, result
574
+ return :tSTAR, result
536
575
  elsif [:expr_beg, :expr_mid].include? @lex_state
537
576
  @lex_state = :expr_beg
538
- return :SPLAT, result
577
+ return :tSTAR, result
539
578
  else
540
579
  @lex_state = :expr_beg
541
- return '*', result
580
+ return :tSTAR2, result
542
581
  end
543
582
  end
544
583
 
545
- elsif scanner.scan(/\!/)
546
- c = scanner.scan(/./)
584
+ elsif scan(/\!/)
585
+ c = scan(/./)
547
586
  if after_operator?
548
587
  @lex_state = :expr_arg
549
588
  if c == "@"
550
- return '!', '!'
589
+ return :tBANG, '!'
551
590
  end
552
591
  else
553
592
  @lex_state = :expr_beg
554
593
  end
555
594
 
556
595
  if c == '='
557
- return '!=', '!='
596
+ return :tNEQ, '!='
558
597
  elsif c == '~'
559
- return '!~', '!~'
598
+ return :tNMATCH, '!~'
560
599
  end
561
600
 
562
601
  scanner.pos = scanner.pos - 1
563
- return '!', '!'
602
+ return :tBANG, '!'
564
603
 
565
- elsif scanner.scan(/\=/)
604
+ elsif scan(/\=/)
566
605
  if @lex_state == :expr_beg and !@space_seen
567
- if scanner.scan(/begin/) and space?
568
- scanner.scan(/(.*)/) # end of line
606
+ if scan(/begin/) and space?
607
+ scan(/(.*)/) # end of line
569
608
  line_count = 0
570
609
 
571
610
  while true
@@ -573,17 +612,17 @@ module Opal
573
612
  raise "embedded document meets end of file"
574
613
  end
575
614
 
576
- if scanner.scan(/\=end/) and space?
615
+ if scan(/\=end/) and space?
577
616
  @line += line_count
578
617
  return next_token
579
618
  end
580
619
 
581
- if scanner.scan(/\n/)
620
+ if scan(/\n/)
582
621
  line_count += 1
583
622
  next
584
623
  end
585
624
 
586
- scanner.scan(/(.*)/)
625
+ scan(/(.*)/)
587
626
  end
588
627
  end
589
628
  end
@@ -594,164 +633,165 @@ module Opal
594
633
  :expr_beg
595
634
  end
596
635
 
597
- if scanner.scan(/\=/)
598
- if scanner.scan(/\=/)
599
- return '===', '==='
636
+ if scan(/\=/)
637
+ if scan(/\=/)
638
+ return :tEQQ, '==='
600
639
  end
601
640
 
602
- return '==', '=='
641
+ return :tEQ, '=='
603
642
  end
604
643
 
605
- if scanner.scan(/\~/)
606
- return '=~', '=~'
607
- elsif scanner.scan(/\>/)
608
- return '=>', '=>'
644
+ if scan(/\~/)
645
+ return :tMATCH, '=~'
646
+ elsif scan(/\>/)
647
+ return :tASSOC, '=>'
609
648
  end
610
649
 
611
- return '=', '='
650
+ return :tEQL, '='
612
651
 
613
- elsif scanner.scan(/\"/)
614
- self.strterm = { :type => :dquote, :beg => '"', :end => '"' }
615
- return :STRING_BEG, scanner.matched
652
+ elsif scan(/\"/)
653
+ self.strterm = new_strterm(:dquote, '"', '"')
654
+ return :tSTRING_BEG, scanner.matched
616
655
 
617
- elsif scanner.scan(/\'/)
618
- self.strterm = { :type => :squote, :beg => "'", :end => "'" }
619
- return :STRING_BEG, scanner.matched
656
+ elsif scan(/\'/)
657
+ self.strterm = new_strterm(:squote, "'", "'")
658
+ return :tSTRING_BEG, scanner.matched
620
659
 
621
- elsif scanner.scan(/\`/)
622
- self.strterm = { :type => :xquote, :beg => "`", :end => "`" }
623
- return :XSTRING_BEG, scanner.matched
660
+ elsif scan(/\`/)
661
+ self.strterm = new_strterm(:xquote, '`', '`')
662
+ return :tXSTRING_BEG, scanner.matched
624
663
 
625
- elsif scanner.scan(/\&/)
626
- if scanner.scan(/\&/)
664
+ elsif scan(/\&/)
665
+ if scan(/\&/)
627
666
  @lex_state = :expr_beg
628
667
 
629
- if scanner.scan(/\=/)
630
- return :OP_ASGN, '&&'
668
+ if scan(/\=/)
669
+ return :tOP_ASGN, '&&'
631
670
  end
632
671
 
633
- return '&&', '&&'
672
+ return :tANDOP, '&&'
634
673
 
635
- elsif scanner.scan(/\=/)
674
+ elsif scan(/\=/)
636
675
  @lex_state = :expr_beg
637
- return :OP_ASGN, '&'
676
+ return :tOP_ASGN, '&'
638
677
  end
639
678
 
640
679
  if spcarg?
641
680
  #puts "warning: `&' interpreted as argument prefix"
642
- result = '&@'
681
+ result = :tAMPER
643
682
  elsif beg?
644
- result = '&@'
683
+ result = :tAMPER
645
684
  else
646
685
  #puts "warn_balanced: & argument prefix"
647
- result = '&'
686
+ result = :tAMPER2
648
687
  end
649
688
 
650
689
  @lex_state = after_operator? ? :expr_arg : :expr_beg
651
690
  return result, '&'
652
691
 
653
- elsif scanner.scan(/\|/)
654
- if scanner.scan(/\|/)
692
+ elsif scan(/\|/)
693
+ if scan(/\|/)
655
694
  @lex_state = :expr_beg
656
- if scanner.scan(/\=/)
657
- return :OP_ASGN, '||'
695
+ if scan(/\=/)
696
+ return :tOP_ASGN, '||'
658
697
  end
659
698
 
660
- return '||', '||'
699
+ return :tOROP, '||'
661
700
 
662
- elsif scanner.scan(/\=/)
663
- return :OP_ASGN, '|'
701
+ elsif scan(/\=/)
702
+ return :tOP_ASGN, '|'
664
703
  end
665
704
 
666
705
  @lex_state = after_operator?() ? :expr_arg : :expr_beg
667
- return '|', '|'
668
-
669
- elsif scanner.scan(/\%W/)
670
- start_word = scanner.scan(/./)
671
- end_word = { '(' => ')', '[' => ']', '{' => '}' }[start_word] || start_word
672
- self.strterm = { :type => :dword, :beg => 'W', :end => end_word }
673
- scanner.scan(/\s*/)
674
- return :WORDS_BEG, scanner.matched
675
-
676
- elsif scanner.scan(/\%w/) or scanner.scan(/\%i/)
677
- start_word = scanner.scan(/./)
678
- end_word = { '(' => ')', '[' => ']', '{' => '}' }[start_word] || start_word
679
- self.strterm = { :type => :sword, :beg => 'w', :end => end_word }
680
- scanner.scan(/\s*/)
681
- return :AWORDS_BEG, scanner.matched
682
-
683
- elsif scanner.scan(/\%[Qq]/)
684
- type = scanner.matched.end_with?('Q') ? :dquote : :squote
685
- start_word = scanner.scan(/./)
686
- end_word = { '(' => ')', '[' => ']', '{' => '}' }[start_word] || start_word
687
- self.strterm = { :type => type, :beg => start_word, :end => end_word, :balance => true, :nesting => 0 }
688
- return :STRING_BEG, scanner.matched
689
-
690
- elsif scanner.scan(/\%x/)
691
- start_word = scanner.scan(/./)
692
- end_word = { '(' => ')', '[' => ']', '{' => '}' }[start_word] || start_word
693
- self.strterm = { :type => :xquote, :beg => start_word, :end => end_word, :balance => true, :nesting => 0 }
694
- return :XSTRING_BEG, scanner.matched
695
-
696
- elsif scanner.scan(/\%r/)
697
- start_word = scanner.scan(/./)
698
- end_word = { '(' => ')', '[' => ']', '{' => '}' }[start_word] || start_word
699
- self.strterm = { :type => :regexp, :beg => start_word, :end => end_word, :regexp => true, :balance => true, :nesting => 0 }
700
- return :REGEXP_BEG, scanner.matched
701
-
702
- elsif scanner.scan(/\//)
706
+ return :tPIPE, '|'
707
+
708
+ elsif scan(/\%[QqWwxr]/)
709
+ str_type = scanner.matched[1, 1]
710
+ paren = scan(/./)
711
+
712
+ term = case paren
713
+ when '(' then ')'
714
+ when '[' then ']'
715
+ when '{' then '}'
716
+ else paren
717
+ end
718
+
719
+ case str_type
720
+ when 'Q'
721
+ self.strterm = new_strterm2(:dquote, paren, term)
722
+ return :tSTRING_BEG, scanner.matched
723
+ when 'q'
724
+ self.strterm = new_strterm2(:squote, paren, term)
725
+ return :tSTRING_BEG, scanner.matched
726
+ when 'W'
727
+ self.strterm = new_strterm(:dword, 'W', term)
728
+ scan(/\s*/)
729
+ return :tWORDS_BEG, scanner.matched
730
+ when 'w', 'i'
731
+ self.strterm = new_strterm(:sword, 'w', term)
732
+ scan(/\s*/)
733
+ return :tAWORDS_BEG, scanner.matched
734
+ when 'x'
735
+ self.strterm = new_strterm2(:xquote, paren, term)
736
+ return :tXSTRING_BEG, scanner.matched
737
+ when 'r'
738
+ self.strterm = new_strterm2(:regexp, paren, term)
739
+ return :tREGEXP_BEG, scanner.matched
740
+ end
741
+
742
+ elsif scan(/\//)
703
743
  if [:expr_beg, :expr_mid].include? @lex_state
704
- self.strterm = { :type => :regexp, :beg => '/', :end => '/', :regexp => true }
705
- return :REGEXP_BEG, scanner.matched
706
- elsif scanner.scan(/\=/)
744
+ self.strterm = new_strterm(:regexp, '/', '/')
745
+ return :tREGEXP_BEG, scanner.matched
746
+ elsif scan(/\=/)
707
747
  @lex_state = :expr_beg
708
- return :OP_ASGN, '/'
748
+ return :tOP_ASGN, '/'
709
749
  elsif @lex_state == :expr_fname or @lex_state == :expr_dot
710
750
  @lex_state = :expr_arg
711
751
  elsif @lex_state == :expr_cmdarg || @lex_state == :expr_arg
712
- if !scanner.check(/\s/) && @space_seen
713
- self.strterm = { :type => :regexp, :beg => '/', :end => '/', :regexp => true }
714
- return :REGEXP_BEG, scanner.matched
752
+ if !check(/\s/) && @space_seen
753
+ self.strterm = new_strterm(:regexp, '/', '/')
754
+ return :tREGEXP_BEG, scanner.matched
715
755
  end
716
756
  else
717
757
  @lex_state = :expr_beg
718
758
  end
719
759
 
720
- return '/', '/'
760
+ return :tDIVIDE, '/'
721
761
 
722
- elsif scanner.scan(/\%/)
723
- if scanner.scan(/\=/)
762
+ elsif scan(/\%/)
763
+ if scan(/\=/)
724
764
  @lex_state = :expr_beg
725
- return :OP_ASGN, '%'
726
- elsif scanner.check(/[^\s]/)
765
+ return :tOP_ASGN, '%'
766
+ elsif check(/[^\s]/)
727
767
  if @lex_state == :expr_beg or (@lex_state == :expr_arg && @space_seen)
728
- start_word = scanner.scan(/./)
768
+ start_word = scan(/./)
729
769
  end_word = { '(' => ')', '[' => ']', '{' => '}' }[start_word] || start_word
730
- self.strterm = { :type => :dquote, :beg => start_word, :end => end_word, :balance => true, :nesting => 0 }
731
- return :STRING_BEG, scanner.matched
770
+ self.strterm = new_strterm2(:dquote, start_word, end_word)
771
+ return :tSTRING_BEG, scanner.matched
732
772
  end
733
773
  end
734
774
 
735
775
  @lex_state = after_operator? ? :expr_arg : :expr_beg
736
776
 
737
- return '%', '%'
777
+ return :tPERCENT, '%'
738
778
 
739
- elsif scanner.scan(/\\/)
740
- if scanner.scan(/\r?\n/)
779
+ elsif scan(/\\/)
780
+ if scan(/\r?\n/)
741
781
  @space_seen = true
742
782
  next
743
783
  end
744
784
 
745
785
  raise SyntaxError, "backslash must appear before newline :#{@file}:#{@line}"
746
786
 
747
- elsif scanner.scan(/\(/)
787
+ elsif scan(/\(/)
748
788
  result = scanner.matched
749
789
  if [:expr_beg, :expr_mid].include? @lex_state
750
- result = :PAREN_BEG
790
+ result = :tLPAREN
751
791
  elsif @space_seen && [:expr_arg, :expr_cmdarg].include?(@lex_state)
752
792
  result = :tLPAREN_ARG
753
793
  else
754
- result = '('
794
+ result = :tLPAREN2
755
795
  end
756
796
 
757
797
  @lex_state = :expr_beg
@@ -760,21 +800,21 @@ module Opal
760
800
 
761
801
  return result, scanner.matched
762
802
 
763
- elsif scanner.scan(/\)/)
803
+ elsif scan(/\)/)
764
804
  cond_lexpop
765
805
  cmdarg_lexpop
766
806
  @lex_state = :expr_end
767
- return ')', scanner.matched
807
+ return :tRPAREN, scanner.matched
768
808
 
769
- elsif scanner.scan(/\[/)
809
+ elsif scan(/\[/)
770
810
  result = scanner.matched
771
811
 
772
812
  if [:expr_fname, :expr_dot].include? @lex_state
773
813
  @lex_state = :expr_arg
774
- if scanner.scan(/\]=/)
775
- return '[]=', '[]='
776
- elsif scanner.scan(/\]/)
777
- return '[]', '[]'
814
+ if scan(/\]=/)
815
+ return :tASET, '[]='
816
+ elsif scan(/\]/)
817
+ return :tAREF, '[]'
778
818
  else
779
819
  raise "Unexpected '[' token"
780
820
  end
@@ -782,102 +822,102 @@ module Opal
782
822
  @lex_state = :expr_beg
783
823
  cond_push 0
784
824
  cmdarg_push 0
785
- return '[', scanner.matched
825
+ return :tLBRACK, scanner.matched
786
826
  else
787
827
  @lex_state = :expr_beg
788
828
  cond_push 0
789
829
  cmdarg_push 0
790
- return '[@', scanner.matched
830
+ return :tLBRACK2, scanner.matched
791
831
  end
792
832
 
793
- elsif scanner.scan(/\]/)
833
+ elsif scan(/\]/)
794
834
  cond_lexpop
795
835
  cmdarg_lexpop
796
836
  @lex_state = :expr_end
797
- return ']', scanner.matched
837
+ return :tRBRACK, scanner.matched
798
838
 
799
- elsif scanner.scan(/\}/)
839
+ elsif scan(/\}/)
800
840
  cond_lexpop
801
841
  cmdarg_lexpop
802
842
  @lex_state = :expr_end
803
843
 
804
- return '}', scanner.matched
844
+ return :tRCURLY, scanner.matched
805
845
 
806
- elsif scanner.scan(/\.\.\./)
846
+ elsif scan(/\.\.\./)
807
847
  @lex_state = :expr_beg
808
- return '...', scanner.matched
848
+ return :tDOT3, scanner.matched
809
849
 
810
- elsif scanner.scan(/\.\./)
850
+ elsif scan(/\.\./)
811
851
  @lex_state = :expr_beg
812
- return '..', scanner.matched
852
+ return :tDOT2, scanner.matched
813
853
 
814
- elsif scanner.scan(/\./)
854
+ elsif scan(/\./)
815
855
  @lex_state = :expr_dot unless @lex_state == :expr_fname
816
- return '.', scanner.matched
856
+ return :tDOT, scanner.matched
817
857
 
818
- elsif scanner.scan(/\:\:/)
858
+ elsif scan(/\:\:/)
819
859
  if [:expr_beg, :expr_mid, :expr_class].include? @lex_state
820
860
  @lex_state = :expr_beg
821
- return '::@', scanner.matched
861
+ return :tCOLON3, scanner.matched
822
862
  elsif @space_seen && @lex_state == :expr_arg
823
863
  @lex_state = :expr_beg
824
- return '::@', scanner.matched
864
+ return :tCOLON3, scanner.matched
825
865
  end
826
866
 
827
867
  @lex_state = :expr_dot
828
- return '::', scanner.matched
868
+ return :tCOLON2, scanner.matched
829
869
 
830
- elsif scanner.scan(/\:/)
831
- if end? || scanner.check(/\s/)
832
- unless scanner.check(/\w/)
870
+ elsif scan(/\:/)
871
+ if end? || check(/\s/)
872
+ unless check(/\w/)
833
873
  @lex_state = :expr_beg
834
- return ':', ':'
874
+ return :tCOLON, ':'
835
875
  end
836
876
 
837
877
  @lex_state = :expr_fname
838
- return :SYMBOL_BEG, ':'
878
+ return :tSYMBEG, ':'
839
879
  end
840
880
 
841
- if scanner.scan(/\'/)
842
- self.strterm = { :type => :ssym, :beg => "'", :end => "'" }
843
- elsif scanner.scan(/\"/)
844
- self.strterm = { :type => :dsym, :beg => '"', :end => '"' }
881
+ if scan(/\'/)
882
+ self.strterm = new_strterm(:ssym, "'", "'")
883
+ elsif scan(/\"/)
884
+ self.strterm = new_strterm(:dsym, '"', '"')
845
885
  end
846
886
 
847
887
  @lex_state = :expr_fname
848
- return :SYMBOL_BEG, ':'
888
+ return :tSYMBEG, ':'
849
889
 
850
- elsif scanner.scan(/\^\=/)
890
+ elsif scan(/\^\=/)
851
891
  @lex_state = :expr_beg
852
- return :OP_ASGN, '^'
853
- elsif scanner.scan(/\^/)
892
+ return :tOP_ASGN, '^'
893
+ elsif scan(/\^/)
854
894
  if @lex_state == :expr_fname or @lex_state == :expr_dot
855
895
  @lex_state = :expr_arg
856
- return '^', scanner.matched
896
+ return :tCARET, scanner.matched
857
897
  end
858
898
 
859
899
  @lex_state = :expr_beg
860
- return '^', scanner.matched
900
+ return :tCARET, scanner.matched
861
901
 
862
- elsif scanner.check(/\</)
863
- if scanner.scan(/\<\<\=/)
902
+ elsif check(/\</)
903
+ if scan(/\<\<\=/)
864
904
  @lex_state = :expr_beg
865
- return :OP_ASGN, '<<'
866
- elsif scanner.scan(/\<\</)
905
+ return :tOP_ASGN, '<<'
906
+ elsif scan(/\<\</)
867
907
  if @lex_state == :expr_fname or @lex_state == :expr_dot
868
908
  @lex_state = :expr_arg
869
- return '<<', '<<'
909
+ return :tLSHFT, '<<'
870
910
  elsif ![:expr_dot, :expr_class].include?(@lex_state) && !end? && (!arg? || @space_seen)
871
911
  if token = heredoc_identifier
872
912
  return token
873
913
  end
874
914
 
875
915
  @lex_state = :expr_beg
876
- return '<<', '<<'
916
+ return :tLSHFT, '<<'
877
917
  end
878
918
  @lex_state = :expr_beg
879
- return '<<', '<<'
880
- elsif scanner.scan(/\<\=\>/)
919
+ return :tLSHFT, '<<'
920
+ elsif scan(/\<\=\>/)
881
921
  if after_operator?
882
922
  @lex_state = :expr_arg
883
923
  else
@@ -888,148 +928,152 @@ module Opal
888
928
  @lex_state = :expr_beg
889
929
  end
890
930
 
891
- return '<=>', '<=>'
892
- elsif scanner.scan(/\<\=/)
931
+ return :tCMP, '<=>'
932
+ elsif scan(/\<\=/)
893
933
  if @lex_state == :expr_fname or @lex_state == :expr_dot
894
934
  @lex_state = :expr_arg
895
935
  else
896
936
  @lex_state = :expr_beg
897
937
  end
898
- return '<=', '<='
899
- elsif scanner.scan(/\</)
938
+ return :tLEQ, '<='
939
+ elsif scan(/\</)
900
940
  if @lex_state == :expr_fname or @lex_state == :expr_dot
901
941
  @lex_state = :expr_arg
902
942
  else
903
943
  @lex_state = :expr_beg
904
944
  end
905
- return '<', '<'
945
+ return :tLT, '<'
906
946
  end
907
947
 
908
- elsif scanner.check(/\>/)
909
- if scanner.scan(/\>\>\=/)
910
- return :OP_ASGN, '>>'
911
- elsif scanner.scan(/\>\>/)
948
+ elsif check(/\>/)
949
+ if scan(/\>\>\=/)
950
+ return :tOP_ASGN, '>>'
951
+ elsif scan(/\>\>/)
912
952
  if @lex_state == :expr_fname or @lex_state == :expr_dot
913
953
  @lex_state = :expr_arg
914
954
  else
915
955
  @lex_state = :expr_beg
916
956
  end
917
- return '>>', '>>'
918
- elsif scanner.scan(/\>\=/)
957
+ return :tRSHFT, '>>'
958
+ elsif scan(/\>\=/)
919
959
  if @lex_state == :expr_fname or @lex_state == :expr_dot
920
960
  @lex_state = :expr_end
921
961
  else
922
962
  @lex_state = :expr_beg
923
963
  end
924
- return '>=', scanner.matched
925
- elsif scanner.scan(/\>/)
964
+ return :tGEQ, scanner.matched
965
+ elsif scan(/\>/)
926
966
  if @lex_state == :expr_fname or @lex_state == :expr_dot
927
967
  @lex_state = :expr_arg
928
968
  else
929
969
  @lex_state = :expr_beg
930
970
  end
931
- return '>', '>'
971
+ return :tGT, '>'
932
972
  end
933
973
 
934
- elsif scanner.scan(/->/)
974
+ elsif scan(/->/)
935
975
  # FIXME: # should be :expr_arg, but '(' breaks it...
936
976
  @lex_state = :expr_end
937
977
  @start_of_lambda = true
938
- return [:LAMBDA, scanner.matched]
978
+ return [:tLAMBDA, scanner.matched]
939
979
 
940
- elsif scanner.scan(/[+-]/)
941
- result = scanner.matched
942
- sign = result + '@'
980
+ elsif scan(/[+-]/)
981
+ matched = scanner.matched
982
+ sign, utype = if matched == '+'
983
+ [:tPLUS, :tUPLUS]
984
+ else
985
+ [:tMINUS, :tUMINUS]
986
+ end
943
987
 
944
- if @lex_state == :expr_beg || @lex_state == :expr_mid
988
+ if beg?
945
989
  @lex_state = :expr_mid
946
- return [sign, sign]
947
- elsif @lex_state == :expr_fname or @lex_state == :expr_dot
990
+ return [utype, matched]
991
+ elsif after_operator?
948
992
  @lex_state = :expr_arg
949
- return [:IDENTIFIER, result + scanner.matched] if scanner.scan(/@/)
950
- return [result, result]
993
+ return [:tIDENTIFIER, matched + '@'] if scan(/@/)
994
+ return [sign, matched]
951
995
  end
952
996
 
953
- if scanner.scan(/\=/)
997
+ if scan(/\=/)
954
998
  @lex_state = :expr_beg
955
- return [:OP_ASGN, result]
999
+ return [:tOP_ASGN, matched]
956
1000
  end
957
1001
 
958
- if @lex_state == :expr_cmdarg || @lex_state == :expr_arg
959
- if !scanner.check(/\s/) && @space_seen
1002
+ if arg?
1003
+ if !space? && @space_seen
960
1004
  @lex_state = :expr_mid
961
- return [sign, sign]
1005
+ return [utype, matched]
962
1006
  end
963
1007
  end
964
1008
 
965
1009
  @lex_state = :expr_beg
966
- return [result, result]
1010
+ return [sign, sign]
967
1011
 
968
- elsif scanner.scan(/\?/)
1012
+ elsif scan(/\?/)
969
1013
  if end?
970
1014
  @lex_state = :expr_beg
971
- return '?', scanner.matched
1015
+ return :tEH, scanner.matched
972
1016
  end
973
1017
 
974
- unless scanner.check(/\ |\t|\r|\s/)
1018
+ unless check(/\ |\t|\r|\s/)
975
1019
  @lex_state = :expr_end
976
- return :STRING, scanner.scan(/./)
1020
+ return :tSTRING, scan(/./)
977
1021
  end
978
1022
 
979
1023
  @lex_state = :expr_beg
980
- return '?', scanner.matched
1024
+ return :tEH, scanner.matched
981
1025
 
982
- elsif scanner.scan(/\~/)
1026
+ elsif scan(/\~/)
983
1027
  if @lex_state == :expr_fname
984
1028
  @lex_state = :expr_end
985
- return '~', '~'
1029
+ return :tTILDE, '~'
986
1030
  end
987
1031
  @lex_state = :expr_beg
988
- return '~', '~'
1032
+ return :tTILDE, '~'
989
1033
 
990
- elsif scanner.check(/\$/)
991
- if scanner.scan(/\$([1-9]\d*)/)
1034
+ elsif check(/\$/)
1035
+ if scan(/\$([1-9]\d*)/)
992
1036
  @lex_state = :expr_end
993
- return :NTH_REF, scanner.matched.sub('$', '')
1037
+ return :tNTH_REF, scanner.matched.sub('$', '')
994
1038
 
995
- elsif scanner.scan(/(\$_)(\w+)/)
1039
+ elsif scan(/(\$_)(\w+)/)
996
1040
  @lex_state = :expr_end
997
- return :GVAR, scanner.matched
1041
+ return :tGVAR, scanner.matched
998
1042
 
999
- elsif scanner.scan(/\$[\+\'\`\&!@\"~*$?\/\\:;=.,<>_]/)
1043
+ elsif scan(/\$[\+\'\`\&!@\"~*$?\/\\:;=.,<>_]/)
1000
1044
  @lex_state = :expr_end
1001
- return :GVAR, scanner.matched
1002
- elsif scanner.scan(/\$\w+/)
1045
+ return :tGVAR, scanner.matched
1046
+ elsif scan(/\$\w+/)
1003
1047
  @lex_state = :expr_end
1004
- return :GVAR, scanner.matched
1048
+ return :tGVAR, scanner.matched
1005
1049
  else
1006
1050
  raise "Bad gvar name: #{scanner.peek(5).inspect}"
1007
1051
  end
1008
1052
 
1009
- elsif scanner.scan(/\$\w+/)
1053
+ elsif scan(/\$\w+/)
1010
1054
  @lex_state = :expr_end
1011
- return :GVAR, scanner.matched
1055
+ return :tGVAR, scanner.matched
1012
1056
 
1013
- elsif scanner.scan(/\@\@\w*/)
1057
+ elsif scan(/\@\@\w*/)
1014
1058
  @lex_state = :expr_end
1015
- return :CVAR, scanner.matched
1059
+ return :tCVAR, scanner.matched
1016
1060
 
1017
- elsif scanner.scan(/\@\w*/)
1061
+ elsif scan(/\@\w*/)
1018
1062
  @lex_state = :expr_end
1019
- return :IVAR, scanner.matched
1063
+ return :tIVAR, scanner.matched
1020
1064
 
1021
- elsif scanner.scan(/\,/)
1065
+ elsif scan(/\,/)
1022
1066
  @lex_state = :expr_beg
1023
- return ',', scanner.matched
1067
+ return :tCOMMA, scanner.matched
1024
1068
 
1025
- elsif scanner.scan(/\{/)
1069
+ elsif scan(/\{/)
1026
1070
  if @start_of_lambda
1027
1071
  @start_of_lambda = false
1028
1072
  @lex_state = :expr_beg
1029
- return [:LAMBEG, scanner.matched]
1073
+ return [:tLAMBEG, scanner.matched]
1030
1074
 
1031
1075
  elsif [:expr_end, :expr_arg, :expr_cmdarg].include? @lex_state
1032
- result = :LCURLY
1076
+ result = :tLCURLY
1033
1077
  elsif @lex_state == :expr_endarg
1034
1078
  result = :LBRACE_ARG
1035
1079
  else
@@ -1041,23 +1085,10 @@ module Opal
1041
1085
  cmdarg_push 0
1042
1086
  return result, scanner.matched
1043
1087
 
1044
- elsif scanner.check(/[0-9]/)
1045
- @lex_state = :expr_end
1046
- if scanner.scan(/0b?(0|1|_)+/)
1047
- return [:INTEGER, scanner.matched.to_i(2)]
1048
- elsif scanner.scan(/0o?([0-7]|_)+/)
1049
- return [:INTEGER, scanner.matched.to_i(8)]
1050
- elsif scanner.scan(/[\d_]+\.[\d_]+\b|[\d_]+(\.[\d_]+)?[eE][-+]?[\d_]+\b/)
1051
- return [:FLOAT, scanner.matched.gsub(/_/, '').to_f]
1052
- elsif scanner.scan(/[\d_]+\b/)
1053
- return [:INTEGER, scanner.matched.gsub(/_/, '').to_i]
1054
- elsif scanner.scan(/0(x|X)(\d|[a-f]|[A-F]|_)+/)
1055
- return [:INTEGER, scanner.matched.to_i(16)]
1056
- else
1057
- raise "Lexing error on numeric type: `#{scanner.peek 5}`"
1058
- end
1088
+ elsif check(/[0-9]/)
1089
+ return process_numeric
1059
1090
 
1060
- elsif scanner.scan(/(\w)+[\?\!]?/)
1091
+ elsif scan(/(\w)+[\?\!]?/)
1061
1092
  return process_identifier scanner.matched, cmd_start
1062
1093
  end
1063
1094