// $Id: parser.h,v 1.3 1999/01/25 20:00:31 shields Exp $
copyright notice

#ifndef parser_INCLUDED
#define parser_INCLUDED

#include "config.h"
#include <limits.h>
#include <ctype.h>
#include <wchar.h>
#include <string.h>
#include <stdio.h>
#include "lpginput.h"

class StoragePool;
class AstPackageDeclaration;
class AstCompilationUnit;
class AstClassBody;
class AstInterfaceDeclaration;
class Ast;
class AstListNode;
 
struct SecondaryRepairInfo
{
    int code,
        distance,
        buffer_position,
        stack_position,
        num_deletions,
        symbol;
 
    bool recovery_on_next_stack;
};

class Parser : public javaprs_table
{
public:     

    Parser() : ast_pool(NULL),
               parse_package_header_only(false),
               parse_header_only(false),
               stack(NULL),
               location_stack(NULL),
               parse_stack(NULL),
               temp_stack(NULL),
               stack_length(0)
    {
        InitRuleAction();
        return;
    }
 
    ~Parser()
    {
        delete [] stack;
        delete [] location_stack;
        delete [] parse_stack;
        delete [] temp_stack;
    }
 
    AstPackageDeclaration *PackageHeaderParse(LexStream *, StoragePool *);
    AstCompilationUnit *HeaderParse(LexStream *, StoragePool * = NULL);
    bool InitializerParse(LexStream *, AstClassBody *);
    bool InitializerParse(LexStream *, AstInterfaceDeclaration *);
    bool BodyParse(LexStream *, AstClassBody *);
    bool BodyParse(LexStream *, AstInterfaceDeclaration *);

protected:

    TokenObject buffer[BUFF_SIZE];
    TokenObject end_token;

    Ast *HeaderParse();
    bool Initializer(AstClassBody *);
    bool Initializer(AstInterfaceDeclaration *);
    bool Body(AstClassBody *);
    bool Body(AstInterfaceDeclaration *);
    Ast *ParseSegment(TokenObject);

#define HEADERS
#include "javaact.h"

    void (Parser::*rule_action[NUM_RULES + 1]) ();

    void InitRuleAction();

    //******************************************************************************
    //
    // Given a rule of the form     A ::= x1 x2 ... xn     n > 0
    //
    // the function Token(i) yields the symbol xi, if xi is a terminal
    // or ti, if xi is a nonterminal that produced a string of the form
    // xi => ti w.
    //
    //******************************************************************************
    inline LexStream::TokenIndex Token(int i)
    {
        return location_stack[state_stack_top + (i - 1)];
    }

    //******************************************************************************
    //
    // Given a rule of the form     A ::= x1 x2 ... xn     n > 0
    //
    // the function Sym(i) yields the AST subtree associated with symbol
    // xi. NOTE that if xi is a terminal, Sym(i) is undefined !
    //
    //******************************************************************************
    inline Ast*& Sym(int i) { return parse_stack[state_stack_top + (i - 1)]; }

    //******************************************************************************
    //
    // When a token is shifted, we also construct a null AST for
    // it.  This is necessary in case we encounter an error and need to
    // delete AST subtrees from the parse stack - those corresponding to
    // shifted tokens should also have a valid subtree.
    //
    //******************************************************************************
    inline void TokenAction(TokenObject curtok) { Sym(1) = NULL; }

    LexStream *lex_stream;

    StoragePool *ast_pool,
                *body_pool,
                *list_node_pool;

    AstListNode *free_list_nodes;
    AstListNode *AllocateListNode();
    void FreeCircularList(AstListNode *);

    bool parse_header_only,
         parse_package_header_only;

    //
    // LOCATION_STACK is a stack that is "parallel" to
    // (STATE_)STACK that is used to keep
    // track of the location of the first token on which an action
    // was executed in the corresponding state.
    //
    Location *location_stack;
    Ast **parse_stack;

    enum { STACK_INCREMENT = 256 };

    int stack_length,
        state_stack_top,
        *stack,
 
        temp_stack_top,
        *temp_stack;

    static inline int Min(int x, int y) { return ((x) < (y) ? (x) : (y)); }
    static inline int Max(int x, int y) { return ((x) > (y) ? (x) : (y)); }

    void AllocateErrorStacks();
    void ReallocateStacks();
    void ErrorRepair(TokenObject error_token);
    void RepairParse(TokenObject);
    SecondaryRepairInfo ErrorSurgery(int stack[],
                                     int stack_top,
                                     int last_index,
                                     SecondaryRepairInfo repair);
    int ParseCheck(int stack[], int stack_top, int first_token, int buffer_position);
};

#endif