#pragma once
// Новый парсер полноценных арифметических выражений

#include "BKToken.h"
#include "ErrorManager.h"
#include "RPNChain.h"

#define L_BRACKET L'<'
#define L_BRACKET2 L'['
#define R_BRACKET L'>'
#define R_BRACKET2 L']'

enum RPNERR : int
{
	RPNERR_NOERR = 0,
	RPNERR_NONEUNOPR,       // нет операнда унарной операции
	RPNERR_NONERGTOP,       // нет операнда источника в двухоперандной операции
	RPNERR_NONELFTOP,       // нет операнда приёмника в двухоперандной операции
	RPNERR_OPRERR,          // неверная операция
	RPNERR_ARGERR,          // неверный тип операнда
	RPNERR_UNEXPECTEDEND,   // неожиданный конец цепочки
	RPNERR_UNEXPECTEDARG,   // лишние аргументы в выражении
};

class CRPNParser
{
	protected:
		RPNChain_t      m_vRPNChain;
		int             m_nLastError{ 0 };
		int             m_nNames{ 0 };      // счётчик глобальных имён
		int             m_nLocNames{ 0 };   // счётчик локальных имён
		int             m_nCounter{ 0 };    // счётчик операндов, чтобы определить первый.
		int             m_nDotsCount{ 0 };  // счётчик встретившихся точек

		void            PushNode(A_OP op);
		void            PushNode(uint32_t num);
		void            PushNode(CBKToken &token);
		void            PushNodeLL(CBKToken &token);
		void            PushNodeDot();

		bool            isOROps(wchar_t ch) noexcept;
		bool            isANDOps(wchar_t ch) noexcept;
		bool            isADDOps(wchar_t ch) noexcept;
		bool            isMULOps(wchar_t ch);

		ERRNUM          Expression(wchar_t &ch);
		ERRNUM          Term_log(wchar_t &ch);
		ERRNUM          Expr_ar(wchar_t &ch);
		ERRNUM          Term(wchar_t &ch);
		ERRNUM          Factor(wchar_t &ch);

		void            RecalcChain(const RPNChain_t &rpn);

	public:
		CRPNParser() = default;
		~CRPNParser() = default;

		inline int      GetNamesNum() const noexcept
		{
			return m_nNames;
		}

		inline int      GetLocNamesNum() const noexcept
		{
			return m_nLocNames;
		}

		inline int      GetDotsNum() const noexcept
		{
			return m_nDotsCount;
		}

		ERRNUM          FullArithmeticParser(wchar_t &ch);
		bool            CalcRpn(int &result);
		bool            CalcRpn(int &result, RPNChain_t &rpn);

		RPNChain_t      GetRPN()
		{
			return m_vRPNChain;
		}

		void            Store(FILE *f); // сохранение в объектный файл
		bool            Load(FILE *f);  // чтение из объектного файла

};

extern CRPNParser g_RPNParser;
