/*
 * [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.Debug
{
    using System.Collections.Generic;
    using ParseTree = Antlr.Runtime.Tree.ParseTree;

    /** <summary>
     *  This parser listener tracks rule entry/exit and token matches
     *  to build a simple parse tree using ParseTree nodes.
     *  </summary>
     */
    public class ParseTreeBuilder : BlankDebugEventListener
    {
        public const string EPSILON_PAYLOAD = "<epsilon>";

        Stack<ParseTree> callStack = new Stack<ParseTree>();
        List<IToken> hiddenTokens = new List<IToken>();
        int backtracking = 0;

        public ParseTreeBuilder( string grammarName )
        {
            ParseTree root = Create( "<grammar " + grammarName + ">" );
            callStack.Push( root );
        }

        public virtual ParseTree Tree
        {
            get
            {
                return callStack.Peek();
            }
        }

        /** <summary>
         *  What kind of node to create.  You might want to override
         *  so I factored out creation here.
         *  </summary>
         */
        public virtual ParseTree Create( object payload )
        {
            return new ParseTree( payload );
        }

        public virtual ParseTree EpsilonNode()
        {
            return Create( EPSILON_PAYLOAD );
        }

        /** <summary>Backtracking or cyclic DFA, don't want to add nodes to tree</summary> */
        public override void EnterDecision( int d, bool couldBacktrack )
        {
            backtracking++;
        }
        public override void ExitDecision( int i )
        {
            backtracking--;
        }

        public override void EnterRule( string filename, string ruleName )
        {
            if ( backtracking > 0 )
                return;
            ParseTree parentRuleNode = callStack.Peek();
            ParseTree ruleNode = Create( ruleName );
            parentRuleNode.AddChild( ruleNode );
            callStack.Push( ruleNode );
        }

        public override void ExitRule( string filename, string ruleName )
        {
            if ( backtracking > 0 )
                return;
            ParseTree ruleNode = callStack.Peek();
            if ( ruleNode.ChildCount == 0 )
            {
                ruleNode.AddChild( EpsilonNode() );
            }
            callStack.Pop();
        }

        public override void ConsumeToken( IToken token )
        {
            if ( backtracking > 0 )
                return;
            ParseTree ruleNode = callStack.Peek();
            ParseTree elementNode = Create( token );
            elementNode.hiddenTokens = this.hiddenTokens;
            this.hiddenTokens = new List<IToken>();
            ruleNode.AddChild( elementNode );
        }

        public override void ConsumeHiddenToken( IToken token )
        {
            if ( backtracking > 0 )
                return;
            hiddenTokens.Add( token );
        }

        public override void RecognitionException( RecognitionException e )
        {
            if ( backtracking > 0 )
                return;
            ParseTree ruleNode = callStack.Peek();
            ParseTree errorNode = Create( e );
            ruleNode.AddChild( errorNode );
        }
    }
}
