1 /* 2 * NOTE TO JL: The original contains references to 3.5-only stuff! 3 * 4 * [The "BSD licence"] 5 * Copyright (c) 2005-2008 Terence Parr 6 * All rights reserved. 7 * 8 * Conversion to C#: 9 * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 namespace Antlr.Runtime { 36 using System.Collections.Generic; 37 38 using ArgumentOutOfRangeException = System.ArgumentOutOfRangeException; 39 using InvalidOperationException = System.InvalidOperationException; 40 using StringBuilder = System.Text.StringBuilder; 41 42 /** <summary> 43 * The most common stream of tokens is one where every token is buffered up 44 * and tokens are prefiltered for a certain channel (the parser will only 45 * see these tokens and cannot change the filter channel number during the 46 * parse). 47 * </summary> 48 * 49 * <remarks>TODO: how to access the full token stream? How to track all tokens matched per rule?</remarks> 50 */ 51 [System.Serializable] 52 public class LegacyCommonTokenStream : ITokenStream { 53 [System.NonSerialized] 54 ITokenSource _tokenSource; 55 56 /** <summary> 57 * Record every single token pulled from the source so we can reproduce 58 * chunks of it later. 59 * </summary> 60 */ 61 protected List<IToken> tokens; 62 63 /** <summary>Map<tokentype, channel> to override some Tokens' channel numbers</summary> */ 64 protected IDictionary<int, int> channelOverrideMap; 65 66 /** <summary>Set<tokentype>; discard any tokens with this type</summary> */ 67 protected Dictionary<int, int> discardSet; 68 69 /** <summary>Skip tokens on any channel but this one; this is how we skip whitespace...</summary> */ 70 protected int channel = TokenChannels.Default; 71 72 /** <summary>By default, track all incoming tokens</summary> */ 73 protected bool discardOffChannelTokens = false; 74 75 /** <summary>Track the last mark() call result value for use in rewind().</summary> */ 76 protected int lastMarker; 77 78 /** <summary> 79 * The index into the tokens list of the current token (next token 80 * to consume). p==-1 indicates that the tokens list is empty 81 * </summary> 82 */ 83 protected int p = -1; 84 LegacyCommonTokenStream()85 public LegacyCommonTokenStream() { 86 tokens = new List<IToken>(500); 87 } 88 LegacyCommonTokenStream(ITokenSource tokenSource)89 public LegacyCommonTokenStream(ITokenSource tokenSource) 90 : this() { 91 this._tokenSource = tokenSource; 92 } 93 LegacyCommonTokenStream(ITokenSource tokenSource, int channel)94 public LegacyCommonTokenStream(ITokenSource tokenSource, int channel) 95 : this(tokenSource) { 96 this.channel = channel; 97 } 98 99 public virtual int Index { 100 get { 101 return p; 102 } 103 } 104 105 /// <summary> 106 /// How deep have we gone? 107 /// </summary> 108 public virtual int Range { 109 get; 110 protected set; 111 } 112 113 /** <summary>Reset this token stream by setting its token source.</summary> */ SetTokenSource(ITokenSource tokenSource)114 public virtual void SetTokenSource(ITokenSource tokenSource) { 115 this._tokenSource = tokenSource; 116 tokens.Clear(); 117 p = -1; 118 channel = TokenChannels.Default; 119 } 120 121 /** <summary> 122 * Load all tokens from the token source and put in tokens. 123 * This is done upon first LT request because you might want to 124 * set some token type / channel overrides before filling buffer. 125 * </summary> 126 */ FillBuffer()127 public virtual void FillBuffer() { 128 // fast return if the buffer is already full 129 if (p != -1) 130 return; 131 132 int index = 0; 133 IToken t = _tokenSource.NextToken(); 134 while (t != null && t.Type != CharStreamConstants.EndOfFile) { 135 bool discard = false; 136 // is there a channel override for token type? 137 int channelI; 138 if (channelOverrideMap != null && channelOverrideMap.TryGetValue(t.Type, out channelI)) 139 t.Channel = channelI; 140 141 //if ( channelOverrideMap != null && channelOverrideMap.ContainsKey( t.getType() ) ) 142 //{ 143 // object channelI = channelOverrideMap.get( t.getType() ); 144 // if ( channelI != null ) 145 // { 146 // t.setChannel( (int)channelI ); 147 // } 148 //} 149 if (discardSet != null && 150 discardSet.ContainsKey(t.Type)) { 151 discard = true; 152 } else if (discardOffChannelTokens && t.Channel != this.channel) { 153 discard = true; 154 } 155 if (!discard) { 156 t.TokenIndex = index; 157 tokens.Add(t); 158 index++; 159 } 160 t = _tokenSource.NextToken(); 161 } 162 // leave p pointing at first token on channel 163 p = 0; 164 p = SkipOffTokenChannels(p); 165 } 166 167 /** <summary> 168 * Move the input pointer to the next incoming token. The stream 169 * must become active with LT(1) available. consume() simply 170 * moves the input pointer so that LT(1) points at the next 171 * input symbol. Consume at least one token. 172 * </summary> 173 * 174 * <remarks> 175 * Walk past any token not on the channel the parser is listening to. 176 * </remarks> 177 */ Consume()178 public virtual void Consume() { 179 if (p < tokens.Count) { 180 p++; 181 p = SkipOffTokenChannels(p); // leave p on valid token 182 } 183 } 184 185 /** <summary>Given a starting index, return the index of the first on-channel token.</summary> */ SkipOffTokenChannels(int i)186 protected virtual int SkipOffTokenChannels(int i) { 187 int n = tokens.Count; 188 while (i < n && ((IToken)tokens[i]).Channel != channel) { 189 i++; 190 } 191 return i; 192 } 193 SkipOffTokenChannelsReverse(int i)194 protected virtual int SkipOffTokenChannelsReverse(int i) { 195 while (i >= 0 && ((IToken)tokens[i]).Channel != channel) { 196 i--; 197 } 198 return i; 199 } 200 201 /** <summary> 202 * A simple filter mechanism whereby you can tell this token stream 203 * to force all tokens of type ttype to be on channel. For example, 204 * when interpreting, we cannot exec actions so we need to tell 205 * the stream to force all WS and NEWLINE to be a different, ignored 206 * channel. 207 * </summary> 208 */ SetTokenTypeChannel(int ttype, int channel)209 public virtual void SetTokenTypeChannel(int ttype, int channel) { 210 if (channelOverrideMap == null) { 211 channelOverrideMap = new Dictionary<int, int>(); 212 } 213 channelOverrideMap[ttype] = channel; 214 } 215 DiscardTokenType(int ttype)216 public virtual void DiscardTokenType(int ttype) { 217 if (discardSet == null) { 218 discardSet = new Dictionary<int, int>(); 219 } 220 discardSet.Add(ttype, ttype); 221 } 222 SetDiscardOffChannelTokens(bool discardOffChannelTokens)223 public virtual void SetDiscardOffChannelTokens(bool discardOffChannelTokens) { 224 this.discardOffChannelTokens = discardOffChannelTokens; 225 } 226 GetTokens()227 public virtual IList<IToken> GetTokens() { 228 if (p == -1) { 229 FillBuffer(); 230 } 231 return tokens; 232 } 233 GetTokens(int start, int stop)234 public virtual IList<IToken> GetTokens(int start, int stop) { 235 return GetTokens(start, stop, (BitSet)null); 236 } 237 238 /** <summary> 239 * Given a start and stop index, return a List of all tokens in 240 * the token type BitSet. Return null if no tokens were found. This 241 * method looks at both on and off channel tokens. 242 * </summary> 243 */ GetTokens(int start, int stop, BitSet types)244 public virtual IList<IToken> GetTokens(int start, int stop, BitSet types) { 245 if (p == -1) { 246 FillBuffer(); 247 } 248 if (stop >= tokens.Count) { 249 stop = tokens.Count - 1; 250 } 251 if (start < 0) { 252 start = 0; 253 } 254 if (start > stop) { 255 return null; 256 } 257 258 // list = tokens[start:stop]:{Token t, t.getType() in types} 259 IList<IToken> filteredTokens = new List<IToken>(); 260 for (int i = start; i <= stop; i++) { 261 IToken t = tokens[i]; 262 if (types == null || types.Member(t.Type)) { 263 filteredTokens.Add(t); 264 } 265 } 266 if (filteredTokens.Count == 0) { 267 filteredTokens = null; 268 } 269 return filteredTokens; 270 } 271 GetTokens(int start, int stop, IList<int> types)272 public virtual IList<IToken> GetTokens(int start, int stop, IList<int> types) { 273 return GetTokens(start, stop, new BitSet(types)); 274 } 275 GetTokens(int start, int stop, int ttype)276 public virtual IList<IToken> GetTokens(int start, int stop, int ttype) { 277 return GetTokens(start, stop, BitSet.Of(ttype)); 278 } 279 280 /** <summary> 281 * Get the ith token from the current position 1..n where k=1 is the 282 * first symbol of lookahead. 283 * </summary> 284 */ LT(int k)285 public virtual IToken LT(int k) { 286 if (p == -1) { 287 FillBuffer(); 288 } 289 if (k == 0) { 290 return null; 291 } 292 if (k < 0) { 293 return LB(-k); 294 } 295 //System.out.print("LT(p="+p+","+k+")="); 296 if ((p + k - 1) >= tokens.Count) { 297 return tokens[tokens.Count - 1]; 298 } 299 //System.out.println(tokens.get(p+k-1)); 300 int i = p; 301 int n = 1; 302 // find k good tokens 303 while (n < k) { 304 // skip off-channel tokens 305 i = SkipOffTokenChannels(i + 1); // leave p on valid token 306 n++; 307 } 308 if (i >= tokens.Count) { 309 return tokens[tokens.Count - 1]; 310 } 311 312 if (i > Range) 313 Range = i; 314 315 return (IToken)tokens[i]; 316 } 317 318 /** <summary>Look backwards k tokens on-channel tokens</summary> */ LB(int k)319 protected virtual IToken LB(int k) { 320 //System.out.print("LB(p="+p+","+k+") "); 321 if (p == -1) { 322 FillBuffer(); 323 } 324 if (k == 0) { 325 return null; 326 } 327 if ((p - k) < 0) { 328 return null; 329 } 330 331 int i = p; 332 int n = 1; 333 // find k good tokens looking backwards 334 while (n <= k) { 335 // skip off-channel tokens 336 i = SkipOffTokenChannelsReverse(i - 1); // leave p on valid token 337 n++; 338 } 339 if (i < 0) { 340 return null; 341 } 342 return (IToken)tokens[i]; 343 } 344 345 /** <summary> 346 * Return absolute token i; ignore which channel the tokens are on; 347 * that is, count all tokens not just on-channel tokens. 348 * </summary> 349 */ Get(int i)350 public virtual IToken Get(int i) { 351 return (IToken)tokens[i]; 352 } 353 354 #if false 355 /** Get all tokens from start..stop inclusively */ Get(int start, int count)356 public virtual List<IToken> Get(int start, int count) 357 { 358 if (start < 0) 359 throw new ArgumentOutOfRangeException("start"); 360 if (count < 0) 361 throw new ArgumentOutOfRangeException("count"); 362 363 if (p == -1) 364 FillBuffer(); 365 366 return new List<IToken>(tokens.Skip(start).Take(count)); 367 } 368 #endif 369 LA(int i)370 public virtual int LA(int i) { 371 return LT(i).Type; 372 } 373 Mark()374 public virtual int Mark() { 375 if (p == -1) { 376 FillBuffer(); 377 } 378 lastMarker = Index; 379 return lastMarker; 380 } 381 Release(int marker)382 public virtual void Release(int marker) { 383 // no resources to release 384 } 385 386 public virtual int Count { 387 get { 388 return tokens.Count; 389 } 390 } 391 Rewind(int marker)392 public virtual void Rewind(int marker) { 393 Seek(marker); 394 } 395 Rewind()396 public virtual void Rewind() { 397 Seek(lastMarker); 398 } 399 Reset()400 public virtual void Reset() { 401 p = 0; 402 lastMarker = 0; 403 } 404 Seek(int index)405 public virtual void Seek(int index) { 406 p = index; 407 } 408 409 public virtual ITokenSource TokenSource { 410 get { 411 return _tokenSource; 412 } 413 } 414 415 public virtual string SourceName { 416 get { 417 return TokenSource.SourceName; 418 } 419 } 420 ToString()421 public override string ToString() { 422 if (p == -1) { 423 throw new InvalidOperationException("Buffer is not yet filled."); 424 } 425 return ToString(0, tokens.Count - 1); 426 } 427 ToString(int start, int stop)428 public virtual string ToString(int start, int stop) { 429 if (start < 0 || stop < 0) { 430 return null; 431 } 432 if (p == -1) { 433 throw new InvalidOperationException("Buffer is not yet filled."); 434 } 435 if (stop >= tokens.Count) { 436 stop = tokens.Count - 1; 437 } 438 StringBuilder buf = new StringBuilder(); 439 for (int i = start; i <= stop; i++) { 440 IToken t = tokens[i]; 441 buf.Append(t.Text); 442 } 443 return buf.ToString(); 444 } 445 ToString(IToken start, IToken stop)446 public virtual string ToString(IToken start, IToken stop) { 447 if (start != null && stop != null) { 448 return ToString(start.TokenIndex, stop.TokenIndex); 449 } 450 return null; 451 } 452 } 453 } 454