/*
 * [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
{

    /** <summary>All debugging events that a recognizer can trigger.</summary>
     *
     *  <remarks>
     *  I did not create a separate AST debugging interface as it would create
     *  lots of extra classes and DebugParser has a dbg var defined, which makes
     *  it hard to change to ASTDebugEventListener.  I looked hard at this issue
     *  and it is easier to understand as one monolithic event interface for all
     *  possible events.  Hopefully, adding ST debugging stuff won't be bad.  Leave
     *  for future. 4/26/2006.
     *  </remarks>
     */
    public interface IDebugEventListener
    {
        void Initialize();

        /** <summary>
         *  The parser has just entered a rule.  No decision has been made about
         *  which alt is predicted.  This is fired AFTER init actions have been
         *  executed.  Attributes are defined and available etc...
         *  The grammarFileName allows composite grammars to jump around among
         *  multiple grammar files.
         *  </summary>
         */
        void EnterRule( string grammarFileName, string ruleName );

        /** <summary>
         *  Because rules can have lots of alternatives, it is very useful to
         *  know which alt you are entering.  This is 1..n for n alts.
         *  </summary>
         */
        void EnterAlt( int alt );

        /** <summary>
         *  This is the last thing executed before leaving a rule.  It is
         *  executed even if an exception is thrown.  This is triggered after
         *  error reporting and recovery have occurred (unless the exception is
         *  not caught in this rule).  This implies an "exitAlt" event.
         *  The grammarFileName allows composite grammars to jump around among
         *  multiple grammar files.
         *  </summary>
         */
        void ExitRule( string grammarFileName, string ruleName );

        /** <summary>Track entry into any (...) subrule other EBNF construct</summary> */
        void EnterSubRule( int decisionNumber );

        void ExitSubRule( int decisionNumber );

        /** <summary>
         *  Every decision, fixed k or arbitrary, has an enter/exit event
         *  so that a GUI can easily track what LT/consume events are
         *  associated with prediction.  You will see a single enter/exit
         *  subrule but multiple enter/exit decision events, one for each
         *  loop iteration.
         *  </summary>
         */
        void EnterDecision(int decisionNumber, bool couldBacktrack);

        void ExitDecision( int decisionNumber );

        /** <summary>
         *  An input token was consumed; matched by any kind of element.
         *  Trigger after the token was matched by things like match(), matchAny().
         *  </summary>
         */
        void ConsumeToken( IToken t );

        /** <summary>
         *  An off-channel input token was consumed.
         *  Trigger after the token was matched by things like match(), matchAny().
         *  (unless of course the hidden token is first stuff in the input stream).
         *  </summary>
         */
        void ConsumeHiddenToken( IToken t );

        /** <summary>
         *  Somebody (anybody) looked ahead.  Note that this actually gets
         *  triggered by both LA and LT calls.  The debugger will want to know
         *  which Token object was examined.  Like consumeToken, this indicates
         *  what token was seen at that depth.  A remote debugger cannot look
         *  ahead into a file it doesn't have so LT events must pass the token
         *  even if the info is redundant.
         *  </summary>
         */
        void LT( int i, IToken t );

        /** <summary>
         *  The parser is going to look arbitrarily ahead; mark this location,
         *  the token stream's marker is sent in case you need it.
         *  </summary>
         */
        void Mark( int marker );

        /** <summary>
         *  After an arbitrairly long lookahead as with a cyclic DFA (or with
         *  any backtrack), this informs the debugger that stream should be
         *  rewound to the position associated with marker.
         *  </summary>
         */
        void Rewind( int marker );

        /** <summary>
         *  Rewind to the input position of the last marker.
         *  Used currently only after a cyclic DFA and just
         *  before starting a sem/syn predicate to get the
         *  input position back to the start of the decision.
         *  Do not "pop" the marker off the state.  mark(i)
         *  and rewind(i) should balance still.
         *  </summary>
         */
        void Rewind();

        void BeginBacktrack( int level );

        void EndBacktrack( int level, bool successful );

        /** <summary>
         *  To watch a parser move through the grammar, the parser needs to
         *  inform the debugger what line/charPos it is passing in the grammar.
         *  For now, this does not know how to switch from one grammar to the
         *  other and back for island grammars etc...
         *  </summary>
         *
         *  <remarks>
         *  This should also allow breakpoints because the debugger can stop
         *  the parser whenever it hits this line/pos.
         *  </remarks>
         */
        void Location( int line, int pos );

        /** <summary>
         *  A recognition exception occurred such as NoViableAltException.  I made
         *  this a generic event so that I can alter the exception hierachy later
         *  without having to alter all the debug objects.
         *  </summary>
         *
         *  <remarks>
         *  Upon error, the stack of enter rule/subrule must be properly unwound.
         *  If no viable alt occurs it is within an enter/exit decision, which
         *  also must be rewound.  Even the rewind for each mark must be unwount.
         *  In the Java target this is pretty easy using try/finally, if a bit
         *  ugly in the generated code.  The rewind is generated in DFA.predict()
         *  actually so no code needs to be generated for that.  For languages
         *  w/o this "finally" feature (C++?), the target implementor will have
         *  to build an event stack or something.
         *
         *  Across a socket for remote debugging, only the RecognitionException
         *  data fields are transmitted.  The token object or whatever that
         *  caused the problem was the last object referenced by LT.  The
         *  immediately preceding LT event should hold the unexpected Token or
         *  char.
         *
         *  Here is a sample event trace for grammar:
         *
         *  b : C ({;}A|B) // {;} is there to prevent A|B becoming a set
         *    | D
         *    ;
         *
         *  The sequence for this rule (with no viable alt in the subrule) for
         *  input 'c c' (there are 3 tokens) is:
         *
         *		commence
         *		LT(1)
         *		enterRule b
         *		location 7 1
         *		enter decision 3
         *		LT(1)
         *		exit decision 3
         *		enterAlt1
         *		location 7 5
         *		LT(1)
         *		consumeToken [c/<4>,1:0]
         *		location 7 7
         *		enterSubRule 2
         *		enter decision 2
         *		LT(1)
         *		LT(1)
         *		recognitionException NoViableAltException 2 1 2
         *		exit decision 2
         *		exitSubRule 2
         *		beginResync
         *		LT(1)
         *		consumeToken [c/<4>,1:1]
         *		LT(1)
         *		endResync
         *		LT(-1)
         *		exitRule b
         *		terminate
         *  </remarks>
         */
        void RecognitionException( RecognitionException e );

        /** <summary>
         *  Indicates the recognizer is about to consume tokens to resynchronize
         *  the parser.  Any consume events from here until the recovered event
         *  are not part of the parse--they are dead tokens.
         *  </summary>
         */
        void BeginResync();

        /** <summary>
         *  Indicates that the recognizer has finished consuming tokens in order
         *  to resychronize.  There may be multiple beginResync/endResync pairs
         *  before the recognizer comes out of errorRecovery mode (in which
         *  multiple errors are suppressed).  This will be useful
         *  in a gui where you want to probably grey out tokens that are consumed
         *  but not matched to anything in grammar.  Anything between
         *  a beginResync/endResync pair was tossed out by the parser.
         *  </summary>
         */
        void EndResync();

        /** <summary>A semantic predicate was evaluate with this result and action text</summary> */
        void SemanticPredicate( bool result, string predicate );

        /** <summary>
         *  Announce that parsing has begun.  Not technically useful except for
         *  sending events over a socket.  A GUI for example will launch a thread
         *  to connect and communicate with a remote parser.  The thread will want
         *  to notify the GUI when a connection is made.  ANTLR parsers
         *  trigger this upon entry to the first rule (the ruleLevel is used to
         *  figure this out).
         *  </summary>
         */
        void Commence();

        /** <summary>
         *  Parsing is over; successfully or not.  Mostly useful for telling
         *  remote debugging listeners that it's time to quit.  When the rule
         *  invocation level goes to zero at the end of a rule, we are done
         *  parsing.
         *  </summary>
         */
        void Terminate();


        #region Tree Parsing

        /** <summary>
         *  Input for a tree parser is an AST, but we know nothing for sure
         *  about a node except its type and text (obtained from the adaptor).
         *  This is the analog of the consumeToken method.  Again, the ID is
         *  the hashCode usually of the node so it only works if hashCode is
         *  not implemented.  If the type is UP or DOWN, then
         *  the ID is not really meaningful as it's fixed--there is
         *  just one UP node and one DOWN navigation node.
         *  </summary>
         *
         *  <param name="t" />
         */
        void ConsumeNode( object t );

        /** <summary>
         *  The tree parser lookedahead.  If the type is UP or DOWN,
         *  then the ID is not really meaningful as it's fixed--there is
         *  just one UP node and one DOWN navigation node.
         *  </summary>
         */
        void LT( int i, object t );

        #endregion


        #region AST Events

        /** <summary>
         *  A nil was created (even nil nodes have a unique ID...
         *  they are not "null" per se).  As of 4/28/2006, this
         *  seems to be uniquely triggered when starting a new subtree
         *  such as when entering a subrule in automatic mode and when
         *  building a tree in rewrite mode.
         *  </summary>
         *
         *  <remarks>
         *  If you are receiving this event over a socket via
         *  RemoteDebugEventSocketListener then only t.ID is set.
         *  </remarks>
         */
        void NilNode( object t );

        /** <summary>
         *  Upon syntax error, recognizers bracket the error with an error node
         *  if they are building ASTs.
         *  </summary>
         *
         *  <param name="t"/>
         */
        void ErrorNode( object t );

        /** <summary>Announce a new node built from token elements such as type etc...</summary>
         * 
         *  <remarks>
         *  If you are receiving this event over a socket via
         *  RemoteDebugEventSocketListener then only t.ID, type, text are
         *  set.
         *  </remarks>
         */
        void CreateNode( object t );

        /** <summary>Announce a new node built from an existing token.</summary>
         *
         *  <remarks>
         *  If you are receiving this event over a socket via
         *  RemoteDebugEventSocketListener then only node.ID and token.tokenIndex
         *  are set.
         *  </remarks>
         */
        void CreateNode( object node, IToken token );

        /** <summary>Make a node the new root of an existing root.  See</summary>
         *
         *  <remarks>
         *  Note: the newRootID parameter is possibly different
         *  than the TreeAdaptor.becomeRoot() newRoot parameter.
         *  In our case, it will always be the result of calling
         *  TreeAdaptor.becomeRoot() and not root_n or whatever.
         *
         *  The listener should assume that this event occurs
         *  only when the current subrule (or rule) subtree is
         *  being reset to newRootID.
         * 
         *  If you are receiving this event over a socket via
         *  RemoteDebugEventSocketListener then only IDs are set.
         *  </remarks>
         *
         *  <seealso cref="Antlr.Runtime.Tree.TreeAdaptor.becomeRoot()"/>
         */
        void BecomeRoot( object newRoot, object oldRoot );

        /** <summary>Make childID a child of rootID.</summary>
         *
         *  <remarks>
         *  If you are receiving this event over a socket via
         *  RemoteDebugEventSocketListener then only IDs are set.
         *  </remarks>
         *
         *  <seealso cref="Antlr.Runtime.Tree.TreeAdaptor.addChild()"/>
         */
        void AddChild( object root, object child );

        /** <summary>Set the token start/stop token index for a subtree root or node.</summary>
         *
         *  <remarks>
         *  If you are receiving this event over a socket via
         *  RemoteDebugEventSocketListener then only t.ID is set.
         *  </remarks>
         */
        void SetTokenBoundaries( object t, int tokenStartIndex, int tokenStopIndex );

        #endregion
    }
}
