Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "tgrammar.h"
Toshihiro Shimizu 890ddd
#include "tparser.h"
Toshihiro Shimizu 890ddd
#include "tunit.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "texpression.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace TSyntax;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************************
Toshihiro Shimizu 890ddd
//    TExpression::Imp  definition
Toshihiro Shimizu 890ddd
//**********************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TExpression::Imp
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	const Grammar *m_grammar; //!< (not owned) The expression's grammar
Toshihiro Shimizu 890ddd
	TDoubleParam *m_param;	//!< (not owned) The expression's owner
Toshihiro Shimizu 890ddd
	Calculator *m_calculator; //!< (owned) Expression calculator object
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::string m_text; //!< Text content
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::string m_error;			//!< Description of an error in the expression's text
Toshihiro Shimizu 890ddd
	std::pair<int, int=""> m_errorPos; //!< Position of the error in the expression's text</int,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool m_isValid,		 //!< Whether the expression is valid
Toshihiro Shimizu 890ddd
		m_hasBeenParsed; //!< Whether the expression has already been parsed
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	Imp() : m_grammar(0), m_param(0), m_calculator(0), m_errorPos(0, -1), m_isValid(false), m_hasBeenParsed(true) {}
Toshihiro Shimizu 890ddd
	~Imp() { delete m_calculator; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************************
Toshihiro Shimizu 890ddd
//    TExpression  implementation
Toshihiro Shimizu 890ddd
//**********************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TExpression::TExpression()
Toshihiro Shimizu 890ddd
	: m_imp(new Imp())
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TExpression::~TExpression()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	delete m_imp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TExpression::TExpression(const TExpression &src)
Toshihiro Shimizu 890ddd
	: m_imp(new Imp())
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_grammar = src.m_imp->m_grammar;
Toshihiro Shimizu 890ddd
	m_imp->m_param = src.m_imp->m_param;
Toshihiro Shimizu 890ddd
	m_imp->m_text = src.m_imp->m_text;
Toshihiro Shimizu 890ddd
	m_imp->m_calculator = 0;
Toshihiro Shimizu 890ddd
	m_imp->m_isValid = src.m_imp->m_isValid;
Toshihiro Shimizu 890ddd
	m_imp->m_error = src.m_imp->m_error;
Toshihiro Shimizu 890ddd
	m_imp->m_errorPos = src.m_imp->m_errorPos;
Toshihiro Shimizu 890ddd
	m_imp->m_hasBeenParsed = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TExpression &TExpression::operator=(TExpression copy)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::swap(copy.m_imp, m_imp);
Toshihiro Shimizu 890ddd
	return *this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TExpression::setGrammar(const TSyntax::Grammar *grammar)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_grammar = grammar;
Toshihiro Shimizu 890ddd
	m_imp->m_hasBeenParsed = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const TSyntax::Grammar *TExpression::getGrammar() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_grammar;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TExpression::setText(string text)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_imp->m_text != text) {
Toshihiro Shimizu 890ddd
		m_imp->m_text = text;
Toshihiro Shimizu 890ddd
		delete m_imp->m_calculator;
Toshihiro Shimizu 890ddd
		m_imp->m_calculator = 0;
Toshihiro Shimizu 890ddd
		m_imp->m_isValid = false;
Toshihiro Shimizu 890ddd
		m_imp->m_hasBeenParsed = false;
Toshihiro Shimizu 890ddd
		m_imp->m_error = "";
Toshihiro Shimizu 890ddd
		m_imp->m_errorPos = std::make_pair(0, -1);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
string TExpression::getText() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_text;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// note: unit is used by the CycleNode node only
Toshihiro Shimizu 890ddd
TSyntax::Calculator *TExpression::getCalculator()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_imp->m_hasBeenParsed)
Toshihiro Shimizu 890ddd
		parse();
Toshihiro Shimizu 890ddd
	if (m_imp->m_isValid && m_imp->m_calculator)
Toshihiro Shimizu 890ddd
		return m_imp->m_calculator;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TExpression::isValid()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_imp->m_hasBeenParsed)
Toshihiro Shimizu 890ddd
		parse();
Toshihiro Shimizu 890ddd
	return m_imp->m_isValid;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
string TExpression::getError() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_error;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
std::pair<int, int=""> TExpression::getErrorPos() const</int,>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_errorPos;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TExpression::accept(TSyntax::CalculatorNodeVisitor &visitor)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_imp->m_hasBeenParsed)
Toshihiro Shimizu 890ddd
		parse();
Toshihiro Shimizu 890ddd
	if (m_imp->m_isValid && m_imp->m_calculator)
Toshihiro Shimizu 890ddd
		m_imp->m_calculator->accept(visitor);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TExpression::parse()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	delete m_imp->m_calculator;
Toshihiro Shimizu 890ddd
	m_imp->m_calculator = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->m_errorPos = std::make_pair(0, -1);
Toshihiro Shimizu 890ddd
	m_imp->m_error = std::string();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_imp->m_grammar) {
Toshihiro Shimizu 890ddd
		m_imp->m_error = "No grammar defined";
Toshihiro Shimizu 890ddd
		m_imp->m_isValid = false;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		Parser parser(m_imp->m_grammar);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_imp->m_calculator = parser.parse(m_imp->m_text);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_imp->m_calculator)
Toshihiro Shimizu 890ddd
			m_imp->m_calculator->setOwnerParameter(m_imp->m_param);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_imp->m_isValid = parser.isValid();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!m_imp->m_isValid) {
Toshihiro Shimizu 890ddd
			m_imp->m_error = parser.getError();
Toshihiro Shimizu 890ddd
			m_imp->m_errorPos = parser.getErrorPos();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->m_hasBeenParsed = true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TExpression::setOwnerParameter(TDoubleParam *param)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_param = param;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_imp->m_calculator)
Toshihiro Shimizu 890ddd
		m_imp->m_calculator->setOwnerParameter(param);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TDoubleParam *TExpression::getOwnerParameter() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_param;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TExpression::isCycling() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// TODO: this is a quick&dirty implementation to be replaced with a more "semantic" one
Toshihiro Shimizu 890ddd
	return getText().find("cycle") != string::npos;
Toshihiro Shimizu 890ddd
}