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 37 using InvalidOperationException = System.InvalidOperationException; 38 using StringBuilder = System.Text.StringBuilder; 39 40 /** <summary> 41 * The most common stream of tokens is one where every token is buffered up 42 * and tokens are prefiltered for a certain channel (the parser will only 43 * see these tokens and cannot change the filter channel number during the 44 * parse). 45 * </summary> 46 * 47 * <remarks>TODO: how to access the full token stream? How to track all tokens matched per rule?</remarks> 48 */ 49 [System.Serializable] 50 public class LegacyCommonTokenStream : ITokenStream 51 { 52 [System.NonSerialized] 53 ITokenSource _tokenSource; 54 55 /** <summary> 56 * Record every single token pulled from the source so we can reproduce 57 * chunks of it later. 58 * </summary> 59 */ 60 protected List<IToken> tokens; 61 62 /** <summary>Map<tokentype, channel> to override some Tokens' channel numbers</summary> */ 63 protected IDictionary<int, int> channelOverrideMap; 64 65 /** <summary>Set<tokentype>; discard any tokens with this type</summary> */ 66 protected List<int> discardSet; 67 68 /** <summary>Skip tokens on any channel but this one; this is how we skip whitespace...</summary> */ 69 protected int channel = TokenChannels.Default; 70 71 /** <summary>By default, track all incoming tokens</summary> */ 72 protected bool discardOffChannelTokens = false; 73 74 /** <summary>Track the last mark() call result value for use in rewind().</summary> */ 75 protected int lastMarker; 76 77 /** <summary> 78 * The index into the tokens list of the current token (next token 79 * to consume). p==-1 indicates that the tokens list is empty 80 * </summary> 81 */ 82 protected int p = -1; 83 LegacyCommonTokenStream()84 public LegacyCommonTokenStream() 85 { 86 tokens = new List<IToken>( 500 ); 87 } 88 LegacyCommonTokenStream(ITokenSource tokenSource)89 public LegacyCommonTokenStream(ITokenSource tokenSource) 90 : this() 91 { 92 this._tokenSource = tokenSource; 93 } 94 LegacyCommonTokenStream( ITokenSource tokenSource, int channel )95 public LegacyCommonTokenStream( ITokenSource tokenSource, int channel ) 96 : this( tokenSource ) 97 { 98 this.channel = channel; 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 /** <summary>Reset this token stream by setting its token source.</summary> */ SetTokenSource( ITokenSource tokenSource )119 public virtual void SetTokenSource( ITokenSource tokenSource ) 120 { 121 this._tokenSource = tokenSource; 122 tokens.Clear(); 123 p = -1; 124 channel = TokenChannels.Default; 125 } 126 127 /** <summary> 128 * Load all tokens from the token source and put in tokens. 129 * This is done upon first LT request because you might want to 130 * set some token type / channel overrides before filling buffer. 131 * </summary> 132 */ FillBuffer()133 public virtual void FillBuffer() 134 { 135 // fast return if the buffer is already full 136 if ( p != -1 ) 137 return; 138 139 int index = 0; 140 IToken t = _tokenSource.NextToken(); 141 while ( t != null && t.Type != CharStreamConstants.EndOfFile ) 142 { 143 bool discard = false; 144 // is there a channel override for token type? 145 int channelI; 146 if ( channelOverrideMap != null && channelOverrideMap.TryGetValue( t.Type, out channelI ) ) 147 t.Channel = channelI; 148 149 //if ( channelOverrideMap != null && channelOverrideMap.ContainsKey( t.getType() ) ) 150 //{ 151 // object channelI = channelOverrideMap.get( t.getType() ); 152 // if ( channelI != null ) 153 // { 154 // t.setChannel( (int)channelI ); 155 // } 156 //} 157 if ( discardSet != null && 158 discardSet.Contains( t.Type ) ) 159 { 160 discard = true; 161 } 162 else if ( discardOffChannelTokens && t.Channel != this.channel ) 163 { 164 discard = true; 165 } 166 if ( !discard ) 167 { 168 t.TokenIndex = index; 169 tokens.Add( t ); 170 index++; 171 } 172 t = _tokenSource.NextToken(); 173 } 174 // leave p pointing at first token on channel 175 p = 0; 176 p = SkipOffTokenChannels( p ); 177 } 178 179 /** <summary> 180 * Move the input pointer to the next incoming token. The stream 181 * must become active with LT(1) available. consume() simply 182 * moves the input pointer so that LT(1) points at the next 183 * input symbol. Consume at least one token. 184 * </summary> 185 * 186 * <remarks> 187 * Walk past any token not on the channel the parser is listening to. 188 * </remarks> 189 */ Consume()190 public virtual void Consume() 191 { 192 if ( p < tokens.Count ) 193 { 194 p++; 195 p = SkipOffTokenChannels( p ); // leave p on valid token 196 } 197 } 198 199 /** <summary>Given a starting index, return the index of the first on-channel token.</summary> */ SkipOffTokenChannels( int i )200 protected virtual int SkipOffTokenChannels( int i ) 201 { 202 int n = tokens.Count; 203 while ( i < n && ( (IToken)tokens[i] ).Channel != channel ) 204 { 205 i++; 206 } 207 return i; 208 } 209 SkipOffTokenChannelsReverse( int i )210 protected virtual int SkipOffTokenChannelsReverse( int i ) 211 { 212 while ( i >= 0 && ( (IToken)tokens[i] ).Channel != channel ) 213 { 214 i--; 215 } 216 return i; 217 } 218 219 /** <summary> 220 * A simple filter mechanism whereby you can tell this token stream 221 * to force all tokens of type ttype to be on channel. For example, 222 * when interpreting, we cannot exec actions so we need to tell 223 * the stream to force all WS and NEWLINE to be a different, ignored 224 * channel. 225 * </summary> 226 */ SetTokenTypeChannel( int ttype, int channel )227 public virtual void SetTokenTypeChannel( int ttype, int channel ) 228 { 229 if ( channelOverrideMap == null ) 230 { 231 channelOverrideMap = new Dictionary<int, int>(); 232 } 233 channelOverrideMap[ttype] = channel; 234 } 235 DiscardTokenType( int ttype )236 public virtual void DiscardTokenType( int ttype ) 237 { 238 if ( discardSet == null ) 239 { 240 discardSet = new List<int>(); 241 } 242 discardSet.Add( ttype ); 243 } 244 SetDiscardOffChannelTokens( bool discardOffChannelTokens )245 public virtual void SetDiscardOffChannelTokens( bool discardOffChannelTokens ) 246 { 247 this.discardOffChannelTokens = discardOffChannelTokens; 248 } 249 GetTokens()250 public virtual IList<IToken> GetTokens() 251 { 252 if ( p == -1 ) 253 { 254 FillBuffer(); 255 } 256 return tokens; 257 } 258 GetTokens( int start, int stop )259 public virtual IList<IToken> GetTokens( int start, int stop ) 260 { 261 return GetTokens( start, stop, (BitSet)null ); 262 } 263 264 /** <summary> 265 * Given a start and stop index, return a List of all tokens in 266 * the token type BitSet. Return null if no tokens were found. This 267 * method looks at both on and off channel tokens. 268 * </summary> 269 */ GetTokens( int start, int stop, BitSet types )270 public virtual IList<IToken> GetTokens( int start, int stop, BitSet types ) 271 { 272 if ( p == -1 ) 273 { 274 FillBuffer(); 275 } 276 if ( stop >= tokens.Count ) 277 { 278 stop = tokens.Count - 1; 279 } 280 if ( start < 0 ) 281 { 282 start = 0; 283 } 284 if ( start > stop ) 285 { 286 return null; 287 } 288 289 // list = tokens[start:stop]:{Token t, t.getType() in types} 290 IList<IToken> filteredTokens = new List<IToken>(); 291 for ( int i = start; i <= stop; i++ ) 292 { 293 IToken t = tokens[i]; 294 if ( types == null || types.Member( t.Type ) ) 295 { 296 filteredTokens.Add( t ); 297 } 298 } 299 if ( filteredTokens.Count == 0 ) 300 { 301 filteredTokens = null; 302 } 303 return filteredTokens; 304 } 305 GetTokens( int start, int stop, IList<int> types )306 public virtual IList<IToken> GetTokens( int start, int stop, IList<int> types ) 307 { 308 return GetTokens( start, stop, new BitSet( types ) ); 309 } 310 GetTokens( int start, int stop, int ttype )311 public virtual IList<IToken> GetTokens( int start, int stop, int ttype ) 312 { 313 return GetTokens( start, stop, BitSet.Of( ttype ) ); 314 } 315 316 /** <summary> 317 * Get the ith token from the current position 1..n where k=1 is the 318 * first symbol of lookahead. 319 * </summary> 320 */ LT( int k )321 public virtual IToken LT( int k ) 322 { 323 if ( p == -1 ) 324 { 325 FillBuffer(); 326 } 327 if ( k == 0 ) 328 { 329 return null; 330 } 331 if ( k < 0 ) 332 { 333 return LB( -k ); 334 } 335 //System.out.print("LT(p="+p+","+k+")="); 336 if ( ( p + k - 1 ) >= tokens.Count ) 337 { 338 return tokens[tokens.Count - 1]; 339 } 340 //System.out.println(tokens.get(p+k-1)); 341 int i = p; 342 int n = 1; 343 // find k good tokens 344 while ( n < k ) 345 { 346 // skip off-channel tokens 347 i = SkipOffTokenChannels( i + 1 ); // leave p on valid token 348 n++; 349 } 350 if ( i >= tokens.Count ) 351 { 352 return tokens[tokens.Count - 1]; 353 } 354 355 if (i > Range) 356 Range = i; 357 358 return (IToken)tokens[i]; 359 } 360 361 /** <summary>Look backwards k tokens on-channel tokens</summary> */ LB( int k )362 protected virtual IToken LB( int k ) 363 { 364 //System.out.print("LB(p="+p+","+k+") "); 365 if ( p == -1 ) 366 { 367 FillBuffer(); 368 } 369 if ( k == 0 ) 370 { 371 return null; 372 } 373 if ( ( p - k ) < 0 ) 374 { 375 return null; 376 } 377 378 int i = p; 379 int n = 1; 380 // find k good tokens looking backwards 381 while ( n <= k ) 382 { 383 // skip off-channel tokens 384 i = SkipOffTokenChannelsReverse( i - 1 ); // leave p on valid token 385 n++; 386 } 387 if ( i < 0 ) 388 { 389 return null; 390 } 391 return (IToken)tokens[i]; 392 } 393 394 /** <summary> 395 * Return absolute token i; ignore which channel the tokens are on; 396 * that is, count all tokens not just on-channel tokens. 397 * </summary> 398 */ Get( int i )399 public virtual IToken Get( int i ) 400 { 401 return (IToken)tokens[i]; 402 } 403 404 #if false 405 /** Get all tokens from start..stop inclusively */ Get(int start, int count)406 public virtual List<IToken> Get(int start, int count) 407 { 408 if (start < 0) 409 throw new ArgumentOutOfRangeException("start"); 410 if (count < 0) 411 throw new ArgumentOutOfRangeException("count"); 412 413 if (p == -1) 414 FillBuffer(); 415 416 return new List<IToken>(tokens.Skip(start).Take(count)); 417 } 418 #endif 419 LA( int i )420 public virtual int LA( int i ) 421 { 422 return LT( i ).Type; 423 } 424 Mark()425 public virtual int Mark() 426 { 427 if ( p == -1 ) 428 { 429 FillBuffer(); 430 } 431 lastMarker = Index; 432 return lastMarker; 433 } 434 Release( int marker )435 public virtual void Release( int marker ) 436 { 437 // no resources to release 438 } 439 440 public virtual int Count 441 { 442 get 443 { 444 return tokens.Count; 445 } 446 } 447 Rewind( int marker )448 public virtual void Rewind( int marker ) 449 { 450 Seek( marker ); 451 } 452 Rewind()453 public virtual void Rewind() 454 { 455 Seek( lastMarker ); 456 } 457 Reset()458 public virtual void Reset() 459 { 460 p = 0; 461 lastMarker = 0; 462 } 463 Seek( int index )464 public virtual void Seek( int index ) 465 { 466 p = index; 467 } 468 469 public virtual ITokenSource TokenSource 470 { 471 get 472 { 473 return _tokenSource; 474 } 475 } 476 477 public virtual string SourceName 478 { 479 get 480 { 481 return TokenSource.SourceName; 482 } 483 } 484 ToString()485 public override string ToString() 486 { 487 if ( p == -1 ) 488 { 489 throw new InvalidOperationException( "Buffer is not yet filled." ); 490 } 491 return ToString( 0, tokens.Count - 1 ); 492 } 493 ToString( int start, int stop )494 public virtual string ToString( int start, int stop ) 495 { 496 if ( start < 0 || stop < 0 ) 497 { 498 return null; 499 } 500 if ( p == -1 ) 501 { 502 throw new InvalidOperationException( "Buffer is not yet filled." ); 503 } 504 if ( stop >= tokens.Count ) 505 { 506 stop = tokens.Count - 1; 507 } 508 StringBuilder buf = new StringBuilder(); 509 for ( int i = start; i <= stop; i++ ) 510 { 511 IToken t = tokens[i]; 512 buf.Append( t.Text ); 513 } 514 return buf.ToString(); 515 } 516 ToString( IToken start, IToken stop )517 public virtual string ToString( IToken start, IToken stop ) 518 { 519 if ( start != null && stop != null ) 520 { 521 return ToString( start.TokenIndex, stop.TokenIndex ); 522 } 523 return null; 524 } 525 } 526 } 527