1#!/usr/bin/ruby 2# encoding: utf-8 3 4module ANTLR3 5 6=begin rdoc ANTLR3::Main::InteractiveStringStream 7 8A special stream used in the <b>interactive mode</b> of the Main scripts. It 9uses Readline (if available) or standard IO#gets to fetch data on demand. 10 11=end 12 13class InteractiveStringStream < StringStream 14 15 if RUBY_VERSION =~ /^1\.9/ 16 17 # creates a new StringStream object where +data+ is the string data to stream. 18 # accepts the following options in a symbol-to-value hash: 19 # 20 # [:file or :name] the (file) name to associate with the stream; default: <tt>'(string)'</tt> 21 # [:line] the initial line number; default: +1+ 22 # [:column] the initial column number; default: +0+ 23 # 24 def initialize( options = {}, &block ) # for 1.9 25 @string = '' 26 @data = [] 27 @position = options.fetch :position, 0 28 @line = options.fetch :line, 1 29 @column = options.fetch :column, 0 30 @markers = [] 31 mark 32 @initialized = @eof = false 33 @readline = block or raise( ArgumentError, "no line-reading block was provided" ) 34 @name ||= options[ :file ] || options[ :name ] || '(interactive)' 35 end 36 37 def readline 38 @initialized = true 39 unless @eof 40 if line = @readline.call 41 line = line.to_s.encode( Encoding::UTF_8 ) 42 @string << line 43 @data.concat( line.codepoints.to_a ) 44 return true 45 else 46 @eof = true 47 return false 48 end 49 end 50 end 51 52 else 53 54 # creates a new StringStream object where +data+ is the string data to stream. 55 # accepts the following options in a symbol-to-value hash: 56 # 57 # [:file or :name] the (file) name to associate with the stream; default: <tt>'(string)'</tt> 58 # [:line] the initial line number; default: +1+ 59 # [:column] the initial column number; default: +0+ 60 # 61 def initialize( options = {}, &block ) 62 @string = @data = '' 63 @position = options.fetch :position, 0 64 @line = options.fetch :line, 1 65 @column = options.fetch :column, 0 66 @markers = [] 67 mark 68 @initialized = @eof = false 69 @readline = block or raise( ArgumentError, "no line-reading block was provided" ) 70 @name ||= options[ :file ] || options[ :name ] || '(interactive)' 71 end 72 73 def readline 74 @initialized = true 75 unless @eof 76 if line = @readline.call 77 @data << line.to_s 78 return true 79 else 80 @eof = true 81 return false 82 end 83 end 84 end 85 86 end 87 88 private :readline 89 90 def consume 91 @position < @data.size and return( super ) 92 unless @eof 93 readline 94 consume 95 end 96 end 97 98 def peek( i = 1 ) 99 i.zero? and return 0 100 i += 1 if i < 0 101 index = @position + i - 1 102 index < 0 and return 0 103 104 if index < @data.size 105 char = @data[ index ] 106 elsif readline 107 peek( i ) 108 else EOF 109 end 110 end 111 112 def look( i = 1 ) 113 peek( i ).chr rescue EOF 114 end 115 116 def substring( start, stop ) 117 fill_through( stop ) 118 @string[ start .. stop ] 119 end 120 121private 122 123 def fill_through( position ) 124 @eof and return 125 if @position < 0 then fill_out 126 else readline until ( @data.size > @position or @eof ) 127 end 128 end 129 130 def fill_out 131 @eof and return 132 readline until @eof 133 end 134end 135 136end 137