Home | History | Annotate | Download | only in Antlr3.Runtime
      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 
     78         public BufferedTokenStream()
     79         {
     80         }
     81 
     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 
    166         public virtual int Mark()
    167         {
    168             if (_p == -1)
    169                 Setup();
    170             _lastMarker = Index;
    171             return _lastMarker;
    172         }
    173 
    174         public virtual void Release(int marker)
    175         {
    176             // no resources to release
    177         }
    178 
    179         public virtual void Rewind(int marker)
    180         {
    181             Seek(marker);
    182         }
    183 
    184         public virtual void Rewind()
    185         {
    186             Seek(_lastMarker);
    187         }
    188 
    189         public virtual void Reset()
    190         {
    191             _p = 0;
    192             _lastMarker = 0;
    193         }
    194 
    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          */
    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. */
    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 */
    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 
    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>
    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 
    275         public virtual int LA(int i)
    276         {
    277             return LT(i).Type;
    278         }
    279 
    280         protected virtual IToken LB(int k)
    281         {
    282             if ((_p - k) < 0)
    283                 return null;
    284 
    285             return _tokens[_p - k];
    286         }
    287 
    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 
    311         protected virtual void Setup()
    312         {
    313             Sync(0);
    314             _p = 0;
    315         }
    316 
    317         public virtual List<IToken> GetTokens()
    318         {
    319             return _tokens;
    320         }
    321 
    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          */
    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 
    359         public virtual List<IToken> GetTokens(int start, int stop, IEnumerable<int> types)
    360         {
    361             return GetTokens(start, stop, new BitSet(types));
    362         }
    363 
    364         public virtual List<IToken> GetTokens(int start, int stop, int ttype)
    365         {
    366             return GetTokens(start, stop, BitSet.Of(ttype));
    367         }
    368 
    369         public override string ToString()
    370         {
    371             if (_p == -1)
    372                 Setup();
    373 
    374             Fill();
    375             return ToString(0, _tokens.Count - 1);
    376         }
    377 
    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 
    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 
    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