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