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