#ifndef BOD_PARSER_BASE_INCLUDED
#define BOD_PARSER_BASE_INCLUDED

#include "../common/ext_list.h"
#include "bod_text_parser.h"
#include "token_stream.h"

// I must get rid of COM S_OK definition to be able to use it later in enum
#ifdef S_OK 
#undef S_OK
#endif

class bod_parser_base
{
	public:
		enum ErrorSeverity
		{
			S_OK = 0,
			S_Error,
			S_Warning
		};

		enum ErrorCode
		{
			E_Error
		};

		enum ErrorFacility
		{
			F_Compiler
		};

		struct Error
		{
			int	code;
			char text[255];
			int line, col;

			void makeCode(ErrorFacility f, ErrorSeverity s, ErrorCode e)
			{
				code=s << 24;
				code|=f << 16;
				code|=e;
			}

			ErrorSeverity severity() const { return (ErrorSeverity)(code >> 24); }
			ErrorFacility facility() const { return (ErrorFacility)((code >> 16) & 0xff); }
			bool failed() const { return (severity() & S_Error) > 0; }
			bool warning() const { return (severity() & S_Warning) > 0; }
			bool succeeded() const { return (severity() & S_OK) == 0; }

			ErrorCode getCode() const { return (ErrorCode)(code & 0xFFFF); }
		};

	protected:
		typedef ext::list<Error*> ErrorList;
		typedef bod_text_parser::token token;

		void error(const bod_text_parser::token *t, ErrorSeverity severity, const char *format, ...);

	public:
		typedef ErrorList::iterator iterator;

		ErrorList errors;

		virtual ~bod_parser_base() { clearErrors(); }

		void clearErrors()
		{
			for(iterator &it=errors.begin(); it!=errors.end(); ++it){
				delete *it;
			}
		}

	protected:
		token* loadValue(token_stream& is, const char *context="");
		bool loadIntValue(token_stream& is, int *i, const char *context="");
		bool loadDoubleValue(token_stream& is, double *d, const char *context="");
		char * loadString(token_stream& is, const char *context="");
		static bool ungetValue(token_stream& s);
};

#endif // !defined(BOD_PARSER_BASE_INCLUDED)