1 /* 2 * [The "BSD license"] 3 * Copyright (c) 2012 Terence Parr 4 * Copyright (c) 2012 Sam Harwell 5 * Copyright (c) 2012 Egbert Voigt 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 module antlr.v4.runtime.ANTLRInputStream; 33 34 import antlr.v4.runtime.CharStream; 35 import antlr.v4.runtime.IntStream; 36 import antlr.v4.runtime.IntStreamConstant; 37 import antlr.v4.runtime.misc.Interval; 38 import std.algorithm; 39 import std.conv; 40 import std.file; 41 import std.format; 42 import std.stdio; 43 44 // Class ANTLRInputStream 45 /** 46 * Vacuum all input from a {@link Reader}/{@link InputStream} and then treat it 47 * like a {@code char[]} buffer. Can also pass in a {@link String} or 48 * {@code char[]} to use. 49 * 50 * <p>If you need encoding, pass in stream/reader with correct encoding.</p> 51 */ 52 class ANTLRInputStream : CharStream 53 { 54 55 public static int READ_BUFFER_SIZE = 1024; 56 57 public static int INITIAL_BUFFER_SIZE = 1024;; 58 59 /** 60 * @uml 61 * The data being scanned 62 */ 63 protected char[] data; 64 65 /** 66 * @uml 67 * How many characters are actually in the buffer 68 */ 69 protected int n; 70 71 /** 72 * @uml 73 * 0..n-1 index into string of next char 74 */ 75 protected int p = 0; 76 77 /** 78 * @uml 79 * What is name or source of this char stream? 80 */ 81 public string name; 82 83 public this() 84 { 85 } 86 87 /** 88 * @uml 89 * Copy data in string to a local char array 90 */ 91 public this(string input) 92 { 93 this.data = input.to!(char []); 94 this.n = to!int(input.length); 95 } 96 97 /** 98 * @uml 99 * This is the preferred constructor for strings as no data is copied 100 */ 101 public this(char[] data, int numberOfActualCharsInArray) 102 { 103 this.data = data; 104 this.n = numberOfActualCharsInArray; 105 } 106 107 public this(File r) 108 { 109 load(r, INITIAL_BUFFER_SIZE, READ_BUFFER_SIZE); 110 } 111 112 public void load(File r, int size, int readChunkSize) 113 { 114 debug(ANTLRInput) 115 writefln("load %1$s in chunks of %2$s", size, readChunkSize); 116 data = to!(char[])(r.name.readText); 117 // set the actual size of the data available; 118 n = to!int(data.length); 119 debug(ANTLRInput) 120 writefln("n= $s", n); 121 } 122 123 /** 124 * @uml 125 * Reset the stream so that it's in the same state it was 126 * when the object was created *except* the data array is not 127 * touched. 128 */ 129 public void reset() 130 { 131 p = 0; 132 } 133 134 /** 135 * @uml 136 * @override 137 */ 138 public override void consume() 139 { 140 if (p >= n) { 141 assert (LA(1) == IntStreamConstant.EOF, "cannot consume EOF"); 142 } 143 //System.out.println("prev p="+p+", c="+(char)data[p]); 144 if (p < n) { 145 p++; 146 //System.out.println("p moves to "+p+" (c='"+(char)data[p]+"')"); 147 } 148 } 149 150 /** 151 * @uml 152 * @override 153 */ 154 public override int LA(int i) 155 { 156 if (i == 0) { 157 return 0; // undefined 158 } 159 if (i < 0) { 160 i++; // e.g., translate LA(-1) to use offset i=0; then data[p+0-1] 161 if ((p + i - 1) < 0) { 162 return IntStreamConstant.EOF; // invalid; no char before first char 163 } 164 } 165 if (( p + i - 1) >= n) { 166 debug(ANTLRInput) { 167 import std.stdio; 168 writefln("char LA(%s)=EOF; p=%s", i, p); 169 } 170 return IntStreamConstant.EOF; 171 } 172 debug(ANTLRInput) { 173 import std.stdio; 174 writefln("LA(%s); p=%s n=%s data.length=%s", i, p, n, data.length); 175 writefln("char LA(%s)=%s; p=%s", i, data[p+i-1], p); 176 } 177 return data[p+i-1]; 178 } 179 180 public int LT(int i) 181 { 182 return LA(i); 183 } 184 185 /** 186 * @uml 187 * @override 188 */ 189 public override int index() 190 { 191 return p; 192 } 193 194 /** 195 * @uml 196 * @override 197 */ 198 public override int size() 199 { 200 return n; 201 } 202 203 /** 204 * @uml 205 * mark/release do nothing; we have entire buffer 206 * @override 207 */ 208 public override int mark() 209 { 210 return -1; 211 } 212 213 /** 214 * @uml 215 * @override 216 */ 217 public override void release(int marker) 218 { 219 } 220 221 /** 222 * @uml 223 * consume() ahead until p==index; can't just set p=index as we must 224 * update line and charPositionInLine. If we seek backwards, just set p 225 * @override 226 */ 227 public override void seek(int index) 228 { 229 if (index <= p) { 230 p = index; // just jump; don't update stream state (line, ...) 231 return; 232 } 233 // seek forward, consume until p hits index or n (whichever comes first) 234 index = min(index, n); 235 while (p < index) { 236 consume(); 237 } 238 } 239 240 /** 241 * @uml 242 * @override 243 */ 244 public override string getText(Interval interval) 245 { 246 int start = interval.a; 247 int stop = interval.b; 248 if (stop >= n) 249 stop = n-1; 250 if (start >= n) return ""; 251 // System.err.println("data: "+Arrays.toString(data)+", n="+n+ 252 // ", start="+start+ 253 // ", stop="+stop); 254 return to!string(data[start..stop+1]); 255 } 256 257 /** 258 * @uml 259 * @override 260 */ 261 public override string getSourceName() 262 { 263 if (name is null || name.length == 0) { 264 return IntStreamConstant.UNKNOWN_SOURCE_NAME; 265 } 266 return name; 267 } 268 269 /** 270 * @uml 271 * @override 272 */ 273 public override string toString() 274 { 275 return to!string(data); 276 } 277 278 }