﻿/*
 * [The "BSD licence"]
 * Copyright (c) 2005-2008 Terence Parr
 * All rights reserved.
 *
 * Conversion to C#:
 * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

namespace Antlr.Runtime
{
    using System.Collections.Generic;
    using CLSCompliant = System.CLSCompliantAttribute;
    using IndexOutOfRangeException = System.IndexOutOfRangeException;
    using StringBuilder = System.Text.StringBuilder;

    /** Buffer all input tokens but do on-demand fetching of new tokens from
     *  lexer. Useful when the parser or lexer has to set context/mode info before
     *  proper lexing of future tokens. The ST template parser needs this,
     *  for example, because it has to constantly flip back and forth between
     *  inside/output templates. E.g., <names:{hi, <it>}> has to parse names
     *  as part of an expression but "hi, <it>" as a nested template.
     *
     *  You can't use this stream if you pass whitespace or other off-channel
     *  tokens to the parser. The stream can't ignore off-channel tokens.
     *  (UnbufferedTokenStream is the same way.)
     *
     *  This is not a subclass of UnbufferedTokenStream because I don't want
     *  to confuse small moving window of tokens it uses for the full buffer.
     */
    [System.Serializable]
    public class BufferedTokenStream : ITokenStream, ITokenStreamInformation
    {
        private ITokenSource _tokenSource;

        /** Record every single token pulled from the source so we can reproduce
         *  chunks of it later.  The buffer in LookaheadStream overlaps sometimes
         *  as its moving window moves through the input.  This list captures
         *  everything so we can access complete input text.
         */
        [CLSCompliant(false)]
        protected List<IToken> _tokens = new List<IToken>(100);

        /** Track the last mark() call result value for use in rewind(). */
        private int _lastMarker;

        /** The index into the tokens list of the current token (next token
         *  to consume).  tokens[p] should be LT(1).  p=-1 indicates need
         *  to initialize with first token.  The ctor doesn't get a token.
         *  First call to LT(1) or whatever gets the first token and sets p=0;
         */
        [CLSCompliant(false)]
        protected int _p = -1;

        public BufferedTokenStream()
        {
        }

        public BufferedTokenStream(ITokenSource tokenSource)
        {
            this._tokenSource = tokenSource;
        }

        public virtual ITokenSource TokenSource
        {
            get
            {
                return _tokenSource;
            }
            set
            {
                this._tokenSource = value;
                _tokens.Clear();
                _p = -1;
            }
        }

        public virtual int Index
        {
            get
            {
                return _p;
            }
        }

        /// <summary>
        /// How deep have we gone?
        /// </summary>
        public virtual int Range
        {
            get;
            protected set;
        }

        public virtual int Count
        {
            get
            {
                return _tokens.Count;
            }
        }

        public virtual string SourceName
        {
            get
            {
                return _tokenSource.SourceName;
            }
        }

        public virtual IToken LastToken
        {
            get
            {
                return LB(1);
            }
        }

        public virtual IToken LastRealToken
        {
            get
            {
                int i = 0;
                IToken token;
                do
                {
                    i++;
                    token = LB(i);
                } while (token != null && token.Line <= 0);

                return token;
            }
        }

        public virtual int MaxLookBehind
        {
            get
            {
                return int.MaxValue;
            }
        }

        public virtual int Mark()
        {
            if (_p == -1)
                Setup();
            _lastMarker = Index;
            return _lastMarker;
        }

        public virtual void Release(int marker)
        {
            // no resources to release
        }

        public virtual void Rewind(int marker)
        {
            Seek(marker);
        }

        public virtual void Rewind()
        {
            Seek(_lastMarker);
        }

        public virtual void Reset()
        {
            _p = 0;
            _lastMarker = 0;
        }

        public virtual void Seek(int index)
        {
            _p = index;
        }

        /** Move the input pointer to the next incoming token.  The stream
         *  must become active with LT(1) available.  consume() simply
         *  moves the input pointer so that LT(1) points at the next
         *  input symbol. Consume at least one token.
         *
         *  Walk past any token not on the channel the parser is listening to.
         */
        public virtual void Consume()
        {
            if (_p == -1)
                Setup();
            _p++;
            Sync(_p);
        }

        /** Make sure index i in tokens has a token. */
        protected virtual void Sync(int i)
        {
            int n = i - _tokens.Count + 1; // how many more elements we need?
            if (n > 0)
                Fetch(n);
        }

        /** add n elements to buffer */
        protected virtual void Fetch(int n)
        {
            for (int i = 0; i < n; i++)
            {
                IToken t = TokenSource.NextToken();
                t.TokenIndex = _tokens.Count;
                _tokens.Add(t);
                if (t.Type == CharStreamConstants.EndOfFile)
                    break;
            }
        }

        public virtual IToken Get(int i)
        {
            if (i < 0 || i >= _tokens.Count)
            {
                throw new IndexOutOfRangeException("token index " + i + " out of range 0.." + (_tokens.Count - 1));
            }
            return _tokens[i];
        }

#if false // why is this different from GetTokens(start, count) ?
        /// <summary>
        /// Get all tokens from start..(start+count-1) inclusively
        /// </summary>
        public virtual List<IToken> Get(int start, int count)
        {
            if (start < 0)
                throw new ArgumentOutOfRangeException("start");
            if (count < 0)
                throw new ArgumentOutOfRangeException("count");
            if (start + count >= _tokens.Count)
                throw new ArgumentException();

            if (_p == -1)
                Setup();

            List<IToken> subset = new List<IToken>(count);
            for (int i = 0; i < count; i++)
            {
                IToken token = _tokens[i];
                if (token.Type == TokenTypes.EndOfFile)
                    break;

                subset.Add(token);
            }

            return subset;
        }
#endif

        public virtual int LA(int i)
        {
            return LT(i).Type;
        }

        protected virtual IToken LB(int k)
        {
            if ((_p - k) < 0)
                return null;

            return _tokens[_p - k];
        }

        public virtual IToken LT(int k)
        {
            if (_p == -1)
                Setup();
            if (k == 0)
                return null;
            if (k < 0)
                return LB(-k);

            int i = _p + k - 1;
            Sync(i);
            if (i >= _tokens.Count)
            {
                // EOF must be last token
                return _tokens[_tokens.Count - 1];
            }

            if (i > Range)
                Range = i;

            return _tokens[_p + k - 1];
        }

        protected virtual void Setup()
        {
            Sync(0);
            _p = 0;
        }

        public virtual List<IToken> GetTokens()
        {
            return _tokens;
        }

        public virtual List<IToken> GetTokens(int start, int stop)
        {
            return GetTokens(start, stop, default(BitSet));
        }

        /** Given a start and stop index, return a List of all tokens in
         *  the token type BitSet.  Return null if no tokens were found.  This
         *  method looks at both on and off channel tokens.
         */
        public virtual List<IToken> GetTokens(int start, int stop, BitSet types)
        {
            if (_p == -1)
                Setup();
            if (stop >= _tokens.Count)
                stop = _tokens.Count - 1;
            if (start < 0)
                start = 0;
            if (start > stop)
                return null;

            // list = tokens[start:stop]:{Token t, t.getType() in types}
            List<IToken> filteredTokens = new List<IToken>();
            for (int i = start; i <= stop; i++)
            {
                IToken t = _tokens[i];
                if (types == null || types.Member(t.Type))
                {
                    filteredTokens.Add(t);
                }
            }
            if (filteredTokens.Count == 0)
            {
                filteredTokens = null;
            }
            return filteredTokens;
        }

        public virtual List<IToken> GetTokens(int start, int stop, IEnumerable<int> types)
        {
            return GetTokens(start, stop, new BitSet(types));
        }

        public virtual List<IToken> GetTokens(int start, int stop, int ttype)
        {
            return GetTokens(start, stop, BitSet.Of(ttype));
        }

        public override string ToString()
        {
            if (_p == -1)
                Setup();

            Fill();
            return ToString(0, _tokens.Count - 1);
        }

        public virtual string ToString(int start, int stop)
        {
            if (start < 0 || stop < 0)
                return null;
            if (_p == -1)
                Setup();
            if (stop >= _tokens.Count)
                stop = _tokens.Count - 1;

            StringBuilder buf = new StringBuilder();
            for (int i = start; i <= stop; i++)
            {
                IToken t = _tokens[i];
                if (t.Type == CharStreamConstants.EndOfFile)
                    break;
                buf.Append(t.Text);
            }

            return buf.ToString();
        }

        public virtual string ToString(IToken start, IToken stop)
        {
            if (start != null && stop != null)
            {
                return ToString(start.TokenIndex, stop.TokenIndex);
            }
            return null;
        }

        public virtual void Fill()
        {
            if (_p == -1)
                Setup();

            if (_tokens[_p].Type == CharStreamConstants.EndOfFile)
                return;

            int i = _p + 1;
            Sync(i);
            while (_tokens[i].Type != CharStreamConstants.EndOfFile)
            {
                i++;
                Sync(i);
            }
        }
    }
}
