Revert to older calc parser code for now
This commit is contained in:
@@ -13,6 +13,7 @@ set(llmath_SOURCE_FILES
|
||||
llbbox.cpp
|
||||
llbboxlocal.cpp
|
||||
llcalc.cpp
|
||||
llcalcparser.cpp
|
||||
llcamera.cpp
|
||||
llcoordframe.cpp
|
||||
llline.cpp
|
||||
|
||||
@@ -28,61 +28,59 @@
|
||||
|
||||
#include "llcalc.h"
|
||||
|
||||
#include "llcalcparser.h"
|
||||
#include "llmath.h"
|
||||
|
||||
#include "llcalcparser.h"
|
||||
|
||||
// Variable names for use in the build floater
|
||||
// must be lower case for parser definition
|
||||
// case-insensitive for actual parsing
|
||||
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";
|
||||
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;
|
||||
|
||||
//TODO: Make this a static global class
|
||||
LLCalc::LLCalc() : mLastErrorPos(0)
|
||||
{
|
||||
// Init table of constants
|
||||
/*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);*/
|
||||
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;
|
||||
}
|
||||
|
||||
LLCalc::~LLCalc()
|
||||
@@ -99,7 +97,7 @@ void LLCalc::cleanUp()
|
||||
//static
|
||||
LLCalc* LLCalc::getInstance()
|
||||
{
|
||||
if (!sInstance) sInstance = new LLCalc();
|
||||
if (!sInstance) sInstance = new LLCalc();
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
@@ -118,35 +116,47 @@ void LLCalc::clearAllVariables()
|
||||
mVariables.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
void LLCalc::updateVariables(LLSD& vars)
|
||||
{
|
||||
LLSD::map_iterator cIt = vars.beginMap();
|
||||
for(; cIt != vars.endMap(); cIt++)
|
||||
{
|
||||
setVar(cIt->first, (F32)(LLSD::Real)cIt->second);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
bool LLCalc::evalString(const std::string& expression, F32& result)
|
||||
{
|
||||
mLastErrorPos = 0;
|
||||
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)
|
||||
{
|
||||
calc.constant.add(iter->first, iter->second);
|
||||
}
|
||||
std::string expr_upper = expression;
|
||||
LLStringUtil::toUpper(expr_upper);
|
||||
|
||||
LLCalcParser calc(result, &mConstants, &mVariables);
|
||||
|
||||
if (!expression::parse<F32,std::string::const_iterator>(itr, expression.end(), calc, result) || itr != expression.end())
|
||||
mLastErrorPos = 0;
|
||||
std::string::iterator start = expr_upper.begin();
|
||||
parse_info<std::string::iterator> info;
|
||||
|
||||
try
|
||||
{
|
||||
mLastErrorPos = itr - expression.begin();
|
||||
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();
|
||||
|
||||
LL_INFOS() << "Calc parser exception: " << e.descriptor << " at " << mLastErrorPos << " in expression: " << expression << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!info.full)
|
||||
{
|
||||
mLastErrorPos = info.stop - expr_upper.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;
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ public:
|
||||
private:
|
||||
std::string::size_type mLastErrorPos;
|
||||
|
||||
calc_map_t mConstants;
|
||||
calc_map_t mVariables;
|
||||
|
||||
// "There shall be only one"
|
||||
|
||||
63
indra/llmath/llcalcparser.cpp
Normal file
63
indra/llmath/llcalcparser.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
@@ -27,218 +27,162 @@
|
||||
#ifndef LL_CALCPARSER_H
|
||||
#define LL_CALCPARSER_H
|
||||
|
||||
#include <boost/spirit/version.hpp>
|
||||
#if !defined(SPIRIT_VERSION) || SPIRIT_VERSION < 0x2010
|
||||
#error "At least Spirit version 2.1 required"
|
||||
#endif
|
||||
#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;
|
||||
|
||||
// Add this in if we want boost math constants.
|
||||
#include <boost/bind.hpp>
|
||||
#include "llcalc.h"
|
||||
#include "llmath.h"
|
||||
|
||||
#if defined(LL_WINDOWS)
|
||||
#pragma warning(push)
|
||||
// warning C4348: 'boost::spirit::terminal<...>::result_helper': redefinition of default parameter: parameter 3, 4
|
||||
#pragma warning(disable: 4348)
|
||||
#endif
|
||||
|
||||
//#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/spirit/include/phoenix.hpp>
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
|
||||
#if defined(LL_WINDOWS)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
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)
|
||||
struct LLCalcParser : grammar<LLCalcParser>
|
||||
{
|
||||
return std::min(a, b);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T max_glue(T a, T b)
|
||||
{
|
||||
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
|
||||
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::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
|
||||
member1 value;
|
||||
};
|
||||
|
||||
template <typename ScannerT>
|
||||
struct definition
|
||||
{
|
||||
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_()
|
||||
// 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)
|
||||
{
|
||||
}
|
||||
} 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 )
|
||||
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 | '_')]
|
||||
;
|
||||
}
|
||||
} ufunc;
|
||||
|
||||
// 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)
|
||||
|
||||
group =
|
||||
'(' >> expression[group.value = arg1] >> assert_syntax(ch_p(')'))
|
||||
;
|
||||
}
|
||||
} 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])
|
||||
|
||||
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)))
|
||||
;
|
||||
|
||||
unary_expr =
|
||||
!ch_p('+') >> factor[unary_expr.value = arg1] |
|
||||
'-' >> factor[unary_expr.value = -arg1]
|
||||
;
|
||||
|
||||
power =
|
||||
unary_expr[power.value = arg1] >>
|
||||
*('^' >> assert_syntax(unary_expr[power.value = bind(&powf)(power.value, arg1)]))
|
||||
;
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user