From e30d50600327458e7b510ad2ae3d9649265f1a08 Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Sat, 8 Aug 2020 17:26:52 -0400
Subject: [PATCH] Replace LLCalc code with alchemy version

---
 indra/llmath/llcalc.cpp       | 133 +++++++-------
 indra/llmath/llcalc.h         |   9 +-
 indra/llmath/llcalcparser.cpp |  63 -------
 indra/llmath/llcalcparser.h   | 328 +++++++++++++++++++---------------
 4 files changed, 255 insertions(+), 278 deletions(-)

diff --git a/indra/llmath/llcalc.cpp b/indra/llmath/llcalc.cpp
index edc6986cc91..85b57d21eba 100644
--- a/indra/llmath/llcalc.cpp
+++ b/indra/llmath/llcalc.cpp
@@ -28,70 +28,67 @@
 
 #include "llcalc.h"
 
-#include "llcalcparser.h"
 #include "llmath.h"
 
+#include "llcalcparser.h"
 
 // Variable names for use in the build floater
-const char* LLCalc::X_POS = "PX";
-const char* LLCalc::Y_POS = "PY";
-const char* LLCalc::Z_POS = "PZ";
-const char* LLCalc::X_SCALE = "SX";
-const char* LLCalc::Y_SCALE = "SY";
-const char* LLCalc::Z_SCALE = "SZ";
-const char* LLCalc::X_ROT = "RX";
-const char* LLCalc::Y_ROT = "RY";
-const char* LLCalc::Z_ROT = "RZ";
-const char* LLCalc::HOLLOW = "HLW";
-const char* LLCalc::CUT_BEGIN = "CB";
-const char* LLCalc::CUT_END = "CE";
-const char* LLCalc::PATH_BEGIN = "PB";
-const char* LLCalc::PATH_END = "PE";
-const char* LLCalc::TWIST_BEGIN = "TB";
-const char* LLCalc::TWIST_END = "TE";
-const char* LLCalc::X_SHEAR = "SHX";
-const char* LLCalc::Y_SHEAR = "SHY";
-const char* LLCalc::X_TAPER = "TPX";
-const char* LLCalc::Y_TAPER = "TPY";
-const char* LLCalc::RADIUS_OFFSET = "ROF";
-const char* LLCalc::REVOLUTIONS = "REV";
-const char* LLCalc::SKEW = "SKW";
-const char* LLCalc::X_HOLE = "HLX";
-const char* LLCalc::Y_HOLE = "HLY";
-const char* LLCalc::TEX_U_SCALE = "TSU";
-const char* LLCalc::TEX_V_SCALE = "TSV";
-const char* LLCalc::TEX_U_OFFSET = "TOU";
-const char* LLCalc::TEX_V_OFFSET = "TOV";
-const char* LLCalc::TEX_ROTATION = "TROT";
-const char* LLCalc::TEX_TRANSPARENCY = "TRNS";
-const char* LLCalc::TEX_GLOW = "GLOW";
-
-
-LLCalc* LLCalc::sInstance = NULL;
+const char* LLCalc::X_POS = "px";
+const char* LLCalc::Y_POS = "py";
+const char* LLCalc::Z_POS = "pz";
+const char* LLCalc::X_SCALE = "sx";
+const char* LLCalc::Y_SCALE = "sy";
+const char* LLCalc::Z_SCALE = "sz";
+const char* LLCalc::X_ROT = "rx";
+const char* LLCalc::Y_ROT = "ry";
+const char* LLCalc::Z_ROT = "rz";
+const char* LLCalc::HOLLOW = "hlw";
+const char* LLCalc::CUT_BEGIN = "cb";
+const char* LLCalc::CUT_END = "ce";
+const char* LLCalc::PATH_BEGIN = "pb";
+const char* LLCalc::PATH_END = "pe";
+const char* LLCalc::TWIST_BEGIN = "tb";
+const char* LLCalc::TWIST_END = "te";
+const char* LLCalc::X_SHEAR = "shx";
+const char* LLCalc::Y_SHEAR = "shy";
+const char* LLCalc::X_TAPER = "tpx";
+const char* LLCalc::Y_TAPER = "tpy";
+const char* LLCalc::RADIUS_OFFSET = "rof";
+const char* LLCalc::REVOLUTIONS = "rev";
+const char* LLCalc::SKEW = "skw";
+const char* LLCalc::X_HOLE = "hlx";
+const char* LLCalc::Y_HOLE = "hly";
+const char* LLCalc::TEX_U_SCALE = "tsu";
+const char* LLCalc::TEX_V_SCALE = "tsv";
+const char* LLCalc::TEX_U_OFFSET = "tou";
+const char* LLCalc::TEX_V_OFFSET = "tov";
+const char* LLCalc::TEX_ROTATION = "trot";
+const char* LLCalc::TEX_TRANSPARENCY = "trns";
+const char* LLCalc::TEX_GLOW = "glow";
+
+
+LLCalc* LLCalc::sInstance = nullptr;
 
 LLCalc::LLCalc() : mLastErrorPos(0)
 {
 	// Init table of constants
-	mConstants["PI"] = F_PI;
-	mConstants["TWO_PI"] = F_TWO_PI;
-	mConstants["PI_BY_TWO"] = F_PI_BY_TWO;
-	mConstants["SQRT_TWO_PI"] = F_SQRT_TWO_PI;
-	mConstants["SQRT2"] = F_SQRT2;
-	mConstants["SQRT3"] = F_SQRT3;
-	mConstants["DEG_TO_RAD"] = DEG_TO_RAD;
-	mConstants["RAD_TO_DEG"] = RAD_TO_DEG;
-	mConstants["GRAVITY"] = GRAVITY;
+	/*setVar("PI", F_PI);
+	setVar("TWO_PI", F_TWO_PI);
+	setVar("PI_BY_TWO", F_PI_BY_TWO);
+	setVar("SQRT_TWO_PI", F_SQRT_TWO_PI);
+	setVar("SQRT2", F_SQRT2);
+	setVar("SQRT3", F_SQRT3);
+	setVar("DEG_TO_RAD", DEG_TO_RAD);
+	setVar("RAD_TO_DEG", RAD_TO_DEG);
+	setVar("GRAVITY", GRAVITY);*/
 }
 
