/*
 * [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.Tree
{
    using ConditionalAttribute = System.Diagnostics.ConditionalAttribute;
    using Regex = System.Text.RegularExpressions.Regex;
    using RegexOptions = System.Text.RegularExpressions.RegexOptions;

    /** <summary>
     *  A parser for a stream of tree nodes.  "tree grammars" result in a subclass
     *  of this.  All the error reporting and recovery is shared with Parser via
     *  the BaseRecognizer superclass.
     *  </summary>
    */
    public class TreeParser : BaseRecognizer
    {
        public const int DOWN = TokenTypes.Down;
        public const int UP = TokenTypes.Up;

        // precompiled regex used by inContext
        static string dotdot = ".*[^.]\\.\\.[^.].*";
        static string doubleEtc = ".*\\.\\.\\.\\s+\\.\\.\\..*";
        static Regex dotdotPattern = new Regex( dotdot, RegexOptions.Compiled );
        static Regex doubleEtcPattern = new Regex( doubleEtc, RegexOptions.Compiled );

        protected ITreeNodeStream input;

        public TreeParser( ITreeNodeStream input )
            : base() // highlight that we go to super to set state object
        {
            SetTreeNodeStream( input );
        }

        public TreeParser( ITreeNodeStream input, RecognizerSharedState state )
            : base( state ) // share the state object with another parser
        {
            SetTreeNodeStream( input );
        }

        public override void Reset()
        {
            base.Reset(); // reset all recognizer state variables
            if ( input != null )
            {
                input.Seek( 0 ); // rewind the input
            }
        }

        /** <summary>Set the input stream</summary> */
        public virtual void SetTreeNodeStream( ITreeNodeStream input )
        {
            this.input = input;
        }

        public virtual ITreeNodeStream GetTreeNodeStream()
        {
            return input;
        }

        public override string SourceName
        {
            get
            {
                return input.SourceName;
            }
        }

        protected override object GetCurrentInputSymbol( IIntStream input )
        {
            return ( (ITreeNodeStream)input ).LT( 1 );
        }

        protected override object GetMissingSymbol( IIntStream input,
                                          RecognitionException e,
                                          int expectedTokenType,
                                          BitSet follow )
        {
            string tokenText =
                "<missing " + TokenNames[expectedTokenType] + ">";
            ITreeAdaptor adaptor = ((ITreeNodeStream)e.Input).TreeAdaptor;
            return adaptor.Create(new CommonToken(expectedTokenType, tokenText));
        }

        /** <summary>
         *  Match '.' in tree parser has special meaning.  Skip node or
         *  entire tree if node has children.  If children, scan until
         *  corresponding UP node.
         *  </summary>
         */
        public override void MatchAny( IIntStream ignore )
        {
            state.errorRecovery = false;
            state.failed = false;
            // always consume the current node
            input.Consume();
            // if the next node is DOWN, then the current node is a subtree:
            // skip to corresponding UP. must count nesting level to get right UP
            int look = input.LA( 1 );
            if ( look == DOWN )
            {
                input.Consume();
                int level = 1;
                while ( level > 0 )
                {
                    switch ( input.LA( 1 ) )
                    {
                    case DOWN:
                        level++;
                        break;
                    case UP:
                        level--;
                        break;
                    case TokenTypes.EndOfFile:
                        return;
                    default:
                        break;
                    }
                    input.Consume();
                }
            }
        }

        /** <summary>
         *  We have DOWN/UP nodes in the stream that have no line info; override.
         *  plus we want to alter the exception type.  Don't try to recover
         *  from tree parser errors inline...
         *  </summary>
         */
        protected override object RecoverFromMismatchedToken( IIntStream input, int ttype, BitSet follow )
        {
            throw new MismatchedTreeNodeException( ttype, (ITreeNodeStream)input );
        }

        /** <summary>
         *  Prefix error message with the grammar name because message is
         *  always intended for the programmer because the parser built
         *  the input tree not the user.
         *  </summary>
         */
        public override string GetErrorHeader( RecognitionException e )
        {
            return GrammarFileName + ": node from " +
                   ( e.ApproximateLineInfo ? "after " : "" ) + "line " + e.Line + ":" + e.CharPositionInLine;
        }

        /** <summary>
         *  Tree parsers parse nodes they usually have a token object as
         *  payload. Set the exception token and do the default behavior.
         *  </summary>
         */
        public override string GetErrorMessage( RecognitionException e, string[] tokenNames )
        {
            if ( this is TreeParser )
            {
                ITreeAdaptor adaptor = ( (ITreeNodeStream)e.Input ).TreeAdaptor;
                e.Token = adaptor.GetToken( e.Node );
                if ( e.Token == null )
                { // could be an UP/DOWN node
                    e.Token = new CommonToken( adaptor.GetType( e.Node ),
                                              adaptor.GetText( e.Node ) );
                }
            }
            return base.GetErrorMessage( e, tokenNames );
        }

        [Conditional("ANTLR_TRACE")]
        public virtual void TraceIn( string ruleName, int ruleIndex )
        {
            base.TraceIn( ruleName, ruleIndex, input.LT( 1 ) );
        }

        [Conditional("ANTLR_TRACE")]
        public virtual void TraceOut( string ruleName, int ruleIndex )
        {
            base.TraceOut( ruleName, ruleIndex, input.LT( 1 ) );
        }

    }
}
