//
// token.h
// Token hierarchy classes
// F.J. Alberti
// Created: 17/07/2001
// Last Modified: 17/07/2001
//
// Modification history:
// FA   17/07/2001    #Define MAXSIZETOKEN as alias of kMaxTokenLength
// FA   07/09/2001    Token lexeme is allocated in the heap      
//

#ifndef _TOKEN_H_
#define _TOKEN_H_


#include "textspan.h"



// Maximum token length. (This includes identifiers, numbers, but not strings)
const uint kMaxTokenLength         = 128;

// Maximum string length
// This constant should *not* be modified!
const uint kMaxStringLiteralLength = 16384;

// Old token length constant
#define MAXSIZETOKEN                 kMaxStringLiteralLength



class Token {
  friend class Lexer;
public:
  typedef enum {
    kNone,     // Null token
    kEOI,      // End of input
    kInt,      // Integer literal
    kFloat,    // Float literal
    kIdent,    // Identifier
    kString,   // String literal
    kChar,     // Character literal
    kDot,      // . 
    kEq,       // == 
    kNe,       // != 
    kIAdd,     // + 
    kISub,     // - 
    kIMul,     // * 
    kIDiv,     // / 
    kIPow,     // ^^ 
    kINot,     // ~ 
    kIAnd,     // & 
    kIOr,      // | 
    kIXor,     // ^ 
    kIShl,     // << 
    kIShr,     // >> 
    kILt,      // < 
    kILe,      // <=  
    kIGt,      // > 
    kIGe,      // >= 
    kLet,      // =    
    kFAdd,     // +. 
    kFSub,     // -. 
    kFMul,     // *. 
    kFDiv,     // /. 
    kFEq,      // =. 
    kFNe,      // !=. 
    kFLt,      // <. 
    kFLe,      // <=. 
    kFGt,      // >. 
    kFGe,      // >=. 
    kLNot,     // ! 
    kLAnd,     // && 
    kLOr,      // || 
    kCons,     // :: 
    kAtSign,   // @ 
    kSeq,      // ; 
    kGoesTo,   // -> 
    kTakes,    // <- 
    kComma,    // , 
    kLParen,   // ( 
    kRParen,   // ) 
    kLCurly,   // { 
    kRCurly,   // } 
    kLBrack,   // [ 
    kRBrack,   // ] 
    kEnds,     // ;; 
    kColon,    // :
    kNewline
  } Kind;
  
  Token();
//Token(Kind kind, const char* lexeme, const TextSpan& span);
  Token(const Token& tok);
  ~Token();
  
  Kind kind() const;
  bool null() const;
  bool is(Kind kind) const;
  const char* lexeme() const;
  const TextSpan& span() const;
  uint length() const;
  Token& operator =(const Token& tok);
  void nullify();
  
private:
  void append(int c);

  Kind     _kind;    // Token kind
  char*    _lexeme;  // Token lexeme (spelling)
  uint     _len;     // Lexeme length
  TextSpan _span;    // Token span in source text
};


inline Token::Kind Token::kind() const
{
  return _kind;
}


inline bool Token::null() const
{
  return _kind == kNone;
}


inline bool Token::is(Kind kind) const
{
  return _kind == kind;
}


inline const char* Token::lexeme() const
{
  return _lexeme;
}


inline const TextSpan& Token::span() const
{
  return _span;
}


inline uint Token::length() const
{
  return _len;
}


/*
class TokenInt: public Token {
public:
  TokenInt(const Token& tok, int val);
  ~TokenInt();

  int value() const;
  
private:  
  int _val;
};


inline TokenInt::TokenInt(const Token& tok, int val)
  : Token(tok), _val(val)
{
}

inline TokenInt::~TokenInt()
{
}

inline TokenInt::value() const
{
  return _val;
}


// Usage:
// Token tok;
// tok = lex.next();
// if (tok.is(Token::kInt))
//   cout << "int is " << ((TokenInt)tok).value() << endl;


class TokenFloat: public Token {
  ...
};

class TokenString: public Token {
  ...
}
*/


#endif // token.h