| 1 | |
|---|
| 2 | str = <<EOT |
|---|
| 3 | class PrintProxy |
|---|
| 4 | # instance_methods.each { |
|---|
| 5 | # |m| undef_method m unless m =~ /(^__|^send$|^object_id$)/ |
|---|
| 6 | # } |
|---|
| 7 | |
|---|
| 8 | def initialize(obj, &block) |
|---|
| 9 | @obj = obj |
|---|
| 10 | end |
|---|
| 11 | |
|---|
| 12 | protected |
|---|
| 13 | |
|---|
| 14 | def method_missing(symbol, *args, &block) |
|---|
| 15 | print "foo" |
|---|
| 16 | if @block then print "foo\n" else print "\n" end |
|---|
| 17 | |
|---|
| 18 | @obj.send(symbol, *args, &block) |
|---|
| 19 | end |
|---|
| 20 | end |
|---|
| 21 | EOT |
|---|
| 22 | |
|---|
| 23 | class StringScanner |
|---|
| 24 | attr_reader :string, :pos |
|---|
| 25 | |
|---|
| 26 | def initialize(string, dup = false) |
|---|
| 27 | @string = string |
|---|
| 28 | @pos = 0 |
|---|
| 29 | end |
|---|
| 30 | |
|---|
| 31 | def eos? |
|---|
| 32 | self.pos >= self.string.size |
|---|
| 33 | end |
|---|
| 34 | |
|---|
| 35 | def rest |
|---|
| 36 | string[pos..-1] |
|---|
| 37 | end |
|---|
| 38 | |
|---|
| 39 | def skip_until(pattern) |
|---|
| 40 | _scan(pattern, true, false, false) |
|---|
| 41 | end |
|---|
| 42 | |
|---|
| 43 | def pos=(n) |
|---|
| 44 | n = (n + string.size) if (n < 0) |
|---|
| 45 | raise RangeError, "index out of range" if (n < 0 || (string && n > string.size)) |
|---|
| 46 | @pos = n |
|---|
| 47 | end |
|---|
| 48 | |
|---|
| 49 | def matched? |
|---|
| 50 | !@match.nil? |
|---|
| 51 | end |
|---|
| 52 | |
|---|
| 53 | def matched |
|---|
| 54 | @match.to_s if matched? |
|---|
| 55 | end |
|---|
| 56 | |
|---|
| 57 | def matched_size |
|---|
| 58 | @match.to_s.size if matched? |
|---|
| 59 | end |
|---|
| 60 | |
|---|
| 61 | def _scan(pattern, succptr, getstr, headonly) |
|---|
| 62 | raise TypeError, "bad pattern argument: #{pattern.inspect}" unless |
|---|
| 63 | String === pattern or Regexp === pattern or pattern.respond_to? :to_str |
|---|
| 64 | |
|---|
| 65 | @match = nil |
|---|
| 66 | rest = self.rest |
|---|
| 67 | |
|---|
| 68 | return nil if rest.size < 0 |
|---|
| 69 | |
|---|
| 70 | if headonly |
|---|
| 71 | headonly_pattern = Regexp.new('^' + pattern.source, pattern.options) |
|---|
| 72 | @match = headonly_pattern.match rest |
|---|
| 73 | else |
|---|
| 74 | @match = pattern.match rest |
|---|
| 75 | end |
|---|
| 76 | |
|---|
| 77 | return nil unless @match |
|---|
| 78 | |
|---|
| 79 | m = rest[0, @match.end(0)] |
|---|
| 80 | |
|---|
| 81 | if succptr |
|---|
| 82 | @prev_pos = pos |
|---|
| 83 | self.pos += m.size |
|---|
| 84 | end |
|---|
| 85 | |
|---|
| 86 | getstr ? m : m.size |
|---|
| 87 | end |
|---|
| 88 | end |
|---|
| 89 | |
|---|
| 90 | match = [] |
|---|
| 91 | ss = StringScanner.new(str) |
|---|
| 92 | |
|---|
| 93 | while ss.skip_until(/(class(?![^ \n])|def(?![^ \n]))/) |
|---|
| 94 | a = ss.pos - ss.matched_size |
|---|
| 95 | b = ss.matched_size |
|---|
| 96 | |
|---|
| 97 | warn "[#{a}, #{b}] = \"#{ss.matched}\"" |
|---|
| 98 | x = [a, b, ss.matched] |
|---|
| 99 | match << x |
|---|
| 100 | end |
|---|
| 101 | |
|---|