ruby_parser 3.14.2 → 3.17.0
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/History.rdoc +60 -0
- data/Manifest.txt +4 -0
- data/Rakefile +83 -16
- data/bin/ruby_parse_extract_error +8 -3
- data/compare/normalize.rb +45 -5
- data/debugging.md +172 -0
- data/lib/ruby20_parser.rb +2953 -2924
- data/lib/ruby20_parser.y +99 -59
- data/lib/ruby21_parser.rb +3008 -2977
- data/lib/ruby21_parser.y +99 -59
- data/lib/ruby22_parser.rb +3011 -2976
- data/lib/ruby22_parser.y +99 -59
- data/lib/ruby23_parser.rb +2955 -2923
- data/lib/ruby23_parser.y +99 -59
- data/lib/ruby24_parser.rb +3024 -2984
- data/lib/ruby24_parser.y +99 -59
- data/lib/ruby25_parser.rb +3023 -2984
- data/lib/ruby25_parser.y +99 -59
- data/lib/ruby26_parser.rb +2954 -2913
- data/lib/ruby26_parser.y +100 -59
- data/lib/ruby27_parser.rb +7393 -0
- data/lib/ruby27_parser.y +2715 -0
- data/lib/ruby30_parser.rb +7393 -0
- data/lib/ruby30_parser.y +2715 -0
- data/lib/ruby_lexer.rb +90 -39
- data/lib/ruby_lexer.rex +6 -7
- data/lib/ruby_lexer.rex.rb +7 -9
- data/lib/ruby_parser.rb +4 -0
- data/lib/ruby_parser.yy +164 -59
- data/lib/ruby_parser_extras.rb +57 -18
- data/test/test_ruby_lexer.rb +64 -16
- data/test/test_ruby_parser.rb +277 -3
- data/tools/munge.rb +9 -4
- metadata +55 -36
- metadata.gz.sig +0 -0
data/lib/ruby_lexer.rb
CHANGED
@@ -25,11 +25,10 @@ class RubyLexer
|
|
25
25
|
|
26
26
|
HAS_ENC = "".respond_to? :encoding
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
28
|
+
BTOKENS = {
|
29
|
+
".." => :tBDOT2,
|
30
|
+
"..." => :tBDOT3,
|
31
|
+
}
|
33
32
|
|
34
33
|
TOKENS = {
|
35
34
|
"!" => :tBANG,
|
@@ -137,6 +136,10 @@ class RubyLexer
|
|
137
136
|
ss.eos?
|
138
137
|
end
|
139
138
|
|
139
|
+
def expr_beg?
|
140
|
+
lex_state =~ EXPR_BEG
|
141
|
+
end
|
142
|
+
|
140
143
|
def expr_dot?
|
141
144
|
lex_state =~ EXPR_DOT
|
142
145
|
end
|
@@ -162,7 +165,7 @@ class RubyLexer
|
|
162
165
|
indent = func =~ STR_FUNC_INDENT ? "[ \t]*" : nil
|
163
166
|
expand = func =~ STR_FUNC_EXPAND
|
164
167
|
eol = last_line && last_line.end_with?("\r\n") ? "\r\n" : "\n"
|
165
|
-
eos_re = /#{indent}#{Regexp.escape eos}(
|
168
|
+
eos_re = /#{indent}#{Regexp.escape eos}(\r*\n|\z)/
|
166
169
|
err_msg = "can't match #{eos_re.inspect} anywhere in "
|
167
170
|
|
168
171
|
rb_compile_error err_msg if end_of_stream?
|
@@ -177,10 +180,15 @@ class RubyLexer
|
|
177
180
|
|
178
181
|
if expand then
|
179
182
|
case
|
180
|
-
when scan(/#[
|
181
|
-
|
183
|
+
when scan(/#(?=\$(-.|[a-zA-Z_0-9~\*\$\?!@\/\\;,\.=:<>\"\&\`\'+]))/) then
|
184
|
+
# TODO: !ISASCII
|
185
|
+
# ?! see parser_peek_variable_name
|
186
|
+
return :tSTRING_DVAR, matched
|
187
|
+
when scan(/#(?=\@\@?[a-zA-Z_])/) then
|
188
|
+
# TODO: !ISASCII
|
182
189
|
return :tSTRING_DVAR, matched
|
183
190
|
when scan(/#[{]/) then
|
191
|
+
self.command_start = true
|
184
192
|
return :tSTRING_DBEG, matched
|
185
193
|
when scan(/#/) then
|
186
194
|
string_buffer << "#"
|
@@ -320,6 +328,11 @@ class RubyLexer
|
|
320
328
|
lpar_beg && lpar_beg == paren_nest
|
321
329
|
end
|
322
330
|
|
331
|
+
def is_local_id id
|
332
|
+
# maybe just make this false for now
|
333
|
+
self.parser.env[id.to_sym] == :lvar # HACK: this isn't remotely right
|
334
|
+
end
|
335
|
+
|
323
336
|
def lvar_defined? id
|
324
337
|
# TODO: (dyna_in_block? && dvar_defined?(id)) || local_id?(id)
|
325
338
|
self.parser.env[id.to_sym] == :lvar
|
@@ -338,9 +351,9 @@ class RubyLexer
|
|
338
351
|
|
339
352
|
if scan(/[a-z0-9]{1,2}/i) then # Long-hand (e.g. %Q{}).
|
340
353
|
rb_compile_error "unknown type of %string" if ss.matched_size == 2
|
341
|
-
c, beg, short_hand = matched,
|
354
|
+
c, beg, short_hand = matched, getch, false
|
342
355
|
else # Short-hand (e.g. %{, %., %!, etc)
|
343
|
-
c, beg, short_hand = "Q",
|
356
|
+
c, beg, short_hand = "Q", getch, true
|
344
357
|
end
|
345
358
|
|
346
359
|
if end_of_stream? or c == RubyLexer::EOF or beg == RubyLexer::EOF then
|
@@ -457,7 +470,7 @@ class RubyLexer
|
|
457
470
|
if text =~ check then
|
458
471
|
content.gsub(ESC) { unescape $1 }
|
459
472
|
else
|
460
|
-
content.gsub(/\\\\/, "\\").gsub(
|
473
|
+
content.gsub(/\\\\/, "\\").gsub(/\\\'/, "'")
|
461
474
|
end
|
462
475
|
end
|
463
476
|
|
@@ -495,16 +508,19 @@ class RubyLexer
|
|
495
508
|
end
|
496
509
|
|
497
510
|
def process_brace_close text
|
498
|
-
# matching compare/parse23.y:8561
|
499
|
-
cond.lexpop
|
500
|
-
cmdarg.lexpop
|
501
|
-
|
502
511
|
case matched
|
503
512
|
when "}" then
|
504
513
|
self.brace_nest -= 1
|
505
|
-
self.lex_state = ruby24minus? ? EXPR_ENDARG : EXPR_END
|
506
|
-
|
507
514
|
return :tSTRING_DEND, matched if brace_nest < 0
|
515
|
+
end
|
516
|
+
|
517
|
+
# matching compare/parse26.y:8099
|
518
|
+
cond.pop
|
519
|
+
cmdarg.pop
|
520
|
+
|
521
|
+
case matched
|
522
|
+
when "}" then
|
523
|
+
self.lex_state = ruby24minus? ? EXPR_ENDARG : EXPR_END
|
508
524
|
return :tRCURLY, matched
|
509
525
|
when "]" then
|
510
526
|
self.paren_nest -= 1
|
@@ -573,6 +589,12 @@ class RubyLexer
|
|
573
589
|
end
|
574
590
|
end
|
575
591
|
|
592
|
+
def process_dots text
|
593
|
+
tokens = ruby27plus? && expr_beg? ? BTOKENS : TOKENS
|
594
|
+
|
595
|
+
result EXPR_BEG, tokens[text], text
|
596
|
+
end
|
597
|
+
|
576
598
|
def process_float text
|
577
599
|
rb_compile_error "Invalid numeric format" if text =~ /__/
|
578
600
|
|
@@ -605,7 +627,7 @@ class RubyLexer
|
|
605
627
|
end
|
606
628
|
|
607
629
|
def process_label text
|
608
|
-
symbol = possibly_escape_string text,
|
630
|
+
symbol = possibly_escape_string text, /^\"/
|
609
631
|
|
610
632
|
result EXPR_LAB, :tLABEL, [symbol, self.lineno]
|
611
633
|
end
|
@@ -619,7 +641,7 @@ class RubyLexer
|
|
619
641
|
text = text[0..-2]
|
620
642
|
end
|
621
643
|
|
622
|
-
result EXPR_END, :tSTRING, text[1..-2].gsub(/\\\\/, "\\").gsub(
|
644
|
+
result EXPR_END, :tSTRING, text[1..-2].gsub(/\\\\/, "\\").gsub(/\\\'/, "\'")
|
623
645
|
end
|
624
646
|
|
625
647
|
def process_lchevron text
|
@@ -791,12 +813,22 @@ class RubyLexer
|
|
791
813
|
c = if scan(/\\/) then
|
792
814
|
self.read_escape
|
793
815
|
else
|
794
|
-
|
816
|
+
getch
|
795
817
|
end
|
796
818
|
|
797
819
|
result EXPR_END, :tSTRING, c
|
798
820
|
end
|
799
821
|
|
822
|
+
def process_simple_string text
|
823
|
+
replacement = text[1..-2].gsub(ESC) {
|
824
|
+
unescape($1).b.force_encoding Encoding::UTF_8
|
825
|
+
}
|
826
|
+
|
827
|
+
replacement = replacement.b unless replacement.valid_encoding?
|
828
|
+
|
829
|
+
result EXPR_END, :tSTRING, replacement
|
830
|
+
end
|
831
|
+
|
800
832
|
def process_slash text
|
801
833
|
if is_beg? then
|
802
834
|
string STR_REGEXP
|
@@ -870,16 +902,16 @@ class RubyLexer
|
|
870
902
|
|
871
903
|
if [:tSTRING_END, :tREGEXP_END, :tLABEL_END].include? token_type then
|
872
904
|
self.lex_strterm = nil
|
873
|
-
self.lex_state = (token_type == :tLABEL_END) ? EXPR_PAR :
|
905
|
+
self.lex_state = (token_type == :tLABEL_END) ? EXPR_PAR : EXPR_LIT
|
874
906
|
end
|
875
907
|
|
876
908
|
return token
|
877
909
|
end
|
878
910
|
|
879
911
|
def process_symbol text
|
880
|
-
symbol = possibly_escape_string text,
|
912
|
+
symbol = possibly_escape_string text, /^:\"/ # stupid emacs
|
881
913
|
|
882
|
-
result
|
914
|
+
result EXPR_LIT, :tSYMBOL, symbol
|
883
915
|
end
|
884
916
|
|
885
917
|
def process_token text
|
@@ -928,6 +960,8 @@ class RubyLexer
|
|
928
960
|
EXPR_END
|
929
961
|
end
|
930
962
|
|
963
|
+
tok_id = :tIDENTIFIER if tok_id == :tCONSTANT && is_local_id(token)
|
964
|
+
|
931
965
|
if last_state !~ EXPR_DOT|EXPR_FNAME and
|
932
966
|
(tok_id == :tIDENTIFIER) and # not EXPR_FNAME, not attrasgn
|
933
967
|
lvar_defined?(token) then
|
@@ -951,18 +985,16 @@ class RubyLexer
|
|
951
985
|
self.command_start = true if lex_state =~ EXPR_BEG
|
952
986
|
|
953
987
|
case
|
954
|
-
when keyword.id0 == :kDO then
|
988
|
+
when keyword.id0 == :kDO then # parse26.y line 7591
|
955
989
|
case
|
956
990
|
when lambda_beginning? then
|
957
991
|
self.lpar_beg = nil # lambda_beginning? == FALSE in the body of "-> do ... end"
|
958
|
-
self.paren_nest -= 1
|
992
|
+
self.paren_nest -= 1 # TODO: question this?
|
959
993
|
result lex_state, :kDO_LAMBDA, value
|
960
994
|
when cond.is_in_state then
|
961
995
|
result lex_state, :kDO_COND, value
|
962
996
|
when cmdarg.is_in_state && state != EXPR_CMDARG then
|
963
997
|
result lex_state, :kDO_BLOCK, value
|
964
|
-
when state =~ EXPR_BEG|EXPR_ENDARG then
|
965
|
-
result lex_state, :kDO_BLOCK, value
|
966
998
|
else
|
967
999
|
result lex_state, :kDO, value
|
968
1000
|
end
|
@@ -979,9 +1011,9 @@ class RubyLexer
|
|
979
1011
|
ss.unscan # put back "_"
|
980
1012
|
|
981
1013
|
if beginning_of_line? && scan(/\__END__(\r?\n|\Z)/) then
|
982
|
-
|
983
|
-
elsif scan(
|
984
|
-
|
1014
|
+
[RubyLexer::EOF, RubyLexer::EOF]
|
1015
|
+
elsif scan(/#{IDENT_CHAR}+/) then
|
1016
|
+
process_token matched
|
985
1017
|
end
|
986
1018
|
end
|
987
1019
|
|
@@ -1018,7 +1050,7 @@ class RubyLexer
|
|
1018
1050
|
when scan(/x([0-9a-fA-F]{1,2})/) then # hex constant
|
1019
1051
|
# TODO: force encode everything to UTF-8?
|
1020
1052
|
ss[1].to_i(16).chr.force_encoding Encoding::UTF_8
|
1021
|
-
when check(/M
|
1053
|
+
when check(/M-\\./) then
|
1022
1054
|
scan(/M-\\/) # eat it
|
1023
1055
|
c = self.read_escape
|
1024
1056
|
c[0] = (c[0].ord | 0x80).chr
|
@@ -1032,6 +1064,11 @@ class RubyLexer
|
|
1032
1064
|
c = self.read_escape
|
1033
1065
|
c[0] = (c[0].ord & 0x9f).chr
|
1034
1066
|
c
|
1067
|
+
when check(/(C-|c)\\(?!u|\\)/) then
|
1068
|
+
scan(/(C-|c)\\/) # eat it
|
1069
|
+
c = read_escape
|
1070
|
+
c[0] = (c[0].ord & 0x9f).chr
|
1071
|
+
c
|
1035
1072
|
when scan(/C-\?|c\?/) then
|
1036
1073
|
127.chr
|
1037
1074
|
when scan(/(C-|c)(.)/) then
|
@@ -1040,17 +1077,25 @@ class RubyLexer
|
|
1040
1077
|
c
|
1041
1078
|
when scan(/^[89]/i) then # bad octal or hex... MRI ignores them :(
|
1042
1079
|
matched
|
1043
|
-
when scan(/u(
|
1044
|
-
[ss[1].
|
1045
|
-
when scan(/u(
|
1080
|
+
when scan(/u(\h{4})/) then
|
1081
|
+
[ss[1].to_i(16)].pack("U")
|
1082
|
+
when scan(/u(\h{1,3})/) then
|
1046
1083
|
rb_compile_error "Invalid escape character syntax"
|
1084
|
+
when scan(/u\{(\h+(?:\s+\h+)*)\}/) then
|
1085
|
+
ss[1].split.map { |s| s.to_i(16) }.pack("U*")
|
1047
1086
|
when scan(/[McCx0-9]/) || end_of_stream? then
|
1048
1087
|
rb_compile_error("Invalid escape character syntax")
|
1049
1088
|
else
|
1050
|
-
|
1089
|
+
getch
|
1051
1090
|
end.dup
|
1052
1091
|
end
|
1053
1092
|
|
1093
|
+
def getch
|
1094
|
+
c = ss.getch
|
1095
|
+
c = ss.getch if c == "\r" && ss.peek(1) == "\n"
|
1096
|
+
c
|
1097
|
+
end
|
1098
|
+
|
1054
1099
|
def regx_options # TODO: rewrite / remove
|
1055
1100
|
good, bad = [], []
|
1056
1101
|
|
@@ -1106,6 +1151,10 @@ class RubyLexer
|
|
1106
1151
|
parser.class.version <= 24
|
1107
1152
|
end
|
1108
1153
|
|
1154
|
+
def ruby27plus?
|
1155
|
+
parser.class.version >= 27
|
1156
|
+
end
|
1157
|
+
|
1109
1158
|
def scan re
|
1110
1159
|
ss.scan re
|
1111
1160
|
end
|
@@ -1274,10 +1323,12 @@ class RubyLexer
|
|
1274
1323
|
s
|
1275
1324
|
when /^[McCx0-9]/ then
|
1276
1325
|
rb_compile_error("Invalid escape character syntax")
|
1277
|
-
when /u(
|
1326
|
+
when /u(\h{4})/ then
|
1278
1327
|
[$1.delete("{}").to_i(16)].pack("U")
|
1279
|
-
when /u(
|
1328
|
+
when /u(\h{1,3})/ then
|
1280
1329
|
rb_compile_error("Invalid escape character syntax")
|
1330
|
+
when /u\{(\h+(?:\s+\h+)*)\}/ then
|
1331
|
+
$1.split.map { |s| s.to_i(16) }.pack("U*")
|
1281
1332
|
else
|
1282
1333
|
s
|
1283
1334
|
end
|
@@ -1355,11 +1406,11 @@ class RubyLexer
|
|
1355
1406
|
# extra fake lex_state names to make things a bit cleaner
|
1356
1407
|
|
1357
1408
|
EXPR_LAB = EXPR_ARG|EXPR_LABELED
|
1358
|
-
|
1409
|
+
EXPR_LIT = EXPR_END|EXPR_ENDARG
|
1359
1410
|
EXPR_PAR = EXPR_BEG|EXPR_LABEL
|
1360
1411
|
EXPR_PAD = EXPR_BEG|EXPR_LABELED
|
1361
1412
|
|
1362
|
-
|
1413
|
+
EXPR_NUM = EXPR_LIT
|
1363
1414
|
|
1364
1415
|
expr_names.merge!(EXPR_NONE => "EXPR_NONE",
|
1365
1416
|
EXPR_BEG => "EXPR_BEG",
|
data/lib/ruby_lexer.rex
CHANGED
@@ -6,9 +6,9 @@ class RubyLexer
|
|
6
6
|
|
7
7
|
macro
|
8
8
|
|
9
|
-
|
9
|
+
IDENT_CHAR /[a-zA-Z0-9_[:^ascii:]]/
|
10
10
|
|
11
|
-
ESC /\\((?>[0-7]{1,3}|x
|
11
|
+
ESC /\\((?>[0-7]{1,3}|x\h{1,2}|M-[^\\]|(C-|c)[^\\]|u\h{1,4}|u\{\h+(?:\s+\h+)*\}|[^0-7xMCc]))/
|
12
12
|
SIMPLE_STRING /((#{ESC}|\#(#{ESC}|[^\{\#\@\$\"\\])|[^\"\\\#])*)/o
|
13
13
|
SSTRING /((\\.|[^\'])*)/
|
14
14
|
|
@@ -48,7 +48,7 @@ rule
|
|
48
48
|
| /\![=~]?/ { result :arg_state, TOKENS[text], text }
|
49
49
|
|
50
50
|
: /\./
|
51
|
-
| /\.\.\.?/
|
51
|
+
| /\.\.\.?/ process_dots
|
52
52
|
| /\.\d/ { rb_compile_error "no .<digit> floating literal anymore put 0 before dot" }
|
53
53
|
| /\./ { self.lex_state = EXPR_BEG; result EXPR_DOT, :tDOT, "." }
|
54
54
|
|
@@ -62,7 +62,7 @@ rule
|
|
62
62
|
| /\=(?=begin\b)/ { result arg_state, TOKENS[text], text }
|
63
63
|
|
64
64
|
ruby22_label? /\"#{SIMPLE_STRING}\":/o process_label
|
65
|
-
/\"(#{SIMPLE_STRING})\"/o
|
65
|
+
/\"(#{SIMPLE_STRING})\"/o process_simple_string
|
66
66
|
/\"/ { string STR_DQUOTE; result nil, :tSTRING_BEG, text }
|
67
67
|
|
68
68
|
/\@\@?\d/ { rb_compile_error "`#{text}` is not allowed as a variable name" }
|
@@ -164,13 +164,12 @@ was_label? /\'#{SSTRING}\':?/o process_label_or_string
|
|
164
164
|
| in_fname? /\$([1-9]\d*)/ process_gvar
|
165
165
|
| /\$([1-9]\d*)/ process_nthref
|
166
166
|
| /\$0/ process_gvar
|
167
|
-
|
|
167
|
+
| /\$#{IDENT_CHAR}+/ process_gvar
|
168
168
|
| /\$\W|\$\z/ process_gvar_oddity
|
169
|
-
| /\$\w+/ process_gvar
|
170
169
|
|
171
170
|
/\_/ process_underscore
|
172
171
|
|
173
|
-
/#{
|
172
|
+
/#{IDENT_CHAR}+/o process_token
|
174
173
|
|
175
174
|
/\004|\032|\000|\Z/ { [RubyLexer::EOF, RubyLexer::EOF] }
|
176
175
|
|
data/lib/ruby_lexer.rex.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
#--
|
3
3
|
# This file is automatically generated. Do not modify it.
|
4
|
-
# Generated by: oedipus_lex version 2.5.
|
4
|
+
# Generated by: oedipus_lex version 2.5.3.
|
5
5
|
# Source: lib/ruby_lexer.rex
|
6
6
|
#++
|
7
7
|
|
@@ -16,8 +16,8 @@ class RubyLexer
|
|
16
16
|
require 'strscan'
|
17
17
|
|
18
18
|
# :stopdoc:
|
19
|
-
|
20
|
-
ESC = /\\((?>[0-7]{1,3}|x
|
19
|
+
IDENT_CHAR = /[a-zA-Z0-9_[:^ascii:]]/
|
20
|
+
ESC = /\\((?>[0-7]{1,3}|x\h{1,2}|M-[^\\]|(C-|c)[^\\]|u\h{1,4}|u\{\h+(?:\s+\h+)*\}|[^0-7xMCc]))/
|
21
21
|
SIMPLE_STRING = /((#{ESC}|\#(#{ESC}|[^\{\#\@\$\"\\])|[^\"\\\#])*)/o
|
22
22
|
SSTRING = /((\\.|[^\'])*)/
|
23
23
|
INT_DEC = /[+]?(?:(?:[1-9][\d_]*|0)(?!\.\d)(ri|r|i)?\b|0d[0-9_]+)(ri|r|i)?/i
|
@@ -138,7 +138,7 @@ class RubyLexer
|
|
138
138
|
when ss.match?(/\./) then
|
139
139
|
case
|
140
140
|
when text = ss.scan(/\.\.\.?/) then
|
141
|
-
|
141
|
+
process_dots text
|
142
142
|
when ss.skip(/\.\d/) then
|
143
143
|
action { rb_compile_error "no .<digit> floating literal anymore put 0 before dot" }
|
144
144
|
when ss.skip(/\./) then
|
@@ -160,7 +160,7 @@ class RubyLexer
|
|
160
160
|
when ruby22_label? && (text = ss.scan(/\"#{SIMPLE_STRING}\":/o)) then
|
161
161
|
process_label text
|
162
162
|
when text = ss.scan(/\"(#{SIMPLE_STRING})\"/o) then
|
163
|
-
|
163
|
+
process_simple_string text
|
164
164
|
when text = ss.scan(/\"/) then
|
165
165
|
action { string STR_DQUOTE; result nil, :tSTRING_BEG, text }
|
166
166
|
when text = ss.scan(/\@\@?\d/) then
|
@@ -328,16 +328,14 @@ class RubyLexer
|
|
328
328
|
process_nthref text
|
329
329
|
when text = ss.scan(/\$0/) then
|
330
330
|
process_gvar text
|
331
|
-
when text = ss.scan(
|
331
|
+
when text = ss.scan(/\$#{IDENT_CHAR}+/) then
|
332
332
|
process_gvar text
|
333
333
|
when text = ss.scan(/\$\W|\$\z/) then
|
334
334
|
process_gvar_oddity text
|
335
|
-
when text = ss.scan(/\$\w+/) then
|
336
|
-
process_gvar text
|
337
335
|
end # group /\$/
|
338
336
|
when text = ss.scan(/\_/) then
|
339
337
|
process_underscore text
|
340
|
-
when text = ss.scan(/#{
|
338
|
+
when text = ss.scan(/#{IDENT_CHAR}+/o) then
|
341
339
|
process_token text
|
342
340
|
when ss.skip(/\004|\032|\000|\Z/) then
|
343
341
|
action { [RubyLexer::EOF, RubyLexer::EOF] }
|
data/lib/ruby_parser.rb
CHANGED
@@ -78,10 +78,14 @@ require "ruby23_parser"
|
|
78
78
|
require "ruby24_parser"
|
79
79
|
require "ruby25_parser"
|
80
80
|
require "ruby26_parser"
|
81
|
+
require "ruby27_parser"
|
82
|
+
require "ruby30_parser"
|
81
83
|
|
82
84
|
class RubyParser # HACK
|
83
85
|
VERSIONS.clear # also a HACK caused by racc namespace issues
|
84
86
|
|
87
|
+
class V30 < ::Ruby30Parser; end
|
88
|
+
class V27 < ::Ruby27Parser; end
|
85
89
|
class V26 < ::Ruby26Parser; end
|
86
90
|
class V25 < ::Ruby25Parser; end
|
87
91
|
class V24 < ::Ruby24Parser; end
|
data/lib/ruby_parser.yy
CHANGED
@@ -14,6 +14,10 @@ class Ruby24Parser
|
|
14
14
|
class Ruby25Parser
|
15
15
|
#elif V == 26
|
16
16
|
class Ruby26Parser
|
17
|
+
#elif V == 27
|
18
|
+
class Ruby27Parser
|
19
|
+
#elif V == 30
|
20
|
+
class Ruby30Parser
|
17
21
|
#else
|
18
22
|
fail "version not specified or supported on code generation"
|
19
23
|
#endif
|
@@ -44,6 +48,9 @@ token kCLASS kMODULE kDEF kUNDEF kBEGIN kRESCUE kENSURE kEND kIF kUNLESS
|
|
44
48
|
#if V >= 23
|
45
49
|
tLONELY
|
46
50
|
#endif
|
51
|
+
#if V >= 26
|
52
|
+
tBDOT2 tBDOT3
|
53
|
+
#endif
|
47
54
|
|
48
55
|
preclow
|
49
56
|
nonassoc tLOWEST
|
@@ -55,7 +62,7 @@ preclow
|
|
55
62
|
right tEQL tOP_ASGN
|
56
63
|
left kRESCUE_MOD
|
57
64
|
right tEH tCOLON
|
58
|
-
nonassoc tDOT2 tDOT3
|
65
|
+
nonassoc tDOT2 tDOT3 tBDOT2 tBDOT3
|
59
66
|
left tOROP
|
60
67
|
left tANDOP
|
61
68
|
nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
|
@@ -78,6 +85,9 @@ rule
|
|
78
85
|
top_compstmt
|
79
86
|
{
|
80
87
|
result = new_compstmt val
|
88
|
+
|
89
|
+
lexer.cond.pop # local_pop
|
90
|
+
lexer.cmdarg.pop
|
81
91
|
}
|
82
92
|
|
83
93
|
top_compstmt: top_stmts opt_terms
|
@@ -286,13 +296,15 @@ rule
|
|
286
296
|
}
|
287
297
|
| primary_value tCOLON2 tCONSTANT tOP_ASGN command_rhs
|
288
298
|
{
|
289
|
-
|
290
|
-
|
299
|
+
lhs1, _, lhs2, op, rhs = val
|
300
|
+
|
301
|
+
result = s(:op_asgn, lhs1, rhs, lhs2.to_sym, op.to_sym)
|
291
302
|
}
|
292
303
|
| primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_rhs
|
293
304
|
{
|
294
|
-
|
295
|
-
|
305
|
+
lhs1, _, lhs2, op, rhs = val
|
306
|
+
|
307
|
+
result = s(:op_asgn, lhs1, rhs, lhs2.to_sym, op.to_sym)
|
296
308
|
}
|
297
309
|
| backref tOP_ASGN command_rhs
|
298
310
|
{
|
@@ -852,6 +864,24 @@ rule
|
|
852
864
|
result = s(:dot3, v1, v2).line v1.line
|
853
865
|
}
|
854
866
|
#endif
|
867
|
+
|
868
|
+
#if V >= 27
|
869
|
+
| tBDOT2 arg
|
870
|
+
{
|
871
|
+
_, v2, = val
|
872
|
+
v1 = nil
|
873
|
+
|
874
|
+
result = s(:dot2, v1, v2).line v2.line
|
875
|
+
}
|
876
|
+
| tBDOT3 arg
|
877
|
+
{
|
878
|
+
_, v2 = val
|
879
|
+
v1 = nil
|
880
|
+
|
881
|
+
result = s(:dot3, v1, v2).line v2.line
|
882
|
+
}
|
883
|
+
#endif
|
884
|
+
|
855
885
|
| arg tPLUS arg
|
856
886
|
{
|
857
887
|
result = new_call val[0], :+, argl(val[2])
|
@@ -1036,6 +1066,26 @@ rule
|
|
1036
1066
|
_, args, _ = val
|
1037
1067
|
result = args
|
1038
1068
|
}
|
1069
|
+
#if V >= 27
|
1070
|
+
| tLPAREN2 args tCOMMA args_forward rparen
|
1071
|
+
{
|
1072
|
+
yyerror "Unexpected ..." unless
|
1073
|
+
self.lexer.is_local_id(:"*") &&
|
1074
|
+
self.lexer.is_local_id(:"**") &&
|
1075
|
+
self.lexer.is_local_id(:"&")
|
1076
|
+
|
1077
|
+
result = call_args val
|
1078
|
+
}
|
1079
|
+
| tLPAREN2 args_forward rparen
|
1080
|
+
{
|
1081
|
+
yyerror "Unexpected ..." unless
|
1082
|
+
self.lexer.is_local_id(:"*") &&
|
1083
|
+
self.lexer.is_local_id(:"**") &&
|
1084
|
+
self.lexer.is_local_id(:"&")
|
1085
|
+
|
1086
|
+
result = call_args val
|
1087
|
+
}
|
1088
|
+
#endif
|
1039
1089
|
|
1040
1090
|
opt_paren_args: none
|
1041
1091
|
| paren_args
|
@@ -1078,12 +1128,39 @@ rule
|
|
1078
1128
|
}
|
1079
1129
|
|
1080
1130
|
command_args: {
|
1081
|
-
|
1131
|
+
# parse26.y line 2200
|
1132
|
+
|
1133
|
+
# If call_args starts with a open paren '(' or
|
1134
|
+
# '[', look-ahead reading of the letters calls
|
1135
|
+
# CMDARG_PUSH(0), but the push must be done
|
1136
|
+
# after CMDARG_PUSH(1). So this code makes them
|
1137
|
+
# consistent by first cancelling the premature
|
1138
|
+
# CMDARG_PUSH(0), doing CMDARG_PUSH(1), and
|
1139
|
+
# finally redoing CMDARG_PUSH(0).
|
1140
|
+
|
1141
|
+
result = yychar = self.last_token_type.first
|
1142
|
+
lookahead = [:tLPAREN, :tLPAREN_ARG, :tLPAREN2, :tLBRACK, :tLBRACK2].include?(yychar)
|
1143
|
+
lexer.cmdarg.pop if lookahead
|
1144
|
+
lexer.cmdarg.push true
|
1145
|
+
lexer.cmdarg.push false if lookahead
|
1082
1146
|
}
|
1083
1147
|
call_args
|
1084
1148
|
{
|
1085
|
-
|
1086
|
-
|
1149
|
+
yychar, args = val
|
1150
|
+
|
1151
|
+
# call_args can be followed by tLBRACE_ARG (that
|
1152
|
+
# does CMDARG_PUSH(0) in the lexer) but the push
|
1153
|
+
# must be done after CMDARG_POP() in the parser.
|
1154
|
+
# So this code does CMDARG_POP() to pop 0 pushed
|
1155
|
+
# by tLBRACE_ARG, CMDARG_POP() to pop 1 pushed
|
1156
|
+
# by command_args, and CMDARG_PUSH(0) to restore
|
1157
|
+
# back the flag set by tLBRACE_ARG.
|
1158
|
+
|
1159
|
+
lookahead = [:tLBRACE_ARG].include?(yychar)
|
1160
|
+
lexer.cmdarg.pop if lookahead
|
1161
|
+
lexer.cmdarg.pop
|
1162
|
+
lexer.cmdarg.push false if lookahead
|
1163
|
+
result = args
|
1087
1164
|
}
|
1088
1165
|
|
1089
1166
|
block_arg: tAMPER arg_value
|
@@ -1101,8 +1178,9 @@ rule
|
|
1101
1178
|
args: arg_value
|
1102
1179
|
{
|
1103
1180
|
arg, = val
|
1181
|
+
lineno = arg.line || lexer.lineno # HACK
|
1104
1182
|
|
1105
|
-
result = s(:array, arg).line
|
1183
|
+
result = s(:array, arg).line lineno
|
1106
1184
|
}
|
1107
1185
|
| tSTAR arg_value
|
1108
1186
|
{
|
@@ -1114,9 +1192,11 @@ rule
|
|
1114
1192
|
args, _, id = val
|
1115
1193
|
result = self.list_append args, id
|
1116
1194
|
}
|
1117
|
-
| args tCOMMA tSTAR
|
1195
|
+
| args tCOMMA tSTAR arg_value
|
1118
1196
|
{
|
1119
|
-
|
1197
|
+
# TODO: the line number from tSTAR has been dropped
|
1198
|
+
args, _, _, id = val
|
1199
|
+
line = lexer.lineno
|
1120
1200
|
result = self.list_append args, s(:splat, id).line(line)
|
1121
1201
|
}
|
1122
1202
|
|
@@ -1137,7 +1217,6 @@ rule
|
|
1137
1217
|
}
|
1138
1218
|
| args tCOMMA tSTAR arg_value
|
1139
1219
|
{
|
1140
|
-
# FIX: bad shift/reduce conflict with rhs' comma star prod
|
1141
1220
|
# TODO: make all tXXXX terminals include lexer.lineno
|
1142
1221
|
arg, _, _, splat = val
|
1143
1222
|
result = self.arg_concat arg, splat
|
@@ -1165,21 +1244,13 @@ rule
|
|
1165
1244
|
}
|
1166
1245
|
| k_begin
|
1167
1246
|
{
|
1247
|
+
lexer.cmdarg.push false
|
1168
1248
|
result = self.lexer.lineno
|
1169
|
-
# TODO:
|
1170
|
-
# $<val>1 = cmdarg_stack;
|
1171
|
-
# CMDARG_SET(0);
|
1172
1249
|
}
|
1173
1250
|
bodystmt k_end
|
1174
1251
|
{
|
1175
|
-
|
1176
|
-
|
1177
|
-
result = s(:nil)
|
1178
|
-
else
|
1179
|
-
result = s(:begin, val[2])
|
1180
|
-
end
|
1181
|
-
|
1182
|
-
result.line = val[1]
|
1252
|
+
lexer.cmdarg.pop
|
1253
|
+
result = new_begin val
|
1183
1254
|
}
|
1184
1255
|
| tLPAREN_ARG
|
1185
1256
|
{
|
@@ -1192,18 +1263,14 @@ rule
|
|
1192
1263
|
result = s(:begin).line line
|
1193
1264
|
}
|
1194
1265
|
| tLPAREN_ARG
|
1195
|
-
{
|
1196
|
-
result = lexer.cmdarg.store false
|
1197
|
-
}
|
1198
1266
|
stmt
|
1199
1267
|
{
|
1200
1268
|
lexer.lex_state = EXPR_ENDARG
|
1201
1269
|
}
|
1202
1270
|
rparen
|
1203
1271
|
{
|
1204
|
-
_,
|
1205
|
-
warning "(...) interpreted as grouped expression"
|
1206
|
-
lexer.cmdarg.restore cmdarg
|
1272
|
+
_, stmt, _, _, = val
|
1273
|
+
# warning "(...) interpreted as grouped expression"
|
1207
1274
|
result = stmt
|
1208
1275
|
}
|
1209
1276
|
| tLPAREN compstmt tRPAREN
|
@@ -1386,48 +1453,61 @@ rule
|
|
1386
1453
|
}
|
1387
1454
|
| k_def fname
|
1388
1455
|
{
|
1389
|
-
result =
|
1456
|
+
result = self.in_def
|
1390
1457
|
|
1391
|
-
self.
|
1392
|
-
self.in_def = true
|
1458
|
+
self.in_def = true # group = local_push
|
1393
1459
|
self.env.extend
|
1394
|
-
|
1395
|
-
|
1396
|
-
|
1460
|
+
lexer.cmdarg.push false
|
1461
|
+
lexer.cond.push false
|
1462
|
+
|
1463
|
+
self.comments.push self.lexer.comments
|
1397
1464
|
}
|
1398
1465
|
f_arglist bodystmt { result = lexer.lineno } k_end
|
1399
1466
|
{
|
1400
|
-
in_def
|
1467
|
+
in_def = val[2]
|
1401
1468
|
|
1402
1469
|
result = new_defn val
|
1403
1470
|
|
1404
|
-
lexer.
|
1471
|
+
lexer.cond.pop # group = local_pop
|
1472
|
+
lexer.cmdarg.pop
|
1405
1473
|
self.env.unextend
|
1406
1474
|
self.in_def = in_def
|
1475
|
+
|
1407
1476
|
self.lexer.comments # we don't care about comments in the body
|
1408
1477
|
}
|
1409
1478
|
| k_def singleton dot_or_colon
|
1410
1479
|
{
|
1411
|
-
self.comments.push self.lexer.comments
|
1412
1480
|
lexer.lex_state = EXPR_FNAME
|
1413
1481
|
}
|
1414
1482
|
fname
|
1415
1483
|
{
|
1416
|
-
self.
|
1484
|
+
result = [self.in_def, lexer.lineno]
|
1485
|
+
|
1486
|
+
self.in_single += 1 # TODO: remove?
|
1487
|
+
|
1488
|
+
self.in_def = true # local_push
|
1417
1489
|
self.env.extend
|
1418
|
-
lexer.
|
1419
|
-
|
1420
|
-
|
1490
|
+
lexer.cmdarg.push false
|
1491
|
+
lexer.cond.push false
|
1492
|
+
|
1493
|
+
lexer.lex_state = EXPR_ENDFN|EXPR_LABEL
|
1494
|
+
self.comments.push self.lexer.comments
|
1421
1495
|
}
|
1422
1496
|
f_arglist bodystmt k_end
|
1423
1497
|
{
|
1424
|
-
_,
|
1425
|
-
result = new_defs val
|
1498
|
+
_, _recv, _, _, _name, (in_def, _lineno), _args, _body, _ = val
|
1426
1499
|
|
1427
|
-
|
1500
|
+
result = new_defs val
|
1428
1501
|
|
1502
|
+
lexer.cond.pop # group = local_pop
|
1503
|
+
lexer.cmdarg.pop
|
1429
1504
|
self.env.unextend
|
1505
|
+
self.in_def = in_def
|
1506
|
+
|
1430
1507
|
self.in_single -= 1
|
1508
|
+
|
1509
|
+
# TODO: restore cur_arg ? what's cur_arg?
|
1510
|
+
|
1431
1511
|
self.lexer.comments # we don't care about comments in the body
|
1432
1512
|
}
|
1433
1513
|
| kBREAK
|
@@ -1712,20 +1792,19 @@ opt_block_args_tail: tCOMMA block_args_tail
|
|
1712
1792
|
}
|
1713
1793
|
f_larglist
|
1714
1794
|
{
|
1715
|
-
|
1795
|
+
lexer.cmdarg.push false
|
1716
1796
|
}
|
1717
1797
|
lambda_body
|
1718
1798
|
{
|
1719
|
-
(line, lpar), args,
|
1799
|
+
(line, lpar), args, _cmdarg, body = val
|
1720
1800
|
lexer.lpar_beg = lpar
|
1721
1801
|
|
1722
|
-
lexer.cmdarg.
|
1723
|
-
lexer.cmdarg.lexpop
|
1802
|
+
lexer.cmdarg.pop
|
1724
1803
|
|
1725
1804
|
call = s(:lambda).line line
|
1726
1805
|
result = new_iter call, args, body
|
1727
1806
|
result.line = line
|
1728
|
-
self.env.unextend
|
1807
|
+
self.env.unextend # TODO: dynapush & dynapop
|
1729
1808
|
}
|
1730
1809
|
|
1731
1810
|
f_larglist: tLPAREN2 f_args opt_bv_decl rparen
|
@@ -1878,7 +1957,7 @@ opt_block_args_tail: tCOMMA block_args_tail
|
|
1878
1957
|
}
|
1879
1958
|
|
1880
1959
|
do_body: { self.env.extend :dynamic; result = self.lexer.lineno }
|
1881
|
-
{
|
1960
|
+
{ lexer.cmdarg.push false }
|
1882
1961
|
opt_block_param
|
1883
1962
|
#if V >= 25
|
1884
1963
|
bodystmt
|
@@ -1886,11 +1965,11 @@ opt_block_args_tail: tCOMMA block_args_tail
|
|
1886
1965
|
compstmt
|
1887
1966
|
#endif
|
1888
1967
|
{
|
1889
|
-
line,
|
1968
|
+
line, _cmdarg, param, cmpstmt = val
|
1890
1969
|
|
1891
1970
|
result = new_do_body param, cmpstmt, line
|
1971
|
+
lexer.cmdarg.pop
|
1892
1972
|
self.env.unextend
|
1893
|
-
lexer.cmdarg.restore cmdarg
|
1894
1973
|
}
|
1895
1974
|
|
1896
1975
|
case_body: k_when
|
@@ -1990,7 +2069,7 @@ opt_block_args_tail: tCOMMA block_args_tail
|
|
1990
2069
|
|
1991
2070
|
xstring: tXSTRING_BEG xstring_contents tSTRING_END
|
1992
2071
|
{
|
1993
|
-
result = new_xstring val
|
2072
|
+
result = new_xstring val
|
1994
2073
|
# TODO: dedent?!?! SERIOUSLY?!?
|
1995
2074
|
}
|
1996
2075
|
|
@@ -2132,12 +2211,13 @@ regexp_contents: none
|
|
2132
2211
|
result = [lexer.lex_strterm,
|
2133
2212
|
lexer.brace_nest,
|
2134
2213
|
lexer.string_nest, # TODO: remove
|
2135
|
-
lexer.cond.store,
|
2136
|
-
lexer.cmdarg.store,
|
2137
2214
|
lexer.lex_state,
|
2138
2215
|
lexer.lineno,
|
2139
2216
|
]
|
2140
2217
|
|
2218
|
+
lexer.cmdarg.push false
|
2219
|
+
lexer.cond.push false
|
2220
|
+
|
2141
2221
|
lexer.lex_strterm = nil
|
2142
2222
|
lexer.brace_nest = 0
|
2143
2223
|
lexer.string_nest = 0
|
@@ -2149,14 +2229,15 @@ regexp_contents: none
|
|
2149
2229
|
{
|
2150
2230
|
_, memo, stmt, _ = val
|
2151
2231
|
|
2152
|
-
lex_strterm, brace_nest, string_nest,
|
2232
|
+
lex_strterm, brace_nest, string_nest, oldlex_state, line = memo
|
2233
|
+
# TODO: heredoc_indent
|
2153
2234
|
|
2154
2235
|
lexer.lex_strterm = lex_strterm
|
2155
2236
|
lexer.brace_nest = brace_nest
|
2156
2237
|
lexer.string_nest = string_nest
|
2157
2238
|
|
2158
|
-
lexer.
|
2159
|
-
lexer.
|
2239
|
+
lexer.cmdarg.pop
|
2240
|
+
lexer.cond.pop
|
2160
2241
|
|
2161
2242
|
lexer.lex_state = oldlex_state
|
2162
2243
|
|
@@ -2305,6 +2386,22 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
|
|
2305
2386
|
self.lexer.lex_state = EXPR_BEG
|
2306
2387
|
self.lexer.command_start = true
|
2307
2388
|
}
|
2389
|
+
#if V >= 27
|
2390
|
+
| tLPAREN2 f_arg tCOMMA args_forward rparen
|
2391
|
+
{
|
2392
|
+
result = args val
|
2393
|
+
|
2394
|
+
self.lexer.lex_state = EXPR_BEG
|
2395
|
+
self.lexer.command_start = true
|
2396
|
+
}
|
2397
|
+
| tLPAREN2 args_forward rparen
|
2398
|
+
{
|
2399
|
+
result = args val
|
2400
|
+
|
2401
|
+
self.lexer.lex_state = EXPR_BEG
|
2402
|
+
self.lexer.command_start = true
|
2403
|
+
}
|
2404
|
+
#endif
|
2308
2405
|
| {
|
2309
2406
|
result = self.in_kwarg
|
2310
2407
|
self.in_kwarg = true
|
@@ -2404,6 +2501,13 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
|
|
2404
2501
|
result = args val
|
2405
2502
|
}
|
2406
2503
|
|
2504
|
+
#if V >= 27
|
2505
|
+
args_forward: tBDOT3
|
2506
|
+
{
|
2507
|
+
result = s(:forward_args).line lexer.lineno
|
2508
|
+
}
|
2509
|
+
#endif
|
2510
|
+
|
2407
2511
|
f_bad_arg: tCONSTANT
|
2408
2512
|
{
|
2409
2513
|
yyerror "formal argument cannot be a constant"
|
@@ -2552,6 +2656,7 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
|
|
2552
2656
|
| kwrest_mark
|
2553
2657
|
{
|
2554
2658
|
result = :"**"
|
2659
|
+
self.env[result] = :lvar
|
2555
2660
|
}
|
2556
2661
|
|
2557
2662
|
#if V == 20
|