/* ANTLRParser.h
 *
 * Define the generic ANTLRParser superclass, which is subclassed to
 * define an actual parser.
 *
 * Before entry into this file: ANTLRTokenType must be set.
 *
 * SOFTWARE RIGHTS
 *
 * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
 * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
 * company may do whatever they wish with source code distributed with
 * PCCTS or the code generated by PCCTS, including the incorporation of
 * PCCTS, or its output, into commerical software.
 *
 * We encourage users to develop software with PCCTS.  However, we do ask
 * that credit is given to us for developing PCCTS.  By "credit",
 * we mean that if you incorporate our source code into one of your
 * programs (commercial product, research project, or otherwise) that you
 * acknowledge this fact somewhere in the documentation, research report,
 * etc...  If you like PCCTS and have developed a nice tool with the
 * output, please mention that you developed it using PCCTS.  In
 * addition, we ask that this header remain intact in our source code.
 * As long as these guidelines are kept, we expect to continue enhancing
 * this system and expect to make other tools available as they are
 * completed.
 *
 * ANTLR 1.33
 * Terence Parr
 * Parr Research Corporation
 * with Purdue University and AHPCRC, University of Minnesota
 * 1989-1998
 */

#ifndef APARSER_H_GATE
#define APARSER_H_GATE

#include "pcctscfg.h"

#include "pccts_stdio.h"
#include "pccts_setjmp.h"

PCCTS_NAMESPACE_STD

#include ATOKEN_H
#include ATOKENBUFFER_H

#ifdef ZZCAN_GUESS
#ifndef ZZINF_LOOK
#define ZZINF_LOOK
#endif
#endif


#define NLA      (token_type[lap&(LLk-1)])/* --> next LA */

typedef unsigned char SetWordType;

/* Define external bit set stuff (for SetWordType) */
#define EXT_WORDSIZE  (sizeof(char)*8)
#define EXT_LOGWORDSIZE  3

           /* s y n t a c t i c  p r e d i c a t e  s t u f f */

#ifndef zzUSER_GUESS_HOOK
#define zzUSER_GUESS_HOOK(seqFrozen,zzrv)
#endif

#ifndef zzUSER_GUESS_DONE_HOOK
#define zzUSER_GUESS_DONE_HOOK(seqFrozen)
#endif

/* MR14 Add zzUSER_GUESS_FAIL_HOOK and related code */

#define zzUSER_GUESS_FAIL_HOOK_INTERNAL zzUSER_GUESS_FAIL_HOOK(SeqFrozen)
#ifndef zzUSER_GUESS_FAIL_HOOK
#define zzUSER_GUESS_FAIL_HOOK(zzGuessSeq)
#endif


typedef struct _zzjmp_buf {
      jmp_buf state;
    } zzjmp_buf;

/* these need to be macros not member functions */
#define zzGUESS_BLOCK    ANTLRParserState zzst; int zzrv; int _marker; int zzGuessSeqFrozen;
#define zzNON_GUESS_MODE  if ( !guessing )
#define zzGUESS_FAIL    guess_fail();

/*  Note:  zzGUESS_DONE does not execute longjmp() */

#define zzGUESS_DONE    {zzrv=1; inputTokens->rewind(_marker); guess_done(&zzst);zzUSER_GUESS_DONE_HOOK(zzGuessSeqFrozen) }
#define zzGUESS        saveState(&zzst); \
              guessing = 1; \
                            zzGuessSeqFrozen = ++zzGuessSeq; \
              _marker = inputTokens->mark(); \
              zzrv = setjmp(guess_start.state); \
                            zzUSER_GUESS_HOOK(zzGuessSeqFrozen,zzrv) \
                if ( zzrv ) zzGUESS_DONE

#define zzTRACEdata     const ANTLRChar *zzTracePrevRuleName = NULL;

#ifndef zzTRACEIN
#define zzTRACEIN(r)  zzTracePrevRuleName=traceCurrentRuleName;tracein(r);
#endif
#ifndef zzTRACEOUT
#define zzTRACEOUT(r)  traceout(r);traceCurrentRuleName=zzTracePrevRuleName;
#endif

                  /* a n t l r  p a r s e r  d e f */

struct ANTLRParserState {
  /* class variables */
  zzjmp_buf guess_start;
  int guessing;

  int inf_labase;
  int inf_last;

  int dirty;

    int             traceOptionValue;       // MR10
    int             traceGuessOptionValue;  // MR10
    const ANTLRChar *traceCurrentRuleName;  // MR10
    int             traceDepth;             // MR10

};

