opal 0.5.2 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
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