ruby_parser 3.0.0.a8 → 3.0.0.a9
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.
Potentially problematic release.
This version of ruby_parser might be problematic. Click here for more details.
- data.tar.gz.sig +0 -0
- data/.autotest +6 -0
- data/History.txt +40 -0
- data/README.txt +6 -11
- data/Rakefile +5 -0
- data/bin/ruby_parse_extract_error +23 -6
- data/lib/ruby18_parser.rb +18 -8
- data/lib/ruby18_parser.y +18 -8
- data/lib/ruby19_parser.rb +67 -35
- data/lib/ruby19_parser.y +62 -32
- data/lib/ruby_lexer.rb +84 -95
- data/lib/ruby_parser_extras.rb +140 -20
- data/test/test_ruby_lexer.rb +58 -3
- data/test/test_ruby_parser.rb +193 -2
- data/test/test_ruby_parser_extras.rb +109 -0
- metadata +17 -22
- metadata.gz.sig +5 -2
data/lib/ruby_parser_extras.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: ASCII-8BIT
|
2
|
+
|
1
3
|
require 'stringio'
|
2
4
|
require 'racc/parser'
|
3
5
|
require 'sexp'
|
@@ -54,7 +56,11 @@ class RPStringScanner < StringScanner
|
|
54
56
|
def unread_many str # TODO: remove this entirely - we should not need it
|
55
57
|
warn({:unread_many => caller[0]}.inspect) if ENV['TALLY']
|
56
58
|
self.extra_lines_added += str.count("\n")
|
57
|
-
|
59
|
+
begin
|
60
|
+
string[pos, 0] = str
|
61
|
+
rescue IndexError
|
62
|
+
# HACK -- this is a bandaid on a dirty rag on an open festering wound
|
63
|
+
end
|
58
64
|
end
|
59
65
|
|
60
66
|
if ENV['DEBUG'] then
|
@@ -79,11 +85,15 @@ class RPStringScanner < StringScanner
|
|
79
85
|
end
|
80
86
|
|
81
87
|
module RubyParserStuff
|
82
|
-
VERSION = '3.0.0.
|
88
|
+
VERSION = '3.0.0.a9' unless constants.include? "VERSION" # SIGH
|
83
89
|
|
84
90
|
attr_accessor :lexer, :in_def, :in_single, :file
|
85
91
|
attr_reader :env, :comments
|
86
92
|
|
93
|
+
def syntax_error msg
|
94
|
+
raise RubyParser::SyntaxError, msg
|
95
|
+
end
|
96
|
+
|
87
97
|
def arg_add(node1, node2) # TODO: nuke
|
88
98
|
return s(:arglist, node2) unless node1
|
89
99
|
|
@@ -192,7 +202,7 @@ module RubyParserStuff
|
|
192
202
|
def block_args19 val, id
|
193
203
|
# HACK OMG THIS CODE IS SOOO UGLY! CLEAN ME
|
194
204
|
untested = %w[1 2 3 4 7 9 10 12 14]
|
195
|
-
raise "no block_args19 #{id} #{val.inspect}" if untested.include? id
|
205
|
+
raise "no block_args19 #{id}\non: #{val.inspect}" if untested.include? id
|
196
206
|
|
197
207
|
r = s(:array)
|
198
208
|
|
@@ -247,7 +257,7 @@ module RubyParserStuff
|
|
247
257
|
raise "oh noes!: #{r.inspect}"
|
248
258
|
end
|
249
259
|
else
|
250
|
-
raise "
|
260
|
+
raise "totally borked: #{r.inspect}"
|
251
261
|
end
|
252
262
|
|
253
263
|
r
|
@@ -261,6 +271,8 @@ module RubyParserStuff
|
|
261
271
|
id = lhs.to_sym
|
262
272
|
id = id.to_sym if Sexp === id
|
263
273
|
|
274
|
+
raise "write a test 1" if id.to_s =~ /^(?:self|nil|true|false|__LINE__|__FILE__)$/
|
275
|
+
|
264
276
|
raise SyntaxError, "Can't change the value of #{id}" if
|
265
277
|
id.to_s =~ /^(?:self|nil|true|false|__LINE__|__FILE__)$/
|
266
278
|
|
@@ -547,8 +559,10 @@ module RubyParserStuff
|
|
547
559
|
# TODO: need a test for this... obviously
|
548
560
|
case ref.first
|
549
561
|
when :nth_ref then
|
562
|
+
raise "write a test 2"
|
550
563
|
raise SyntaxError, "Can't set variable %p" % ref.last
|
551
564
|
when :back_ref then
|
565
|
+
raise "write a test 3"
|
552
566
|
raise SyntaxError, "Can't set back reference %p" % ref.last
|
553
567
|
else
|
554
568
|
raise "Unknown backref type: #{ref.inspect}"
|
@@ -861,6 +875,7 @@ module RubyParserStuff
|
|
861
875
|
|
862
876
|
def new_yield args = nil
|
863
877
|
# TODO: raise args.inspect unless [:arglist].include? args.first # HACK
|
878
|
+
raise "write a test 4" if args && args.node_type == :block_pass
|
864
879
|
raise SyntaxError, "Block argument should not be given." if
|
865
880
|
args && args.node_type == :block_pass
|
866
881
|
|
@@ -902,6 +917,99 @@ module RubyParserStuff
|
|
902
917
|
lhs
|
903
918
|
end
|
904
919
|
|
920
|
+
##
|
921
|
+
# Returns a UTF-8 encoded string after processing BOMs and magic
|
922
|
+
# encoding comments.
|
923
|
+
#
|
924
|
+
# Holy crap... ok. Here goes:
|
925
|
+
#
|
926
|
+
# Ruby's file handling and encoding support is insane. We need to be
|
927
|
+
# able to lex a file. The lexer file is explicitly UTF-8 to make
|
928
|
+
# things cleaner. This allows us to deal with extended chars in
|
929
|
+
# class and method names. In order to do this, we need to encode all
|
930
|
+
# input source files as UTF-8. First, we look for a UTF-8 BOM by
|
931
|
+
# looking at the first line while forcing its encoding to
|
932
|
+
# ASCII-8BIT. If we find a BOM, we strip it and set the expected
|
933
|
+
# encoding to UTF-8. Then, we search for a magic encoding comment.
|
934
|
+
# If found, it overrides the BOM. Finally, we force the encoding of
|
935
|
+
# the input string to whatever was found, and then encode that to
|
936
|
+
# UTF-8 for compatibility with the lexer.
|
937
|
+
|
938
|
+
def handle_encoding str
|
939
|
+
str = str.dup
|
940
|
+
ruby19 = str.respond_to? :encoding
|
941
|
+
encoding = nil
|
942
|
+
|
943
|
+
header = str.lines.first(2)
|
944
|
+
header.map! { |s| s.force_encoding "ASCII-8BIT" } if ruby19
|
945
|
+
|
946
|
+
first = header.first || ""
|
947
|
+
encoding, str = "utf-8", str[3..-1] if first =~ /\A\xEF\xBB\xBF/
|
948
|
+
|
949
|
+
encoding = $1.strip if header.find { |s|
|
950
|
+
s[/^#.*?-\*-.*?coding:\s*([^ ;]+).*?-\*-/, 1] ||
|
951
|
+
s[/^#.*(?:en)?coding(?:\s*[:=])\s*([\w-]+)/, 1]
|
952
|
+
}
|
953
|
+
|
954
|
+
if encoding then
|
955
|
+
if ruby19 then
|
956
|
+
encoding.sub!(/utf-8-.+$/, 'utf-8') # HACK for stupid emacs formats
|
957
|
+
hack_encoding str, encoding
|
958
|
+
else
|
959
|
+
warn "Skipping magic encoding comment"
|
960
|
+
end
|
961
|
+
else
|
962
|
+
# nothing specified... ugh. try to encode as utf-8
|
963
|
+
if ruby19 then
|
964
|
+
begin
|
965
|
+
str.encode! "utf-8"
|
966
|
+
rescue Encoding::InvalidByteSequenceError, Encoding::UndefinedConversionError
|
967
|
+
# OK... You really suck. You have extended chars but didn't
|
968
|
+
# specify what they were. Now we try to force it and double
|
969
|
+
# check that it is valid.
|
970
|
+
|
971
|
+
hack_encoding str
|
972
|
+
end
|
973
|
+
end
|
974
|
+
end
|
975
|
+
|
976
|
+
str
|
977
|
+
end
|
978
|
+
|
979
|
+
def hack_encoding str, extra = nil
|
980
|
+
# this is in sorted order of occurrence according to
|
981
|
+
# charlock_holmes against 500k files
|
982
|
+
encodings = [
|
983
|
+
extra,
|
984
|
+
Encoding::ISO_8859_1,
|
985
|
+
Encoding::UTF_8,
|
986
|
+
Encoding::ISO_8859_2,
|
987
|
+
Encoding::ISO_8859_9,
|
988
|
+
Encoding::SHIFT_JIS,
|
989
|
+
Encoding::WINDOWS_1252,
|
990
|
+
Encoding::EUC_JP,
|
991
|
+
].compact
|
992
|
+
|
993
|
+
# terrible, horrible, no good, very bad, last ditch effort.
|
994
|
+
encodings.each do |enc|
|
995
|
+
begin
|
996
|
+
str.force_encoding enc
|
997
|
+
if str.valid_encoding? then
|
998
|
+
str.encode! Encoding::UTF_8
|
999
|
+
break
|
1000
|
+
end
|
1001
|
+
rescue Encoding::InvalidByteSequenceError
|
1002
|
+
# do nothing
|
1003
|
+
rescue Encoding::UndefinedConversionError
|
1004
|
+
# do nothing
|
1005
|
+
end
|
1006
|
+
end
|
1007
|
+
|
1008
|
+
# no amount of pain is enough for you.
|
1009
|
+
raise "Bad encoding. Need a magic encoding comment." unless
|
1010
|
+
str.encoding.name == "UTF-8"
|
1011
|
+
end
|
1012
|
+
|
905
1013
|
##
|
906
1014
|
# Parse +str+ at path +file+ and return a sexp. Raises
|
907
1015
|
# Timeout::Error if it runs for more than +time+ seconds.
|
@@ -910,20 +1018,9 @@ module RubyParserStuff
|
|
910
1018
|
Timeout.timeout time do
|
911
1019
|
raise "bad val: #{str.inspect}" unless String === str
|
912
1020
|
|
913
|
-
str
|
914
|
-
encoding = $1
|
915
|
-
|
916
|
-
str = str.dup
|
917
|
-
|
918
|
-
if encoding then
|
919
|
-
if defined?(Encoding) then
|
920
|
-
str.force_encoding(encoding).encode! "utf-8"
|
921
|
-
else
|
922
|
-
warn "Skipping magic encoding comment"
|
923
|
-
end
|
924
|
-
end
|
1021
|
+
str = handle_encoding str
|
925
1022
|
|
926
|
-
self.file = file
|
1023
|
+
self.file = file.dup
|
927
1024
|
self.lexer.src = str
|
928
1025
|
|
929
1026
|
@yydebug = ENV.has_key? 'DEBUG'
|
@@ -951,8 +1048,15 @@ module RubyParserStuff
|
|
951
1048
|
self.comments.clear
|
952
1049
|
end
|
953
1050
|
|
1051
|
+
def block_dup_check call_or_args, block
|
1052
|
+
syntax_error "Both block arg and actual block given." if
|
1053
|
+
block and call_or_args.block_pass?
|
1054
|
+
end
|
1055
|
+
|
954
1056
|
def ret_args node
|
955
1057
|
if node then
|
1058
|
+
raise "write a test 5" if node[0] == :block_pass
|
1059
|
+
|
956
1060
|
raise SyntaxError, "block argument should not be given" if
|
957
1061
|
node[0] == :block_pass
|
958
1062
|
|
@@ -1169,11 +1273,14 @@ module RubyParserStuff
|
|
1169
1273
|
end
|
1170
1274
|
|
1171
1275
|
class StackState
|
1276
|
+
attr_reader :name
|
1172
1277
|
attr_reader :stack
|
1278
|
+
attr_accessor :debug
|
1173
1279
|
|
1174
1280
|
def initialize(name)
|
1175
1281
|
@name = name
|
1176
1282
|
@stack = [false]
|
1283
|
+
@debug = false
|
1177
1284
|
end
|
1178
1285
|
|
1179
1286
|
def inspect
|
@@ -1181,10 +1288,12 @@ module RubyParserStuff
|
|
1181
1288
|
end
|
1182
1289
|
|
1183
1290
|
def is_in_state
|
1291
|
+
p :stack_is_in_state => [name, @stack.last, caller.first] if debug
|
1184
1292
|
@stack.last
|
1185
1293
|
end
|
1186
1294
|
|
1187
1295
|
def lexpop
|
1296
|
+
p :stack_lexpop => caller.first if debug
|
1188
1297
|
raise if @stack.size == 0
|
1189
1298
|
a = @stack.pop
|
1190
1299
|
b = @stack.pop
|
@@ -1193,12 +1302,15 @@ module RubyParserStuff
|
|
1193
1302
|
|
1194
1303
|
def pop
|
1195
1304
|
r = @stack.pop
|
1305
|
+
p :stack_pop => [name, r, @stack, caller.first] if debug
|
1196
1306
|
@stack.push false if @stack.size == 0
|
1197
1307
|
r
|
1198
1308
|
end
|
1199
1309
|
|
1200
1310
|
def push val
|
1201
1311
|
@stack.push val
|
1312
|
+
p :stack_push => [name, @stack, caller.first] if debug
|
1313
|
+
nil
|
1202
1314
|
end
|
1203
1315
|
end
|
1204
1316
|
end
|
@@ -1217,6 +1329,8 @@ end
|
|
1217
1329
|
# parse error.
|
1218
1330
|
|
1219
1331
|
class RubyParser
|
1332
|
+
class SyntaxError < RuntimeError; end
|
1333
|
+
|
1220
1334
|
def initialize
|
1221
1335
|
@p18 = Ruby18Parser.new
|
1222
1336
|
@p19 = Ruby19Parser.new
|
@@ -1239,9 +1353,11 @@ end
|
|
1239
1353
|
############################################################
|
1240
1354
|
# HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK
|
1241
1355
|
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1356
|
+
unless "".respond_to?(:grep) then
|
1357
|
+
class String
|
1358
|
+
def grep re
|
1359
|
+
lines.grep re
|
1360
|
+
end
|
1245
1361
|
end
|
1246
1362
|
end
|
1247
1363
|
|
@@ -1270,6 +1386,10 @@ class Sexp
|
|
1270
1386
|
raise "no: #{self.inspect}.add_all #{x.inspect}" # TODO: need a test to trigger this
|
1271
1387
|
end
|
1272
1388
|
|
1389
|
+
def block_pass?
|
1390
|
+
any? { |s| Sexp === s && s[0] == :block_pass }
|
1391
|
+
end
|
1392
|
+
|
1273
1393
|
alias :node_type :sexp_type
|
1274
1394
|
alias :values :sexp_body # TODO: retire
|
1275
1395
|
end
|
data/test/test_ruby_lexer.rb
CHANGED
@@ -318,7 +318,7 @@ class TestRubyLexer < MiniTest::Unit::TestCase
|
|
318
318
|
end
|
319
319
|
|
320
320
|
def test_yylex_cvar_bad
|
321
|
-
assert_raises SyntaxError do
|
321
|
+
assert_raises RubyParser::SyntaxError do
|
322
322
|
util_lex_token "@@1"
|
323
323
|
end
|
324
324
|
end
|
@@ -744,6 +744,22 @@ class TestRubyLexer < MiniTest::Unit::TestCase
|
|
744
744
|
:tASSOC, "=>")
|
745
745
|
end
|
746
746
|
|
747
|
+
def test_yylex_identifier_equals3
|
748
|
+
# @lex.lex_state = :expr_fname
|
749
|
+
util_lex_token(":a===b",
|
750
|
+
:tSYMBOL, "a",
|
751
|
+
:tEQQ, "===",
|
752
|
+
:tIDENTIFIER, "b")
|
753
|
+
end
|
754
|
+
|
755
|
+
def test_yylex_identifier_equals_equals_arrow
|
756
|
+
# @lex.lex_state = :expr_fname
|
757
|
+
util_lex_token(":a==>b",
|
758
|
+
:tSYMBOL, "a=",
|
759
|
+
:tASSOC, "=>",
|
760
|
+
:tIDENTIFIER, "b")
|
761
|
+
end
|
762
|
+
|
747
763
|
def test_yylex_identifier_equals_caret
|
748
764
|
util_lex_fname "^", :tCARET
|
749
765
|
end
|
@@ -1136,6 +1152,45 @@ class TestRubyLexer < MiniTest::Unit::TestCase
|
|
1136
1152
|
util_lex_token "+@", :tUPLUS, "+@"
|
1137
1153
|
end
|
1138
1154
|
|
1155
|
+
def test_yylex_numbers
|
1156
|
+
util_lex_token "0b10", :tINTEGER, 2
|
1157
|
+
util_lex_token "0B10", :tINTEGER, 2
|
1158
|
+
|
1159
|
+
util_lex_token "0d10", :tINTEGER, 10
|
1160
|
+
util_lex_token "0D10", :tINTEGER, 10
|
1161
|
+
|
1162
|
+
util_lex_token "0x10", :tINTEGER, 16
|
1163
|
+
util_lex_token "0X10", :tINTEGER, 16
|
1164
|
+
|
1165
|
+
util_lex_token "0o10", :tINTEGER, 8
|
1166
|
+
util_lex_token "0O10", :tINTEGER, 8
|
1167
|
+
util_lex_token "0o", :tINTEGER, 0
|
1168
|
+
util_lex_token "0O", :tINTEGER, 0
|
1169
|
+
|
1170
|
+
util_lex_token "0o", :tINTEGER, 0
|
1171
|
+
util_lex_token "0O", :tINTEGER, 0
|
1172
|
+
|
1173
|
+
util_lex_token "0", :tINTEGER, 0
|
1174
|
+
|
1175
|
+
util_bad_token "0x"
|
1176
|
+
util_bad_token "0X"
|
1177
|
+
util_bad_token "0b"
|
1178
|
+
util_bad_token "0B"
|
1179
|
+
util_bad_token "0d"
|
1180
|
+
util_bad_token "0D"
|
1181
|
+
|
1182
|
+
util_bad_token "08"
|
1183
|
+
util_bad_token "09"
|
1184
|
+
util_bad_token "0o8"
|
1185
|
+
util_bad_token "0o9"
|
1186
|
+
util_bad_token "0O8"
|
1187
|
+
util_bad_token "0O9"
|
1188
|
+
|
1189
|
+
util_bad_token "1_e1"
|
1190
|
+
util_bad_token "1_.1"
|
1191
|
+
util_bad_token "1__1"
|
1192
|
+
end
|
1193
|
+
|
1139
1194
|
def test_yylex_plus_unary_number
|
1140
1195
|
util_lex_token("+42",
|
1141
1196
|
:tINTEGER, 42)
|
@@ -1867,7 +1922,7 @@ class TestRubyLexer < MiniTest::Unit::TestCase
|
|
1867
1922
|
############################################################
|
1868
1923
|
|
1869
1924
|
def util_bad_token s, *args
|
1870
|
-
assert_raises SyntaxError do
|
1925
|
+
assert_raises RubyParser::SyntaxError do
|
1871
1926
|
util_lex_token s, *args
|
1872
1927
|
end
|
1873
1928
|
end
|
@@ -1879,7 +1934,7 @@ class TestRubyLexer < MiniTest::Unit::TestCase
|
|
1879
1934
|
|
1880
1935
|
def util_escape_bad input
|
1881
1936
|
@lex.src = input
|
1882
|
-
assert_raises SyntaxError do
|
1937
|
+
assert_raises RubyParser::SyntaxError do
|
1883
1938
|
@lex.read_escape
|
1884
1939
|
end
|
1885
1940
|
end
|
data/test/test_ruby_parser.rb
CHANGED
@@ -33,6 +33,17 @@ class RubyParserTestCase < ParseTreeTestCase
|
|
33
33
|
assert_equal pt, result
|
34
34
|
end
|
35
35
|
|
36
|
+
def assert_syntax_error rb, emsg
|
37
|
+
e = nil
|
38
|
+
assert_silent do
|
39
|
+
e = assert_raises RubyParser::SyntaxError do
|
40
|
+
processor.parse rb
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
assert_equal emsg, e.message.strip # TODO: why strip?
|
45
|
+
end
|
46
|
+
|
36
47
|
def assert_parse_error rb, emsg
|
37
48
|
e = nil
|
38
49
|
out, err = capture_io do
|
@@ -59,6 +70,58 @@ module TestRubyParserShared
|
|
59
70
|
# p :test => [self.class, __name__]
|
60
71
|
end
|
61
72
|
|
73
|
+
BLOCK_DUP_MSG = "Both block arg and actual block given."
|
74
|
+
|
75
|
+
def test_double_block_error_01
|
76
|
+
assert_syntax_error "a(1, &b) { }", BLOCK_DUP_MSG
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_double_block_error_02
|
80
|
+
assert_syntax_error "a(1, &b) do end", BLOCK_DUP_MSG
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_double_block_error_03
|
84
|
+
assert_syntax_error "a 1, &b do end", BLOCK_DUP_MSG
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_double_block_error_04
|
88
|
+
assert_syntax_error "m.a(1, &b) { }", BLOCK_DUP_MSG
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_double_block_error_05
|
92
|
+
assert_syntax_error "m.a(1, &b) do end", BLOCK_DUP_MSG
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_double_block_error_06
|
96
|
+
assert_syntax_error "m.a 1, &b do end", BLOCK_DUP_MSG
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_double_block_error_07
|
100
|
+
assert_syntax_error "m::a(1, &b) { }", BLOCK_DUP_MSG
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_double_block_error_08
|
104
|
+
assert_syntax_error "m::a(1, &b) do end", BLOCK_DUP_MSG
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_double_block_error_09
|
108
|
+
assert_syntax_error "m::a 1, &b do end", BLOCK_DUP_MSG
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_wtf_7
|
112
|
+
assert_parse "a.b (1) {c}", s(:iter,
|
113
|
+
s(:call, s(:call, nil, :a), :b, s(:lit, 1)),
|
114
|
+
nil,
|
115
|
+
s(:call, nil, :c))
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_wtf_8
|
119
|
+
assert_parse "a::b (1) {c}", s(:iter,
|
120
|
+
s(:call, s(:call, nil, :a), :b, s(:lit, 1)),
|
121
|
+
nil,
|
122
|
+
s(:call, nil, :c))
|
123
|
+
end
|
124
|
+
|
62
125
|
def test_attrasgn_array_lhs
|
63
126
|
rb = '[1, 2, 3, 4][from .. to] = ["a", "b", "c"]'
|
64
127
|
pt = s(:attrasgn,
|
@@ -808,6 +871,8 @@ module TestRubyParserShared
|
|
808
871
|
end
|
809
872
|
EOM
|
810
873
|
|
874
|
+
rb.force_encoding "ASCII-8BIT" if rb.respond_to? :force_encoding
|
875
|
+
|
811
876
|
# TODO: class vars
|
812
877
|
# TODO: odd-ternary: a ?bb : c
|
813
878
|
# TODO: globals
|
@@ -968,6 +1033,34 @@ class TestRuby18Parser < RubyParserTestCase
|
|
968
1033
|
|
969
1034
|
assert_parse rb, pt
|
970
1035
|
end
|
1036
|
+
|
1037
|
+
def test_double_block_error_10
|
1038
|
+
assert_syntax_error "a.b (&b) {}", BLOCK_DUP_MSG
|
1039
|
+
end
|
1040
|
+
|
1041
|
+
def test_double_block_error_11
|
1042
|
+
assert_syntax_error "a (1, &b) { }", BLOCK_DUP_MSG
|
1043
|
+
end
|
1044
|
+
|
1045
|
+
def test_double_block_error_12
|
1046
|
+
assert_syntax_error "a (1, &b) do end", BLOCK_DUP_MSG
|
1047
|
+
end
|
1048
|
+
|
1049
|
+
def test_double_block_error_13
|
1050
|
+
assert_syntax_error "m.a (1, &b) { }", BLOCK_DUP_MSG
|
1051
|
+
end
|
1052
|
+
|
1053
|
+
def test_double_block_error_14
|
1054
|
+
assert_syntax_error "m.a (1, &b) do end", BLOCK_DUP_MSG
|
1055
|
+
end
|
1056
|
+
|
1057
|
+
def test_double_block_error_15
|
1058
|
+
assert_syntax_error "m::a (1, &b) { }", BLOCK_DUP_MSG
|
1059
|
+
end
|
1060
|
+
|
1061
|
+
def test_double_block_error_16
|
1062
|
+
assert_syntax_error "m::a (1, &b) do end", BLOCK_DUP_MSG
|
1063
|
+
end
|
971
1064
|
end
|
972
1065
|
|
973
1066
|
class TestRuby19Parser < RubyParserTestCase
|
@@ -1193,7 +1286,7 @@ class TestRuby19Parser < RubyParserTestCase
|
|
1193
1286
|
rb = "a { |b = 1| }"
|
1194
1287
|
pt = s(:iter,
|
1195
1288
|
s(:call, nil, :a),
|
1196
|
-
s(:
|
1289
|
+
s(:args, :b, s(:block, s(:lasgn, :b, s(:lit, 1)))))
|
1197
1290
|
|
1198
1291
|
assert_parse rb, pt
|
1199
1292
|
end
|
@@ -1238,7 +1331,7 @@ class TestRuby19Parser < RubyParserTestCase
|
|
1238
1331
|
# pt = s(:iter,
|
1239
1332
|
# s(:call, nil, :lambda),
|
1240
1333
|
# s(:args, :a, :b,
|
1241
|
-
# s(:block, s(:lasgn, :b, s(nil)))),
|
1334
|
+
# s(:block, s(:lasgn, :b, s(:nil)))),
|
1242
1335
|
# s(:call, nil, :p, s(:array, s(:lvar, :a), s(:lvar, :b))))
|
1243
1336
|
#
|
1244
1337
|
# assert_parse rb, pt
|
@@ -1247,4 +1340,102 @@ class TestRuby19Parser < RubyParserTestCase
|
|
1247
1340
|
#
|
1248
1341
|
# assert_parse rb, pt
|
1249
1342
|
# end
|
1343
|
+
|
1344
|
+
def test_block_args_opt1
|
1345
|
+
rb = "f { |a, b = 42| [a, b] }"
|
1346
|
+
pt = s(:iter,
|
1347
|
+
s(:call, nil, :f),
|
1348
|
+
s(:args, :a, :b,
|
1349
|
+
s(:block, s(:lasgn, :b, s(:lit, 42)))),
|
1350
|
+
s(:array, s(:lvar, :a), s(:lvar, :b)))
|
1351
|
+
|
1352
|
+
assert_parse rb, pt
|
1353
|
+
end
|
1354
|
+
|
1355
|
+
def test_block_args_opt2
|
1356
|
+
rb = "f { |a, b = 42, c = 24| [a, b, c] }"
|
1357
|
+
pt = s(:iter,
|
1358
|
+
s(:call, nil, :f),
|
1359
|
+
s(:args, :a, :b, :c,
|
1360
|
+
s(:block, s(:lasgn, :b, s(:lit, 42)), s(:lasgn, :c, s(:lit, 24)))),
|
1361
|
+
s(:array, s(:lvar, :a), s(:lvar, :b), s(:lvar, :c)))
|
1362
|
+
|
1363
|
+
assert_parse rb, pt
|
1364
|
+
end
|
1365
|
+
|
1366
|
+
def test_block_args_opt3
|
1367
|
+
rb = "f { |a, b = 42, c = 24, &d| [a, b, c, d] }"
|
1368
|
+
pt = s(:iter,
|
1369
|
+
s(:call, nil, :f),
|
1370
|
+
s(:args, :a, :b, :c, :"&d",
|
1371
|
+
s(:block, s(:lasgn, :b, s(:lit, 42)), s(:lasgn, :c, s(:lit, 24)))),
|
1372
|
+
s(:array, s(:lvar, :a), s(:lvar, :b), s(:lvar, :c), s(:lvar, :d)))
|
1373
|
+
|
1374
|
+
assert_parse rb, pt
|
1375
|
+
end
|
1376
|
+
|
1377
|
+
def test_i_have_no_freakin_clue
|
1378
|
+
rb = "1 ? b('') : 2\na d: 3"
|
1379
|
+
pt = s(:block,
|
1380
|
+
s(:if, s(:lit, 1), s(:call, nil, :b, s(:str, "")), s(:lit, 2)),
|
1381
|
+
s(:call, nil, :a, s(:hash, s(:lit, :d), s(:lit, 3))))
|
1382
|
+
|
1383
|
+
assert_parse rb, pt
|
1384
|
+
end
|
1385
|
+
|
1386
|
+
def test_motherfuckin_leading_dots
|
1387
|
+
rb = "a\n.b"
|
1388
|
+
pt = s(:call, s(:call, nil, :a), :b)
|
1389
|
+
|
1390
|
+
assert_parse rb, pt
|
1391
|
+
end
|
1392
|
+
|
1393
|
+
def test_motherfuckin_leading_dots2
|
1394
|
+
rb = "a\n..b"
|
1395
|
+
|
1396
|
+
assert_parse_error rb, 'parse error on value ".." (tDOT2)'
|
1397
|
+
end
|
1398
|
+
|
1399
|
+
def test_kill_me
|
1400
|
+
rb = "f { |a, (b, *c)| }"
|
1401
|
+
pt = s(:iter,
|
1402
|
+
s(:call, nil, :f),
|
1403
|
+
s(:masgn,
|
1404
|
+
s(:array,
|
1405
|
+
s(:lasgn, :a),
|
1406
|
+
s(:masgn,
|
1407
|
+
s(:array,
|
1408
|
+
s(:lasgn, :b),
|
1409
|
+
s(:splat, :c)))))) # TODO: omg this is so horrible
|
1410
|
+
|
1411
|
+
assert_parse rb, pt
|
1412
|
+
end
|
1413
|
+
|
1414
|
+
def test_kill_me2
|
1415
|
+
rb = "f { |*a, b| }"
|
1416
|
+
pt = s(:iter, s(:call, nil, :f), s(:args, :"*a", :b))
|
1417
|
+
|
1418
|
+
assert_parse rb, pt
|
1419
|
+
end
|
1420
|
+
|
1421
|
+
def test_kill_me3
|
1422
|
+
rb = "f { |*a, b, &c| }"
|
1423
|
+
pt = s(:iter, s(:call, nil, :f), s(:args, :"*a", :b, :"&c"))
|
1424
|
+
|
1425
|
+
assert_parse rb, pt
|
1426
|
+
end
|
1427
|
+
|
1428
|
+
def test_kill_me4
|
1429
|
+
rb = "a=b ? true: false"
|
1430
|
+
pt = s(:lasgn, :a, s(:if, s(:call, nil, :b), s(:true), s(:false)))
|
1431
|
+
|
1432
|
+
assert_parse rb, pt
|
1433
|
+
end
|
1434
|
+
|
1435
|
+
# def test_kill_me5
|
1436
|
+
# rb = "f ->() { g do end }"
|
1437
|
+
# pt = 42
|
1438
|
+
#
|
1439
|
+
# assert_parse rb, pt
|
1440
|
+
# end
|
1250
1441
|
end
|