/* notes:
 *
 * multiple inheritance is a cool way to include what stuff is needed
 * in this structure (like guess stuff).  however, i'm not convinced that
 * multiple inheritance works correctly on all platforms.  not that
 * much space is used--just include all possibly useful members.
 *
 * the class should also be a template with arguments for the lookahead
 * depth and so on.  that way, more than one parser can be defined (as
 * each will probably have different lookahead requirements).  however,
 * am i sure that templates work?  no, i'm not sure.
 *
 * no attributes are maintained and, hence, the 'asp' variable is not
 * needed.  $i can still be referenced, but it refers to the token
 * associated with that rule element.  question: where are the token's
 * stored if not on the software stack?  in local variables created
 * and assigned to by antlr.
 */
class ANTLRParser {
protected:
  /* class variables */
  static SetWordType bitmask[sizeof(SetWordType)*8];
  static char eMsgBuffer[500];

protected:
  int LLk;          // number of lookahead symbols (old LL_K)
  int demand_look;
  ANTLRTokenType eofToken;      // when do I stop during resynch()s
  int bsetsize;                 // size of bitsets created by ANTLR in
                        // units of SetWordType

  ANTLRTokenBuffer *inputTokens;  //place to get input tokens

  zzjmp_buf guess_start;    // where to jump back to upon failure
  int guessing;        // if guessing (using (...)? predicate)

  // infinite lookahead stuff
  int can_use_inf_look;    // set by subclass (generated by ANTLR)
  int inf_lap;
  int inf_labase;
  int inf_last;
  int *_inf_line;

  const ANTLRChar **token_tbl; // pointer to table of token type strings MR20 const

  int dirty;          // used during demand lookahead

  ANTLRTokenType *token_type;    // fast reference cache of token.getType()
//  ANTLRLightweightToken **token;  // the token with all its attributes
  int lap;
  int labase;
#ifdef ZZDEFER_FETCH
  int stillToFetch;                               // MR19 V.H. Simonis
#endif

private:
  void fill_inf_look();

protected:
  virtual void guess_fail() {                         // MR9 27-Sep-97 make virtual
        traceGuessFail();                               // MR10
        longjmp(guess_start.state, 1); }                // MR9
  virtual void guess_done(ANTLRParserState *st) {     // MR9 27-Sep-97 make virtual
         restoreState(st); }                            // MR9
  virtual int guess(ANTLRParserState *);              // MR9 27-Sep-97 make virtual
  void look(int);
    int _match(ANTLRTokenType, ANTLRChar **, ANTLRTokenType *,
         _ANTLRTokenPtr *, SetWordType **);
    int _setmatch(SetWordType *, ANTLRChar **, ANTLRTokenType *,
         _ANTLRTokenPtr *, SetWordType **);
    int _match_wsig(ANTLRTokenType);
    int _setmatch_wsig(SetWordType *);
    virtual void consume();
    virtual void resynch(SetWordType *wd,SetWordType mask); // MR21
  void prime_lookahead();
  virtual void tracein(const ANTLRChar *r);              // MR10
  virtual void traceout(const ANTLRChar *r);             // MR10
  static unsigned MODWORD(unsigned x) {return x & (EXT_WORDSIZE-1);}  // x % EXT_WORDSIZE // MR9
  static unsigned DIVWORD(unsigned x) {return x >> EXT_LOGWORDSIZE;}  // x / EXT_WORDSIZE // MR9
  int set_deg(SetWordType *);
  int set_el(ANTLRTokenType, SetWordType *);
  virtual void edecode(SetWordType *);        // MR1
  virtual void FAIL(int k, ...);              // MR1
    int                 traceOptionValue;                           // MR10
    int                 traceGuessOptionValue;                      // MR10
    const ANTLRChar     *traceCurrentRuleName;                      // MR10
    int                 traceDepth;                                 // MR10
    void                traceReset();                               // MR10
    virtual void        traceGuessFail();                           // MR10
    virtual void        traceGuessDone(const ANTLRParserState *);   // MR10
    int                 zzGuessSeq;                                 // MR10

public:
  ANTLRParser(ANTLRTokenBuffer *,
        int k=1,
        int use_inf_look=0,
        int demand_look=0,
        int bsetsize=1);
  virtual ~ANTLRParser();

  virtual void init();
  
  ANTLRTokenType LA(int i)
  {
//
//  MR14 demand look will always be 0 for C++ mode
//
////  return demand_look ? token_type[(labase+(i)-1)&(LLk-1)] :
////            token_type[(lap+(i)-1)&(LLk-1)];

// MR19 V.H. Simonis Defer fetch feature

#ifdef ZZDEFER_FETCH
      undeferFetch();
#endif
    return token_type[(lap+(i)-1)&(LLk-1)];
  }
  _ANTLRTokenPtr LT(int i);

  void setEofToken(ANTLRTokenType t)  { eofToken = t; }
  ANTLRTokenType getEofToken() const  { return eofToken; }    // MR14

  void noGarbageCollectTokens()  { inputTokens->noGarbageCollectTokens(); }
  void garbageCollectTokens()    { inputTokens->garbageCollectTokens(); }

