• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 CommonTokenStream : BufferedTokenStream
51     {
52         /** Skip tokens on any channel but this one; this is how we skip whitespace... */
53         private int _channel;
54 
CommonTokenStream()55         public CommonTokenStream()
56         {
57         }
58 
CommonTokenStream(ITokenSource tokenSource)59         public CommonTokenStream(ITokenSource tokenSource)
60             : this(tokenSource, TokenChannels.Default)
61         {
62         }
63 
CommonTokenStream(ITokenSource tokenSource, int channel)64         public CommonTokenStream(ITokenSource tokenSource, int channel)
65             : base(tokenSource)
66         {
67             this._channel = channel;
68         }
69 
70         public int Channel
71         {
72             get
73             {
74                 return _channel;
75             }
76         }
77 
78         /** Reset this token stream by setting its token source. */
79         public override ITokenSource TokenSource
80         {
81             get
82             {
83                 return base.TokenSource;
84             }
85             set
86             {
87                 base.TokenSource = value;
88                 _channel = TokenChannels.Default;
89             }
90         }
91 
92         /** Always leave p on an on-channel token. */
Consume()93         public override void Consume()
94         {
95             if (_p == -1)
96                 Setup();
97             _p++;
98             _p = SkipOffTokenChannels(_p);
99         }
100 
LB(int k)101         protected override IToken LB(int k)
102         {
103             if (k == 0 || (_p - k) < 0)
104                 return null;
105 
106             int i = _p;
107             int n = 1;
108             // find k good tokens looking backwards
109             while (n <= k)
110             {
111                 // skip off-channel tokens
112                 i = SkipOffTokenChannelsReverse(i - 1);
113                 n++;
114             }
115             if (i < 0)
116                 return null;
117             return _tokens[i];
118         }
119 
LT(int k)120         public override IToken LT(int k)
121         {
122             if (_p == -1)
123                 Setup();
124             if (k == 0)
125                 return null;
126             if (k < 0)
127                 return LB(-k);
128             int i = _p;
129             int n = 1; // we know tokens[p] is a good one
130             // find k good tokens
131             while (n < k)
132             {
133                 // skip off-channel tokens
134                 i = SkipOffTokenChannels(i + 1);
135                 n++;
136             }
137 
138             if (i > Range)
139                 Range = i;
140 
141             return _tokens[i];
142         }
143 
144         /** Given a starting index, return the index of the first on-channel
145          *  token.
146          */
SkipOffTokenChannels(int i)147         protected virtual int SkipOffTokenChannels(int i)
148         {
149             Sync(i);
150             while (_tokens[i].Channel != _channel)
151             {
152                 // also stops at EOF (it's on channel)
153                 i++;
154                 Sync(i);
155             }
156             return i;
157         }
158 
SkipOffTokenChannelsReverse(int i)159         protected virtual int SkipOffTokenChannelsReverse(int i)
160         {
161             while (i >= 0 && ((IToken)_tokens[i]).Channel != _channel)
162             {
163                 i--;
164             }
165 
166             return i;
167         }
168 
Setup()169         protected override void Setup()
170         {
171             _p = 0;
172             _p = SkipOffTokenChannels(_p);
173         }
174     }
175 }
176