ruby_parser 3.0.0.a3 → 3.0.0.a4
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/History.txt +21 -0
- data/Rakefile +10 -1
- data/bin/ruby_parse_extract_error +6 -4
- data/lib/ruby19_parser.rb +16 -9
- data/lib/ruby19_parser.y +19 -9
- data/lib/ruby_lexer.rb +4 -2
- data/lib/ruby_parser_extras.rb +21 -44
- data/test/test_ruby_parser.rb +83 -5
- metadata +7 -7
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/History.txt
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
=== 3.0.0.a4 / 2012-07-26
|
2
|
+
|
3
|
+
* 10 minor enhancements:
|
4
|
+
|
5
|
+
* 'rake debug' defaults to 1.9 parser since that's all I'm doing these days
|
6
|
+
* 1.9: Fixed f { |(a, b, ...), ...| ... } handling.
|
7
|
+
* Added 'rake extract F=path' task to quickly extract errors from large files
|
8
|
+
* Added on_error handler to provide more readable error message.
|
9
|
+
* Aliased #process to #parse.
|
10
|
+
* Renamed #parse to #process (legacy name), added default path of '(string)'
|
11
|
+
* cleaned ruby_parse_extract_error output and fixed to 1.9 parser
|
12
|
+
* ruby_parse_extract_error expands shell globs from ARGV
|
13
|
+
* ruby_parse_extract_error should also capture RuntimeError
|
14
|
+
* yyerror(msg) now warns with the message instead of ignoring it.
|
15
|
+
|
16
|
+
* 3 bug fixes:
|
17
|
+
|
18
|
+
* 1.9: Fixed bug lexing/parsing [ in rhs.
|
19
|
+
* 1.9: Fixed f { |((a, b), c)| ... } handling
|
20
|
+
* 1.9: fixed newline handling during expr_value
|
21
|
+
|
1
22
|
=== 3.0.0.a3 / 2012-07-03
|
2
23
|
|
3
24
|
* 1 major enhancement:
|
data/Rakefile
CHANGED
@@ -139,7 +139,7 @@ task :compare19 do
|
|
139
139
|
end
|
140
140
|
|
141
141
|
task :debug => :isolate do
|
142
|
-
ENV["V"] ||= "
|
142
|
+
ENV["V"] ||= "19"
|
143
143
|
Rake.application[:parser].invoke # this way we can have DEBUG set
|
144
144
|
|
145
145
|
$: << "lib"
|
@@ -171,4 +171,13 @@ task :debug => :isolate do
|
|
171
171
|
end
|
172
172
|
end
|
173
173
|
|
174
|
+
task :extract => :isolate do
|
175
|
+
ENV["V"] ||= "19"
|
176
|
+
Rake.application[:parser].invoke # this way we can have DEBUG set
|
177
|
+
|
178
|
+
file = ENV["F"] || ENV["FILE"]
|
179
|
+
|
180
|
+
ruby "-Ilib", "bin/ruby_parse_extract_error", file
|
181
|
+
end
|
182
|
+
|
174
183
|
# vim: syntax=Ruby
|
@@ -26,7 +26,7 @@ class Racc::Parser
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def retest_for_errors defs
|
29
|
-
|
29
|
+
warn "# retest: #{defs.size}"
|
30
30
|
|
31
31
|
parser = self.class.new
|
32
32
|
|
@@ -37,12 +37,14 @@ end
|
|
37
37
|
ARGV.replace ARGV.map { |path|
|
38
38
|
if File.directory? path then
|
39
39
|
Dir.glob File.join path, "**/*.rb"
|
40
|
+
elsif path =~ /\*\*/ then
|
41
|
+
Dir.glob path
|
40
42
|
else
|
41
43
|
path
|
42
44
|
end
|
43
45
|
}.flatten
|
44
46
|
|
45
|
-
parser =
|
47
|
+
parser = Ruby19Parser.new
|
46
48
|
|
47
49
|
ARGV.each do |file|
|
48
50
|
ruby = file == "-" ? $stdin.read : File.read(file)
|
@@ -51,8 +53,8 @@ ARGV.each do |file|
|
|
51
53
|
$stderr.print "Validating #{file}: "
|
52
54
|
parser.process(ruby, file)
|
53
55
|
$stderr.puts "good"
|
54
|
-
rescue Racc::ParseError => e
|
55
|
-
$stderr.puts "error: #{e.
|
56
|
+
rescue RuntimeError, Racc::ParseError => e
|
57
|
+
$stderr.puts "error: #{e.message.strip}"
|
56
58
|
$stderr.puts
|
57
59
|
|
58
60
|
defs = parser.extract_defs
|
data/lib/ruby19_parser.rb
CHANGED
@@ -4858,31 +4858,31 @@ def _reduce_353(val, _values, result)
|
|
4858
4858
|
end
|
4859
4859
|
|
4860
4860
|
def _reduce_354(val, _values, result)
|
4861
|
-
|
4861
|
+
result = assignable val[0]
|
4862
4862
|
|
4863
4863
|
result
|
4864
4864
|
end
|
4865
4865
|
|
4866
4866
|
def _reduce_355(val, _values, result)
|
4867
|
-
|
4867
|
+
result = val[1]
|
4868
4868
|
|
4869
4869
|
result
|
4870
4870
|
end
|
4871
4871
|
|
4872
4872
|
def _reduce_356(val, _values, result)
|
4873
|
-
|
4873
|
+
result = s(:array, val[0])
|
4874
4874
|
|
4875
4875
|
result
|
4876
4876
|
end
|
4877
4877
|
|
4878
4878
|
def _reduce_357(val, _values, result)
|
4879
|
-
|
4879
|
+
result = list_append val[0], val[2]
|
4880
4880
|
|
4881
4881
|
result
|
4882
4882
|
end
|
4883
4883
|
|
4884
4884
|
def _reduce_358(val, _values, result)
|
4885
|
-
|
4885
|
+
result = block_var val[0], nil, nil
|
4886
4886
|
|
4887
4887
|
result
|
4888
4888
|
end
|
@@ -5840,7 +5840,7 @@ def _reduce_523(val, _values, result)
|
|
5840
5840
|
identifier = val[0].to_sym
|
5841
5841
|
self.env[identifier] = :lvar
|
5842
5842
|
|
5843
|
-
result =
|
5843
|
+
result = identifier
|
5844
5844
|
|
5845
5845
|
result
|
5846
5846
|
end
|
@@ -5848,14 +5848,21 @@ end
|
|
5848
5848
|
# reduce 524 omitted
|
5849
5849
|
|
5850
5850
|
def _reduce_525(val, _values, result)
|
5851
|
-
|
5851
|
+
result = val[1]
|
5852
5852
|
|
5853
5853
|
result
|
5854
5854
|
end
|
5855
5855
|
|
5856
5856
|
def _reduce_526(val, _values, result)
|
5857
|
-
|
5858
|
-
|
5857
|
+
case val[0]
|
5858
|
+
when Symbol then
|
5859
|
+
result = s(:args)
|
5860
|
+
result << val[0].to_sym
|
5861
|
+
when Sexp then
|
5862
|
+
result = val[0]
|
5863
|
+
else
|
5864
|
+
raise "Unknown f_arg type: #{val.inspect}"
|
5865
|
+
end
|
5859
5866
|
|
5860
5867
|
result
|
5861
5868
|
end
|
data/lib/ruby19_parser.y
CHANGED
@@ -1191,25 +1191,25 @@ rule
|
|
1191
1191
|
|
1192
1192
|
f_marg: f_norm_arg
|
1193
1193
|
{
|
1194
|
-
|
1194
|
+
result = assignable val[0]
|
1195
1195
|
}
|
1196
1196
|
| tLPAREN f_margs rparen
|
1197
1197
|
{
|
1198
|
-
|
1198
|
+
result = val[1]
|
1199
1199
|
}
|
1200
1200
|
|
1201
1201
|
f_marg_list: f_marg
|
1202
1202
|
{
|
1203
|
-
|
1203
|
+
result = s(:array, val[0])
|
1204
1204
|
}
|
1205
1205
|
| f_marg_list tCOMMA f_marg
|
1206
1206
|
{
|
1207
|
-
|
1207
|
+
result = list_append val[0], val[2]
|
1208
1208
|
}
|
1209
1209
|
|
1210
1210
|
f_margs: f_marg_list
|
1211
1211
|
{
|
1212
|
-
|
1212
|
+
result = block_var val[0], nil, nil
|
1213
1213
|
}
|
1214
1214
|
| f_marg_list tCOMMA tSTAR f_norm_arg
|
1215
1215
|
{
|
@@ -1883,19 +1883,29 @@ keyword_variable: kNIL { result = s(:nil) }
|
|
1883
1883
|
identifier = val[0].to_sym
|
1884
1884
|
self.env[identifier] = :lvar
|
1885
1885
|
|
1886
|
-
result =
|
1886
|
+
result = identifier
|
1887
1887
|
}
|
1888
1888
|
|
1889
1889
|
f_arg_item: f_norm_arg
|
1890
|
+
# { # TODO
|
1891
|
+
# result = assignable val[0]
|
1892
|
+
# }
|
1890
1893
|
| tLPAREN f_margs rparen
|
1891
1894
|
{
|
1892
|
-
|
1895
|
+
result = val[1]
|
1893
1896
|
}
|
1894
1897
|
|
1895
1898
|
f_arg: f_arg_item
|
1896
1899
|
{
|
1897
|
-
|
1898
|
-
|
1900
|
+
case val[0]
|
1901
|
+
when Symbol then
|
1902
|
+
result = s(:args)
|
1903
|
+
result << val[0].to_sym
|
1904
|
+
when Sexp then
|
1905
|
+
result = val[0]
|
1906
|
+
else
|
1907
|
+
raise "Unknown f_arg type: #{val.inspect}"
|
1908
|
+
end
|
1899
1909
|
}
|
1900
1910
|
| f_arg tCOMMA f_arg_item
|
1901
1911
|
{
|
data/lib/ruby_lexer.rb
CHANGED
@@ -666,6 +666,8 @@ class RubyLexer
|
|
666
666
|
self.lineno = nil
|
667
667
|
c = src.matched
|
668
668
|
if c == '#' then
|
669
|
+
# TODO: add magic comment handling?
|
670
|
+
|
669
671
|
src.pos -= 1
|
670
672
|
|
671
673
|
while src.scan(/\s*#.*(\n+|\z)/) do
|
@@ -681,7 +683,7 @@ class RubyLexer
|
|
681
683
|
src.scan(/\n+/)
|
682
684
|
|
683
685
|
if [:expr_beg, :expr_fname,
|
684
|
-
:expr_dot, :expr_class].include? lex_state then
|
686
|
+
:expr_dot, :expr_class, :expr_value].include? lex_state then
|
685
687
|
next
|
686
688
|
end
|
687
689
|
|
@@ -807,7 +809,7 @@ class RubyLexer
|
|
807
809
|
else
|
808
810
|
rb_compile_error "unexpected '['"
|
809
811
|
end
|
810
|
-
elsif
|
812
|
+
elsif is_beg? then
|
811
813
|
self.tern.push false
|
812
814
|
result = :tLBRACK
|
813
815
|
elsif lex_state.is_argument && space_seen then
|
data/lib/ruby_parser_extras.rb
CHANGED
@@ -75,48 +75,10 @@ class RPStringScanner < StringScanner
|
|
75
75
|
s
|
76
76
|
end
|
77
77
|
end
|
78
|
-
|
79
|
-
# TODO:
|
80
|
-
# def last_line(src)
|
81
|
-
# if n = src.rindex("\n")
|
82
|
-
# src[(n+1) .. -1]
|
83
|
-
# else
|
84
|
-
# src
|
85
|
-
# end
|
86
|
-
# end
|
87
|
-
# private :last_line
|
88
|
-
|
89
|
-
# def next_words_on_error
|
90
|
-
# if n = @src.rest.index("\n")
|
91
|
-
# @src.rest[0 .. (n-1)]
|
92
|
-
# else
|
93
|
-
# @src.rest
|
94
|
-
# end
|
95
|
-
# end
|
96
|
-
|
97
|
-
# def prev_words_on_error(ev)
|
98
|
-
# pre = @pre
|
99
|
-
# if ev and /#{Regexp.quote(ev)}$/ =~ pre
|
100
|
-
# pre = $`
|
101
|
-
# end
|
102
|
-
# last_line(pre)
|
103
|
-
# end
|
104
|
-
|
105
|
-
# def on_error(et, ev, values)
|
106
|
-
# lines_of_rest = @src.rest.to_a.length
|
107
|
-
# prev_words = prev_words_on_error(ev)
|
108
|
-
# at = 4 + prev_words.length
|
109
|
-
# message = <<-MSG
|
110
|
-
# RD syntax error: line #{@blockp.line_index - lines_of_rest}:
|
111
|
-
# ...#{prev_words} #{(ev||'')} #{next_words_on_error()} ...
|
112
|
-
# MSG
|
113
|
-
# message << " " * at + "^" * (ev ? ev.length : 0) + "\n"
|
114
|
-
# raise ParseError, message
|
115
|
-
# end
|
116
78
|
end
|
117
79
|
|
118
80
|
module RubyParserStuff
|
119
|
-
VERSION = '3.0.0.
|
81
|
+
VERSION = '3.0.0.a4' unless constants.include? "VERSION" # SIGH
|
120
82
|
|
121
83
|
attr_accessor :lexer, :in_def, :in_single, :file
|
122
84
|
attr_reader :env, :comments
|
@@ -207,6 +169,8 @@ module RubyParserStuff
|
|
207
169
|
raise "wtf? #{val.inspect}" unless lasgn[0] == :lasgn
|
208
170
|
result << lasgn[1]
|
209
171
|
end
|
172
|
+
when :lasgn then
|
173
|
+
result << val
|
210
174
|
else
|
211
175
|
raise "unhandled sexp: #{val.inspect}"
|
212
176
|
end
|
@@ -240,6 +204,8 @@ module RubyParserStuff
|
|
240
204
|
r.concat v[1..-1].map { |s| s(:lasgn, s) }
|
241
205
|
when :block_arg then
|
242
206
|
r << s(:lasgn, :"&#{v.last}")
|
207
|
+
when :masgn then
|
208
|
+
r << v
|
243
209
|
else
|
244
210
|
raise "block_args19 #{id} unhandled sexp type:: #{v.inspect}"
|
245
211
|
end
|
@@ -263,7 +229,7 @@ module RubyParserStuff
|
|
263
229
|
case r.last.first
|
264
230
|
when :splat then
|
265
231
|
r = s(:masgn, r)
|
266
|
-
when :lasgn then
|
232
|
+
when :lasgn, :masgn then
|
267
233
|
r = r.last
|
268
234
|
else
|
269
235
|
raise "oh noes!: #{r.inspect}"
|
@@ -995,8 +961,17 @@ module RubyParserStuff
|
|
995
961
|
end
|
996
962
|
|
997
963
|
def yyerror msg
|
998
|
-
|
964
|
+
warn msg
|
965
|
+
super()
|
966
|
+
end
|
967
|
+
|
968
|
+
def on_error(et, ev, values)
|
999
969
|
super
|
970
|
+
rescue Racc::ParseError => e
|
971
|
+
# I don't like how the exception obscures the error message
|
972
|
+
msg = "# ERROR: %s:%p :: %s" % [self.file, lexer.lineno, e.message.strip]
|
973
|
+
warn msg
|
974
|
+
raise
|
1000
975
|
end
|
1001
976
|
|
1002
977
|
class Keyword
|
@@ -1215,11 +1190,13 @@ class RubyParser
|
|
1215
1190
|
@p19 = Ruby19Parser.new
|
1216
1191
|
end
|
1217
1192
|
|
1218
|
-
def
|
1219
|
-
|
1193
|
+
def process s, f = "(string)"
|
1194
|
+
Ruby19Parser.new.process s, f
|
1220
1195
|
rescue Racc::ParseError
|
1221
|
-
|
1196
|
+
Ruby18Parser.new.process s, f
|
1222
1197
|
end
|
1198
|
+
|
1199
|
+
alias :parse :process
|
1223
1200
|
end
|
1224
1201
|
|
1225
1202
|
############################################################
|
data/test/test_ruby_parser.rb
CHANGED
@@ -33,10 +33,16 @@ class RubyParserTestCase < ParseTreeTestCase
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def assert_parse_error rb, emsg
|
36
|
-
e =
|
37
|
-
|
36
|
+
e = nil
|
37
|
+
out, err = capture_io do
|
38
|
+
e = assert_raises Racc::ParseError do
|
39
|
+
processor.parse rb
|
40
|
+
end
|
38
41
|
end
|
39
42
|
|
43
|
+
assert_equal "", out
|
44
|
+
assert_match(/parse error on value/, err)
|
45
|
+
|
40
46
|
assert_equal emsg, e.message.strip # TODO: why strip?
|
41
47
|
end
|
42
48
|
|
@@ -47,6 +53,11 @@ class RubyParserTestCase < ParseTreeTestCase
|
|
47
53
|
end
|
48
54
|
|
49
55
|
module TestRubyParserShared
|
56
|
+
def setup
|
57
|
+
super
|
58
|
+
# p :test => [self.class, __name__]
|
59
|
+
end
|
60
|
+
|
50
61
|
def test_attrasgn_array_lhs
|
51
62
|
rb = '[1, 2, 3, 4][from .. to] = ["a", "b", "c"]'
|
52
63
|
pt = s(:attrasgn,
|
@@ -613,6 +624,67 @@ module TestRubyParserShared
|
|
613
624
|
assert_equal 3, result.if.return.line
|
614
625
|
assert_equal 3, result.if.return.lit.line
|
615
626
|
end
|
627
|
+
|
628
|
+
def test_bug_and
|
629
|
+
rb = "true and []"
|
630
|
+
pt = s(:and, s(:true), s(:array))
|
631
|
+
|
632
|
+
assert_parse rb, pt
|
633
|
+
|
634
|
+
rb = "true and\ntrue"
|
635
|
+
pt = s(:and, s(:true), s(:true))
|
636
|
+
|
637
|
+
assert_parse rb, pt
|
638
|
+
end
|
639
|
+
|
640
|
+
def test_bug_args
|
641
|
+
rb = "f { |(a, b)| d }"
|
642
|
+
pt = s(:iter, s(:call, nil, :f),
|
643
|
+
s(:masgn, s(:array, s(:lasgn, :a), s(:lasgn, :b))),
|
644
|
+
s(:call, nil, :d))
|
645
|
+
|
646
|
+
assert_parse rb, pt
|
647
|
+
end
|
648
|
+
|
649
|
+
def test_bug_args_masgn
|
650
|
+
rb = "f { |((a, b), c)| }"
|
651
|
+
pt = s(:iter,
|
652
|
+
s(:call, nil, :f),
|
653
|
+
s(:masgn,
|
654
|
+
s(:array,
|
655
|
+
s(:masgn, s(:array, s(:lasgn, :a), s(:lasgn, :b))),
|
656
|
+
s(:lasgn, :c))))
|
657
|
+
|
658
|
+
assert_parse rb, pt
|
659
|
+
end
|
660
|
+
|
661
|
+
# TODO:
|
662
|
+
# def test_bug_args_masgn2
|
663
|
+
# rb = "f { |((a, b), c), d| }"
|
664
|
+
# pt = s(:iter,
|
665
|
+
# s(:call, nil, :f),
|
666
|
+
# s(:masgn,
|
667
|
+
# s(:array,
|
668
|
+
# s(:masgn,
|
669
|
+
# s(:array,
|
670
|
+
# s(:masgn,
|
671
|
+
# s(:array, s(:lasgn, :a), s(:lasgn, :b))),
|
672
|
+
# s(:lasgn, :c))),
|
673
|
+
# s(:lasgn, :d))))
|
674
|
+
#
|
675
|
+
# assert_parse rb, pt
|
676
|
+
# end
|
677
|
+
|
678
|
+
# TODO:
|
679
|
+
# def test_bug_comma
|
680
|
+
# rb = "if test ?d, dir then end"
|
681
|
+
# pt = s(:if,
|
682
|
+
# s(:call, nil, :test, s(:lit, 100), s(:call, nil, :dir)),
|
683
|
+
# nil,
|
684
|
+
# nil)
|
685
|
+
#
|
686
|
+
# assert_parse rb, pt
|
687
|
+
# end
|
616
688
|
end
|
617
689
|
|
618
690
|
class TestRubyParser < MiniTest::Unit::TestCase
|
@@ -623,7 +695,12 @@ class TestRubyParser < MiniTest::Unit::TestCase
|
|
623
695
|
rb = "while false : 42 end"
|
624
696
|
pt = s(:while, s(:false), s(:lit, 42), true)
|
625
697
|
|
626
|
-
|
698
|
+
out, err = capture_io do
|
699
|
+
assert_equal pt, processor.parse(rb)
|
700
|
+
end
|
701
|
+
|
702
|
+
assert_empty out
|
703
|
+
assert_match(/parse error on value .:/, err)
|
627
704
|
|
628
705
|
# 1.9 only syntax
|
629
706
|
rb = "a.()"
|
@@ -633,7 +710,9 @@ class TestRubyParser < MiniTest::Unit::TestCase
|
|
633
710
|
|
634
711
|
# bad syntax
|
635
712
|
e = assert_raises Racc::ParseError do
|
636
|
-
|
713
|
+
capture_io do
|
714
|
+
processor.parse "a.("
|
715
|
+
end
|
637
716
|
end
|
638
717
|
|
639
718
|
msg = "parse error on value \"(\" (tLPAREN2)"
|
@@ -977,4 +1056,3 @@ class TestRuby19Parser < RubyParserTestCase
|
|
977
1056
|
# assert_parse rb, pt
|
978
1057
|
# end
|
979
1058
|
end
|
980
|
-
|
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: 1314497749
|
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
|
+
- 4
|
12
|
+
version: 3.0.0.a4
|
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-07-
|
41
|
+
date: 2012-07-26 00:00:00 Z
|
42
42
|
dependencies:
|
43
43
|
- !ruby/object:Gem::Dependency
|
44
44
|
name: sexp_processor
|
@@ -63,11 +63,11 @@ dependencies:
|
|
63
63
|
requirements:
|
64
64
|
- - ~>
|
65
65
|
- !ruby/object:Gem::Version
|
66
|
-
hash:
|
66
|
+
hash: 3
|
67
67
|
segments:
|
68
68
|
- 3
|
69
|
-
-
|
70
|
-
version: "3.
|
69
|
+
- 2
|
70
|
+
version: "3.2"
|
71
71
|
type: :development
|
72
72
|
version_requirements: *id002
|
73
73
|
- !ruby/object:Gem::Dependency
|
metadata.gz.sig
CHANGED
Binary file
|