    virtual void syn(_ANTLRTokenPtr tok, ANTLRChar *egroup,
           SetWordType *eset, ANTLRTokenType etok, int k);
  virtual void saveState(ANTLRParserState *);     // MR9 27-Sep-97 make virtual
  virtual void restoreState(ANTLRParserState *);  // MR9 27-Sep-97 make virtual

  virtual void panic(const char *msg); // MR20 const
  static char *eMsgd(char *,int);
  static char *eMsg(char *,char *);
  static char *eMsg2(char *,char *,char *);

  void consumeUntil(SetWordType *st);
  void consumeUntilToken(int t);

  virtual int _setmatch_wdfltsig(SetWordType *tokensWanted,
           ANTLRTokenType tokenTypeOfSet,
           SetWordType *whatFollows);
  virtual int _match_wdfltsig(ANTLRTokenType tokenWanted,
           SetWordType *whatFollows);
  
  const ANTLRChar * parserTokenName(int tok);      // MR1

    int                 traceOptionValueDefault;        // MR11
    int                 traceOption(int delta);         // MR11
    int                 traceGuessOption(int delta);    // MR11

//  MR8  5-Aug-97   S.Bochnak@microtool.com.pl
//  MR8             Move resynch static local variable
//  MR8               to class instance

    int                 syntaxErrCount;                      // MR12
    ANTLRTokenStream   *getLexer() const {                   // MR12
      return inputTokens ? inputTokens->getLexer() : 0; }    // MR12
protected:                                              // MR8
    int     resynchConsumed;                            // MR8
    char    *zzFAILtext; // workarea required by zzFAIL // MR9
    void    undeferFetch();                             // MR19 V.H. Simonis
    int     isDeferFetchEnabled();                      // MR19 V.H. Simonis
};

#define zzmatch(_t)              \
  if ( !_match((ANTLRTokenType)_t, &zzMissText, &zzMissTok, \
         (_ANTLRTokenPtr *) &zzBadTok, &zzMissSet) ) goto fail;

#define zzmatch_wsig(_t,handler)            \
  if ( !_match_wsig((ANTLRTokenType)_t) ) if ( guessing ) zzGUESS_FAIL else {_signal=MismatchedToken; goto handler;}

#define zzsetmatch(_ts)              \
  if ( !_setmatch(_ts, &zzMissText, &zzMissTok, \
         (_ANTLRTokenPtr *) &zzBadTok, &zzMissSet) ) goto fail;

#define zzsetmatch_wsig(_ts, handler)        \
  if ( !_setmatch_wsig(_ts) ) if ( guessing ) zzGUESS_FAIL else {_signal=MismatchedToken; goto handler;}

/* For the dflt signal matchers, a FALSE indicates that an error occurred
 * just like the other matchers, but in this case, the routine has already
 * recovered--we do NOT want to consume another token.  However, when
 * the match was successful, we do want to consume hence _signal=0 so that
 * a token is consumed by the "if (!_signal) consume(); _signal=NoSignal;"
 * preamble.
 */
#define zzsetmatch_wdfltsig(tokensWanted, tokenTypeOfSet, whatFollows) \
  if ( !_setmatch_wdfltsig(tokensWanted, tokenTypeOfSet, whatFollows) ) \
    _signal = MismatchedToken;

#define zzmatch_wdfltsig(tokenWanted, whatFollows) \
  if ( !_match_wdfltsig(tokenWanted, whatFollows) ) _signal = MismatchedToken;


//  MR1  10-Apr-97   zzfailed_pred() macro does not backtrack
//  MR1        in guess mode.
//  MR1      Identification and correction due to J. Lilley

#ifndef zzfailed_pred
#define zzfailed_pred(_p) \
  if (guessing) { \
    zzGUESS_FAIL; \
  } else { \
    fprintf(stdout,"line %d: semantic error; failed predicate: '%s'\n", \
  LT(1)->getLine(), _p); \
  }
#endif

#define zzRULE \
    SetWordType *zzMissSet=NULL; ANTLRTokenType zzMissTok=(ANTLRTokenType)0;  \
    _ANTLRTokenPtr zzBadTok=NULL; ANTLRChar *zzBadText=(ANTLRChar *)"";  \
    int zzErrk=1,zzpf=0; \
        zzTRACEdata \
    ANTLRChar *zzMissText=(ANTLRChar *)"";

#endif

        /* S t a n d a r d  E x c e p t i o n  S i g n a l s */

#define NoSignal      0
#define MismatchedToken    1
#define NoViableAlt      2
#define NoSemViableAlt    3

/* MR7  Allow more control over signalling                                  */
/*        by adding "Unwind" and "SetSignal"                                */

#define Unwind              4
#define setSignal(newValue) *_retsignal=_signal=(newValue)
#define suppressSignal       *_retsignal=_signal=0
#define exportSignal        *_retsignal=_signal
