#ifndef TOKEN_H
#define TOKEN_H

#include <stdint.h>

#include "config.h"
#include "string_manager.h"



#ifdef __cplusplus
extern "C" {
#endif



/**
 * トークン種別.
 */
typedef enum
{
	TT_UNKNOWN			= 0,			///< 未定義.

	TT_EOF,								///< End Of File.
	TT_EOL,								///< End Of Line.
	TT_SPACE,							///< Space [0x20,0x09,0x0B,0x0C].
	TT_COMMENT,							///< Comment.

	TT_IDENTIFIER,						///< 識別子.
	TT_STRING,							///< 文字列リテラル.
	TT_COMMAND,							///< コマンドリテラル.
	TT_CHARACTER,						///< 文字リテラル.
	TT_INTEGER,							///< 整数リテラル.
	TT_FLOAT,							///< 小数リテラル.
	TT_KEYWORD,							///< キーワード.

	TT_NOT,								///< !
	TT_NOTE,							///< !=
	TT_NOTLT,							///< !<
	TT_NOTGT,							///< !>
	TT_NOTLTE,							///< !<=
	TT_NOTGTE,							///< !>=
	TT_NOTLTGT,							///< !<>
	TT_NOTLTGTE,						///< !<>=

	TT_LT,								///< <
	TT_LTE,								///< <=
	TT_LTD,								///< <<
	TT_LTGT,							///< <>
	TT_LTDE,							///< <<=
	TT_LTGTE,							///< <>=

	TT_GT,								///< >
	TT_GTE,								///< >=
	TT_GTD,								///< >>
	TT_GTDE,							///< >>=
	TT_GTT,								///< >>>
	TT_GTTE,							///< >>>=

	TT_DOT,								///< .
	TT_DOTD,							///< ..
	TT_DOTT,							///< ...

	TT_AMP,								///< &
	TT_AMPE,							///< &=
	TT_AMPD,							///< &&

	TT_PIPE,							///< |
	TT_PIPEE,							///< |=
	TT_PIPED,							///< ||

	TT_MINUS,							///< -
	TT_MINUSE,							///< -=
	TT_MINUSD,							///< --


	TT_PLUS,							///< +
	TT_PLUSE,							///< +=
	TT_PLUSD,							///< ++

	TT_SLASH,							///< /
	TT_SLASHE,							///< /=

	TT_STAR,							///< *
	TT_STARE,							///< *=

	TT_EQUAL,							///< =
	TT_EQUALE,							///< ==

	TT_PARCENT,							///< %
	TT_PARCENTE,						///< %=

	TT_HAT,								///< ^
	TT_HATE,							///< ^=

	TT_TILD,							///< ~
	TT_TILDE,							///< ~=

	TT_PARENL,							///< (
	TT_PARENR,							///< )
	TT_BRACKETL,						///< [
	TT_BRACKETR,						///< ]
	TT_CURLYL,							///< {
	TT_CURLYR,							///< }
	TT_QUESTION,						///< ?
	TT_COMMA,							///< ,
	TT_SEMICOLON,						///< ;
	TT_COLON,							///< :
	TT_DOLLAR,							///< $
	TT_AT,								///< @
	TT_HASH,							///< #
	TT_ESCAPE,							///< '\\'

	TT_ID_END							///< トークン種別 ID の終わり.
} TokenType;


/**
 * キーワード.
 */
typedef enum
{
	K_UNKNOWN			= 0,			///< 未定義.
	K_IF,								///< if
	K_FOR,								///< for

	K_ID_END							///< キーワード ID の終わり.
} Keyword;


/**
 * トークンを表す.
 */
typedef struct
{
	TokenType		type;				///< トークン種別.
	union {
		char*		sVal;				///< 文字列, 識別子, コマンドリテラル.
		char		cVal;				///< 文字リテラル.
		uint64_t	iVal;				///< 整数リテラル.
		double		dVal;				///< 小数リテラル.
		Keyword		kVal;				///< キーワード.
	} v;
	char			file[MAX_FILENAME];	///< ファイル名.
	int				line;				///< 行番号.
	int				column;				///< カラム番号.
} Token;

/**
 * トークンリスト.
 */
typedef struct TokenList_
{
	Token* (*add)(struct TokenList_* const list, TokenType type,
			const void* const value, const char* const file, int line, int column);
	Token* (*get)(struct TokenList_* const list, const int index);
	void   (*clear)(struct TokenList_* const list);

	Token*			tokens;				///< トークン配列
	StringManager*	sm;					///< トークンで扱う文字列管理
	int				size;				///< トークンが格納されている数
	int				capacity;			///< 現在確保しているトークン配列数
} TokenList;


TokenList* TokenList_new(int cap);
void       TokenList_delete(TokenList* list);



#ifdef __cplusplus
}
#endif

#endif	/* TOKEN_H	*/

