137 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Ruby
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			137 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Ruby
		
	
	
		
			Executable File
		
	
	
#!/usr/bin/ruby
 | 
						|
# encoding: utf-8
 | 
						|
 | 
						|
module ANTLR3
 | 
						|
 | 
						|
=begin rdoc ANTLR3::Main::InteractiveStringStream
 | 
						|
 | 
						|
A special stream used in the <b>interactive mode</b> of the Main scripts. It
 | 
						|
uses Readline (if available) or standard IO#gets to fetch data on demand.
 | 
						|
 | 
						|
=end
 | 
						|
 | 
						|
class InteractiveStringStream < StringStream
 | 
						|
  
 | 
						|
  if RUBY_VERSION =~ /^1\.9/
 | 
						|
    
 | 
						|
    # creates a new StringStream object where +data+ is the string data to stream.
 | 
						|
    # accepts the following options in a symbol-to-value hash:
 | 
						|
    #
 | 
						|
    # [:file or :name] the (file) name to associate with the stream; default: <tt>'(string)'</tt>
 | 
						|
    # [:line] the initial line number; default: +1+
 | 
						|
    # [:column] the initial column number; default: +0+
 | 
						|
    # 
 | 
						|
    def initialize( options = {}, &block )      # for 1.9
 | 
						|
      @string = ''
 | 
						|
      @data   = []
 | 
						|
      @position = options.fetch :position, 0
 | 
						|
      @line     = options.fetch :line, 1
 | 
						|
      @column   = options.fetch :column, 0
 | 
						|
      @markers  = []
 | 
						|
      mark
 | 
						|
      @initialized = @eof = false
 | 
						|
      @readline = block or raise( ArgumentError, "no line-reading block was provided" )
 | 
						|
      @name ||= options[ :file ] || options[ :name ] || '(interactive)'
 | 
						|
    end
 | 
						|
    
 | 
						|
    def readline
 | 
						|
      @initialized = true
 | 
						|
      unless @eof
 | 
						|
        if line = @readline.call
 | 
						|
          line = line.to_s.encode( Encoding::UTF_8 )
 | 
						|
          @string << line
 | 
						|
          @data.concat( line.codepoints.to_a )
 | 
						|
          return true
 | 
						|
        else
 | 
						|
          @eof = true
 | 
						|
          return false
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
    
 | 
						|
  else
 | 
						|
    
 | 
						|
    # creates a new StringStream object where +data+ is the string data to stream.
 | 
						|
    # accepts the following options in a symbol-to-value hash:
 | 
						|
    #
 | 
						|
    # [:file or :name] the (file) name to associate with the stream; default: <tt>'(string)'</tt>
 | 
						|
    # [:line] the initial line number; default: +1+
 | 
						|
    # [:column] the initial column number; default: +0+
 | 
						|
    # 
 | 
						|
    def initialize( options = {}, &block )
 | 
						|
      @string = @data = ''
 | 
						|
      @position = options.fetch :position, 0
 | 
						|
      @line     = options.fetch :line, 1
 | 
						|
      @column   = options.fetch :column, 0
 | 
						|
      @markers = []
 | 
						|
      mark
 | 
						|
      @initialized = @eof = false
 | 
						|
      @readline = block or raise( ArgumentError, "no line-reading block was provided" )
 | 
						|
      @name ||= options[ :file ] || options[ :name ] || '(interactive)'
 | 
						|
    end
 | 
						|
    
 | 
						|
    def readline
 | 
						|
      @initialized = true
 | 
						|
      unless @eof
 | 
						|
        if line = @readline.call
 | 
						|
          @data << line.to_s
 | 
						|
          return true
 | 
						|
        else
 | 
						|
          @eof = true
 | 
						|
          return false
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
    
 | 
						|
  end
 | 
						|
  
 | 
						|
  private :readline
 | 
						|
  
 | 
						|
  def consume
 | 
						|
    @position < @data.size and return( super )
 | 
						|
    unless @eof
 | 
						|
      readline
 | 
						|
      consume
 | 
						|
    end
 | 
						|
  end
 | 
						|
  
 | 
						|
  def peek( i = 1 )
 | 
						|
    i.zero? and return 0
 | 
						|
    i += 1 if i < 0
 | 
						|
    index = @position + i - 1
 | 
						|
    index < 0 and return 0
 | 
						|
    
 | 
						|
    if index < @data.size
 | 
						|
      char = @data[ index ]
 | 
						|
    elsif readline
 | 
						|
      peek( i )
 | 
						|
    else EOF
 | 
						|
    end
 | 
						|
  end
 | 
						|
  
 | 
						|
  def look( i = 1 )
 | 
						|
    peek( i ).chr rescue EOF
 | 
						|
  end
 | 
						|
  
 | 
						|
  def substring( start, stop )
 | 
						|
    fill_through( stop )
 | 
						|
    @string[ start .. stop ]
 | 
						|
  end
 | 
						|
  
 | 
						|
private
 | 
						|
  
 | 
						|
  def fill_through( position )
 | 
						|
    @eof and return
 | 
						|
    if @position < 0 then fill_out
 | 
						|
    else readline until ( @data.size > @position or @eof )
 | 
						|
    end
 | 
						|
  end
 | 
						|
  
 | 
						|
  def fill_out
 | 
						|
    @eof and return
 | 
						|
    readline until @eof
 | 
						|
  end
 | 
						|
end
 | 
						|
 | 
						|
end
 |