-LLCalc::~LLCalc()
-{
-}
 
 //static
 void LLCalc::cleanUp()
 {
 	delete sInstance;
-	sInstance = NULL;
+	sInstance = nullptr;
 }
 
 //static
@@ -129,34 +126,36 @@ void LLCalc::updateVariables(LLSD& vars)
 
 bool LLCalc::evalString(const std::string& expression, F32& result)
 {
-	std::string expr_upper = expression;
-	LLStringUtil::toUpper(expr_upper);
 	
-	LLCalcParser calc(result, &mConstants, &mVariables);
 
 	mLastErrorPos = 0;
-	std::string::iterator start = expr_upper.begin();
- 	parse_info<std::string::iterator> info;
-	
-	try
+	std::string::const_iterator itr = expression.begin();
+	expression::grammar<F32,std::string::const_iterator> calc;
+	calc.constant.add
+				("pi", F_PI)
+				("two_pi", F_TWO_PI)
+				("pi_by_two", F_PI_BY_TWO)
+				("sqrt_two_pi", F_SQRT_TWO_PI)
+				("sqrt2", F_SQRT2)
+				("sqrt3", F_SQRT3)
+				("deg_to_rad", DEG_TO_RAD)
+				("rad_to_deg", RAD_TO_DEG)
+				("gravity", GRAVITY)
+			;
+	for(calc_map_t::const_iterator iter = mVariables.begin();
+		iter != mVariables.end();
+		++iter)
 	{
-		info = parse(start, expr_upper.end(), calc, space_p);
-		LL_DEBUGS() << "Math expression: " << expression << " = " << result << LL_ENDL;
-	}
-	catch(parser_error<std::string, std::string::iterator> &e)
-	{
-		mLastErrorPos = e.where - expr_upper.begin();
+		calc.constant.add(iter->first, iter->second);
 		
-		LL_INFOS() << "Calc parser exception: " << e.descriptor << " at " << mLastErrorPos << " in expression: " << expression << LL_ENDL;
-		return false;
 	}
 	
-	if (!info.full)
+	if (!expression::parse<F32,std::string::const_iterator>(itr, expression.end(), calc, result) || itr !=  expression.end())
 	{
-		mLastErrorPos = info.stop - expr_upper.begin();
+		mLastErrorPos = itr - expression.begin();
 		LL_INFOS() << "Unhandled syntax error at " << mLastErrorPos << " in expression: " << expression << LL_ENDL;
 		return false;
 	}
-	
+	LL_DEBUGS() << "Math expression: " << expression << " = " << result << LL_ENDL;
 	return true;
 }
