1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
|
/***************************************************************************\
|* Function Parser for C++ v4.5.2 *|
|*-------------------------------------------------------------------------*|
|* Copyright: Juha Nieminen, Joel Yliluoma *|
|* *|
|* This library is distributed under the terms of the *|
|* GNU Lesser General Public License version 3. *|
|* (See lgpl.txt and gpl.txt for the license text.) *|
\***************************************************************************/
#ifndef ONCE_FPARSER_H_
#define ONCE_FPARSER_H_
#include <string>
#include <vector>
#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
#include <iostream>
#endif
#ifdef _MSC_VER
// Visual Studio's warning about missing definitions for the explicit
// FunctionParserBase instantiations is irrelevant here.
#pragma warning(disable : 4661)
#endif
namespace FPoptimizer_CodeTree { template<typename Value_t> class CodeTree; }
template<typename Value_t>
class FunctionParserBase
{
public:
enum ParseErrorType
{
SYNTAX_ERROR=0, MISM_PARENTH, MISSING_PARENTH, EMPTY_PARENTH,
EXPECT_OPERATOR, OUT_OF_MEMORY, UNEXPECTED_ERROR, INVALID_VARS,
ILL_PARAMS_AMOUNT, PREMATURE_EOS, EXPECT_PARENTH_FUNC,
UNKNOWN_IDENTIFIER,
NO_FUNCTION_PARSED_YET,
FP_NO_ERROR
};
typedef Value_t value_type;
int Parse(const char* Function, const std::string& Vars,
bool useDegrees = false);
int Parse(const std::string& Function, const std::string& Vars,
bool useDegrees = false);
void setDelimiterChar(char);
static Value_t epsilon();
static void setEpsilon(Value_t);
const char* ErrorMsg() const;
ParseErrorType GetParseErrorType() const;
Value_t Eval(const Value_t* Vars);
int EvalError() const;
bool AddConstant(const std::string& name, Value_t value);
bool AddUnit(const std::string& name, Value_t value);
typedef Value_t (*FunctionPtr)(const Value_t*);
bool AddFunction(const std::string& name,
FunctionPtr, unsigned paramsAmount);
bool AddFunction(const std::string& name, FunctionParserBase&);
class FunctionWrapper;
template<typename DerivedWrapper>
bool AddFunctionWrapper(const std::string& name, const DerivedWrapper&,
unsigned paramsAmount);
FunctionWrapper* GetFunctionWrapper(const std::string& name);
bool RemoveIdentifier(const std::string& name);
void Optimize();
int ParseAndDeduceVariables(const std::string& function,
int* amountOfVariablesFound = 0,
bool useDegrees = false);
int ParseAndDeduceVariables(const std::string& function,
std::string& resultVarString,
int* amountOfVariablesFound = 0,
bool useDegrees = false);
int ParseAndDeduceVariables(const std::string& function,
std::vector<std::string>& resultVars,
bool useDegrees = false);
FunctionParserBase();
~FunctionParserBase();
// Copy constructor and assignment operator (implemented using the
// copy-on-write technique for efficiency):
FunctionParserBase(const FunctionParserBase&);
FunctionParserBase& operator=(const FunctionParserBase&);
void ForceDeepCopy();
#ifdef FUNCTIONPARSER_SUPPORT_DEBUGGING
// For debugging purposes only.
// Performs no sanity checks or anything. If the values are wrong, the
// library will crash. Do not use unless you know what you are doing.
void InjectRawByteCode(const unsigned* bytecode, unsigned bytecodeAmount,
const Value_t* immed, unsigned immedAmount,
unsigned stackSize);
void PrintByteCode(std::ostream& dest, bool showExpression = true) const;
#endif
//========================================================================
protected:
//========================================================================
// A derived class can implement its own evaluation logic by using
// the parser data (found in fptypes.hh).
struct Data;
Data* getParserData();
//========================================================================
private:
//========================================================================
friend class FPoptimizer_CodeTree::CodeTree<Value_t>;
// Private data:
// ------------
Data* mData;
unsigned mStackPtr;
// Private methods:
// ---------------
void CopyOnWrite();
bool CheckRecursiveLinking(const FunctionParserBase*) const;
bool NameExists(const char*, unsigned);
bool ParseVariables(const std::string&);
int ParseFunction(const char*, bool);
const char* SetErrorType(ParseErrorType, const char*);
void AddFunctionOpcode(unsigned);
void AddImmedOpcode(Value_t v);
void incStackPtr();
void CompilePowi(long);
bool TryCompilePowi(Value_t);
const char* CompileIf(const char*);
const char* CompileFunctionParams(const char*, unsigned);
const char* CompileElement(const char*);
const char* CompilePossibleUnit(const char*);
const char* CompilePow(const char*);
const char* CompileUnaryMinus(const char*);
const char* CompileMult(const char*);
const char* CompileAddition(const char*);
const char* CompileComparison(const char*);
const char* CompileAnd(const char*);
const char* CompileExpression(const char*);
inline const char* CompileFunction(const char*, unsigned);
inline const char* CompileParenthesis(const char*);
inline const char* CompileLiteral(const char*);
template<bool SetFlag>
inline void PushOpcodeParam(unsigned);
template<bool SetFlag>
inline void PutOpcodeParamAt(unsigned, unsigned offset);
const char* Compile(const char*);
bool addFunctionWrapperPtr(const std::string&, FunctionWrapper*, unsigned);
static void incFuncWrapperRefCount(FunctionWrapper*);
static unsigned decFuncWrapperRefCount(FunctionWrapper*);
protected:
// Parsing utility functions
static std::pair<const char*, Value_t> ParseLiteral(const char*);
static unsigned ParseIdentifier(const char*);
};
class FunctionParser: public FunctionParserBase<double> {};
class FunctionParser_f: public FunctionParserBase<float> {};
class FunctionParser_ld: public FunctionParserBase<long double> {};
class FunctionParser_li: public FunctionParserBase<long> {};
#include <complex>
class FunctionParser_cd: public FunctionParserBase<std::complex<double> > {};
class FunctionParser_cf: public FunctionParserBase<std::complex<float> > {};
class FunctionParser_cld: public FunctionParserBase<std::complex<long double> > {};
template<typename Value_t>
class FunctionParserBase<Value_t>::FunctionWrapper
{
unsigned mReferenceCount;
friend class FunctionParserBase<Value_t>;
public:
FunctionWrapper(): mReferenceCount(1) {}
FunctionWrapper(const FunctionWrapper&): mReferenceCount(1) {}
virtual ~FunctionWrapper() {}
FunctionWrapper& operator=(const FunctionWrapper&) { return *this; }
virtual Value_t callFunction(const Value_t*) = 0;
};
template<typename Value_t>
template<typename DerivedWrapper>
bool FunctionParserBase<Value_t>::AddFunctionWrapper
(const std::string& name, const DerivedWrapper& wrapper, unsigned paramsAmount)
{
return addFunctionWrapperPtr
(name, new DerivedWrapper(wrapper), paramsAmount);
}
#endif
|