//---------------------------------------------------------------------------

#ifndef lexanH
#define lexanH

#include <fstream>
#include <list>
#include <stdexcept>
#include <string>
#include "err.h"
class Lexan;
// ----------------------- exception components -----------------
class TokenReason {			// expected some tokens but other came
    int got_, exp1_, exp2_, exp3_;
    Lexan& lx_;
public:
    static const int none_;
    TokenReason (Lexan&, int, int, int =none_, int =none_);
    TokenReason (const TokenReason&);
    std::string tell (void) const; 
};
//---------------------------------------------------------------------------
class KWReason {
    Lexan& lx_;
public:
    KWReason (Lexan&);
    KWReason (const KWReason&);
    std::string tell (void) const; 
};//---------------------------------------------------------------------------
class NotYetReason {
    std::string feature_;
public:
    NotYetReason (const std::string&);
    NotYetReason (const NotYetReason&);
    std::string tell (void) const; 
};
// ==========================================================================
typedef CException <std::runtime_error, TokenReason,  FilePosition> SyntaxException;
typedef CException <std::runtime_error, KWReason,     FilePosition> KWException;
typedef CException <std::runtime_error, NotYetReason, FilePosition> NotYetException;
// ==========================================================================
class LexPosition;

class Lexan {
protected:
   std::ifstream F;

   // ----------------------- error reporting -----------------------
   friend class IOReason;
   friend class TokenReason;
   friend class LexPosition;

   std::list<std::pair<int,std::string> > keywords;
   std::list<std::pair<int,std::string> > symbols;
   std::string fn;
 
public:
    const std::string& DecodeSymbol(int);
    // ----------------------- output -------------------------------
    int Lex_AInt;
    double Lex_AReal;
    std::string Lex_AStr;
    int rowcount;
   

    Lexan(const char *);
    Lexan(){};
    virtual ~Lexan(){F.close();}

    void init(const char *);		// open input 
    virtual int NextToken()=0;		// give next token
    static const int none_;			// get next token and check against 1-3 values
    int CheckNextToken (int, int =none_, int =none_);
	int CheckNextToken (bool chk (int), int);
    int CheckToken (int, int, int =none_, int =none_);
};

//---------------------------------------------------------------------------
class LexPosition: public FilePosition {
public:
    LexPosition (Lexan& lx): FilePosition (lx.fn, lx.rowcount) {}
};

#endif
