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
33namespace 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
55        public CommonTokenStream()
56        {
57        }
58
59        public CommonTokenStream(ITokenSource tokenSource)
60            : this(tokenSource, TokenChannels.Default)
61        {
62        }
63
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. */
93        public override void Consume()
94        {
95            if (_p == -1)
96                Setup();
97            _p++;
98            _p = SkipOffTokenChannels(_p);
99        }
100
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
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         */
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
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
169        protected override void Setup()
170        {
171            _p = 0;
172            _p = SkipOffTokenChannels(_p);
173        }
174    }
175}
176