ruby_parser 2.0.5 → 3.0.0.a1

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.
data/lib/ruby_lexer.rb CHANGED
@@ -2,10 +2,17 @@ class RubyLexer
2
2
  attr_accessor :command_start
3
3
  attr_accessor :cmdarg
4
4
  attr_accessor :cond
5
+ attr_accessor :tern
5
6
  attr_accessor :nest
6
7
 
7
8
  ESC_RE = /\\([0-7]{1,3}|x[0-9a-fA-F]{1,2}|M-[^\\]|(C-|c)[^\\]|[^0-7xMCc])/
8
9
 
10
+ ##
11
+ # What version of ruby to parse. 18 and 19 are the only valid values
12
+ # currently supported.
13
+
14
+ attr_accessor :version
15
+
9
16
  # Additional context surrounding tokens that both the lexer and
10
17
  # grammar use.
11
18
  attr_reader :lex_state
@@ -35,7 +42,7 @@ class RubyLexer
35
42
  STR_FUNC_ESCAPE = 0x01 # TODO: remove and replace with REGEXP
36
43
  STR_FUNC_EXPAND = 0x02
37
44
  STR_FUNC_REGEXP = 0x04
38
- STR_FUNC_AWORDS = 0x08
45
+ STR_FUNC_QWORDS = 0x08
39
46
  STR_FUNC_SYMBOL = 0x10
40
47
  STR_FUNC_INDENT = 0x20 # <<-HEREDOC
41
48
 
@@ -58,6 +65,7 @@ class RubyLexer
58
65
  "===" => :tEQQ,
59
66
  "=>" => :tASSOC,
60
67
  "=~" => :tMATCH,
68
+ "->" => :tLAMBDA,
61
69
  }
62
70
 
63
71
  # How the parser advances to the next token.
@@ -130,7 +138,7 @@ class RubyLexer
130
138
  string_buffer << '#'
131
139
  end
132
140
 
133
- until src.scan(eos_re) do
141
+ until src.check(eos_re) do
134
142
  c = tokadd_string func, "\n", nil
135
143
 
136
144
  rb_compile_error err_msg if
@@ -146,9 +154,6 @@ class RubyLexer
146
154
  rb_compile_error err_msg if
147
155
  src.eos?
148
156
  end
149
-
150
- # tack on a NL after the heredoc token - FIX NL should not be needed
151
- src.unread_many(eos + "\n") # TODO: remove this... stupid stupid stupid
152
157
  else
153
158
  until src.check(eos_re) do
154
159
  string_buffer << src.scan(/.*(\n|\z)/)
@@ -195,11 +200,10 @@ class RubyLexer
195
200
  return nil
196
201
  end
197
202
 
198
- if src.check(/.*\n/) then
203
+ if src.scan(/.*\n/) then
199
204
  # TODO: think about storing off the char range instead
200
- line = src.string[src.pos, src.matched_size]
201
- src.string[src.pos, src.matched_size] = "\n"
202
- src.pos += 1
205
+ line = src.matched
206
+ src.extra_lines_added += 1
203
207
  else
204
208
  line = nil
205
209
  end
@@ -215,9 +219,11 @@ class RubyLexer
215
219
  end
216
220
  end
217
221
 
218
- def initialize
219
- self.cond = StackState.new(:cond)
220
- self.cmdarg = StackState.new(:cmdarg)
222
+ def initialize v = 18
223
+ self.version = v
224
+ self.cond = RubyParser::StackState.new(:cond)
225
+ self.cmdarg = RubyParser::StackState.new(:cmdarg)
226
+ self.tern = RubyParser::StackState.new(:tern)
221
227
  self.nest = 0
222
228
  @comments = []
223
229
 
@@ -231,7 +237,7 @@ class RubyLexer
231
237
  end
232
238
 
233
239
  def lex_state= o
234
- raise "wtf?" unless Symbol === o
240
+ raise "wtf\?" unless Symbol === o
235
241
  @lex_state = o
236
242
  end
237
243
 
@@ -308,10 +314,10 @@ class RubyLexer
308
314
  [:tSTRING_BEG, STR_SQUOTE]
309
315
  when 'W' then
310
316
  src.scan(/\s*/)
311
- [:tWORDS_BEG, STR_DQUOTE | STR_FUNC_AWORDS]
317
+ [:tWORDS_BEG, STR_DQUOTE | STR_FUNC_QWORDS]
312
318
  when 'w' then
313
319
  src.scan(/\s*/)
314
- [:tAWORDS_BEG, STR_SQUOTE | STR_FUNC_AWORDS]
320
+ [:tQWORDS_BEG, STR_SQUOTE | STR_FUNC_QWORDS]
315
321
  when 'x' then
