1/* 2 [The "BSD licence"] 3 Copyright (c) 2005-2006 Terence Parr 4 All rights reserved. 5 6 Redistribution and use in source and binary forms, with or without 7 modification, are permitted provided that the following conditions 8 are met: 9 1. Redistributions of source code must retain the above copyright 10 notice, this list of conditions and the following disclaimer. 11 2. Redistributions in binary form must reproduce the above copyright 12 notice, this list of conditions and the following disclaimer in the 13 documentation and/or other materials provided with the distribution. 14 3. The name of the author may not be used to endorse or promote products 15 derived from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27*/ 28package org.antlr.runtime { 29 30 public class ANTLRStringStream implements CharStream { 31 /** The data being scanned */ 32 protected var data:String; 33 34 /** How many characters are actually in the buffer */ 35 protected var n:int; 36 37 /** 0..n-1 index into string of next char */ 38 protected var p:int = 0; 39 40 /** line number 1..n within the input */ 41 protected var _line:int = 1; 42 43 /** The index of the character relative to the beginning of the line 0..n-1 */ 44 protected var _charPositionInLine:int = 0; 45 46 /** tracks how deep mark() calls are nested */ 47 protected var markDepth:int = 0; 48 49 /** A list of CharStreamState objects that tracks the stream state 50 * values line, charPositionInLine, and p that can change as you 51 * move through the input stream. Indexed from 1..markDepth. 52 * A null is kept @ index 0. Create upon first call to mark(). 53 */ 54 protected var markers:Array; 55 56 /** Track the last mark() call result value for use in rewind(). */ 57 protected var lastMarker:int; 58 59 protected var _sourceName:String; 60 61 protected var _lineDelimiter:String; 62 63 /** Copy data in string to a local char array */ 64 public function ANTLRStringStream(input:String = null, lineDelimiter:String = "\n") { 65 this._lineDelimiter = lineDelimiter; 66 if (input != null) { 67 this.data = input; 68 this.n = input.length; 69 } 70 } 71 72 /** Reset the stream so that it's in the same state it was 73 * when the object was created *except* the data array is not 74 * touched. 75 */ 76 public function reset():void { 77 p = 0; 78 _line = 1; 79 _charPositionInLine = 0; 80 markDepth = 0; 81 } 82 83 public function consume():void { 84 if ( p < n ) { 85 _charPositionInLine++; 86 if ( data.charAt(p)==_lineDelimiter ) { 87 _line++; 88 _charPositionInLine=0; 89 } 90 p++; 91 } 92 } 93 94 public function LA(i:int):int { 95 if ( i==0 ) { 96 return 0; // undefined 97 } 98 if ( i<0 ) { 99 i++; // e.g., translate LA(-1) to use offset i=0; then data[p+0-1] 100 if ( (p+i-1) < 0 ) { 101 return CharStreamConstants.EOF; // invalid; no char before first char 102 } 103 } 104 105 if ( (p+i-1) >= n ) { 106 return CharStreamConstants.EOF; 107 } 108 return data.charCodeAt(p+i-1); 109 } 110 111 public function LT(i:int):int { 112 return LA(i); 113 } 114 115 /** Return the current input symbol index 0..n where n indicates the 116 * last symbol has been read. The index is the index of char to 117 * be returned from LA(1). 118 */ 119 public function get index():int { 120 return p; 121 } 122 123 public function get size():int { 124 return n; 125 } 126 127 public function mark():int { 128 if ( markers==null ) { 129 markers = new Array(); 130 markers.push(null); // depth 0 means no backtracking, leave blank 131 } 132 markDepth++; 133 var state:CharStreamState = null; 134 if ( markDepth>=markers.length ) { 135 state = new CharStreamState(); 136 markers.push(state); 137 } 138 else { 139 state = CharStreamState(markers[markDepth]); 140 } 141 state.p = p; 142 state.line = _line; 143 state.charPositionInLine = _charPositionInLine; 144 lastMarker = markDepth; 145 return markDepth; 146 } 147 148 public function rewindTo(m:int):void { 149 var state:CharStreamState = CharStreamState(markers[m]); 150 // restore stream state 151 seek(state.p); 152 _line = state.line; 153 _charPositionInLine = state.charPositionInLine; 154 release(m); 155 } 156 157 public function rewind():void { 158 rewindTo(lastMarker); 159 } 160 161 public function release(marker:int):void { 162 // unwind any other markers made after m and release m 163 markDepth = marker; 164 // release this marker 165 markDepth--; 166 } 167 168 /** consume() ahead until p==index; can't just set p=index as we must 169 * update line and charPositionInLine. 170 */ 171 public function seek(index:int):void { 172 if ( index<=p ) { 173 p = index; // just jump; don't update stream state (line, ...) 174 return; 175 } 176 // seek forward, consume until p hits index 177 while ( p<index ) { 178 consume(); 179 } 180 } 181 182 public function substring(start:int, stop:int):String { 183 return data.substring(start, stop + 1); 184 } 185 186 public function get line():int { 187 return _line; 188 } 189 190 public function get charPositionInLine():int { 191 return _charPositionInLine; 192 } 193 194 public function set line(line:int):void { 195 this._line = line; 196 } 197 198 public function set charPositionInLine(pos:int):void { 199 this._charPositionInLine = pos; 200 } 201 202 public function get sourceName():String { 203 return _sourceName; 204 } 205 206 public function set sourceName(sourceName:String):void { 207 _sourceName = sourceName; 208 } 209 210 } 211 212}