ruby_parser 3.0.0.a5 → 3.0.0.a6
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 +1 -0
- data/History.txt +18 -0
- data/bin/ruby_parse_extract_error +39 -18
- data/lib/ruby18_parser.rb +1 -1
- data/lib/ruby19_parser.rb +4 -4
- data/lib/ruby19_parser.y +3 -3
- data/lib/ruby_lexer.rb +21 -7
- data/lib/ruby_parser_extras.rb +22 -4
- data/test/test_ruby_parser.rb +88 -4
- metadata +4 -4
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/.autotest
CHANGED
data/History.txt
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
=== 3.0.0.a6 / 2012-08-20
|
2
|
+
|
3
|
+
* 2 minor enhancements:
|
4
|
+
|
5
|
+
* 1.8: Added basic encoding support to 1.8 parser. Assumes -Ku.
|
6
|
+
* 1.9: Added encoding magic comment support to 1.9 parser.
|
7
|
+
|
8
|
+
* 8 bug fixes:
|
9
|
+
|
10
|
+
* 1.9: Fixed lexing of -1 w/in conditionals. yeah... I dunno.
|
11
|
+
* 1.9: Fixed parsing of a do | | end.
|
12
|
+
* 1.9: Fixed parsing of not(x).
|
13
|
+
* 1.9: Fixed parsing of op_asgn + rescue: 'a ||= b rescue nil'
|
14
|
+
* 1.9: added \r to the EOL backslash handler. dos files blow
|
15
|
+
* 1.9: hacked in a workaround for 1.9 specific regexps running in 1.8.
|
16
|
+
* Added #reset to RubyParser proxy class
|
17
|
+
* Fixed lexing of conditional w/ %() tokens
|
18
|
+
|
1
19
|
=== 3.0.0.a5 / 2012-07-31
|
2
20
|
|
3
21
|
* 5 bug fixes:
|
@@ -1,5 +1,10 @@
|
|
1
1
|
#!/usr/bin/ruby -ws
|
2
2
|
|
3
|
+
$d ||= false
|
4
|
+
$d ||= ENV["DELETE"]
|
5
|
+
$q ||= false
|
6
|
+
$q ||= ENV["QUIET"]
|
7
|
+
|
3
8
|
require 'rubygems'
|
4
9
|
require 'ruby_parser'
|
5
10
|
|
@@ -13,6 +18,8 @@ class Racc::Parser
|
|
13
18
|
|
14
19
|
defs = pre_error.grep(/^ *def/)
|
15
20
|
|
21
|
+
raise "can't figure out where the bad code starts" unless defs.last
|
22
|
+
|
16
23
|
last_def_indent = defs.last[/^ */]
|
17
24
|
|
18
25
|
post_error = src[ss.pos..-1]
|
@@ -30,7 +37,9 @@ class Racc::Parser
|
|
30
37
|
|
31
38
|
parser = self.class.new
|
32
39
|
|
33
|
-
parser.process(defs.join("\n\n"))
|
40
|
+
parser.process(defs.join("\n\n"))
|
41
|
+
rescue SyntaxError, StandardError
|
42
|
+
nil
|
34
43
|
end
|
35
44
|
end
|
36
45
|
|
@@ -46,34 +55,46 @@ ARGV.replace ARGV.map { |path|
|
|
46
55
|
f =~ /bad_ruby_file/ # I have intentionally bad code in my test dirs
|
47
56
|
}
|
48
57
|
|
49
|
-
parser = Ruby19Parser.new
|
50
|
-
|
51
58
|
ARGV.each do |file|
|
52
59
|
ruby = file == "-" ? $stdin.read : File.read(file)
|
53
60
|
|
54
61
|
begin
|
55
|
-
$stderr.print "Validating #{file}: "
|
62
|
+
$stderr.print "# Validating #{file}: "
|
63
|
+
parser = Ruby19Parser.new
|
56
64
|
parser.process(ruby, file)
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
$
|
65
|
+
warn "good"
|
66
|
+
File.unlink file if $d
|
67
|
+
rescue StandardError, SyntaxError, Racc::ParseError => e
|
68
|
+
warn "# error: #{e.message.strip}" unless $q
|
69
|
+
warn ""
|
70
|
+
next if $q
|
61
71
|
|
62
|
-
|
72
|
+
begin
|
73
|
+
defs = parser.extract_defs
|
63
74
|
|
64
|
-
|
65
|
-
parser.retest_for_errors defs
|
75
|
+
orig_size = defs.size
|
66
76
|
|
67
|
-
|
77
|
+
if parser.retest_for_errors defs then
|
78
|
+
warn "Can't reproduce error with just methods, punting..."
|
79
|
+
next
|
80
|
+
end
|
68
81
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
82
|
+
mandatory = defs.pop
|
83
|
+
|
84
|
+
catch :extract_done do
|
85
|
+
(1..defs.size).each do |perm_size|
|
86
|
+
defs.combination(perm_size).each do |trial|
|
87
|
+
trial << mandatory
|
88
|
+
unless parser.retest_for_errors trial then
|
89
|
+
puts trial.join "\n"
|
90
|
+
warn "# reduced repro found!"
|
91
|
+
throw :extract_done
|
92
|
+
end
|
93
|
+
end
|
75
94
|
end
|
76
95
|
end
|
96
|
+
rescue RuntimeError, Racc::ParseError => e
|
97
|
+
warn "# error: #{e.message.strip}"
|
77
98
|
end
|
78
99
|
end
|
79
100
|
end
|
data/lib/ruby18_parser.rb
CHANGED
data/lib/ruby19_parser.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# DO NOT MODIFY!!!!
|
3
|
-
# This file is automatically generated by Racc 1.4.
|
3
|
+
# This file is automatically generated by Racc 1.4.9
|
4
4
|
# from Racc grammer file "".
|
5
5
|
#
|
6
6
|
|
@@ -3992,7 +3992,7 @@ end
|
|
3992
3992
|
|
3993
3993
|
def _reduce_198(val, _values, result)
|
3994
3994
|
result = new_op_asgn val
|
3995
|
-
result =
|
3995
|
+
result = s(:rescue, result, new_resbody(s(:array), val[4]))
|
3996
3996
|
|
3997
3997
|
result
|
3998
3998
|
end
|
@@ -4540,7 +4540,7 @@ def _reduce_292(val, _values, result)
|
|
4540
4540
|
end
|
4541
4541
|
|
4542
4542
|
def _reduce_293(val, _values, result)
|
4543
|
-
|
4543
|
+
result = s(:call, val[2], :"!")
|
4544
4544
|
|
4545
4545
|
result
|
4546
4546
|
end
|
@@ -5029,7 +5029,7 @@ end
|
|
5029
5029
|
# reduce 383 omitted
|
5030
5030
|
|
5031
5031
|
def _reduce_384(val, _values, result)
|
5032
|
-
|
5032
|
+
result = val[1] || 0
|
5033
5033
|
|
5034
5034
|
result
|
5035
5035
|
end
|
data/lib/ruby19_parser.y
CHANGED
@@ -582,7 +582,7 @@ rule
|
|
582
582
|
| var_lhs tOP_ASGN arg kRESCUE_MOD arg
|
583
583
|
{
|
584
584
|
result = new_op_asgn val
|
585
|
-
result =
|
585
|
+
result = s(:rescue, result, new_resbody(s(:array), val[4]))
|
586
586
|
}
|
587
587
|
| primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN arg
|
588
588
|
{
|
@@ -966,7 +966,7 @@ rule
|
|
966
966
|
}
|
967
967
|
| kNOT tLPAREN2 expr rparen
|
968
968
|
{
|
969
|
-
|
969
|
+
result = s(:call, val[2], :"!")
|
970
970
|
}
|
971
971
|
| kNOT tLPAREN2 rparen
|
972
972
|
{
|
@@ -1309,7 +1309,7 @@ rule
|
|
1309
1309
|
|
1310
1310
|
block_param_def: tPIPE opt_bv_decl tPIPE
|
1311
1311
|
{
|
1312
|
-
|
1312
|
+
result = val[1] || 0
|
1313
1313
|
}
|
1314
1314
|
| tOROP
|
1315
1315
|
{
|
data/lib/ruby_lexer.rb
CHANGED
@@ -1,4 +1,18 @@
|
|
1
|
+
# encoding: US-ASCII
|
2
|
+
|
1
3
|
class RubyLexer
|
4
|
+
|
5
|
+
IDENT_CHAR_RE = case RUBY_VERSION
|
6
|
+
when /^1\.8/ then
|
7
|
+
/[\w\x80-\xFF]/
|
8
|
+
when /^(1\.9|2\.0)/ then # HACK - matching 2.0 for now
|
9
|
+
/[\w\u0080-\uFFFF]/u
|
10
|
+
else
|
11
|
+
raise "bork"
|
12
|
+
end
|
13
|
+
|
14
|
+
IDENT_RE = /^#{IDENT_CHAR_RE}+/
|
15
|
+
|
2
16
|
attr_accessor :command_start
|
3
17
|
attr_accessor :cmdarg
|
4
18
|
attr_accessor :cond
|
@@ -773,7 +787,7 @@ class RubyLexer
|
|
773
787
|
self.lex_state = :expr_dot
|
774
788
|
self.yacc_value = "::"
|
775
789
|
return :tCOLON2
|
776
|
-
elsif ! is_end? && src.scan(/:([a-zA-Z_]
|
790
|
+
elsif ! is_end? && src.scan(/:([a-zA-Z_]#{IDENT_CHAR_RE}*(?:[?!]|=(?!>))?)/) then
|
777
791
|
# scanning shortcut to symbols
|
778
792
|
self.yacc_value = src[1]
|
779
793
|
self.lex_state = :expr_end
|
@@ -898,7 +912,7 @@ class RubyLexer
|
|
898
912
|
return :tOP_ASGN
|
899
913
|
end
|
900
914
|
|
901
|
-
if (
|
915
|
+
if (is_beg? ||
|
902
916
|
(lex_state.is_argument && space_seen && !src.check(/\s/))) then
|
903
917
|
if lex_state.is_argument then
|
904
918
|
arg_ambiguous
|
@@ -1144,14 +1158,14 @@ class RubyLexer
|
|
1144
1158
|
|
1145
1159
|
return :tTILDE
|
1146
1160
|
elsif src.scan(/\\/) then
|
1147
|
-
if src.scan(/\n/) then
|
1161
|
+
if src.scan(/\r?\n/) then
|
1148
1162
|
self.lineno = nil
|
1149
1163
|
self.space_seen = true
|
1150
1164
|
next
|
1151
1165
|
end
|
1152
1166
|
rb_compile_error "bare backslash only allowed before newline"
|
1153
1167
|
elsif src.scan(/\%/) then
|
1154
|
-
if
|
1168
|
+
if is_beg? then
|
1155
1169
|
return parse_quote
|
1156
1170
|
end
|
1157
1171
|
|
@@ -1229,12 +1243,12 @@ class RubyLexer
|
|
1229
1243
|
if src.scan(/\004|\032|\000/) || src.eos? then # ^D, ^Z, EOF
|
1230
1244
|
return RubyLexer::EOF
|
1231
1245
|
else # alpha check
|
1232
|
-
|
1246
|
+
unless src.check IDENT_RE then
|
1233
1247
|
rb_compile_error "Invalid char #{src.matched.inspect} in expression"
|
1234
1248
|
end
|
1235
1249
|
end
|
1236
1250
|
|
1237
|
-
self.token = src.matched if self.src.scan
|
1251
|
+
self.token = src.matched if self.src.scan IDENT_RE
|
1238
1252
|
|
1239
1253
|
return process_token(command_state)
|
1240
1254
|
end
|
@@ -1311,7 +1325,7 @@ class RubyLexer
|
|
1311
1325
|
|
1312
1326
|
def process_token(command_state)
|
1313
1327
|
|
1314
|
-
token << src.matched if token =~
|
1328
|
+
token << src.matched if token =~ IDENT_RE && src.scan(/[\!\?](?!=)/)
|
1315
1329
|
|
1316
1330
|
result = nil
|
1317
1331
|
last_state = lex_state
|
data/lib/ruby_parser_extras.rb
CHANGED
@@ -78,7 +78,7 @@ class RPStringScanner < StringScanner
|
|
78
78
|
end
|
79
79
|
|
80
80
|
module RubyParserStuff
|
81
|
-
VERSION = '3.0.0.
|
81
|
+
VERSION = '3.0.0.a6' unless constants.include? "VERSION" # SIGH
|
82
82
|
|
83
83
|
attr_accessor :lexer, :in_def, :in_single, :file
|
84
84
|
attr_reader :env, :comments
|
@@ -749,7 +749,7 @@ module RubyParserStuff
|
|
749
749
|
Regexp.new(node[1], o, k)
|
750
750
|
else
|
751
751
|
Regexp.new(node[1], o)
|
752
|
-
end
|
752
|
+
end rescue node[1] # HACK - drops options
|
753
753
|
when :dstr then
|
754
754
|
if options =~ /o/ then
|
755
755
|
node[0] = :dregx_once
|
@@ -902,8 +902,21 @@ module RubyParserStuff
|
|
902
902
|
def process(str, file = "(string)")
|
903
903
|
raise "bad val: #{str.inspect}" unless String === str
|
904
904
|
|
905
|
+
str.lines.first(2).find { |s| s[/^# encoding: (.+)/, 1] }
|
906
|
+
encoding = $1
|
907
|
+
|
908
|
+
str = str.dup
|
909
|
+
|
910
|
+
if encoding then
|
911
|
+
if defined?(Encoding) then
|
912
|
+
str.force_encoding(encoding).encode! "utf-8"
|
913
|
+
else
|
914
|
+
warn "Skipping magic encoding comment"
|
915
|
+
end
|
916
|
+
end
|
917
|
+
|
905
918
|
self.file = file
|
906
|
-
self.lexer.src = str
|
919
|
+
self.lexer.src = str
|
907
920
|
|
908
921
|
@yydebug = ENV.has_key? 'DEBUG'
|
909
922
|
|
@@ -1199,13 +1212,18 @@ class RubyParser
|
|
1199
1212
|
@p19 = Ruby19Parser.new
|
1200
1213
|
end
|
1201
1214
|
|
1202
|
-
def process
|
1215
|
+
def process(s, f = "(string)") # parens for emacs *sigh*
|
1203
1216
|
Ruby19Parser.new.process s, f
|
1204
1217
|
rescue Racc::ParseError
|
1205
1218
|
Ruby18Parser.new.process s, f
|
1206
1219
|
end
|
1207
1220
|
|
1208
1221
|
alias :parse :process
|
1222
|
+
|
1223
|
+
def reset
|
1224
|
+
@p18.reset
|
1225
|
+
@p19.reset
|
1226
|
+
end
|
1209
1227
|
end
|
1210
1228
|
|
1211
1229
|
############################################################
|
data/test/test_ruby_parser.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#!/usr/local/bin/ruby
|
2
|
+
# encoding: utf-8
|
2
3
|
|
3
4
|
# ENV['VERBOSE'] = "1"
|
4
5
|
|
@@ -646,6 +647,13 @@ module TestRubyParserShared
|
|
646
647
|
assert_parse rb, pt
|
647
648
|
end
|
648
649
|
|
650
|
+
def test_bug_cond_pct
|
651
|
+
rb = "case; when %r%blahblah%; end"
|
652
|
+
pt = s(:case, nil, s(:when, s(:array, s(:lit, /blahblah/)), nil), nil)
|
653
|
+
|
654
|
+
assert_parse rb, pt
|
655
|
+
end
|
656
|
+
|
649
657
|
# according to 2.3.1 parser:
|
650
658
|
# rp.process("f { |(a,b),c| }") == rp.process("f { |((a,b),c)| }")
|
651
659
|
|
@@ -657,7 +665,7 @@ module TestRubyParserShared
|
|
657
665
|
# s(:array,
|
658
666
|
# s(:masgn, s(:array, s(:lasgn, :a), s(:lasgn, :b))),
|
659
667
|
# s(:lasgn, :c))))
|
660
|
-
#
|
668
|
+
#
|
661
669
|
# assert_parse rb, pt.dup
|
662
670
|
# end
|
663
671
|
|
@@ -690,11 +698,18 @@ module TestRubyParserShared
|
|
690
698
|
# assert_parse rb, pt
|
691
699
|
# end
|
692
700
|
|
701
|
+
def ruby18
|
702
|
+
Ruby18Parser === self.processor
|
703
|
+
end
|
704
|
+
|
705
|
+
def ruby19
|
706
|
+
Ruby19Parser === self.processor
|
707
|
+
end
|
708
|
+
|
693
709
|
def test_bug_comma
|
694
|
-
val =
|
695
|
-
when Ruby18Parser then
|
710
|
+
val = if ruby18 then
|
696
711
|
s(:lit, 100)
|
697
|
-
|
712
|
+
elsif ruby19 then
|
698
713
|
s(:str, "d")
|
699
714
|
else
|
700
715
|
raise "wtf"
|
@@ -745,6 +760,68 @@ module TestRubyParserShared
|
|
745
760
|
|
746
761
|
assert_parse rb, pt
|
747
762
|
end
|
763
|
+
|
764
|
+
|
765
|
+
def test_bug_not_parens
|
766
|
+
rb = "not(a)"
|
767
|
+
pt = if ruby18 then
|
768
|
+
s(:not, s(:call, nil, :a))
|
769
|
+
elsif ruby19 then
|
770
|
+
s(:call, s(:call, nil, :a), :"!")
|
771
|
+
else
|
772
|
+
raise "wtf"
|
773
|
+
end
|
774
|
+
|
775
|
+
assert_parse rb, pt
|
776
|
+
end
|
777
|
+
|
778
|
+
def test_pipe_space
|
779
|
+
rb = "a.b do | | end"
|
780
|
+
pt = s(:iter, s(:call, s(:call, nil, :a), :b), 0)
|
781
|
+
|
782
|
+
assert_parse rb, pt
|
783
|
+
end
|
784
|
+
|
785
|
+
def test_cond_unary_minus
|
786
|
+
rb = "if -1; end"
|
787
|
+
pt = s(:if, s(:lit, -1), nil, nil)
|
788
|
+
|
789
|
+
assert_parse rb, pt
|
790
|
+
end
|
791
|
+
|
792
|
+
def test_bug_op_asgn_rescue
|
793
|
+
rb = "a ||= b rescue nil"
|
794
|
+
pt = s(:rescue,
|
795
|
+
s(:op_asgn_or, s(:lvar, :a), s(:lasgn, :a, s(:call, nil, :b))),
|
796
|
+
s(:resbody, s(:array), s(:nil)))
|
797
|
+
|
798
|
+
assert_parse rb, pt
|
799
|
+
end
|
800
|
+
|
801
|
+
def test_magic_encoding_comment
|
802
|
+
rb = <<-EOM.gsub(/^ /, '')
|
803
|
+
# encoding: utf-8
|
804
|
+
class ExampleUTF8ClassNameVarietà
|
805
|
+
def self.è
|
806
|
+
così = :però
|
807
|
+
end
|
808
|
+
end
|
809
|
+
EOM
|
810
|
+
|
811
|
+
# TODO: class vars
|
812
|
+
# TODO: odd-ternary: a ?bb : c
|
813
|
+
# TODO: globals
|
814
|
+
|
815
|
+
pt = s(:class, :"ExampleUTF8ClassNameVariet\303\240", nil,
|
816
|
+
s(:defs, s(:self), :"\303\250", s(:args),
|
817
|
+
s(:lasgn, :"cos\303\254", s(:lit, :"per\303\262"))))
|
818
|
+
|
819
|
+
err = RUBY_VERSION =~ /^1\.8/ ? "Skipping magic encoding comment\n" : ""
|
820
|
+
|
821
|
+
assert_output "", err do
|
822
|
+
assert_parse rb, pt
|
823
|
+
end
|
824
|
+
end
|
748
825
|
end
|
749
826
|
|
750
827
|
class TestRubyParser < MiniTest::Unit::TestCase
|
@@ -1112,6 +1189,13 @@ class TestRuby19Parser < RubyParserTestCase
|
|
1112
1189
|
assert_parse rb, pt
|
1113
1190
|
end
|
1114
1191
|
|
1192
|
+
# def test_pipe_semicolon # HACK
|
1193
|
+
# rb = "a.b do | ; c | end"
|
1194
|
+
# pt = s(:iter, s(:call, s(:call, nil, :a), :b), 0)
|
1195
|
+
#
|
1196
|
+
# assert_parse rb, pt
|
1197
|
+
# end
|
1198
|
+
|
1115
1199
|
# HACK: need to figure out the desired structure and get this working
|
1116
1200
|
# def test_wtf
|
1117
1201
|
# # lambda -> f_larglist lambda_body
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 4039646929
|
5
5
|
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 3
|
8
8
|
- 0
|
9
9
|
- 0
|
10
10
|
- a
|
11
|
-
-
|
12
|
-
version: 3.0.0.
|
11
|
+
- 6
|
12
|
+
version: 3.0.0.a6
|
13
13
|
platform: ruby
|
14
14
|
authors:
|
15
15
|
- Ryan Davis
|
@@ -38,7 +38,7 @@ cert_chain:
|
|
38
38
|
FBHgymkyj/AOSqKRIpXPhjC6
|
39
39
|
-----END CERTIFICATE-----
|
40
40
|
|
41
|
-
date: 2012-08-
|
41
|
+
date: 2012-08-20 00:00:00 Z
|
42
42
|
dependencies:
|
43
43
|
- !ruby/object:Gem::Dependency
|
44
44
|
name: sexp_processor
|
metadata.gz.sig
CHANGED
Binary file
|