#include <windows.h>
#include "coutputwnd.h"
#include "cstringtable.h"

//TODO - dovolit v stringu ' a "
//ak string zacne ' potom '    "      "    " " ' je ok, moze sa tam nachadzat milion "
//ak chcem dat ', potom musim dat dve za sebou ' '' '  to je string obsahujuci ', teda "'"
//podobne z "   '' ' ' ' ''''' "" " - obsahuje ' a jednu "

#ifndef __LEXICALCLASS
#define __LEXICALCLASS

//definuj max. velkost tokenu
//cisla v postgresql typu numeric su dlhe max. 1000 znakov, preto dlzka tohto tokenu by nemala byt > ako 1000
#define	LEXICAL_MAX_TOKEN_LENGTH			100


#define LEXICAL_TOKEN_UNDEFINED				0
#define LEXICAL_TOKEN_WHITESPACE			1
#define LEXICAL_TOKEN_NUMBER				2
#define LEXICAL_TOKEN_IDENTIFIER			3
#define LEXICAL_TOKEN_LEFTPARENTHESIS		4
#define LEXICAL_TOKEN_RIGHTPARENTHESIS		5
#define LEXICAL_TOKEN_STRING				6
#define LEXICAL_TOKEN_EXCLAMATION			7
#define LEXICAL_TOKEN_PLUS					8
#define LEXICAL_TOKEN_MINUS					9
#define LEXICAL_TOKEN_MULTIPLY				10
#define LEXICAL_TOKEN_DIVIDE				11
#define LEXICAL_TOKEN_DOT					12
#define LEXICAL_TOKEN_LESS					13
#define LEXICAL_TOKEN_GREATER				14
#define LEXICAL_TOKEN_EQUAL					15
#define LEXICAL_TOKEN_COMMA					16
#define LEXICAL_TOKEN_SEMICOLON				17
#define LEXICAL_TOKEN_UNDERSCORE			18
#define LEXICAL_TOKEN_KEYWORD				19
#define LEXICAL_TOKEN_EOL					-1	//koniec riadku, end of line

/*#define LEXICAL_ATOMREL						1
#define LEXICAL_ATOMARIT					2

/*#define LEXICAL_READ_ONLYRELATOM			1
#define LEXICAL_READ_WITHINLINE				2 //hlada len v danom riadku*/

/*#define LEXICAL_EXP_BLANK					0
#define LEXICAL_EXP_STRING					1
#define LEXICAL_EXP_EXP						2
#define LEXICAL_EXP_INVALID					3 //chyba vo vyraze, nespravny vyraz*/

#define LEXICAL_HILIGHT_IDBATOM			1
#define LEXICAL_HILIGHT_EDBATOM			2
#define LEXICAL_HILIGHT_NUMBER			3
#define LEXICAL_HILIGHT_KEYWORD			4
#define LEXICAL_HILIGHT_ANSWER			5		//IDB atom answer()
#define LEXICAL_HILIGHT_STRING			6

struct LEXICAL_HILIGHTED_ATOMS_POS
{
	DWORD pos_begin;//pozicia v stringu, ktory berie funkcia na vstupe
	DWORD pos_end;//konecna pozicia v stringu, ktory bere funkcia na vstupe
	BYTE type;//typ - ex/in/subtotal
};

#pragma warning(push)
#pragma warning( disable : 4200 ) //kvoli poliam nulovej velkosti, tj. []

//pre metodu ::GetHilightedAtoms
struct LEXICAL_HILIGHTED_ATOMS
{
	DWORD count;//pocet zvyraznenych atomov
	LEXICAL_HILIGHTED_ATOMS_POS item[];
};
#pragma warning(pop)

class CLexicalAnalyzer
{
	private:
		const char* input;//pointer do pamate, kde sme skoncili
		const char* _input;//vstup lexikalneho analyzatora
		char* token;//rozpoznany token
		DWORD tokenType;//typ rozpoznaneho tokenu
		char charReaded;//nacitany znak
		char charReadedOld;//charReaded pre rollback
		DWORD inputIndex;//pointer na nenacitany znak
		DWORD inputIndexOld;//pointer na nenacitany znak predchadzajuceho tokenu (kvoli RollbackToken)
		DWORD lineNum;//cislo spracovavaneho riadku (kvoli chybe)
		DWORD lineNumOld;//lineNum pre rollback
		DWORD charPos;//cislo aktualneho znaku v celkom texte
		DWORD charPosOld;//charPos pre rollback
		DWORD charPosInLine;//cislo aktualneho znaku v riadku
		DWORD charPosInLineOld;//charPosInLine pre rollback
		bool flagEOL;//ak je flag true a nacita sa nieco z riadku, tak lineNum++
	public:
		char ReadChar();//nacita jeden znak zo vstupu
		char GetChar();//vrati uz nacitany znak zo vstupu
		char LookAheadChar();//vrati nasledujuci (este nenacitany) znak
		CLexicalAnalyzer(void*);
		~CLexicalAnalyzer();
		DWORD GetToken(const char** str);//vrati uz nacitany token v str a jeho typ
		void RollbackToken();//vrati posledny token znova na vstup (teda na opatovne precitanie)
		DWORD LookAheadToken();//vrati typ nasledujuceho tokenu
		DWORD GetLineNumber();//vrati aktualne cislo riadku
		DWORD GetCharPos();//vrati poziciu aktualneho znaku v texte
		DWORD GetCharPosInLine();//vrati poziciu znaku v riadku
		void Restart();//zacne citat vstup odznova
		bool EndOfInput();//vrati true, ak uz nie je ziaden znak na vstupe
		void GoToNextLine();//postavi sa na zaciatok noveho riadku
		void SkipEmptyLines();//preskoci prazdne riadky a zastane na prvom neprazdnom
		static bool IsKeyword(const char *str);//klucove slovo?

		LEXICAL_HILIGHTED_ATOMS *HilightsWords(CStringTable *atomsIDB);

		//const char* SetInput(char* input);//nastavi premennu input a vrati povodnu hodnotu
		DWORD ReadToken(const char** str);//nacita novy token do str a vrati jeho typ
		DWORD ReadToken_NoWhiteSpaces(const char** str);//nacita token do str a vrati jeho typ; pri whitespaces cita este raz
};

#endif __LEXICALCLASS