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