316
322
  [:tXSTRING_BEG, STR_XQUOTE]
317
323
  when 'r' then
@@ -337,7 +343,7 @@ class RubyLexer
337
343
  paren = open
338
344
  term_re = Regexp.escape term
339
345
 
340
- awords = (func & STR_FUNC_AWORDS) != 0
346
+ qwords = (func & STR_FUNC_QWORDS) != 0
341
347
  regexp = (func & STR_FUNC_REGEXP) != 0
342
348
  expand = (func & STR_FUNC_EXPAND) != 0
343
349
 
@@ -346,10 +352,10 @@ class RubyLexer
346
352
  return :tSTRING_END
347
353
  end
348
354
 
349
- space = true if awords and src.scan(/\s+/)
355
+ space = true if qwords and src.scan(/\s+/)
350
356
 
351
357
  if self.nest == 0 && src.scan(/#{term_re}/) then
352
- if awords then
358
+ if qwords then
353
359
  quote[1] = nil
354
360
  return :tSPACE
355
361
  elsif regexp then
@@ -386,7 +392,6 @@ class RubyLexer
386
392
 
387
393
  self.yacc_value = string_buffer.join
388
394
 
389
-
390
395
  return :tSTRING_CONTENT
391
396
  end
392
397
 
@@ -473,6 +478,10 @@ class RubyLexer
473
478
  @lex_state = nil
474
479
  end
475
480
 
481
+ def ruby18
482
+ Ruby18Parser === parser
483
+ end
484
+
476
485
  def src= src
477
486
  raise "bad src: #{src.inspect}" unless String === src
478
487
  @src = RPStringScanner.new(src)
@@ -499,7 +508,7 @@ class RubyLexer
499
508
  end
500
509
 
501
510
  def tokadd_string(func, term, paren) # 105 lines
502
- awords = (func & STR_FUNC_AWORDS) != 0
511
+ qwords = (func & STR_FUNC_QWORDS) != 0
503
512
  escape = (func & STR_FUNC_ESCAPE) != 0
504
513
  expand = (func & STR_FUNC_EXPAND) != 0
505
514
  regexp = (func & STR_FUNC_REGEXP) != 0
@@ -519,7 +528,7 @@ class RubyLexer
519
528
  self.nest += 1
520
529
  when src.scan(term_re) then
521
530
  self.nest -= 1
522
- when awords && src.scan(/\s/) then
531
+ when qwords && src.scan(/\s/) then
523
532
  src.pos -= 1
524
533
  break
525
534
  when expand && src.scan(/#(?=[\$\@\{])/) then
@@ -529,10 +538,10 @@ class RubyLexer
529
538
  # do nothing
530
539
  when src.check(/\\/) then
531
540
  case
532
- when awords && src.scan(/\\\n/) then
541
+ when qwords && src.scan(/\\\n/) then
533
542
  string_buffer << "\n"
534
543
  next
535
- when awords && src.scan(/\\\s/) then
544
+ when qwords && src.scan(/\\\s/) then
536
545
  c = ' '
537
546
  when expand && src.scan(/\\\n/) then
538
547
  next
@@ -561,7 +570,7 @@ class RubyLexer
561
570
 
562
571
  t = Regexp.escape term
563
572
  x = Regexp.escape(paren) if paren && paren != "\000"
564
- re = if awords then
573
+ re = if qwords then
565
574
  /[^#{t}#{x}\#\0\\\n\ ]+|./ # |. to pick up whatever
566
575
  else
567
576
  /[^#{t}#{x}\#\0\\]+|./
@@ -630,7 +639,6 @@ class RubyLexer
630
639
  # @return Description of the Returned Value
631
640
 
632
641
  def yylex # 826 lines
633
-
634
642
  c = ''
635
643
  space_seen = false
636
644
  command_state = false
@@ -655,7 +663,7 @@ class RubyLexer
655
663
  self.lineno = nil
656
664
  c = src.matched
657
665
  if c == '#' then
658
- src.unread c # ok
666
+ src.pos -= 1
659
667
 
660
668
  while src.scan(/\s*#.*(\n+|\z)/) do
661
669
  @comments << src.matched.gsub(/^ +#/, '#').gsub(/^ +$/, '')
@@ -687,6 +695,7 @@ class RubyLexer
687
695
  "]" => :tRBRACK,
688
696
  "}" => :tRCURLY
689
697
  }[src.matched]
698
+ self.tern.lexpop if [:tRBRACK, :tRCURLY].include?(result)
690
699
  return result
691
700
  elsif src.scan(/\.\.\.?|,|![=~]?/) then
692
701
  self.lex_state = :expr_beg
@@ -701,19 +710,11 @@ class RubyLexer
701
710
  return :tDOT
702
711
  end
703
712
  elsif src.scan(/\(/) then
704
- result = :tLPAREN2
705
- self.command_start = true
706
-
707
- if lex_state == :expr_beg || lex_state == :expr_mid then
708
- result = :tLPAREN
709
- elsif space_seen then
710
- if lex_state == :expr_cmdarg then
711
- result = :tLPAREN_ARG
712
- elsif lex_state == :expr_arg then
713
- warning("don't put space before argument parentheses")
714
- result = :tLPAREN2
715
- end
716
- end
713
+ result = if ruby18 then
714
+ yylex_paren18 space_seen
715
+ else
716
+ yylex_paren19 space_seen
717
+ end
717
718
 
718
719
  self.expr_beg_push "("
719
720
 
@@ -723,11 +724,11 @@ class RubyLexer
723
724
  self.fix_arg_lex_state
724
725
  tok = self.yacc_value = src.matched
725
726
  return TOKENS[tok]
726
- elsif src.was_begin_of_line and src.scan(/\=begin(?=\s)/) then
727
+ elsif src.scan(/\=begin(?=\s)/) then
727
728
  # @comments << '=' << src.matched
728
729
  @comments << src.matched
729
730
 
730
- unless src.scan(/.*?\n=end\s*(\n|\z)/m) then
731
+ unless src.scan(/.*?\n=end( |\t|\f)*[^\n]*(\n|\z)/m) then
731
732
  @comments.clear
732
733
  rb_compile_error("embedded document meets end of file")
733
734
  end
@@ -807,9 +808,13 @@ class RubyLexer
807
808
  rb_compile_error "unexpected '['"
808
809
  end
809
810
  elsif lex_state == :expr_beg || lex_state == :expr_mid then
811
+ self.tern.push false
810
812
  result = :tLBRACK
811
813
  elsif lex_state.is_argument && space_seen then
814
+ self.tern.push false
812
815
  result = :tLBRACK
816
+ else
817
+ result = :tLBRACK2
813
818
  end
814
819
 
815
820
  self.expr_beg_push "["
@@ -838,17 +843,29 @@ class RubyLexer
838
843
  return :tPIPE
839
844
  end
840
845
  elsif src.scan(/\{/) then
846
+ if defined?(@hack_expects_lambda) && @hack_expects_lambda
847
+ @hack_expects_lambda = false
848
+ self.lex_state = :expr_beg
849
+ return :tLAMBEG
850
+ end
851
+
841
852
  result = if lex_state.is_argument || lex_state == :expr_end then
842
853
  :tLCURLY # block (primary)
843
854
  elsif lex_state == :expr_endarg then
844
855
  :tLBRACE_ARG # block (expr)
845
856
  else
857
+ self.tern.push false
846
858
  :tLBRACE # hash
847
859
  end
848
860
 
849
861
  self.expr_beg_push "{"
862
+ self.command_start = true unless result == :tLBRACE
850
863
 
851
864
  return result
865
+ elsif src.scan(/->/) then
866
+ @hack_expects_lambda = true
867
+ self.lex_state = :expr_arg
868
+ return :tLAMBDA
852
869
  elsif src.scan(/[+-]/) then
853
870
  sign = src.matched
854
871
  utype, type = if sign == "+" then
@@ -994,6 +1011,7 @@ class RubyLexer
994
1011
  elsif src.scan(/\?/) then
995
1012
  if lex_state == :expr_end || lex_state == :expr_endarg then
996
1013
  self.lex_state = :expr_beg
1014
+ self.tern.push true
997
1015
  self.yacc_value = "?"
998
1016
  return :tEH
999
1017
  end
@@ -1018,10 +1036,12 @@ class RubyLexer
1018
1036
 
1019
1037
  # ternary
1020
1038
  self.lex_state = :expr_beg
1039
+ self.tern.push true
1021
1040
  self.yacc_value = "?"
1022
1041
  return :tEH
1023
1042
  elsif src.check(/\w(?=\w)/) then # ternary, also
1024
1043
  self.lex_state = :expr_beg
1044
+ self.tern.push true
1025
1045
  self.yacc_value = "?"
1026
1046
  return :tEH
1027
1047
  end
@@ -1032,8 +1052,14 @@ class RubyLexer
1032
1052
  src.getch
1033
1053
  end
1034
1054
  self.lex_state = :expr_end
1035
- self.yacc_value = c[0].ord & 0xff
1036
- return :tINTEGER
1055
+
1056
+ if version == 18 then
1057
+ self.yacc_value = c[0].ord & 0xff
1058
+ return :tINTEGER
1059
+ else
1060
+ self.yacc_value = c
1061
+ return :tSTRING
1062
+ end
1037
1063
  elsif src.check(/\&/) then
1038
1064
  if src.scan(/\&\&\=/) then
1039
1065
  self.yacc_value = "&&"
@@ -1207,6 +1233,53 @@ class RubyLexer
1207
1233
  end
1208
1234
  end
1209
1235
 
1236
+ def yylex_paren18 space_seen
1237
+ self.command_start = true
1238
+ result = :tLPAREN2
1239
+
1240
+ if lex_state == :expr_beg || lex_state == :expr_mid then
1241
+ result = :tLPAREN
1242
+ elsif space_seen then
1243
+ if lex_state == :expr_cmdarg then
1244
+ result = :tLPAREN_ARG
1245
+ elsif lex_state == :expr_arg then
1246
+ self.tern.push false
1247
+ warning "don't put space before argument parentheses"
1248
+ end
1249
+ else
1250
+ self.tern.push false
1251
+ end
1252
+
1253
+ result
1254
+ end
1255
+
1256
+ def yylex_paren19 space_seen
1257
+ if (lex_state == :expr_beg || lex_state == :expr_mid ||
1258
+ lex_state == :expr_value || lex_state == :expr_class) then
1259
+ result = :tLPAREN
1260
+ elsif ((lex_state == :expr_arg || lex_state == :expr_cmdarg) and
1261
+ space_seen) then
1262
+ result = :tLPAREN_ARG
1263
+ else
1264
+ self.tern.push false
1265
+ result = :tLPAREN2
1266
+ end
1267
+ # HACK paren_nest++;
1268
+
1269
+ # HACK: this is a mess, but it makes the tests pass, so suck it
1270
+ # (stolen from the 1.8 side)
1271
+ if lex_state == :expr_beg || lex_state == :expr_mid then
1272
+ # do nothing
1273
+ elsif space_seen then
1274
+ if lex_state == :expr_arg then
1275
+ self.tern.push false
1276
+ end
1277
+ else
1278
+ self.tern.push false
1279
+ end
1280
+ result
1281
+ end
1282
+
1210
1283
  def process_token(command_state)
1211
1284
 
1212
1285
  token << src.matched if token =~ /^\w/ && src.scan(/[\!\?](?!=)/)
@@ -1214,7 +1287,6 @@ class RubyLexer
1214
1287
  result = nil
1215
1288
  last_state = lex_state
1216
1289
 
1217
-
1218
1290
  case token
1219
1291
  when /^\$/ then
1220
1292
  self.lex_state, result = :expr_end, :tGVAR
@@ -1242,24 +1314,51 @@ class RubyLexer
1242
1314
  end
1243
1315
  end
1244
1316
 
1317
+ unless self.tern.is_in_state
1318
+ if (lex_state == :expr_beg && (ruby18 || !command_state)) ||
1319
+ lex_state == :expr_arg ||
1320
+ lex_state == :expr_cmdarg then
1321
+ colon = src.scan(/:/)
1322
+
1323
+ if colon && src.peek(1) != ":"
1324
+ src.unscan
1325
+ self.lex_state = :expr_beg
1326
+ src.scan(/:/)
1327
+ self.yacc_value = [token, src.lineno]
1328
+ return :tLABEL
1329
+ end
1330
+
1331
+ src.unscan if colon
1332
+ end
1333
+ end unless ruby18
1334
+
1245
1335
  unless lex_state == :expr_dot then
1246
1336
  # See if it is a reserved word.
1247
- keyword = Keyword.keyword token
1337
+ keyword = RubyParser::Keyword.keyword token
1248
1338
 
1249
1339
  if keyword then
1250
1340
  state = lex_state
1251
1341
  self.lex_state = keyword.state
1252
- self.yacc_value = token
1342
+ self.yacc_value = [token, src.lineno]
1343
+
1344
+ if state == :expr_fname then
1345
+ self.yacc_value = keyword.name
1346
+ return keyword.id0
1347
+ end
1253
1348
 
1254
1349
  if keyword.id0 == :kDO then
1255
1350
  self.command_start = true
1256
1351
  return :kDO_COND if cond.is_in_state
1257
1352
  return :kDO_BLOCK if cmdarg.is_in_state && state != :expr_cmdarg
1258
1353
  return :kDO_BLOCK if state == :expr_endarg
1354
+ if defined?(@hack_expects_lambda) && @hack_expects_lambda
1355
+ @hack_expects_lambda = false
1356
+ return :kDO_LAMBDA
1357
+ end
1259
1358
  return :kDO
1260
1359
  end
1261
1360
 
1262
- return keyword.id0 if state == :expr_beg
1361
+ return keyword.id0 if state == :expr_beg or state == :expr_value
1263
1362
 
1264
1363
  self.lex_state = :expr_beg if keyword.id0 != keyword.id1
1265
1364