1324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver#!/usr/bin/ruby
2324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver# encoding: utf-8
3324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
4324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruvermodule ANTLR3
5324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
6324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=begin rdoc ANTLR3::Main::InteractiveStringStream
7324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
8324c4644fee44b9898524c09511bd33c3f12e2dfBen GruverA special stream used in the <b>interactive mode</b> of the Main scripts. It
9324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruveruses Readline (if available) or standard IO#gets to fetch data on demand.
10324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
11324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver=end
12324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
13324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverclass InteractiveStringStream < StringStream
14324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
15324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  if RUBY_VERSION =~ /^1\.9/
16324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
17324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    # creates a new StringStream object where +data+ is the string data to stream.
18324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    # accepts the following options in a symbol-to-value hash:
19324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    #
20324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    # [:file or :name] the (file) name to associate with the stream; default: <tt>'(string)'</tt>
21324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    # [:line] the initial line number; default: +1+
22324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    # [:column] the initial column number; default: +0+
23324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    # 
24324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def initialize( options = {}, &block )      # for 1.9
25324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @string = ''
26324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @data   = []
27324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @position = options.fetch :position, 0
28324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @line     = options.fetch :line, 1
29324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @column   = options.fetch :column, 0
30324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @markers  = []
31324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      mark
32324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @initialized = @eof = false
33324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @readline = block or raise( ArgumentError, "no line-reading block was provided" )
34324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @name ||= options[ :file ] || options[ :name ] || '(interactive)'
35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def readline
38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @initialized = true
39324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      unless @eof
40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if line = @readline.call
41324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          line = line.to_s.encode( Encoding::UTF_8 )
42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          @string << line
43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          @data.concat( line.codepoints.to_a )
44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          return true
45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        else
46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          @eof = true
47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          return false
48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        end
49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
50324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
51324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
52324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  else
53324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
54324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    # creates a new StringStream object where +data+ is the string data to stream.
55324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    # accepts the following options in a symbol-to-value hash:
56324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    #
57324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    # [:file or :name] the (file) name to associate with the stream; default: <tt>'(string)'</tt>
58324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    # [:line] the initial line number; default: +1+
59324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    # [:column] the initial column number; default: +0+
60324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    # 
61324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def initialize( options = {}, &block )
62324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @string = @data = ''
63324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @position = options.fetch :position, 0
64324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @line     = options.fetch :line, 1
65324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @column   = options.fetch :column, 0
66324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @markers = []
67324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      mark
68324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @initialized = @eof = false
69324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @readline = block or raise( ArgumentError, "no line-reading block was provided" )
70324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @name ||= options[ :file ] || options[ :name ] || '(interactive)'
71324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
72324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
73324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    def readline
74324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      @initialized = true
75324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      unless @eof
76324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if line = @readline.call
77324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          @data << line.to_s
78324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          return true
79324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        else
80324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          @eof = true
81324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver          return false
82324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        end
83324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      end
84324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
85324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
86324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
87324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
88324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  private :readline
89324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
90324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def consume
91324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @position < @data.size and return( super )
92324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    unless @eof
93324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      readline
94324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      consume
95324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
96324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
97324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
98324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def peek( i = 1 )
99324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    i.zero? and return 0
100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    i += 1 if i < 0
101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    index = @position + i - 1
102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    index < 0 and return 0
103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    
104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if index < @data.size
105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      char = @data[ index ]
106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    elsif readline
107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver      peek( i )
108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    else EOF
109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def look( i = 1 )
113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    peek( i ).chr rescue EOF
114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def substring( start, stop )
117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    fill_through( stop )
118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @string[ start .. stop ]
119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverprivate
122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def fill_through( position )
124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @eof and return
125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    if @position < 0 then fill_out
126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    else readline until ( @data.size > @position or @eof )
127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    end
128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  
130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  def fill_out
131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @eof and return
132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    readline until @eof
133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver  end
134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend
135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverend
137