ruby_parser
Advanced tools
+21
-0
@@ -0,1 +1,22 @@ | ||
| === 3.0.0.a4 / 2012-07-26 | ||
| * 10 minor enhancements: | ||
| * 'rake debug' defaults to 1.9 parser since that's all I'm doing these days | ||
| * 1.9: Fixed f { |(a, b, ...), ...| ... } handling. | ||
| * Added 'rake extract F=path' task to quickly extract errors from large files | ||
| * Added on_error handler to provide more readable error message. | ||
| * Aliased #process to #parse. | ||
| * Renamed #parse to #process (legacy name), added default path of '(string)' | ||
| * cleaned ruby_parse_extract_error output and fixed to 1.9 parser | ||
| * ruby_parse_extract_error expands shell globs from ARGV | ||
| * ruby_parse_extract_error should also capture RuntimeError | ||
| * yyerror(msg) now warns with the message instead of ignoring it. | ||
| * 3 bug fixes: | ||
| * 1.9: Fixed bug lexing/parsing [ in rhs. | ||
| * 1.9: Fixed f { |((a, b), c)| ... } handling | ||
| * 1.9: fixed newline handling during expr_value | ||
| === 3.0.0.a3 / 2012-07-03 | ||
@@ -2,0 +23,0 @@ |
@@ -669,2 +669,4 @@ class RubyLexer | ||
| if c == '#' then | ||
| # TODO: add magic comment handling? | ||
| src.pos -= 1 | ||
@@ -685,3 +687,3 @@ | ||
| if [:expr_beg, :expr_fname, | ||
| :expr_dot, :expr_class].include? lex_state then | ||
| :expr_dot, :expr_class, :expr_value].include? lex_state then | ||
| next | ||
@@ -812,3 +814,3 @@ end | ||
| end | ||
| elsif lex_state == :expr_beg || lex_state == :expr_mid then | ||
| elsif is_beg? then | ||
| self.tern.push false | ||
@@ -815,0 +817,0 @@ result = :tLBRACK |
@@ -78,44 +78,6 @@ require 'stringio' | ||
| end | ||
| # TODO: | ||
| # def last_line(src) | ||
| # if n = src.rindex("\n") | ||
| # src[(n+1) .. -1] | ||
| # else | ||
| # src | ||
| # end | ||
| # end | ||
| # private :last_line | ||
| # def next_words_on_error | ||
| # if n = @src.rest.index("\n") | ||
| # @src.rest[0 .. (n-1)] | ||
| # else | ||
| # @src.rest | ||
| # end | ||
| # end | ||
| # def prev_words_on_error(ev) | ||
| # pre = @pre | ||
| # if ev and /#{Regexp.quote(ev)}$/ =~ pre | ||
| # pre = $` | ||
| # end | ||
| # last_line(pre) | ||
| # end | ||
| # def on_error(et, ev, values) | ||
| # lines_of_rest = @src.rest.to_a.length | ||
| # prev_words = prev_words_on_error(ev) | ||
| # at = 4 + prev_words.length | ||
| # message = <<-MSG | ||
| # RD syntax error: line #{@blockp.line_index - lines_of_rest}: | ||
| # ...#{prev_words} #{(ev||'')} #{next_words_on_error()} ... | ||
| # MSG | ||
| # message << " " * at + "^" * (ev ? ev.length : 0) + "\n" | ||
| # raise ParseError, message | ||
| # end | ||
| end | ||
| module RubyParserStuff | ||
| VERSION = '3.0.0.a3' unless constants.include? "VERSION" # SIGH | ||
| VERSION = '3.0.0.a4' unless constants.include? "VERSION" # SIGH | ||
@@ -211,2 +173,4 @@ attr_accessor :lexer, :in_def, :in_single, :file | ||
| end | ||
| when :lasgn then | ||
| result << val | ||
| else | ||
@@ -245,2 +209,4 @@ raise "unhandled sexp: #{val.inspect}" | ||
| r << s(:lasgn, :"&#{v.last}") | ||
| when :masgn then | ||
| r << v | ||
| else | ||
@@ -269,3 +235,3 @@ raise "block_args19 #{id} unhandled sexp type:: #{v.inspect}" | ||
| r = s(:masgn, r) | ||
| when :lasgn then | ||
| when :lasgn, :masgn then | ||
| r = r.last | ||
@@ -1002,4 +968,13 @@ else | ||
| def yyerror msg | ||
| # for now do nothing with the msg | ||
| warn msg | ||
| super() | ||
| end | ||
| def on_error(et, ev, values) | ||
| super | ||
| rescue Racc::ParseError => e | ||
| # I don't like how the exception obscures the error message | ||
| msg = "# ERROR: %s:%p :: %s" % [self.file, lexer.lineno, e.message.strip] | ||
| warn msg | ||
| raise | ||
| end | ||
@@ -1223,7 +1198,9 @@ | ||
| def parse s | ||
| @p19.parse s | ||
| def process s, f = "(string)" | ||
| Ruby19Parser.new.process s, f | ||
| rescue Racc::ParseError | ||
| @p18.parse s | ||
| Ruby18Parser.new.process s, f | ||
| end | ||
| alias :parse :process | ||
| end | ||
@@ -1230,0 +1207,0 @@ |
+10
-1
@@ -142,3 +142,3 @@ # -*- ruby -*- | ||
| task :debug => :isolate do | ||
| ENV["V"] ||= "18" | ||
| ENV["V"] ||= "19" | ||
| Rake.application[:parser].invoke # this way we can have DEBUG set | ||
@@ -175,2 +175,11 @@ | ||
| task :extract => :isolate do | ||
| ENV["V"] ||= "19" | ||
| Rake.application[:parser].invoke # this way we can have DEBUG set | ||
| file = ENV["F"] || ENV["FILE"] | ||
| ruby "-Ilib", "bin/ruby_parse_extract_error", file | ||
| end | ||
| # vim: syntax=Ruby |
@@ -36,6 +36,12 @@ #!/usr/local/bin/ruby | ||
| def assert_parse_error rb, emsg | ||
| e = assert_raises Racc::ParseError do | ||
| processor.parse rb | ||
| e = nil | ||
| out, err = capture_io do | ||
| e = assert_raises Racc::ParseError do | ||
| processor.parse rb | ||
| end | ||
| end | ||
| assert_equal "", out | ||
| assert_match(/parse error on value/, err) | ||
| assert_equal emsg, e.message.strip # TODO: why strip? | ||
@@ -51,2 +57,7 @@ end | ||
| module TestRubyParserShared | ||
| def setup | ||
| super | ||
| # p :test => [self.class, __name__] | ||
| end | ||
| def test_attrasgn_array_lhs | ||
@@ -618,2 +629,63 @@ rb = '[1, 2, 3, 4][from .. to] = ["a", "b", "c"]' | ||
| end | ||
| def test_bug_and | ||
| rb = "true and []" | ||
| pt = s(:and, s(:true), s(:array)) | ||
| assert_parse rb, pt | ||
| rb = "true and\ntrue" | ||
| pt = s(:and, s(:true), s(:true)) | ||
| assert_parse rb, pt | ||
| end | ||
| def test_bug_args | ||
| rb = "f { |(a, b)| d }" | ||
| pt = s(:iter, s(:call, nil, :f), | ||
| s(:masgn, s(:array, s(:lasgn, :a), s(:lasgn, :b))), | ||
| s(:call, nil, :d)) | ||
| assert_parse rb, pt | ||
| end | ||
| def test_bug_args_masgn | ||
| rb = "f { |((a, b), c)| }" | ||
| pt = s(:iter, | ||
| s(:call, nil, :f), | ||
| s(:masgn, | ||
| s(:array, | ||
| s(:masgn, s(:array, s(:lasgn, :a), s(:lasgn, :b))), | ||
| s(:lasgn, :c)))) | ||
| assert_parse rb, pt | ||
| end | ||
| # TODO: | ||
| # def test_bug_args_masgn2 | ||
| # rb = "f { |((a, b), c), d| }" | ||
| # pt = s(:iter, | ||
| # s(:call, nil, :f), | ||
| # s(:masgn, | ||
| # s(:array, | ||
| # s(:masgn, | ||
| # s(:array, | ||
| # s(:masgn, | ||
| # s(:array, s(:lasgn, :a), s(:lasgn, :b))), | ||
| # s(:lasgn, :c))), | ||
| # s(:lasgn, :d)))) | ||
| # | ||
| # assert_parse rb, pt | ||
| # end | ||
| # TODO: | ||
| # def test_bug_comma | ||
| # rb = "if test ?d, dir then end" | ||
| # pt = s(:if, | ||
| # s(:call, nil, :test, s(:lit, 100), s(:call, nil, :dir)), | ||
| # nil, | ||
| # nil) | ||
| # | ||
| # assert_parse rb, pt | ||
| # end | ||
| end | ||
@@ -629,4 +701,9 @@ | ||
| assert_equal pt, processor.parse(rb) | ||
| out, err = capture_io do | ||
| assert_equal pt, processor.parse(rb) | ||
| end | ||
| assert_empty out | ||
| assert_match(/parse error on value .:/, err) | ||
| # 1.9 only syntax | ||
@@ -640,3 +717,5 @@ rb = "a.()" | ||
| e = assert_raises Racc::ParseError do | ||
| processor.parse "a.(" | ||
| capture_io do | ||
| processor.parse "a.(" | ||
| end | ||
| end | ||
@@ -985,2 +1064,1 @@ | ||
| end | ||
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet