1module REXML
2  class ParseException < RuntimeError
3    attr_accessor :source, :parser, :continued_exception
4
5    def initialize( message, source=nil, parser=nil, exception=nil )
6      super(message)
7      @source = source
8      @parser = parser
9      @continued_exception = exception
10    end
11
12    def to_s
13      # Quote the original exception, if there was one
14      if @continued_exception
15        err = @continued_exception.inspect
16        err << "\n"
17        err << @continued_exception.backtrace.join("\n")
18        err << "\n...\n"
19      else
20        err = ""
21      end
22
23      # Get the stack trace and error message
24      err << super
25
26      # Add contextual information
27      if @source
28        err << "\nLine: #{line}\n"
29        err << "Position: #{position}\n"
30        err << "Last 80 unconsumed characters:\n"
31        err << @source.buffer[0..80].force_encoding("ASCII-8BIT").gsub(/\n/, ' ')
32      end
33
34      err
35    end
36
37    def position
38      @source.current_line[0] if @source and defined? @source.current_line and
39      @source.current_line
40    end
41
42    def line
43      @source.current_line[2] if @source and defined? @source.current_line and
44      @source.current_line
45    end
46
47    def context
48      @source.current_line
49    end
50  end
51end
52