diff --git a/indra/llmath/llcalc.h b/indra/llmath/llcalc.h
index ceb9dce585d..17782fb88bf 100644
--- a/indra/llmath/llcalc.h
+++ b/indra/llmath/llcalc.h
@@ -34,7 +34,7 @@ class LLCalc
 {
 public:
 	LLCalc();
-	~LLCalc();
+	~LLCalc() = default;
 
 	// Variable name constants
 	static const char* X_POS;
@@ -86,13 +86,8 @@ class LLCalc
 private:
 	std::string::size_type	mLastErrorPos;
 	
-	calc_map_t	mConstants;
 	calc_map_t	mVariables;
-	
-	// *TODO: Add support for storing user defined variables, and stored functions.
-	//	Will need UI work, and a means to save them between sessions.
-//	calc_map_t mUserVariables;
-	
+
 	// "There shall be only one"
 	static LLCalc*	sInstance;
 };
diff --git a/indra/llmath/llcalcparser.cpp b/indra/llmath/llcalcparser.cpp
index b4ca3206594..e69de29bb2d 100644
--- a/indra/llmath/llcalcparser.cpp
+++ b/indra/llmath/llcalcparser.cpp
@@ -1,63 +0,0 @@
-/*
- *  LLCalcParser.cpp
- *  Copyright 2008 Aimee Walton.
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2008, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- *
- */
-
-#include "linden_common.h"
-
-#include "llcalcparser.h"
-using namespace boost::spirit::classic;
-
-F32 LLCalcParser::lookup(const std::string::iterator& start, const std::string::iterator& end) const
-{
-	LLCalc::calc_map_t::iterator iter;
-
-	std::string name(start, end);
-	
-	if (mConstants)
-	{
-		iter = mConstants->find(name);
-		if (iter != mConstants->end())
-		{
-			return (*iter).second;
-		}
-	}
-	else
-	{
-		// This should never happen!
-		throw_(end, std::string("Missing constants table"));
-	}
-	
-	if (mVariables)
-	{
-		iter = mVariables->find(name);
-		if (iter != mVariables->end())
-		{
-			return (*iter).second;
-		}
-	}
-	
-	throw_(end, std::string("Unknown symbol " + name));
-	return 0.f;
-}
diff --git a/indra/llmath/llcalcparser.h b/indra/llmath/llcalcparser.h
index e2388d6702d..bc1b2b150da 100644
--- a/indra/llmath/llcalcparser.h
+++ b/indra/llmath/llcalcparser.h
@@ -27,162 +27,208 @@
 #ifndef LL_CALCPARSER_H
 #define LL_CALCPARSER_H
 
-#include <boost/spirit/include/classic_attribute.hpp>
-#include <boost/spirit/include/classic_core.hpp>
-#include <boost/spirit/include/classic_error_handling.hpp>
-#include <boost/spirit/include/classic_position_iterator.hpp>
-#include <boost/spirit/include/phoenix1_binders.hpp>
-#include <boost/spirit/include/classic_symbols.hpp>
-using namespace boost::spirit::classic;
+#include <boost/spirit/version.hpp>
+#if !defined(SPIRIT_VERSION) || SPIRIT_VERSION < 0x2010
+#error "At least Spirit version 2.1 required"
+#endif
 
-#include "llcalc.h"
-#include "llmath.h"
+// Add this in if we want boost math constants.
+#include <boost/bind.hpp>
+//#include <boost/math/constants/constants.hpp>
+#include <boost/spirit/include/phoenix.hpp>
+#include <boost/spirit/include/qi.hpp>
 
