/**
 * \file
 * The definition of all debugging events that a recognizer can trigger.
 *
 * \remark
 *  From the java implementation by Terence Parr...
 *  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.
 */

#ifndef  ANTLR3_DEBUG_EVENT_LISTENER_H
#define  ANTLR3_DEBUG_EVENT_LISTENER_H

// [The "BSD licence"]
// Copyright (c) 2005-2009 Jim Idle, Temporal Wave LLC
// http://www.temporal-wave.com
// http://www.linkedin.com/in/jimidle
//
// 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.

#include    <antlr3defs.h>
#include    <antlr3basetree.h>
#include    <antlr3commontoken.h>


/// Default debugging port
///
#define DEFAULT_DEBUGGER_PORT    0xBFCC;

#ifdef __cplusplus
extern "C" {
#endif

/** The ANTLR3 debugging interface for communicating with ANLTR Works. Function comments
 *  mostly taken from the Java version.
 */
typedef struct ANTLR3_DEBUG_EVENT_LISTENER_struct
{
  /// The port number which the debug listener should listen on for a connection
  ///
  ANTLR3_UINT32    port;

  /// The socket structure we receive after a successful accept on the serverSocket
  ///
  SOCKET        socket;

  /** The version of the debugging protocol supported by the providing
   *  instance of the debug event listener.
   */
  int          PROTOCOL_VERSION;

  /// The name of the grammar file that we are debugging
  ///
  pANTLR3_STRING    grammarFileName;

  /// Indicates whether we have already connected or not
  ///
  ANTLR3_BOOLEAN    initialized;

  /// Used to serialize the values of any particular token we need to
  /// send back to the debugger.
  ///
  pANTLR3_STRING    tokenString;


  /// Allows the debug event system to access the adapter in use
  /// by the recognizer, if this is a tree parser of some sort.
  ///
  pANTLR3_BASE_TREE_ADAPTOR  adaptor;

  /// Wait for a connection from the debugger and initiate the
  /// debugging session.
  ///
  ANTLR3_BOOLEAN  (*handshake)    (pANTLR3_DEBUG_EVENT_LISTENER delboy);

  /** 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...
   */
  void      (*enterRule)    (pANTLR3_DEBUG_EVENT_LISTENER delboy, const char * grammarFileName, const char * ruleName);

  /** 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.
   */
  void      (*enterAlt)      (pANTLR3_DEBUG_EVENT_LISTENER delboy, int alt);

  /** 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.
   */
  void      (*exitRule)      (pANTLR3_DEBUG_EVENT_LISTENER delboy, const char * grammarFileName, const char * ruleName);

  /** Track entry into any (...) subrule other EBNF construct 
   */
  void      (*enterSubRule)    (pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber);
  
  void      (*exitSubRule)    (pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber);

  /** 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.
   */
  void      (*enterDecision)  (pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber);

  void      (*exitDecision)    (pANTLR3_DEBUG_EVENT_LISTENER delboy, int decisionNumber);

  /** An input token was consumed; matched by any kind of element.
   *  Trigger after the token was matched by things like match(), matchAny().
   */
  void      (*consumeToken)    (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_COMMON_TOKEN t);

  /** 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).
   */
  void      (*consumeHiddenToken)  (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_COMMON_TOKEN t);

  /** 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.
   */
  void      (*LT)        (pANTLR3_DEBUG_EVENT_LISTENER delboy, int i, pANTLR3_COMMON_TOKEN t);

  /** The parser is going to look arbitrarily ahead; mark this location,
   *  the token stream's marker is sent in case you need it.
   */
  void      (*mark)        (pANTLR3_DEBUG_EVENT_LISTENER delboy, ANTLR3_MARKER marker);

  /** After an arbitrarily 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.
   */
  void      (*rewind)      (pANTLR3_DEBUG_EVENT_LISTENER delboy, ANTLR3_MARKER marker);

  /** 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.
   */
  void      (*rewindLast)    (pANTLR3_DEBUG_EVENT_LISTENER delboy);

  void      (*beginBacktrack)  (pANTLR3_DEBUG_EVENT_LISTENER delboy, int level);

  void      (*endBacktrack)    (pANTLR3_DEBUG_EVENT_LISTENER delboy, int level, ANTLR3_BOOLEAN successful);

  /** 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...
   *
   *  This should also allow breakpoints because the debugger can stop
   *  the parser whenever it hits this line/pos.
   */
  void      (*location)      (pANTLR3_DEBUG_EVENT_LISTENER delboy, int line, int pos);

  /** A recognition exception occurred such as NoViableAltException.  I made
   *  this a generic event so that I can alter the exception hierarchy later
   *  without having to alter all the debug objects.
   *
   *  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 unwound.
   *  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
   */
  void      (*recognitionException)  (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_EXCEPTION e);

  /** 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.
   */
  void      (*beginResync)      (pANTLR3_DEBUG_EVENT_LISTENER delboy);

  /** Indicates that the recognizer has finished consuming tokens in order
   *  to resynchronize.  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.
   */
  void      (*endResync)      (pANTLR3_DEBUG_EVENT_LISTENER delboy);

  /** A semantic predicate was evaluate with this result and action text 
  */
  void      (*semanticPredicate)  (pANTLR3_DEBUG_EVENT_LISTENER delboy, ANTLR3_BOOLEAN result, const char * predicate);

  /** 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).
   */
  void      (*commence)        (pANTLR3_DEBUG_EVENT_LISTENER delboy);

  /** 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.
   */
  void      (*terminate)      (pANTLR3_DEBUG_EVENT_LISTENER delboy);

  /// Retrieve acknowledge response from the debugger. in fact this
  /// response is never used at the moment. So we just read whatever
  /// is in the socket buffer and throw it away.
  ///
  void      (*ack)          (pANTLR3_DEBUG_EVENT_LISTENER delboy);

  // T r e e  P a r s i n g

  /** 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.  The ID is usually 
   *  the memory address of the node.
   *  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.
   *
   *  Note that unlike the Java version, the node type of the C parsers
   *  is always fixed as pANTLR3_BASE_TREE because all such structures
   *  contain a super pointer to their parent, which is generally COMMON_TREE and within
   *  that there is a super pointer that can point to a user type that encapsulates it.
   *  Almost akin to saying that it is an interface pointer except we don't need to
   *  know what the interface is in full, just those bits that are the base.
   * @param t
   */
  void      (*consumeNode)      (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t);

  /** The tree parser looked ahead.  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.
   */
  void      (*LTT)          (pANTLR3_DEBUG_EVENT_LISTENER delboy, int i, pANTLR3_BASE_TREE t);


  // A S T  E v e n t s

  /** 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.
     *
    *  If you are receiving this event over a socket via
   *  RemoteDebugEventSocketListener then only t.ID is set.
   */
  void      (*nilNode)        (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t);

  /** If a syntax error occurs, recognizers bracket the error
   *  with an error node if they are building ASTs. This event
   *  notifies the listener that this is the case
   */
  void      (*errorNode)      (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t);

  /** Announce a new node built from token elements such as type etc...
   * 
   *  If you are receiving this event over a socket via
   *  RemoteDebugEventSocketListener then only t.ID, type, text are
   *  set.
   */
  void      (*createNode)      (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t);

  /** Announce a new node built from an existing token.
   *
   *  If you are receiving this event over a socket via
   *  RemoteDebugEventSocketListener then only node.ID and token.tokenIndex
   *  are set.
   */
  void      (*createNodeTok)    (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE node, pANTLR3_COMMON_TOKEN token);

  /** Make a node the new root of an existing root.  See
   *
   *  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.
   *
   *  @see org.antlr.runtime.tree.TreeAdaptor.becomeRoot()
   */
  void      (*becomeRoot)      (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE newRoot, pANTLR3_BASE_TREE oldRoot);

  /** Make childID a child of rootID.
   *
   *  If you are receiving this event over a socket via
   *  RemoteDebugEventSocketListener then only IDs are set.
   * 
   *  @see org.antlr.runtime.tree.TreeAdaptor.addChild()
   */
  void      (*addChild)        (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE root, pANTLR3_BASE_TREE child);

  /** Set the token start/stop token index for a subtree root or node.
   *
   *  If you are receiving this event over a socket via
   *  RemoteDebugEventSocketListener then only t.ID is set.
   */
  void      (*setTokenBoundaries)  (pANTLR3_DEBUG_EVENT_LISTENER delboy, pANTLR3_BASE_TREE t, ANTLR3_MARKER tokenStartIndex, ANTLR3_MARKER tokenStopIndex);

  /// Free up the resources allocated to this structure
  ///
  void      (*free)          (pANTLR3_DEBUG_EVENT_LISTENER delboy);

}
  ANTLR3_DEBUG_EVENT_LISTENER;

#ifdef __cplusplus
}
#endif

#endif

