1 /* 2 * [The "BSD licence"] 3 * Copyright (c) 2005-2008 Terence Parr 4 * All rights reserved. 5 * 6 * Conversion to C#: 7 * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 namespace Antlr.Runtime 34 { 35 using System.Collections.Generic; 36 using CLSCompliant = System.CLSCompliantAttribute; 37 using IndexOutOfRangeException = System.IndexOutOfRangeException; 38 using StringBuilder = System.Text.StringBuilder; 39 40 /** Buffer all input tokens but do on-demand fetching of new tokens from 41 * lexer. Useful when the parser or lexer has to set context/mode info before 42 * proper lexing of future tokens. The ST template parser needs this, 43 * for example, because it has to constantly flip back and forth between 44 * inside/output templates. E.g., <names:{hi, <it>}> has to parse names 45 * as part of an expression but "hi, <it>" as a nested template. 46 * 47 * You can't use this stream if you pass whitespace or other off-channel 48 * tokens to the parser. The stream can't ignore off-channel tokens. 49 * (UnbufferedTokenStream is the same way.) 50 * 51 * This is not a subclass of UnbufferedTokenStream because I don't want 52 * to confuse small moving window of tokens it uses for the full buffer. 53 */ 54 [System.Serializable] 55 public class BufferedTokenStream : ITokenStream, ITokenStreamInformation 56 { 57 private ITokenSource _tokenSource; 58 59 /** Record every single token pulled from the source so we can reproduce 60 * chunks of it later. The buffer in LookaheadStream overlaps sometimes 61 * as its moving window moves through the input. This list captures 62 * everything so we can access complete input text. 63 */ 64 [CLSCompliant(false)] 65 protected List<IToken> _tokens = new List<IToken>(100); 66 67 /** Track the last mark() call result value for use in rewind(). */ 68 private int _lastMarker; 69 70 /** The index into the tokens list of the current token (next token 71 * to consume). tokens[p] should be LT(1). p=-1 indicates need 72 * to initialize with first token. The ctor doesn't get a token. 73 * First call to LT(1) or whatever gets the first token and sets p=0; 74 */ 75 [CLSCompliant(false)] 76 protected int _p = -1; 77 BufferedTokenStream()78 public BufferedTokenStream() 79 { 80 } 81 BufferedTokenStream(ITokenSource tokenSource)82 public BufferedTokenStream(ITokenSource tokenSource) 83 { 84 this._tokenSource = tokenSource; 85 } 86 87 public virtual ITokenSource TokenSource 88 { 89 get 90 { 91 return _tokenSource; 92 } 93 set 94 { 95 this._tokenSource = value; 96 _tokens.Clear(); 97 _p = -1; 98 } 99 } 100 101 public virtual int Index 102 { 103 get 104 { 105 return _p; 106 } 107 } 108 109 /// <summary> 110 /// How deep have we gone? 111 /// </summary> 112 public virtual int Range 113 { 114 get; 115 protected set; 116 } 117 118 public virtual int Count 119 { 120 get 121 { 122 return _tokens.Count; 123 } 124 } 125 126 public virtual string SourceName 127 { 128 get 129 { 130 return _tokenSource.SourceName; 131 } 132 } 133 134 public virtual IToken LastToken 135 { 136 get 137 { 138 return LB(1); 139 } 140 } 141 142 public virtual IToken LastRealToken 143 { 144 get 145 { 146 int i = 0; 147 IToken token; 148 do 149 { 150 i++; 151 token = LB(i); 152 } while (token != null && token.Line <= 0); 153 154 return token; 155 } 156 } 157 158 public virtual int MaxLookBehind 159 { 160 get 161 { 162 return int.MaxValue; 163 } 164 } 165 Mark()166 public virtual int Mark() 167 { 168 if (_p == -1) 169 Setup(); 170 _lastMarker = Index; 171 return _lastMarker; 172 } 173 Release(int marker)174 public virtual void Release(int marker) 175 { 176 // no resources to release 177 } 178 Rewind(int marker)179 public virtual void Rewind(int marker) 180 { 181 Seek(marker); 182 } 183 Rewind()184 public virtual void Rewind() 185 { 186 Seek(_lastMarker); 187 } 188 Reset()189 public virtual void Reset() 190 { 191 _p = 0; 192 _lastMarker = 0; 193 } 194 Seek(int index)195 public virtual void Seek(int index) 196 { 197 _p = index; 198 } 199 200 /** Move the input pointer to the next incoming token. The stream 201 * must become active with LT(1) available. consume() simply 202 * moves the input pointer so that LT(1) points at the next 203 * input symbol. Consume at least one token. 204 * 205 * Walk past any token not on the channel the parser is listening to. 206 */ Consume()207 public virtual void Consume() 208 { 209 if (_p == -1) 210 Setup(); 211 _p++; 212 Sync(_p); 213 } 214 215 /** Make sure index i in tokens has a token. */ Sync(int i)216 protected virtual void Sync(int i) 217 { 218 int n = i - _tokens.Count + 1; // how many more elements we need? 219 if (n > 0) 220 Fetch(n); 221 } 222 223 /** add n elements to buffer */ Fetch(int n)224 protected virtual void Fetch(int n) 225 { 226 for (int i = 0; i < n; i++) 227 { 228 IToken t = TokenSource.NextToken(); 229 t.TokenIndex = _tokens.Count; 230 _tokens.Add(t); 231 if (t.Type == CharStreamConstants.EndOfFile) 232 break; 233 } 234 } 235 Get(int i)236 public virtual IToken Get(int i) 237 { 238 if (i < 0 || i >= _tokens.Count) 239 { 240 throw new IndexOutOfRangeException("token index " + i + " out of range 0.." + (_tokens.Count - 1)); 241 } 242 return _tokens[i]; 243 } 244 245 #if false // why is this different from GetTokens(start, count) ? 246 /// <summary> 247 /// Get all tokens from start..(start+count-1) inclusively 248 /// </summary> Get(int start, int count)249 public virtual List<IToken> Get(int start, int count) 250 { 251 if (start < 0) 252 throw new ArgumentOutOfRangeException("start"); 253 if (count < 0) 254 throw new ArgumentOutOfRangeException("count"); 255 if (start + count >= _tokens.Count) 256 throw new ArgumentException(); 257 258 if (_p == -1) 259 Setup(); 260 261 List<IToken> subset = new List<IToken>(count); 262 for (int i = 0; i < count; i++) 263 { 264 IToken token = _tokens[i]; 265 if (token.Type == TokenTypes.EndOfFile) 266 break; 267 268 subset.Add(token); 269 } 270 271 return subset; 272 } 273 #endif 274 LA(int i)275 public virtual int LA(int i) 276 { 277 return LT(i).Type; 278 } 279 LB(int k)280 protected virtual IToken LB(int k) 281 { 282 if ((_p - k) < 0) 283 return null; 284 285 return _tokens[_p - k]; 286 } 287 LT(int k)288 public virtual IToken LT(int k) 289 { 290 if (_p == -1) 291 Setup(); 292 if (k == 0) 293 return null; 294 if (k < 0) 295 return LB(-k); 296 297 int i = _p + k - 1; 298 Sync(i); 299 if (i >= _tokens.Count) 300 { 301 // EOF must be last token 302 return _tokens[_tokens.Count - 1]; 303 } 304 305 if (i > Range) 306 Range = i; 307 308 return _tokens[_p + k - 1]; 309 } 310 Setup()311 protected virtual void Setup() 312 { 313 Sync(0); 314 _p = 0; 315 } 316 GetTokens()317 public virtual List<IToken> GetTokens() 318 { 319 return _tokens; 320 } 321 GetTokens(int start, int stop)322 public virtual List<IToken> GetTokens(int start, int stop) 323 { 324 return GetTokens(start, stop, default(BitSet)); 325 } 326 327 /** Given a start and stop index, return a List of all tokens in 328 * the token type BitSet. Return null if no tokens were found. This 329 * method looks at both on and off channel tokens. 330 */ GetTokens(int start, int stop, BitSet types)331 public virtual List<IToken> GetTokens(int start, int stop, BitSet types) 332 { 333 if (_p == -1) 334 Setup(); 335 if (stop >= _tokens.Count) 336 stop = _tokens.Count - 1; 337 if (start < 0) 338 start = 0; 339 if (start > stop) 340 return null; 341 342 // list = tokens[start:stop]:{Token t, t.getType() in types} 343 List<IToken> filteredTokens = new List<IToken>(); 344 for (int i = start; i <= stop; i++) 345 { 346 IToken t = _tokens[i]; 347 if (types == null || types.Member(t.Type)) 348 { 349 filteredTokens.Add(t); 350 } 351 } 352 if (filteredTokens.Count == 0) 353 { 354 filteredTokens = null; 355 } 356 return filteredTokens; 357 } 358 GetTokens(int start, int stop, IEnumerable<int> types)359 public virtual List<IToken> GetTokens(int start, int stop, IEnumerable<int> types) 360 { 361 return GetTokens(start, stop, new BitSet(types)); 362 } 363 GetTokens(int start, int stop, int ttype)364 public virtual List<IToken> GetTokens(int start, int stop, int ttype) 365 { 366 return GetTokens(start, stop, BitSet.Of(ttype)); 367 } 368 ToString()369 public override string ToString() 370 { 371 if (_p == -1) 372 Setup(); 373 374 Fill(); 375 return ToString(0, _tokens.Count - 1); 376 } 377 ToString(int start, int stop)378 public virtual string ToString(int start, int stop) 379 { 380 if (start < 0 || stop < 0) 381 return null; 382 if (_p == -1) 383 Setup(); 384 if (stop >= _tokens.Count) 385 stop = _tokens.Count - 1; 386 387 StringBuilder buf = new StringBuilder(); 388 for (int i = start; i <= stop; i++) 389 { 390 IToken t = _tokens[i]; 391 if (t.Type == CharStreamConstants.EndOfFile) 392 break; 393 buf.Append(t.Text); 394 } 395 396 return buf.ToString(); 397 } 398 ToString(IToken start, IToken stop)399 public virtual string ToString(IToken start, IToken stop) 400 { 401 if (start != null && stop != null) 402 { 403 return ToString(start.TokenIndex, stop.TokenIndex); 404 } 405 return null; 406 } 407 Fill()408 public virtual void Fill() 409 { 410 if (_p == -1) 411 Setup(); 412 413 if (_tokens[_p].Type == CharStreamConstants.EndOfFile) 414 return; 415 416 int i = _p + 1; 417 Sync(i); 418 while (_tokens[i].Type != CharStreamConstants.EndOfFile) 419 { 420 i++; 421 Sync(i); 422 } 423 } 424 } 425 } 426