Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "trandom.h"
Toshihiro Shimizu 890ddd
#include "tutil.h"
Toshihiro Shimizu 890ddd
#include "tconvert.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "ttokenizer.h"
Toshihiro Shimizu 890ddd
#include "tunit.h"
Toshihiro Shimizu 890ddd
#include "tparser.h"
Toshihiro Shimizu 890ddd
#include "tdoubleparam.h"
Toshihiro Shimizu 890ddd
#include "tdoublekeyframe.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// STD includes
Toshihiro Shimizu 890ddd
#include <map></map>
Toshihiro Shimizu 890ddd
#include <math.h></math.h>
Toshihiro Shimizu 890ddd
#include <functional></functional>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Qt includes
Toshihiro Shimizu 890ddd
#include <qstring></qstring>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tgrammar.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const double PI = 4 * atan(1.0);
Toshihiro Shimizu 890ddd
const double toDeg(double rad) { return rad * 180.0 / PI; }
Toshihiro Shimizu 890ddd
const double toRad(double deg) { return deg / 180.0 * PI; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace TSyntax
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// RandomManager
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//   es. x = RandomManager::instance()->getValue(seed, frame);
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class RandomSequence
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRandom m_rnd;
Toshihiro Shimizu 890ddd
	std::vector<double> m_values;</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	RandomSequence(UINT seed) : m_rnd(seed) {}
Toshihiro Shimizu 890ddd
	double getValue(int i)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		assert(i >= 0);
Toshihiro Shimizu 890ddd
		if (i >= (int)m_values.size()) {
Toshihiro Shimizu 890ddd
			m_values.reserve(i + 1);
Toshihiro Shimizu 890ddd
			while (i >= (int)m_values.size())
Toshihiro Shimizu 890ddd
				m_values.push_back(m_rnd.getDouble());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		return m_values[i];
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class RandomManager
Toshihiro Shimizu 890ddd
{ // singleton
Toshihiro Shimizu 890ddd
	typedef std::map<uint, *="" randomsequence=""> Table;</uint,>
Toshihiro Shimizu 890ddd
	Table m_table;
Toshihiro Shimizu 890ddd
	RandomManager() {}
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	~RandomManager()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		for (Table::iterator i = m_table.begin(); i != m_table.end(); ++i)
Toshihiro Shimizu 890ddd
			delete i->second;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	static RandomManager *instance()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		static RandomManager _instance;
Toshihiro Shimizu 890ddd
		return &_instance;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	RandomSequence *getSequence(UINT seed)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		Table::iterator i = m_table.find(seed);
Toshihiro Shimizu 890ddd
		if (i == m_table.end()) {
Toshihiro Shimizu 890ddd
			RandomSequence *seq = new RandomSequence(seed);
Toshihiro Shimizu 890ddd
			m_table[seed] = seq;
Toshihiro Shimizu 890ddd
			return seq;
Toshihiro Shimizu 890ddd
		} else
Toshihiro Shimizu 890ddd
			return i->second;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double getValue(UINT seed, double t)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		RandomSequence *seq = getSequence(seed);
Toshihiro Shimizu 890ddd
		return seq->getValue(t > 0 ? tfloor(t) : 0);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
// Calculator
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Calculator::Calculator()
Toshihiro Shimizu 890ddd
	: m_rootNode(0), m_param(0), m_unit(0)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Calculator::~Calculator()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	delete m_rootNode;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Calculator::setRootNode(CalculatorNode *node)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (node != m_rootNode) {
Toshihiro Shimizu 890ddd
		delete m_rootNode;
Toshihiro Shimizu 890ddd
		m_rootNode = node;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
// Nodes
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class op=""></class>
Toshihiro Shimizu 890ddd
class Op0Node : public CalculatorNode
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	Op0Node(Calculator *calc)
Toshihiro Shimizu 890ddd
		: CalculatorNode(calc) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double compute(double vars[3]) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		Op op;
Toshihiro Shimizu 890ddd
		return op();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class op=""></class>
Toshihiro Shimizu 890ddd
class Op1Node : public CalculatorNode
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	std::auto_ptr<calculatornode> m_a;</calculatornode>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	Op1Node(Calculator *calc, CalculatorNode *a)
Toshihiro Shimizu 890ddd
		: CalculatorNode(calc), m_a(a) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double compute(double vars[3]) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		Op op;
Toshihiro Shimizu 890ddd
		return op(m_a->compute(vars));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void accept(CalculatorNodeVisitor &visitor) { m_a->accept(visitor); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class op=""></class>
Toshihiro Shimizu 890ddd
class Op2Node : public CalculatorNode
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	std::auto_ptr<calculatornode> m_a, m_b;</calculatornode>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	Op2Node(Calculator *calc, CalculatorNode *a, CalculatorNode *b)
Toshihiro Shimizu 890ddd
		: CalculatorNode(calc), m_a(a), m_b(b) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double compute(double vars[3]) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		Op op;
Toshihiro Shimizu 890ddd
		return op(m_a->compute(vars), m_b->compute(vars));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void accept(CalculatorNodeVisitor &visitor)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_a->accept(visitor), m_b->accept(visitor);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class op=""></class>
Toshihiro Shimizu 890ddd
class Op3Node : public CalculatorNode
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	std::auto_ptr<calculatornode> m_a, m_b, m_c;</calculatornode>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	Op3Node(Calculator *calc, CalculatorNode *a, CalculatorNode *b, CalculatorNode *c)
Toshihiro Shimizu 890ddd
		: CalculatorNode(calc), m_a(a), m_b(b), m_c(c) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double compute(double vars[3]) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		Op op;
Toshihiro Shimizu 890ddd
		return op(m_a->compute(vars), m_b->compute(vars), m_c->compute(vars));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void accept(CalculatorNodeVisitor &visitor)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_a->accept(visitor), m_b->accept(visitor), m_c->accept(visitor);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class ChsNode : public CalculatorNode
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::auto_ptr<calculatornode> m_a;</calculatornode>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	ChsNode(Calculator *calc, CalculatorNode *a) : CalculatorNode(calc), m_a(a) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double compute(double vars[3]) const { return -m_a->compute(vars); }
Toshihiro Shimizu 890ddd
	void accept(CalculatorNodeVisitor &visitor) { m_a->accept(visitor); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class QuestionNode : public CalculatorNode
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::auto_ptr<calculatornode> m_a, m_b, m_c;</calculatornode>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	QuestionNode(Calculator *calc, CalculatorNode *a, CalculatorNode *b, CalculatorNode *c)
Toshihiro Shimizu 890ddd
		: CalculatorNode(calc), m_a(a), m_b(b), m_c(c) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double compute(double vars[3]) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return (m_a->compute(vars) != 0) ? m_b->compute(vars) : m_c->compute(vars);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void accept(CalculatorNodeVisitor &visitor)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_a->accept(visitor), m_b->accept(visitor), m_c->accept(visitor);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class NotNode : public CalculatorNode
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::auto_ptr<calculatornode> m_a;</calculatornode>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	NotNode(Calculator *calc, CalculatorNode *a) : CalculatorNode(calc), m_a(a) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double compute(double vars[3]) const { return m_a->compute(vars) == 0; }
Toshihiro Shimizu 890ddd
	void accept(CalculatorNodeVisitor &visitor) { m_a->accept(visitor); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class CycleNode : public CalculatorNode
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::auto_ptr<calculatornode> m_a;</calculatornode>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	CycleNode(Calculator *calc, CalculatorNode *a) : CalculatorNode(calc), m_a(a) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double compute(double vars[3]) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		struct locals {
Toshihiro Shimizu 890ddd
			static inline double compute(const TDoubleParam ¶m, double f)
Toshihiro Shimizu 890ddd
			{
Toshihiro Shimizu 890ddd
				if (param.getKeyframeCount() >= 2 && f < param.keyframeIndexToFrame(0)) {
Toshihiro Shimizu 890ddd
					TDoubleKeyframe kf = param.getKeyframe(0);
Toshihiro Shimizu 890ddd
					if (kf.m_type == TDoubleKeyframe::Expression || kf.m_type == TDoubleKeyframe::SimilarShape)
Toshihiro Shimizu 890ddd
						return param.getDefaultValue();
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				double value = param.getValue(f);
Toshihiro Shimizu 890ddd
				return value;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double delta = tmax(1.0, m_a->compute(vars));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		const TDoubleParam *ownerParam = getCalculator()->getOwnerParameter();
Toshihiro Shimizu 890ddd
		if (!ownerParam)
Toshihiro Shimizu 890ddd
			return 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		double value = locals::compute(*ownerParam, vars[FRAME] - 1 - delta);
Toshihiro Shimizu 890ddd
		if (getCalculator()->getUnit())
Toshihiro Shimizu 890ddd
			value = getCalculator()->getUnit()->convertTo(value);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return value;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void accept(CalculatorNodeVisitor &visitor) { m_a->accept(visitor); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class RandomNode : public CalculatorNode
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::auto_ptr<calculatornode> m_seed, m_min, m_max, m_arg;</calculatornode>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	RandomNode(Calculator *calc) : CalculatorNode(calc), m_seed(0), m_min(0), m_max(0)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_arg.reset(new VariableNode(calc, CalculatorNode::FRAME));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void setSeed(CalculatorNode *arg)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		assert(m_seed.get() == 0);
Toshihiro Shimizu 890ddd
		m_seed.reset(arg);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	void setMax(CalculatorNode *arg)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		assert(m_max.get() == 0);
Toshihiro Shimizu 890ddd
		m_max.reset(arg);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	void setMin(CalculatorNode *arg)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		assert(m_min.get() == 0);
Toshihiro Shimizu 890ddd
		m_min.reset(arg);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double compute(double vars[3]) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		double s = (m_seed.get() != 0) ? m_seed->compute(vars) : 0;
Toshihiro Shimizu 890ddd
		double r = RandomManager::instance()->getValue(s, fabs(m_arg->compute(vars)));
Toshihiro Shimizu 890ddd
		if (m_min.get() == 0)
Toshihiro Shimizu 890ddd
			if (m_max.get() == 0)
Toshihiro Shimizu 890ddd
				return r;
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				return m_max->compute(vars) * r;
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			return (1 - r) * m_min->compute(vars) + r * m_max->compute(vars);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void accept(CalculatorNodeVisitor &visitor)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_arg->accept(visitor);
Toshihiro Shimizu 890ddd
		if (m_seed.get())
Toshihiro Shimizu 890ddd
			m_seed->accept(visitor);
Toshihiro Shimizu 890ddd
		if (m_min.get())
Toshihiro Shimizu 890ddd
			m_min->accept(visitor);
Toshihiro Shimizu 890ddd
		if (m_max.get())
Toshihiro Shimizu 890ddd
			m_max->accept(visitor);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
// Patterns
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
CalculatorNode *Pattern::popNode(std::vector<calculatornode *=""> &stack) const</calculatornode>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	CalculatorNode *node = stack.back();
Toshihiro Shimizu 890ddd
	stack.pop_back();
Toshihiro Shimizu 890ddd
	return node;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class NumberPattern : public Pattern
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	bool matchToken(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.empty() && token.getType() == Token::Number;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	bool isFinished(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.size() == 1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TokenType getTokenType(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return Number;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	void createNode(
Toshihiro Shimizu 890ddd
		Calculator *calc,
Toshihiro Shimizu 890ddd
		std::vector<calculatornode *=""> &stack,</calculatornode>
Toshihiro Shimizu 890ddd
		const std::vector<token> &tokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		assert(tokens.size() == 1);
Toshihiro Shimizu 890ddd
		assert(tokens[0].getType() == Token::Number);
Toshihiro Shimizu 890ddd
		stack.push_back(new NumberNode(calc, tokens[0].getDoubleValue()));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class ConstantPattern : public Pattern
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	string m_constantName;
Toshihiro Shimizu 890ddd
	double m_value;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	ConstantPattern(string constantName, double value, string description = "")
Toshihiro Shimizu 890ddd
		: m_constantName(constantName), m_value(value)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		setDescription(description);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	string getFirstKeyword() const { return m_constantName; }
Toshihiro Shimizu 890ddd
	bool matchToken(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.empty() && token.getText() == m_constantName;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	bool isFinished(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.size() == 1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TokenType getTokenType(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return Constant;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void createNode(
Toshihiro Shimizu 890ddd
		Calculator *calc,
Toshihiro Shimizu 890ddd
		std::vector<calculatornode *=""> &stack,</calculatornode>
Toshihiro Shimizu 890ddd
		const std::vector<token> &tokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		assert(tokens.size() == 1);
Toshihiro Shimizu 890ddd
		stack.push_back(new NumberNode(calc, m_value));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class VariablePattern : public Pattern
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	string m_variableName;
Toshihiro Shimizu 890ddd
	int m_varIdx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	VariablePattern(string variableName, int varIdx, string description = "")
Toshihiro Shimizu 890ddd
		: m_variableName(variableName), m_varIdx(varIdx)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		setDescription(description);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	string getFirstKeyword() const { return m_variableName; }
Toshihiro Shimizu 890ddd
	bool matchToken(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.empty() && token.getText() == m_variableName;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	bool isFinished(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.size() == 1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TokenType getTokenType(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return Variable;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void createNode(
Toshihiro Shimizu 890ddd
		Calculator *calc,
Toshihiro Shimizu 890ddd
		std::vector<calculatornode *=""> &stack,</calculatornode>
Toshihiro Shimizu 890ddd
		const std::vector<token> &tokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		assert(tokens.size() == 1);
Toshihiro Shimizu 890ddd
		assert(tokens[0].getText() == m_variableName);
Toshihiro Shimizu 890ddd
		stack.push_back(new VariableNode(calc, m_varIdx));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class op=""></class>
Toshihiro Shimizu 890ddd
class Op2Pattern : public Pattern
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	string m_opName;
Toshihiro Shimizu 890ddd
	int m_priority;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	Op2Pattern(string opName, int priority)
Toshihiro Shimizu 890ddd
		: m_opName(opName), m_priority(priority) {}
Toshihiro Shimizu 890ddd
	int getPriority() const { return m_priority; }
Toshihiro Shimizu 890ddd
	string getFirstKeyword() const { return m_opName; }
Toshihiro Shimizu 890ddd
	bool expressionExpected(const std::vector<token> &previousTokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.empty() || previousTokens.size() == 2;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	bool matchToken(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.size() == 1 && token.getText() == m_opName;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	bool isFinished(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.size() == 3;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TokenType getTokenType(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.size() == 1 ? Operator : InternalError;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	void createNode(
Toshihiro Shimizu 890ddd
		Calculator *calc,
Toshihiro Shimizu 890ddd
		std::vector<calculatornode *=""> &stack,</calculatornode>
Toshihiro Shimizu 890ddd
		const std::vector<token> &tokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		assert(tokens.size() == 3);
Toshihiro Shimizu 890ddd
		assert(tokens[1].getText() == m_opName);
Toshihiro Shimizu 890ddd
		CalculatorNode *b = popNode(stack);
Toshihiro Shimizu 890ddd
		CalculatorNode *a = popNode(stack);
Toshihiro Shimizu 890ddd
		stack.push_back(new Op2Node<op>(calc, a, b));</op>
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class UnaryMinusPattern : public Pattern
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	UnaryMinusPattern() {}
Toshihiro Shimizu 890ddd
	int getPriority() const { return 50; }
Toshihiro Shimizu 890ddd
	string getFirstKeyword() const { return "-"; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool expressionExpected(const std::vector<token> &previousTokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.size() == 1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	bool matchToken(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.empty() && token.getText() == "-";
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	bool isFinished(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.size() == 2;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TokenType getTokenType(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return Operator;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void createNode(
Toshihiro Shimizu 890ddd
		Calculator *calc,
Toshihiro Shimizu 890ddd
		std::vector<calculatornode *=""> &stack,</calculatornode>
Toshihiro Shimizu 890ddd
		const std::vector<token> &tokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		assert(tokens.size() == 2);
Toshihiro Shimizu 890ddd
		assert(tokens[0].getText() == "-");
Toshihiro Shimizu 890ddd
		stack.push_back(new ChsNode(calc, popNode(stack)));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class NotPattern : public Pattern
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	string m_prefix;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	NotPattern(string prefix, string description) : m_prefix(prefix)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		setDescription(description);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	int getPriority() const { return 5; }
Toshihiro Shimizu 890ddd
	string getFirstKeyword() const { return m_prefix; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool expressionExpected(const std::vector<token> &previousTokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.size() == 1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	bool matchToken(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.empty() && token.getText() == m_prefix;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	bool isFinished(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.size() == 2;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TokenType getTokenType(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return Operator;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	void createNode(
Toshihiro Shimizu 890ddd
		Calculator *calc,
Toshihiro Shimizu 890ddd
		std::vector<calculatornode *=""> &stack,</calculatornode>
Toshihiro Shimizu 890ddd
		const std::vector<token> &tokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		assert(tokens.size() == 2);
Toshihiro Shimizu 890ddd
		assert(tokens[0].getText() == m_prefix);
Toshihiro Shimizu 890ddd
		stack.push_back(new NotNode(calc, popNode(stack)));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class QuestionTernaryPattern : public Pattern
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	QuestionTernaryPattern() {}
Toshihiro Shimizu 890ddd
	int getPriority() const { return 5; }
Toshihiro Shimizu 890ddd
	string getFirstKeyword() const { return "?"; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool expressionExpected(const std::vector<token> &previousTokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		int i = (int)previousTokens.size();
Toshihiro Shimizu 890ddd
		return i == 0 || i == 2 || i == 4;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	bool matchToken(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		int i = (int)previousTokens.size();
Toshihiro Shimizu 890ddd
		return i == 1 && token.getText() == "?" || i == 3 && token.getText() == ":";
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	bool isFinished(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.size() == 5;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TokenType getTokenType(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		int i = (int)previousTokens.size();
Toshihiro Shimizu 890ddd
		return (i == 1 || i == 3) ? Operator : InternalError;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	void createNode(
Toshihiro Shimizu 890ddd
		Calculator *calc,
Toshihiro Shimizu 890ddd
		std::vector<calculatornode *=""> &stack,</calculatornode>
Toshihiro Shimizu 890ddd
		const std::vector<token> &tokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		CalculatorNode *node1 = popNode(stack);
Toshihiro Shimizu 890ddd
		CalculatorNode *node2 = popNode(stack);
Toshihiro Shimizu 890ddd
		CalculatorNode *node3 = popNode(stack);
Toshihiro Shimizu 890ddd
		stack.push_back(new QuestionNode(calc, node3, node2, node1));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class BraketPattern : public Pattern
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	BraketPattern() {}
Toshihiro Shimizu 890ddd
	int getPriority() const { return 5; }
Toshihiro Shimizu 890ddd
	string getFirstKeyword() const { return "("; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool expressionExpected(const std::vector<token> &previousTokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.size() == 1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	bool matchToken(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.empty() && token.getText() == "(" ||
Toshihiro Shimizu 890ddd
			   previousTokens.size() == 2 && token.getText() == ")";
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	bool isFinished(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.size() == 3;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TokenType getTokenType(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return previousTokens.size() != 1 ? Parenthesis : InternalError;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	void createNode(
Toshihiro Shimizu 890ddd
		Calculator *calc,
Toshihiro Shimizu 890ddd
		std::vector<calculatornode *=""> &stack,</calculatornode>
Toshihiro Shimizu 890ddd
		const std::vector<token> &tokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		assert(tokens.size() == 3);
Toshihiro Shimizu 890ddd
		assert(tokens[0].getText() == "(");
Toshihiro Shimizu 890ddd
		assert(tokens[2].getText() == ")");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class FunctionPattern : public Pattern
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	string m_functionName;
Toshihiro Shimizu 890ddd
	bool m_implicitArgAllowed;
Toshihiro Shimizu 890ddd
	// if m_implicitArgAllowed == true then the first argument is the frame number
Toshihiro Shimizu 890ddd
	// e.g. f(5) means f(frame,5)
Toshihiro Shimizu 890ddd
	// to use a different first argument (e.g. t*10) you have to write f(t*10;5)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int m_minArgCount;
Toshihiro Shimizu 890ddd
	std::vector<double> m_optionalArgDefaults;</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	FunctionPattern(string functionName, int minArgCount)
Toshihiro Shimizu 890ddd
		: m_functionName(functionName), m_implicitArgAllowed(false), m_minArgCount(minArgCount)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void allowImplicitArg(bool allowed) { m_implicitArgAllowed = allowed; }
Toshihiro Shimizu 890ddd
	void addOptionalArg(double value) { m_optionalArgDefaults.push_back(value); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	string getFirstKeyword() const { return m_functionName; }
Toshihiro Shimizu 890ddd
	bool expressionExpected(const std::vector<token> &previousTokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		int n = (int)previousTokens.size();
Toshihiro Shimizu 890ddd
		return 2 <= n && (n & 1) == 0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool matchToken(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		int i = (int)previousTokens.size();
Toshihiro Shimizu 890ddd
		string s = toLower(token.getText());
Toshihiro Shimizu 890ddd
		if (i == 0)
Toshihiro Shimizu 890ddd
			return s == toLower(m_functionName);
Toshihiro Shimizu 890ddd
		else if (i == 1)
Toshihiro Shimizu 890ddd
			return s == "(";
Toshihiro Shimizu 890ddd
		else if ((i & 1) == 0)
Toshihiro Shimizu 890ddd
			return true;
Toshihiro Shimizu 890ddd
		else if (s == ",")
Toshihiro Shimizu 890ddd
			return true;
Toshihiro Shimizu 890ddd
		else if (s == ";")
Toshihiro Shimizu 890ddd
			return i == 3 && m_implicitArgAllowed;
Toshihiro Shimizu 890ddd
		else if (s == ")") {
Toshihiro Shimizu 890ddd
			int n = (i - 1) / 2;
Toshihiro Shimizu 890ddd
			if (previousTokens.size() > 3 && previousTokens[3].getText() == ";")
Toshihiro Shimizu 890ddd
				n--;
Toshihiro Shimizu 890ddd
			if (n < m_minArgCount || n > m_minArgCount + (int)m_optionalArgDefaults.size())
Toshihiro Shimizu 890ddd
				return false;
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				return true;
Toshihiro Shimizu 890ddd
		} else
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	bool isFinished(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (previousTokens.empty())
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
		return m_minArgCount == 0 && previousTokens.size() == 1 && token.getText() != "(" ||
Toshihiro Shimizu 890ddd
			   previousTokens.back().getText() == ")";
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TokenType getTokenType(const std::vector<token> &previousTokens, const Token &token) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		int i = (int)previousTokens.size();
Toshihiro Shimizu 890ddd
		if (i == 0)
Toshihiro Shimizu 890ddd
			return Function;
Toshihiro Shimizu 890ddd
		else if (i == 1 || token.getText() == ")")
Toshihiro Shimizu 890ddd
			return Function;
Toshihiro Shimizu 890ddd
		else if (i == 3)
Toshihiro Shimizu 890ddd
			return token.getText() == ";" ? Comma : Comma;
Toshihiro Shimizu 890ddd
		else if (i & 1)
Toshihiro Shimizu 890ddd
			return Comma;
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			return InternalError;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void getArgs(
Toshihiro Shimizu 890ddd
		std::vector<calculatornode *=""> &nodes,</calculatornode>
Toshihiro Shimizu 890ddd
		Calculator *calc, std::vector<calculatornode *=""> &stack,</calculatornode>
Toshihiro Shimizu 890ddd
		const std::vector<token> &tokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		bool implicitArgUsed = m_implicitArgAllowed && tokens.size() > 3 && tokens[3].getText() == ";";
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// n = number of arguments to provide (mandatory + optional + implicit)
Toshihiro Shimizu 890ddd
		int n = m_minArgCount + (int)m_optionalArgDefaults.size() + (m_implicitArgAllowed ? 1 : 0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// m = number of default arguments to assign (with their default value)
Toshihiro Shimizu 890ddd
		int m = n - (tokens.size() - 2) / 2;
Toshihiro Shimizu 890ddd
		if (m_implicitArgAllowed && !implicitArgUsed)
Toshihiro Shimizu 890ddd
			m--;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		assert(m <= (int)m_optionalArgDefaults.size());
Toshihiro Shimizu 890ddd
		if (m > (int)m_optionalArgDefaults.size())
Toshihiro Shimizu 890ddd
			m = (int)m_optionalArgDefaults.size();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		nodes.resize(n);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// fetch arguments from the stack
Toshihiro Shimizu 890ddd
		int k = n - m;
Toshihiro Shimizu 890ddd
		if (implicitArgUsed) {
Toshihiro Shimizu 890ddd
			while (k > 0)
Toshihiro Shimizu 890ddd
				nodes[--k] = popNode(stack);
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			while (k > 1)
Toshihiro Shimizu 890ddd
				nodes[--k] = popNode(stack);
Toshihiro Shimizu 890ddd
			nodes[0] = new VariableNode(calc, CalculatorNode::FRAME);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// add default values
Toshihiro Shimizu 890ddd
		for (int i = 0; i < m; i++)
Toshihiro Shimizu 890ddd
			nodes[n - m + i] = new NumberNode(calc, m_optionalArgDefaults[i]);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class function=""></class>
Toshihiro Shimizu 890ddd
class F0Pattern : public FunctionPattern
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	F0Pattern(string functionName) : FunctionPattern(functionName, 0) {}
Toshihiro Shimizu 890ddd
	void createNode(Calculator *calc, std::vector<calculatornode *=""> &stack,</calculatornode>
Toshihiro Shimizu 890ddd
					const std::vector<token> &tokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		stack.push_back(new Op0Node<function>(calc, m_functionName));</function>
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class function=""></class>
Toshihiro Shimizu 890ddd
class F1Pattern : public FunctionPattern
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	F1Pattern(string functionName, string descr = "") : FunctionPattern(functionName, 1) { setDescription(descr); }
Toshihiro Shimizu 890ddd
	void createNode(Calculator *calc, std::vector<calculatornode *=""> &stack,</calculatornode>
Toshihiro Shimizu 890ddd
					const std::vector<token> &tokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		stack.push_back(new Op1Node<function>(calc, popNode(stack)));</function>
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class function=""></class>
Toshihiro Shimizu 890ddd
class F2Pattern : public FunctionPattern
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	F2Pattern(string functionName, string descr = "") : FunctionPattern(functionName, 2) { setDescription(descr); }
Toshihiro Shimizu 890ddd
	void createNode(Calculator *calc, std::vector<calculatornode *=""> &stack,</calculatornode>
Toshihiro Shimizu 890ddd
					const std::vector<token> &tokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		CalculatorNode *b = popNode(stack);
Toshihiro Shimizu 890ddd
		CalculatorNode *a = popNode(stack);
Toshihiro Shimizu 890ddd
		stack.push_back(new Op2Node<function>(calc, a, b));</function>
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class function=""></class>
Toshihiro Shimizu 890ddd
class F3Pattern : public FunctionPattern
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	F3Pattern(string functionName, string descr = "") : FunctionPattern(functionName, 3) { setDescription(descr); }
Toshihiro Shimizu 890ddd
	void createNode(Calculator *calc, std::vector<calculatornode *=""> &stack,</calculatornode>
Toshihiro Shimizu 890ddd
					const std::vector<token> &tokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		CalculatorNode *c = popNode(stack);
Toshihiro Shimizu 890ddd
		CalculatorNode *b = popNode(stack);
Toshihiro Shimizu 890ddd
		CalculatorNode *a = popNode(stack);
Toshihiro Shimizu 890ddd
		stack.push_back(new Op3Node<function>(calc, a, b, c));</function>
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class function=""></class>
Toshihiro Shimizu 890ddd
class Fs2Pattern : public FunctionPattern
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	Fs2Pattern(string functionName, string description)
Toshihiro Shimizu 890ddd
		: FunctionPattern(functionName, 1)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		allowImplicitArg(true);
Toshihiro Shimizu 890ddd
		setDescription(description);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	void createNode(Calculator *calc, std::vector<calculatornode *=""> &stack,</calculatornode>
Toshihiro Shimizu 890ddd
					const std::vector<token> &tokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::vector<calculatornode *=""> nodes;</calculatornode>
Toshihiro Shimizu 890ddd
		getArgs(nodes, calc, stack, tokens);
Toshihiro Shimizu 890ddd
		stack.push_back(new Op2Node<function>(calc, nodes[0], nodes[1]));</function>
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class function=""></class>
Toshihiro Shimizu 890ddd
class Fs3Pattern : public FunctionPattern
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	Fs3Pattern(string functionName, double defVal, string descr)
Toshihiro Shimizu 890ddd
		: FunctionPattern(functionName, 1)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		allowImplicitArg(true);
Toshihiro Shimizu 890ddd
		addOptionalArg(defVal);
Toshihiro Shimizu 890ddd
		setDescription(descr);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	void createNode(Calculator *calc, std::vector<calculatornode *=""> &stack,</calculatornode>
Toshihiro Shimizu 890ddd
					const std::vector<token> &tokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::vector<calculatornode *=""> nodes;</calculatornode>
Toshihiro Shimizu 890ddd
		getArgs(nodes, calc, stack, tokens);
Toshihiro Shimizu 890ddd
		stack.push_back(new Op3Node<function>(calc, nodes[0], nodes[1], nodes[2]));</function>
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class CyclePattern : public FunctionPattern
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	CyclePattern(string functionName) : FunctionPattern(functionName, 1)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		setDescription("cycle(period)\nCycles the transitions of the period previous frames to the selected range");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	void createNode(Calculator *calc, std::vector<calculatornode *=""> &stack,</calculatornode>
Toshihiro Shimizu 890ddd
					const std::vector<token> &tokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		CalculatorNode *a = popNode(stack);
Toshihiro Shimizu 890ddd
		stack.push_back(new CycleNode(calc, a));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class RandomPattern : public FunctionPattern
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	bool m_seed;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	RandomPattern(string functionName, bool seed, string description)
Toshihiro Shimizu 890ddd
		: FunctionPattern(functionName, seed ? 1 : 0), m_seed(seed)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		allowImplicitArg(true);
Toshihiro Shimizu 890ddd
		addOptionalArg(0);
Toshihiro Shimizu 890ddd
		addOptionalArg(0);
Toshihiro Shimizu 890ddd
		setDescription(description);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	void createNode(Calculator *calc, std::vector<calculatornode *=""> &stack,</calculatornode>
Toshihiro Shimizu 890ddd
					const std::vector<token> &tokens) const</token>
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		int n = ((int)tokens.size() - 1) / 2;
Toshihiro Shimizu 890ddd
		if (m_seed)
Toshihiro Shimizu 890ddd
			n--;
Toshihiro Shimizu 890ddd
		RandomNode *randomNode = new RandomNode(calc);
Toshihiro Shimizu 890ddd
		if (n > 0) {
Toshihiro Shimizu 890ddd
			randomNode->setMax(popNode(stack));
Toshihiro Shimizu 890ddd
			if (n > 1)
Toshihiro Shimizu 890ddd
				randomNode->setMin(popNode(stack));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (m_seed)
Toshihiro Shimizu 890ddd
			randomNode->setSeed(popNode(stack));
Toshihiro Shimizu 890ddd
		stack.push_back(randomNode);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class PatternTable
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::map<string, *="" pattern=""> m_kTable;</string,>
Toshihiro Shimizu 890ddd
	std::vector<pattern *=""> m_uTable;</pattern>
Toshihiro Shimizu 890ddd
	Grammar::Position m_position;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	PatternTable(Grammar::Position position) : m_position(position) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~PatternTable()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		for (std::map<string, *="" pattern="">::iterator</string,>
Toshihiro Shimizu 890ddd
				 it = m_kTable.begin();
Toshihiro Shimizu 890ddd
			 it != m_kTable.end(); ++it)
Toshihiro Shimizu 890ddd
			delete it->second;
Toshihiro Shimizu 890ddd
		for (std::vector<pattern *="">::iterator</pattern>
Toshihiro Shimizu 890ddd
				 it = m_uTable.begin();
Toshihiro Shimizu 890ddd
			 it != m_uTable.end(); ++it)
Toshihiro Shimizu 890ddd
			delete *it;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void addPattern(Pattern *pattern)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		string keyword = pattern->getFirstKeyword();
Toshihiro Shimizu 890ddd
		if (keyword != "") {
Toshihiro Shimizu 890ddd
			// first keyword should be unique
Toshihiro Shimizu 890ddd
			assert(m_kTable.count(keyword) == 0);
Toshihiro Shimizu 890ddd
			m_kTable[keyword] = pattern;
Toshihiro Shimizu 890ddd
		} else
Toshihiro Shimizu 890ddd
			m_uTable.push_back(pattern);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	const Pattern *getPattern(const Token &token) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		std::vector<token> tokens;</token>
Toshihiro Shimizu 890ddd
		if (m_position == Grammar::ExpressionEnd)
Toshihiro Shimizu 890ddd
			tokens.push_back(Token());
Toshihiro Shimizu 890ddd
		if (token.getType() == Token::Punct || token.getType() == Token::Ident) {
Toshihiro Shimizu 890ddd
			string keyword = token.getText();
Toshihiro Shimizu 890ddd
			std::map<string, *="" pattern="">::const_iterator it = m_kTable.find(keyword);</string,>
Toshihiro Shimizu 890ddd
			if (it != m_kTable.end()) {
Toshihiro Shimizu 890ddd
				Pattern *pattern = it->second;
Toshihiro Shimizu 890ddd
				if (pattern->matchToken(tokens, token)) {
Toshihiro Shimizu 890ddd
					return pattern;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		for (int i = 0; i < (int)m_uTable.size(); i++) {
Toshihiro Shimizu 890ddd
			Pattern *pattern = m_uTable[i];
Toshihiro Shimizu 890ddd
			if (pattern->matchToken(tokens, token)) {
Toshihiro Shimizu 890ddd
				return pattern;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void getSuggestions(Grammar::Suggestions &suggestions) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		std::map<string, *="" pattern="">::const_iterator it;</string,>
Toshihiro Shimizu 890ddd
		for (it = m_kTable.begin(); it != m_kTable.end(); ++it) {
Toshihiro Shimizu 890ddd
			suggestions.push_back(std::make_pair(it->first, it->second->getDescription()));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		for (int i = 0; i < (int)m_uTable.size(); i++) {
Toshihiro Shimizu 890ddd
			std::vector<std::string> keywords;</std::string>
Toshihiro Shimizu 890ddd
			m_uTable[i]->getAcceptableKeywords(keywords);
Toshihiro Shimizu 890ddd
			for (int j = 0; j < (int)keywords.size(); j++)
Toshihiro Shimizu 890ddd
				suggestions.push_back(std::make_pair(keywords[j], m_uTable[i]->getDescription()));
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// funzioni trigonometriche, log, exp, ecc.
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class Pow
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x, double y) const { return pow(x, y); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
// class Mod   {public: double operator()(double x, double y) const {return (int)x % (int)y;} };
Toshihiro Shimizu 890ddd
class Sin
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x) const { return sin(toRad(x)); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Cos
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x) const { return cos(toRad(x)); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Tan
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x) const { return tan(toRad(x)); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Sinh
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x) const { return sinh(toRad(x)); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Cosh
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x) const { return cosh(toRad(x)); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Tanh
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x) const { return tanh(toRad(x)); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Atan
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x) const { return toDeg(atan(x)); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Atan2
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x, double y) const { return toDeg(atan2(x, y)); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Log
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x) const { return log(x); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Exp
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x) const { return exp(x); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Floor
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x) const { return tfloor(x); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Ceil
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x) const { return tceil(x); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Round
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x) const { return tround(x); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Abs
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x) const { return fabs(x); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Sign
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x) const { return x > 0 ? 1 : x < 0 ? -1 : 0; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Sqrt
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x) const { return x >= 0.0 ? sqrt(x) : 0; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Sqr
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x) const { return x * x; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Crop
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x, double a, double b) const { return tcrop(x, a, b); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Step
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x, double y) const { return x < y ? 0 : 1; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class Mod
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x, double y) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (y == 0.0)
Toshihiro Shimizu 890ddd
			return 0;
Toshihiro Shimizu 890ddd
		return x - y * floor(x / y);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class Min
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x, double y) const { return x < y ? x : y; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Max
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x, double y) const { return x > y ? x : y; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class Gt
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x, double y) const { return x > y ? 1 : 0; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Ge
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x, double y) const { return x >= y ? 1 : 0; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Lt
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x, double y) const { return x < y ? 1 : 0; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Le
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x, double y) const { return x <= y ? 1 : 0; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Ne
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x, double y) const { return x != y ? 1 : 0; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Eq
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x, double y) const { return x == y ? 1 : 0; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class And
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x, double y) const { return (x != 0) && (y != 0) ? 1 : 0; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Or
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x, double y) const { return (x != 0) || (y != 0) ? 1 : 0; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Not
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x) const { return x == 0; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class Smoothstep
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double v, double min, double max) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (v <= min)
Toshihiro Shimizu 890ddd
			return 0;
Toshihiro Shimizu 890ddd
		else if (v >= max)
Toshihiro Shimizu 890ddd
			return 1;
Toshihiro Shimizu 890ddd
		double t = (v - min) / (max - min);
Toshihiro Shimizu 890ddd
		return -2 * t * t * t + 3 * t * t;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Pulse
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x, double x0, double length) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		// double length=5.0;
Toshihiro Shimizu 890ddd
		double b = (.69315 * 4.0) / (length * length);
Toshihiro Shimizu 890ddd
		x -= x0;
Toshihiro Shimizu 890ddd
		return exp(-x * x * b);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Saw
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x, double length, double height) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (length <= 0.0)
Toshihiro Shimizu 890ddd
			return 0.0;
Toshihiro Shimizu 890ddd
		if (height <= 0.0)
Toshihiro Shimizu 890ddd
			height = length;
Toshihiro Shimizu 890ddd
		double q = x / length;
Toshihiro Shimizu 890ddd
		return height * (q - floor(q));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
class Wave
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	double operator()(double x, double length) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (length <= 0.0)
Toshihiro Shimizu 890ddd
			return 0.0;
Toshihiro Shimizu 890ddd
		return sin(x * 2 * PI / length);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class Grammar::Imp
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	PatternTable m_prePatterns, m_postPatterns;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	Imp()
Toshihiro Shimizu 890ddd
		: m_prePatterns(Grammar::ExpressionStart), m_postPatterns(Grammar::ExpressionEnd)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	~Imp() {}
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Grammar::Grammar()
Toshihiro Shimizu 890ddd
	: m_imp(new Imp())
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	addPattern(new NumberPattern());
Toshihiro Shimizu 890ddd
	addPattern(new ConstantPattern("pi", PI, "3.14159265..."));
Toshihiro Shimizu 890ddd
	addPattern(new VariablePattern("t", CalculatorNode::T, "ranges from 0.0 to 1.0 along the transition"));
Toshihiro Shimizu 890ddd
	const string f_desc = "the current frame number";
Toshihiro Shimizu 890ddd
	addPattern(new VariablePattern("f", CalculatorNode::FRAME, f_desc));
Toshihiro Shimizu 890ddd
	addPattern(new VariablePattern("frame", CalculatorNode::FRAME, f_desc));
Toshihiro Shimizu 890ddd
	const string r_desc = "the current frame number, relative to the transition";
Toshihiro Shimizu 890ddd
	addPattern(new VariablePattern("r", CalculatorNode::RFRAME, r_desc));
Toshihiro Shimizu 890ddd
	addPattern(new VariablePattern("rframe", CalculatorNode::RFRAME, r_desc));
Toshihiro Shimizu 890ddd
	addPattern(new Op2Pattern<std::plus<double>>("+", 10));</std::plus<double>
Toshihiro Shimizu 890ddd
	addPattern(new Op2Pattern<std::multiplies<double>>("*", 20));</std::multiplies<double>
Toshihiro Shimizu 890ddd
	addPattern(new Op2Pattern<pow>("^", 30));</pow>
Toshihiro Shimizu 890ddd
	addPattern(new Op2Pattern<std::minus<double>>("-", 10));</std::minus<double>
Toshihiro Shimizu 890ddd
	addPattern(new Op2Pattern<std::divides<double>>("/", 20));</std::divides<double>
Toshihiro Shimizu 890ddd
	addPattern(new Op2Pattern<mod>("%", 8));</mod>
Toshihiro Shimizu 890ddd
	addPattern(new Op2Pattern<gt>(">", 6));</gt>
Toshihiro Shimizu 890ddd
	addPattern(new Op2Pattern<ge>(">=", 6));</ge>
Toshihiro Shimizu 890ddd
	addPattern(new Op2Pattern<lt>("<", 6));</lt>
Toshihiro Shimizu 890ddd
	addPattern(new Op2Pattern<le>("<=", 6));</le>
Toshihiro Shimizu 890ddd
	addPattern(new Op2Pattern<eq>("==", 6));</eq>
Toshihiro Shimizu 890ddd
	addPattern(new Op2Pattern<ne>("!=", 6));</ne>
Toshihiro Shimizu 890ddd
	addPattern(new Op2Pattern<and>("&&", 3));</and>
Toshihiro Shimizu 890ddd
	addPattern(new Op2Pattern<or>("||", 2));</or>
Toshihiro Shimizu 890ddd
	addPattern(new Op2Pattern<and>("and", 3));</and>
Toshihiro Shimizu 890ddd
	addPattern(new Op2Pattern<or>("or", 2));</or>
Toshihiro Shimizu 890ddd
	addPattern(new NotPattern("!", "not"));
Toshihiro Shimizu 890ddd
	addPattern(new NotPattern("not", ""));
Toshihiro Shimizu 890ddd
	addPattern(new UnaryMinusPattern());
Toshihiro Shimizu 890ddd
	addPattern(new BraketPattern());
Toshihiro Shimizu 890ddd
	addPattern(new QuestionTernaryPattern());
Toshihiro Shimizu 890ddd
	addPattern(new F1Pattern<sin>("sin", "sin(degree)"));</sin>
Toshihiro Shimizu 890ddd
	addPattern(new F1Pattern<cos>("cos", "cos(degree)"));</cos>
Toshihiro Shimizu 890ddd
	addPattern(new F1Pattern<tan>("tan", "tan(degree)"));</tan>
Toshihiro Shimizu 890ddd
	addPattern(new F1Pattern<sinh>("sinh", "sinh(degree)\nHyperbolic sine"));</sinh>
Toshihiro Shimizu 890ddd
	addPattern(new F1Pattern<cosh>("cosh", "cosh(degree)\nHyperbolic cosine"));</cosh>
Toshihiro Shimizu 890ddd
	addPattern(new F1Pattern<tanh>("tanh", "tanh(degree)\nHyperbolic tangent"));</tanh>
Toshihiro Shimizu 890ddd
	addPattern(new F1Pattern<atan>("atan", "atan(x)\nArctangent : the inverse of tan()"));</atan>
Toshihiro Shimizu 890ddd
	addPattern(new F2Pattern<atan2>("atan2", "atan2(y,x)\nThe counter-clockwise angle in degree between the x-axis and the point(x,y)"));</atan2>
Toshihiro Shimizu 890ddd
	addPattern(new F1Pattern<log>("log", "log(x)\nThe natural logarithm of x (base e)"));</log>
Toshihiro Shimizu 890ddd
	addPattern(new F1Pattern<exp>("exp", "exp(x)\nThe base-e exponential of x"));</exp>
Toshihiro Shimizu 890ddd
	addPattern(new F1Pattern<floor>("floor", "floor(x)\nThe greatest integer <= x"));</floor>
Toshihiro Shimizu 890ddd
	const string ceil_desc = "The smallest integer >= x";
Toshihiro Shimizu 890ddd
	addPattern(new F1Pattern<ceil>("ceil", "ceil(x)\n" + ceil_desc));</ceil>
Toshihiro Shimizu 890ddd
	addPattern(new F1Pattern<ceil>("ceiling", "ceiling(x)\n" + ceil_desc));</ceil>
Toshihiro Shimizu 890ddd
	addPattern(new F1Pattern<round>("round", "round(x)\nThe integer nearest to x"));</round>
Toshihiro Shimizu 890ddd
	addPattern(new F1Pattern<abs>("abs", "abs(x)\nThe absolute value of x"));</abs>
Toshihiro Shimizu 890ddd
	addPattern(new F1Pattern<sign>("sign", "sign(x)\n-1 if x<0, 1 if x>0 and 0 if x=0"));</sign>
Toshihiro Shimizu 890ddd
	const string sqrt_desc = "Square root of x";
Toshihiro Shimizu 890ddd
	addPattern(new F1Pattern<sqrt>("sqrt", "sqrt(x)\n" + sqrt_desc));</sqrt>
Toshihiro Shimizu 890ddd
	addPattern(new F1Pattern<sqr>("sqr", "sqr(x)\n" + sqrt_desc));</sqr>
Toshihiro Shimizu 890ddd
	addPattern(new F3Pattern<crop>("crop", "crop(x,a,b)\na if x<a, b="" if="" x="">b, x if x in [a,b]"));</a,></crop>
Toshihiro Shimizu 890ddd
	addPattern(new F3Pattern<crop>("clamp", "clamp(x,a,b)\na if x<a, b="" if="" x="">b, x if x in [a,b]"));</a,></crop>
Toshihiro Shimizu 890ddd
	addPattern(new F2Pattern<min>("min", "min(a,b)"));</min>
Toshihiro Shimizu 890ddd
	addPattern(new F2Pattern<max>("max", "max(a,b)"));</max>
Toshihiro Shimizu 890ddd
	addPattern(new F2Pattern<step>("step", "min(x,x0)\n0 if x<x0, 1="" if="" x="">=x0"));</x0,></step>
Toshihiro Shimizu 890ddd
	addPattern(new F3Pattern<smoothstep>("smoothstep", "smoothstep(x,x0)\n0 if x<x0, 1="" if="" x="">=x0\nas step, but with smooth transition"));</x0,></smoothstep>
Toshihiro Shimizu 890ddd
	const string pulse_desc = "Generates a bump ranging from 0.0 to 1.0 set at position pos";
Toshihiro Shimizu 890ddd
	addPattern(new Fs3Pattern<pulse>("pulse", 0.5, "pulse(pos)\npulse(pos,length)\npulse(arg; pos)\npulse(arg;pos,length)\n" + pulse_desc));</pulse>
Toshihiro Shimizu 890ddd
	addPattern(new Fs3Pattern<pulse>("bump", 0.5, "bump(pos)\nbump(pos,length)\nbump(arg; pos)\nbump(arg;pos,length)\n" + pulse_desc));</pulse>
Toshihiro Shimizu 890ddd
	const string saw_desc = "Generates a periodic sawtooth shaped curve";
Toshihiro Shimizu 890ddd
	addPattern(new Fs3Pattern<saw>("sawtooth", 0.0, "sawtooth(length)\nsawtooth(length, height)\nsawtooth(arg; length)\nsawtooth(arg; length, height)\n" + saw_desc));</saw>
Toshihiro Shimizu 890ddd
	addPattern(new Fs3Pattern<saw>("saw", 0.0, "saw(length)\nsaw(length, height)\nsaw(arg; length)\nsaw(arg; length, height)\n" + saw_desc));</saw>
Toshihiro Shimizu 890ddd
	addPattern(new Fs2Pattern<wave>("wave", "wave(_length)\nwave(_arg;_length)\nsame as sin(f*180/length)"));</wave>
Toshihiro Shimizu 890ddd
	const string rnd_desc = "Generates random number between min and max";
Toshihiro Shimizu 890ddd
	addPattern(new RandomPattern("random", false, "random = random(0,1)\nrandom(max) = random(0,max)\nrandom(min,max)\n" + rnd_desc));
Toshihiro Shimizu 890ddd
	addPattern(new RandomPattern("rnd", false, "rnd = rnd(0,1)\nrnd(max) = rnd(0,max)\nrnd(min,max)\n" + rnd_desc));
Toshihiro Shimizu 890ddd
	const string rnd_s_desc = rnd_desc + "; seed select different random sequences";
Toshihiro Shimizu 890ddd
	addPattern(new RandomPattern("random_s", true, "random_s(seed) = random_s(seed, 0,1)\nrandom_s(seed,max) = random_s(seed, 0,max)\nrandom_s(seed,min,max)\n" + rnd_s_desc));
Toshihiro Shimizu 890ddd
	addPattern(new RandomPattern("rnd_s", true, "rnd_s(seed) = rnd_s(seed, 0,1)\nrnd_s(seed,max) = rnd_s(seed, 0,max)\nrnd_s(seed,min,max)\n" + rnd_s_desc));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	addPattern(new CyclePattern("cycle"));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Grammar::~Grammar()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	delete m_imp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Grammar::addPattern(Pattern *pattern)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::vector<token> noTokens;</token>
Toshihiro Shimizu 890ddd
	if (pattern->expressionExpected(noTokens))
Toshihiro Shimizu 890ddd
		m_imp->m_postPatterns.addPattern(pattern);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		m_imp->m_prePatterns.addPattern(pattern);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const Pattern *Grammar::getPattern(Position position, const Token &token) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	Pattern *pattern = 0;
Toshihiro Shimizu 890ddd
	if (position == ExpressionStart)
Toshihiro Shimizu 890ddd
		return m_imp->m_prePatterns.getPattern(token);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return m_imp->m_postPatterns.getPattern(token);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void Grammar::getSuggestions(Grammar::Suggestions &suggestions, Position position) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (position == ExpressionStart)
Toshihiro Shimizu 890ddd
		return m_imp->m_prePatterns.getSuggestions(suggestions);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return m_imp->m_postPatterns.getSuggestions(suggestions);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace TSyntax