-struct LLCalcParser : grammar<LLCalcParser>
+namespace expression {
+
+
+//TODO: If we can find a better way to do this with boost::pheonix::bind lets do it
+//namespace { // anonymous
+
+template <typename T>
+T min_glue(T a, T b)
+{
+	return std::min(a, b);
+}
+
+template <typename T>
+T max_glue(T a, T b)
 {
-	LLCalcParser(F32& result, LLCalc::calc_map_t* constants, LLCalc::calc_map_t* vars) :
-		mResult(result), mConstants(constants), mVariables(vars) {};
-	
-	struct value_closure : closure<value_closure, F32>
+	return std::max(a, b);
+}
+
+struct lazy_pow_
+{
+	template <typename X, typename Y>
+	struct result { typedef X type; };
+ 
+	template <typename X, typename Y>
+	X operator()(X x, Y y) const
 	{
-		member1 value;
-	};
-	
-	template <typename ScannerT>
-	struct definition
+		return std::pow(x, y);
+	}
+};
+ 
+struct lazy_ufunc_
+{
+	template <typename F, typename A1>
+	struct result { typedef A1 type; };
+ 
+	template <typename F, typename A1>
+	A1 operator()(F f, A1 a1) const
 	{
-		// Rule declarations
-		rule<ScannerT> statement, identifier;
-		rule<ScannerT, value_closure::context_t> expression, term,
-			power, 
-			unary_expr, 
-			factor, 
-			unary_func, 
-			binary_func,
-			group;
-
-		// start() should return the starting symbol
-		rule<ScannerT> const& start() const { return statement; }
-		
-		definition(LLCalcParser const& self)
+		return f(a1);
+	}
+};
+ 
+struct lazy_bfunc_
+{
+	template <typename F, typename A1, typename A2>
+	struct result { typedef A1 type; };
+ 
+	template <typename F, typename A1, typename A2>
+	A1 operator()(F f, A1 a1, A2 a2) const
+	{
+		return f(a1, a2);
+	}
+};
+ 
+//} // end namespace anonymous
+ 
+template <typename FPT, typename Iterator>
+struct grammar
+	: boost::spirit::qi::grammar<
+			Iterator, FPT(), boost::spirit::ascii::space_type
+		>
+{
+ 
+	// symbol table for constants
+	// to be added by the actual calculator
+	struct constant_
+		: boost::spirit::qi::symbols<
+				typename std::iterator_traits<Iterator>::value_type,
+				FPT
+			>
+	{
+		constant_()
 		{
-			using namespace phoenix;
-			
-			assertion<std::string> assert_domain("Domain error");
-//			assertion<std::string> assert_symbol("Unknown symbol");
-			assertion<std::string> assert_syntax("Syntax error");
-			
-			identifier =
-				lexeme_d[(alpha_p | '_') >> *(alnum_p | '_')]
-			;
-			
-			group =
-				'(' >> expression[group.value = arg1] >> assert_syntax(ch_p(')'))
-			;
-
-			unary_func =
-				((str_p("SIN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_sin)(self,arg1)]) |
-				 (str_p("COS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_cos)(self,arg1)]) |
-				 (str_p("TAN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_tan)(self,arg1)]) |
-				 (str_p("ASIN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_asin)(self,arg1)]) |
-				 (str_p("ACOS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_acos)(self,arg1)]) |
-				 (str_p("ATAN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_atan)(self,arg1)]) |
-				 (str_p("SQRT") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_sqrt)(self,arg1)]) |
-				 (str_p("LOG") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_log)(self,arg1)]) |
-				 (str_p("EXP") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_exp)(self,arg1)]) |
-				 (str_p("ABS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_fabs)(self,arg1)]) |
-				 (str_p("FLR") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_floor)(self,arg1)]) |
-				 (str_p("CEIL") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_ceil)(self,arg1)])
-				) >> assert_syntax(ch_p(')'))
-			;
-			
-			binary_func =
-				((str_p("ATAN2") >> '(' >> expression[binary_func.value = arg1] >> ',' >>
-				  expression[binary_func.value = bind(&LLCalcParser::_atan2)(self, binary_func.value, arg1)]) |
-				 (str_p("MIN") >> '(' >> expression[binary_func.value = arg1] >> ',' >> 
-				  expression[binary_func.value = bind(&LLCalcParser::_min)(self, binary_func.value, arg1)]) |
-				 (str_p("MAX") >> '(' >> expression[binary_func.value = arg1] >> ',' >> 
-				  expression[binary_func.value = bind(&LLCalcParser::_max)(self, binary_func.value, arg1)])
-				) >> assert_syntax(ch_p(')'))
-			;
-			
-			// *TODO: Localisation of the decimal point?
-			// Problem, LLLineEditor::postvalidateFloat accepts a comma when appropriate
-			// for the current locale. However to do that here could clash with using
-			// the comma as a separator when passing arguments to functions.
-			factor =
-				(ureal_p[factor.value = arg1] |
-				 group[factor.value = arg1] |
-				 unary_func[factor.value = arg1] |
-				 binary_func[factor.value = arg1] |
-				 // Lookup throws an Unknown Symbol error if it is unknown, while this works fine,
-				 // would be "neater" to handle symbol lookup from here with an assertive parser.
-//				 constants_p[factor.value = arg1]|
-				 identifier[factor.value = bind(&LLCalcParser::lookup)(self, arg1, arg2)]
-				) >>
-				// Detect and throw math errors.
-				assert_domain(eps_p(bind(&LLCalcParser::checkNaN)(self, factor.value)))
+		}
+	} constant;
+ 
+	// symbol table for unary functions like "abs"
+	struct ufunc_
+		: boost::spirit::qi::symbols<
+				typename std::iterator_traits<Iterator>::value_type,
+				FPT (*)(FPT)
+			>
+	{
+		ufunc_()
+		{
+			this->add
+				("abs"   , (FPT (*)(FPT)) std::abs  )
+				("acos"  , (FPT (*)(FPT)) std::acos )
+				("asin"  , (FPT (*)(FPT)) std::asin )
+				("atan"  , (FPT (*)(FPT)) std::atan )
+				("ceil"  , (FPT (*)(FPT)) std::ceil	)
+				("cos"   , (FPT (*)(FPT)) std::cos  )
+				("cosh"  , (FPT (*)(FPT)) std::cosh )
+				("exp"   , (FPT (*)(FPT)) std::exp  )
+				("floor" , (FPT (*)(FPT)) std::floor)
+				("log"   , (FPT (*)(FPT)) std::log  )
+				("log10" , (FPT (*)(FPT)) std::log10)
+				("sin"   , (FPT (*)(FPT)) std::sin  )
+				("sinh"  , (FPT (*)(FPT)) std::sinh )
+				("sqrt"  , (FPT (*)(FPT)) std::sqrt )
+				("tan"   , (FPT (*)(FPT)) std::tan  )
+				("tanh"  , (FPT (*)(FPT)) std::tanh )
 			;
+		}
+	} ufunc;
 
-			unary_expr =
-				!ch_p('+') >> factor[unary_expr.value = arg1] |
-				'-' >> factor[unary_expr.value = -arg1]
+	// symbol table for binary functions like "pow"
+	struct bfunc_
+		: boost::spirit::qi::symbols<
+				typename std::iterator_traits<Iterator>::value_type,
+				FPT (*)(FPT, FPT)
+			>
+	{
+		bfunc_()
+		{
+			using boost::bind;
+			this->add
+				("pow"  , (FPT (*)(FPT, FPT)) std::pow	)
+				("atan2", (FPT (*)(FPT, FPT)) std::atan2)
+				("min"	, (FPT (*)(FPT, FPT)) min_glue)
+				("max"	, (FPT (*)(FPT, FPT)) max_glue)
 			;
-			
-			power =
-				unary_expr[power.value = arg1] >>
-				*('^' >> assert_syntax(unary_expr[power.value = bind(&powf)(power.value, arg1)]))
+		}
+	} bfunc;
+ 
+	boost::spirit::qi::rule<
+			Iterator, FPT(), boost::spirit::ascii::space_type
+		> expression, term, factor, primary;
+ 
+	grammar() : grammar::base_type(expression)
+	{
+		using boost::spirit::qi::real_parser;
+		using boost::spirit::qi::real_policies;
+		real_parser<FPT,real_policies<FPT> > real;
+ 
+		using boost::spirit::qi::_1;
+		using boost::spirit::qi::_2;
+		using boost::spirit::qi::_3;
+		using boost::spirit::qi::no_case;
+		using boost::spirit::qi::_val;
+ 
+		boost::phoenix::function<lazy_pow_>   lazy_pow;
+		boost::phoenix::function<lazy_ufunc_> lazy_ufunc;
+		boost::phoenix::function<lazy_bfunc_> lazy_bfunc;
+ 
+		expression =
+			term                   [_val =  _1]
+			>> *(  ('+' >> term    [_val += _1])
+				|  ('-' >> term    [_val -= _1])
+				)
 			;
-			
-			term =
-				power[term.value = arg1] >>
-				*(('*' >> assert_syntax(power[term.value *= arg1])) |
-				  ('/' >> assert_syntax(power[term.value /= arg1])) |
-				  ('%' >> assert_syntax(power[term.value = bind(&fmodf)(term.value, arg1)]))
+ 
+		term =
+			factor                 [_val =  _1]
+			>> *(  ('*' >> factor  [_val *= _1])
+				|  ('/' >> factor  [_val /= _1])
 				)
 			;
-			
-			expression =
-				assert_syntax(term[expression.value = arg1]) >>
-				*(('+' >> assert_syntax(term[expression.value += arg1])) |
-				  ('-' >> assert_syntax(term[expression.value -= arg1]))
+ 
+		factor =
+			primary                [_val =  _1]
+			>> *(  ("**" >> factor [_val = lazy_pow(_val, _1)])
 				)
 			;
-
-			statement =
-				!ch_p('=') >> ( expression )[var(self.mResult) = arg1] >> (end_p)
+ 
+		primary =
+			real                   [_val =  _1]
+			|   '(' >> expression  [_val =  _1] >> ')'
+			|   ('-' >> primary    [_val = -_1])
+			|   ('+' >> primary    [_val =  _1])
+			|   (no_case[ufunc] >> '(' >> expression >> ')')
+								   [_val = lazy_ufunc(_1, _2)]
+			|   (no_case[bfunc] >> '(' >> expression >> ','
+									   >> expression >> ')')
+								   [_val = lazy_bfunc(_1, _2, _3)]
+			|   no_case[constant]  [_val =  _1]
 			;
-		}
-	};
-	
-private:
-	// Member functions for semantic actions
-	F32	lookup(const std::string::iterator&, const std::string::iterator&) const;
-	F32 _min(const F32& a, const F32& b) const { return llmin(a, b); }
-	F32 _max(const F32& a, const F32& b) const { return llmax(a, b); }
-	
-	bool checkNaN(const F32& a) const { return !llisnan(a); }
-	
-	//FIX* non ambiguous function fix making SIN() work for calc -Cryogenic Blitz
-	F32 _sin(const F32& a) const { return sin(DEG_TO_RAD * a); }
-	F32 _cos(const F32& a) const { return cos(DEG_TO_RAD * a); }
-	F32 _tan(const F32& a) const { return tan(DEG_TO_RAD * a); }
-	F32 _asin(const F32& a) const { return asin(a) * RAD_TO_DEG; }
-	F32 _acos(const F32& a) const { return acos(a) * RAD_TO_DEG; }
-	F32 _atan(const F32& a) const { return atan(a) * RAD_TO_DEG; }
-	F32 _sqrt(const F32& a) const { return sqrt(a); }
-	F32 _log(const F32& a) const { return log(a); }
-	F32 _exp(const F32& a) const { return exp(a); }
-	F32 _fabs(const F32& a) const { return fabs(a); }
-	F32 _floor(const F32& a) const { return (F32)llfloor(a); }
-	F32 _ceil(const F32& a) const { return llceil(a); }
-	F32 _atan2(const F32& a,const F32& b) const { return atan2(a,b); }
-
-	LLCalc::calc_map_t* mConstants;
-	LLCalc::calc_map_t* mVariables;
-//	LLCalc::calc_map_t* mUserVariables;
-	
-	F32&		mResult;
+ 
+	}
 };
+ 
+template <typename FPT, typename Iterator>
+bool parse(Iterator &iter,
+		   Iterator end,
+		   const grammar<FPT,Iterator> &g,
+		   FPT &result)
+{
+	return boost::spirit::qi::phrase_parse(
+				iter, end, g, boost::spirit::ascii::space, result);
+}
+ 
+} // end namespace expression
 
 #endif // LL_CALCPARSER_H
-- 
GitLab