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 
     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 LegacyCommonTokenStream : ITokenStream
     51     {
     52         [System.NonSerialized]
     53         ITokenSource _tokenSource;
     54 
     55         /** <summary>
     56          *  Record every single token pulled from the source so we can reproduce
     57          *  chunks of it later.
     58          *  </summary>
     59          */
     60         protected List<IToken> tokens;
     61 
     62         /** <summary>Map<tokentype, channel> to override some Tokens' channel numbers</summary> */
     63         protected IDictionary<int, int> channelOverrideMap;
     64 
     65         /** <summary>Set<tokentype>; discard any tokens with this type</summary> */
     66         protected List<int> discardSet;
     67 
     68         /** <summary>Skip tokens on any channel but this one; this is how we skip whitespace...</summary> */
     69         protected int channel = TokenChannels.Default;
     70 
     71         /** <summary>By default, track all incoming tokens</summary> */
     72         protected bool discardOffChannelTokens = false;
     73 
     74         /** <summary>Track the last mark() call result value for use in rewind().</summary> */
     75         protected int lastMarker;
     76 
     77         /** <summary>
     78          *  The index into the tokens list of the current token (next token
     79          *  to consume).  p==-1 indicates that the tokens list is empty
     80          *  </summary>
     81          */
     82         protected int p = -1;
     83 
     84         public LegacyCommonTokenStream()
     85         {
     86             tokens = new List<IToken>( 500 );
     87         }
     88 
     89         public LegacyCommonTokenStream(ITokenSource tokenSource)
     90             : this()
     91         {
     92             this._tokenSource = tokenSource;
     93         }
     94 
     95         public LegacyCommonTokenStream( ITokenSource tokenSource, int channel )
     96             : this( tokenSource )
     97         {
     98             this.channel = channel;
     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         /** <summary>Reset this token stream by setting its token source.</summary> */
    119         public virtual void SetTokenSource( ITokenSource tokenSource )
    120         {
    121             this._tokenSource = tokenSource;
    122             tokens.Clear();
    123             p = -1;
    124             channel = TokenChannels.Default;
    125         }
    126 
    127         /** <summary>
    128          *  Load all tokens from the token source and put in tokens.
    129          *  This is done upon first LT request because you might want to
    130          *  set some token type / channel overrides before filling buffer.
    131          *  </summary>
    132          */
    133         public virtual void FillBuffer()
    134         {
    135             // fast return if the buffer is already full
    136             if ( p != -1 )
    137                 return;
    138 
    139             int index = 0;
    140             IToken t = _tokenSource.NextToken();
    141             while ( t != null && t.Type != CharStreamConstants.EndOfFile )
    142             {
    143                 bool discard = false;
    144                 // is there a channel override for token type?
    145                 int channelI;
    146                 if ( channelOverrideMap != null && channelOverrideMap.TryGetValue( t.Type, out channelI ) )
    147                     t.Channel = channelI;
    148 
    149                 //if ( channelOverrideMap != null && channelOverrideMap.ContainsKey( t.getType() ) )
    150                 //{
    151                 //    object channelI = channelOverrideMap.get( t.getType() );
    152                 //    if ( channelI != null )
    153                 //    {
    154                 //        t.setChannel( (int)channelI );
    155                 //    }
    156                 //}
    157                 if ( discardSet != null &&
    158                      discardSet.Contains( t.Type ) )
    159                 {
    160                     discard = true;
    161                 }
    162                 else if ( discardOffChannelTokens && t.Channel != this.channel )
    163                 {
    164                     discard = true;
    165                 }
    166                 if ( !discard )
    167                 {
    168                     t.TokenIndex = index;
    169                     tokens.Add( t );
    170                     index++;
    171                 }
    172                 t = _tokenSource.NextToken();
    173             }
    174             // leave p pointing at first token on channel
    175             p = 0;
    176             p = SkipOffTokenChannels( p );
    177         }
    178 
    179         /** <summary>
    180          *  Move the input pointer to the next incoming token.  The stream
    181          *  must become active with LT(1) available.  consume() simply
    182          *  moves the input pointer so that LT(1) points at the next
    183          *  input symbol. Consume at least one token.
    184          *  </summary>
    185          *
    186          *  <remarks>
    187          *  Walk past any token not on the channel the parser is listening to.
    188          *  </remarks>
    189          */
    190         public virtual void Consume()
    191         {
    192             if ( p < tokens.Count )
    193             {
    194                 p++;
    195                 p = SkipOffTokenChannels( p ); // leave p on valid token
    196             }
    197         }
    198 
    199         /** <summary>Given a starting index, return the index of the first on-channel token.</summary> */
    200         protected virtual int SkipOffTokenChannels( int i )
    201         {
    202             int n = tokens.Count;
    203             while ( i < n && ( (IToken)tokens[i] ).Channel != channel )
    204             {
    205                 i++;
    206             }
    207             return i;
    208         }
    209 
    210         protected virtual int SkipOffTokenChannelsReverse( int i )
    211         {
    212             while ( i >= 0 && ( (IToken)tokens[i] ).Channel != channel )
    213             {
    214                 i--;
    215             }
    216             return i;
    217         }
    218 
    219         /** <summary>
    220          *  A simple filter mechanism whereby you can tell this token stream
    221          *  to force all tokens of type ttype to be on channel.  For example,
    222          *  when interpreting, we cannot exec actions so we need to tell
    223          *  the stream to force all WS and NEWLINE to be a different, ignored
    224          *  channel.
    225          *  </summary>
    226          */
    227         public virtual void SetTokenTypeChannel( int ttype, int channel )
    228         {
    229             if ( channelOverrideMap == null )
    230             {
    231                 channelOverrideMap = new Dictionary<int, int>();
    232             }
    233             channelOverrideMap[ttype] = channel;
    234         }
    235 
    236         public virtual void DiscardTokenType( int ttype )
    237         {
    238             if ( discardSet == null )
    239             {
    240                 discardSet = new List<int>();
    241             }
    242             discardSet.Add( ttype );
    243         }
    244 
    245         public virtual void SetDiscardOffChannelTokens( bool discardOffChannelTokens )
    246         {
    247             this.discardOffChannelTokens = discardOffChannelTokens;
    248         }
    249 
    250         public virtual IList<IToken> GetTokens()
    251         {
    252             if ( p == -1 )
    253             {
    254                 FillBuffer();
    255             }
    256             return tokens;
    257         }
    258 
    259         public virtual IList<IToken> GetTokens( int start, int stop )
    260         {
    261             return GetTokens( start, stop, (BitSet)null );
    262         }
    263 
    264         /** <summary>
    265          *  Given a start and stop index, return a List of all tokens in
    266          *  the token type BitSet.  Return null if no tokens were found.  This
    267          *  method looks at both on and off channel tokens.
    268          *  </summary>
    269          */
    270         public virtual IList<IToken> GetTokens( int start, int stop, BitSet types )
    271         {
    272             if ( p == -1 )
    273             {
    274                 FillBuffer();
    275             }
    276             if ( stop >= tokens.Count )
    277             {
    278                 stop = tokens.Count - 1;
    279             }
    280             if ( start < 0 )
    281             {
    282                 start = 0;
    283             }
    284             if ( start > stop )
    285             {
    286                 return null;
    287             }
    288 
    289             // list = tokens[start:stop]:{Token t, t.getType() in types}
    290             IList<IToken> filteredTokens = new List<IToken>();
    291             for ( int i = start; i <= stop; i++ )
    292             {
    293                 IToken t = tokens[i];
    294                 if ( types == null || types.Member( t.Type ) )
    295                 {
    296                     filteredTokens.Add( t );
    297                 }
    298             }
    299             if ( filteredTokens.Count == 0 )
    300             {
    301                 filteredTokens = null;
    302             }
    303             return filteredTokens;
    304         }
    305 
    306         public virtual IList<IToken> GetTokens( int start, int stop, IList<int> types )
    307         {
    308             return GetTokens( start, stop, new BitSet( types ) );
    309         }
    310 
    311         public virtual IList<IToken> GetTokens( int start, int stop, int ttype )
    312         {
    313             return GetTokens( start, stop, BitSet.Of( ttype ) );
    314         }
    315 
    316         /** <summary>
    317          *  Get the ith token from the current position 1..n where k=1 is the
    318          *  first symbol of lookahead.
    319          *  </summary>
    320          */
    321         public virtual IToken LT( int k )
    322         {
    323             if ( p == -1 )
    324             {
    325                 FillBuffer();
    326             }
    327             if ( k == 0 )
    328             {
    329                 return null;
    330             }
    331             if ( k < 0 )
    332             {
    333                 return LB( -k );
    334             }
    335             //System.out.print("LT(p="+p+","+k+")=");
    336             if ( ( p + k - 1 ) >= tokens.Count )
    337             {
    338                 return tokens[tokens.Count - 1];
    339             }
    340             //System.out.println(tokens.get(p+k-1));
    341             int i = p;
    342             int n = 1;
    343             // find k good tokens
    344             while ( n < k )
    345             {
    346                 // skip off-channel tokens
    347                 i = SkipOffTokenChannels( i + 1 ); // leave p on valid token
    348                 n++;
    349             }
    350             if ( i >= tokens.Count )
    351             {
    352                 return tokens[tokens.Count - 1];
    353             }
    354 
    355             if (i > Range)
    356                 Range = i;
    357 
    358             return (IToken)tokens[i];
    359         }
    360 
    361         /** <summary>Look backwards k tokens on-channel tokens</summary> */
    362         protected virtual IToken LB( int k )
    363         {
    364             //System.out.print("LB(p="+p+","+k+") ");
    365             if ( p == -1 )
    366             {
    367                 FillBuffer();
    368             }
    369             if ( k == 0 )
    370             {
    371                 return null;
    372             }
    373             if ( ( p - k ) < 0 )
    374             {
    375                 return null;
    376             }
    377 
    378             int i = p;
    379             int n = 1;
    380             // find k good tokens looking backwards
    381             while ( n <= k )
    382             {
    383                 // skip off-channel tokens
    384                 i = SkipOffTokenChannelsReverse( i - 1 ); // leave p on valid token
    385                 n++;
    386             }
    387             if ( i < 0 )
    388             {
    389                 return null;
    390             }
    391             return (IToken)tokens[i];
    392         }
    393 
    394         /** <summary>
    395          *  Return absolute token i; ignore which channel the tokens are on;
    396          *  that is, count all tokens not just on-channel tokens.
    397          *  </summary>
    398          */
    399         public virtual IToken Get( int i )
    400         {
    401             return (IToken)tokens[i];
    402         }
    403 
    404 #if false
    405         /** Get all tokens from start..stop inclusively */
    406         public virtual List<IToken> Get(int start, int count)
    407         {
    408             if (start < 0)
    409                 throw new ArgumentOutOfRangeException("start");
    410             if (count < 0)
    411                 throw new ArgumentOutOfRangeException("count");
    412 
    413             if (p == -1)
    414                 FillBuffer();
    415 
    416             return new List<IToken>(tokens.Skip(start).Take(count));
    417         }
    418 #endif
    419 
    420         public virtual int LA( int i )
    421         {
    422             return LT( i ).Type;
    423         }
    424 
    425         public virtual int Mark()
    426         {
    427             if ( p == -1 )
    428             {
    429                 FillBuffer();
    430             }
    431             lastMarker = Index;
    432             return lastMarker;
    433         }
    434 
    435         public virtual void Release( int marker )
    436         {
    437             // no resources to release
    438         }
    439 
    440         public virtual int Count
    441         {
    442             get
    443             {
    444                 return tokens.Count;
    445             }
    446         }
    447 
    448         public virtual void Rewind( int marker )
    449         {
    450             Seek( marker );
    451         }
    452 
    453         public virtual void Rewind()
    454         {
    455             Seek( lastMarker );
    456         }
    457 
    458         public virtual void Reset()
    459         {
    460             p = 0;
    461             lastMarker = 0;
    462         }
    463 
    464         public virtual void Seek( int index )
    465         {
    466             p = index;
    467         }
    468 
    469         public virtual ITokenSource TokenSource
    470         {
    471             get
    472             {
    473                 return _tokenSource;
    474             }
    475         }
    476 
    477         public virtual string SourceName
    478         {
    479             get
    480             {
    481                 return TokenSource.SourceName;
    482             }
    483         }
    484 
    485         public override string ToString()
    486         {
    487             if ( p == -1 )
    488             {
    489                 throw new InvalidOperationException( "Buffer is not yet filled." );
    490             }
    491             return ToString( 0, tokens.Count - 1 );
    492         }
    493 
    494         public virtual string ToString( int start, int stop )
    495         {
    496             if ( start < 0 || stop < 0 )
    497             {
    498                 return null;
    499             }
    500             if ( p == -1 )
    501             {
    502                 throw new InvalidOperationException( "Buffer is not yet filled." );
    503             }
    504             if ( stop >= tokens.Count )
    505             {
    506                 stop = tokens.Count - 1;
    507             }
    508             StringBuilder buf = new StringBuilder();
    509             for ( int i = start; i <= stop; i++ )
    510             {
    511                 IToken t = tokens[i];
    512                 buf.Append( t.Text );
    513             }
    514             return buf.ToString();
    515         }
    516 
    517         public virtual string ToString( IToken start, IToken stop )
    518         {
    519             if ( start != null && stop != null )
    520             {
    521                 return ToString( start.TokenIndex, stop.TokenIndex );
    522             }
    523             return null;
    524         }
    525     }
    526 }
    527