added: expreval third party library
this is a library to perform analytic function evaluation git-svn-id: http://svn.sintef.no/trondheim/IFEM/trunk@1335 e10b68d5-8a6e-419e-a041-bce267b0401d
This commit is contained in:
parent
9ddf27e7ff
commit
1d3cfbfacf
26
3rdparty/expreval/defs.h
vendored
Normal file
26
3rdparty/expreval/defs.h
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
// File: defs.h
|
||||
// Author: Brian Vanderburg II
|
||||
// Purpose: Definitions for ExprEval
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef __EXPREVAL_DEFS_H
|
||||
#define __EXPREVAL_DEFS_H
|
||||
|
||||
namespace ExprEval
|
||||
{
|
||||
// constants
|
||||
const double EXPREVAL_PI = 3.14159265358979323846;
|
||||
const double EXPREVAL_E = 2.7182818284590452354;
|
||||
|
||||
} // namespace ExprEval
|
||||
|
||||
// CHANGED from original code: due to auto_ptr deprecation in c++0x
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
#define aptr(x) std::unique_ptr<x>
|
||||
#else
|
||||
#define aptr(x) std::auto_ptr<x>
|
||||
#endif
|
||||
|
||||
|
||||
#endif // __EXPREVAL_DEFS_H
|
||||
|
33
3rdparty/expreval/docs/changes.txt
vendored
Normal file
33
3rdparty/expreval/docs/changes.txt
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
IFEM Hacks
|
||||
----------
|
||||
- Added a define in defs.h. auto_ptr is deprecated in c++0x. uses
|
||||
std::unique_ptr instead. Quells the warnings
|
||||
|
||||
ExprEval 3.6
|
||||
------------
|
||||
- Removed support for arbitrary data objects. It seemed unused anyhow.
|
||||
- Fixed locale handling. It can now parse expressions correctly no matter
|
||||
what locale the program is in.
|
||||
|
||||
ExprEval 3.3
|
||||
------------
|
||||
- Added support for arbitrary data objects to be passed to functions
|
||||
with the '@' operator. The expression library itself does not have
|
||||
any understanding of the arbitrary data, but the functions can.
|
||||
|
||||
ExprEval 3.2
|
||||
------------
|
||||
- Added Exception::GetType method to determine the type of error
|
||||
without needing many catch statements.
|
||||
|
||||
ExprEval 3.1
|
||||
------------
|
||||
- Removed Exception::what due to language problems. Each application should
|
||||
do testing and report the exception to the user itself, in whatever language
|
||||
it needs.
|
||||
- Added Exception::GetStart and Exception::GetEnd to report where in the
|
||||
expression string the error occurs when parsing.
|
||||
- Added Exception::GetValue to get the name of the object, function, etc
|
||||
that is responsible for an exception, depending on the exception itself
|
||||
- In header files, replaced 'std::X' with '::std::X'
|
||||
|
771
3rdparty/expreval/docs/expreval.txt
vendored
Normal file
771
3rdparty/expreval/docs/expreval.txt
vendored
Normal file
@ -0,0 +1,771 @@
|
||||
ExprEval 3.x Help
|
||||
-----------------
|
||||
|
||||
Introduction
|
||||
------------
|
||||
ExprEval 3.x is an expression evaluation library for C++. It can take an
|
||||
expression string, parse it, and evaluate it. Several key features of ExprEval
|
||||
include:
|
||||
|
||||
- Object Oriented. ExprEval 3.x is a C++ library, where 2.x was a C library.
|
||||
- POEM (Parse Once, Evaluate Many), the expression string is parsed on time.
|
||||
After that, it can be evaluated over and over many times.
|
||||
- Seperation of objects. By keeping the function and value lists seperate from
|
||||
the expression, the programmer can choose how to connect them. Each
|
||||
expression may have a private value list, or several expressions can share
|
||||
a single value list.
|
||||
- Fast variable lookup. The variables and constants are stored as pointers in
|
||||
the parsed expression. This means there is no need to search through a list
|
||||
for the value. Additionally, applications can do the same.
|
||||
- Custom functions. An application can create custom functions for use by an
|
||||
expression. Doing so is easy.
|
||||
- Variable constants. As the name suggests, a constant that is variable. The
|
||||
expression can NOT change a constant, but the application can.
|
||||
|
||||
Syntax
|
||||
------
|
||||
Expression syntax is similar to what it may look like written on paper. The
|
||||
operators '+', '-', '*', '/', and '^', are the addition, subtraction,
|
||||
multiplication, division, and exponent operators and the '=' operator is used to
|
||||
assign to a variable.
|
||||
|
||||
k = (x * x) + (y * y)
|
||||
|
||||
is the same as
|
||||
|
||||
k = x ^ 2 + y ^ 2
|
||||
|
||||
Parentheses are used to group items in an expression and for the
|
||||
arguments to a function.
|
||||
|
||||
d = sqrt((x * x) + (y * y))
|
||||
|
||||
Semicolons are used to seperate expressions. In this way, an expresion string
|
||||
can contain more than one expression. The result is the value of the last
|
||||
expression.
|
||||
|
||||
x = r * cos(d); y = r * sin(d)
|
||||
|
||||
Functions can take normal arguments and reference arguments. Functions that
|
||||
take reference arguments can modify the reference variable. Constants can NOT
|
||||
be passed by reference. Also, normal and reference arguments can be mixed, as
|
||||
long as the order is the same. Commas(',') at a parentheses level of 0 are used
|
||||
to seperate the arguments. Reference parameters must be prefixed with an
|
||||
ampersand('&').
|
||||
|
||||
f(x, y, z, &a, &b, &c)
|
||||
|
||||
is the same as
|
||||
|
||||
f(x, &a, y, &b, z, &c)
|
||||
|
||||
Anything that is a sub-expression is still an expression, and can be anything
|
||||
that an expression can be.
|
||||
|
||||
y = x = 0
|
||||
|
||||
x = r * cos(r1 ; r2) ; y = (z ; r) * cos(r1 + sin(r2) ; r2)
|
||||
|
||||
Order of Operators
|
||||
------------------
|
||||
Within an expression, the order of operators is as follows.
|
||||
|
||||
1. Parentheses
|
||||
2. Exponents, left to right
|
||||
3. Negation, right to left
|
||||
4. Multiplication/division, left to right
|
||||
5. Addition/subtration, left to right
|
||||
6. Assignment, right to left
|
||||
|
||||
The entire expression is actually parsed as a tree. This expression will look
|
||||
a little like this: (view with a fixed-width font)
|
||||
|
||||
y = q = x + -z^-2^3 - 5 * (x + 2) * sin(x)
|
||||
|
||||
assign(y)
|
||||
|
|
||||
assign(q)
|
||||
|
|
||||
subtract
|
||||
________________/ \_____________
|
||||
/ \
|
||||
add multiply
|
||||
___/ \___ _____/ \_____
|
||||
/ \ / \
|
||||
variable(x) negate multiply function(sin)
|
||||
| __/ \___ |
|
||||
power / \ variable(x)
|
||||
__/ \___ value(5) add
|
||||
/ \ ____/ \_____
|
||||
power value(3) / \
|
||||
___/ \___ variable(x) value(2)
|
||||
/ \
|
||||
variable(z) negate
|
||||
|
|
||||
value(2)
|
||||
|
||||
Using ExprEval
|
||||
--------------
|
||||
To use ExprEval, just include 'expreval.h' in your program. All the items are
|
||||
under the 'ExprEval' namespace:
|
||||
|
||||
#include "expreval.h"
|
||||
using namespace ExprEval;
|
||||
using namespace std;
|
||||
|
||||
Then, create the value and function lists, and initialize them as desired.
|
||||
|
||||
ValueList vlist;
|
||||
FunctionLIst flist;
|
||||
|
||||
vlist.AddDefaultValues();
|
||||
flist.AddDefaultFunctions();
|
||||
|
||||
Finally, create the expression and set it to use the values and functions.
|
||||
|
||||
Expression e;
|
||||
e.SetValueList(&vlist);
|
||||
e.SetFunctionList(&flist);
|
||||
|
||||
Now the expression is ready to be parsed and evaluated.
|
||||
|
||||
e.Parse("y=5");
|
||||
result = e.Evaluate();
|
||||
|
||||
User Abort
|
||||
----------
|
||||
It is possible that an evaluation can take a long amount of time or enter an
|
||||
infinite loop, depending on the functions used and the expression. To help
|
||||
with this, an abort mechanism is introduced. Every time 'Node::Evaluate' gets
|
||||
called, it calls 'Expression::TestAbort', and then 'Node::DoEvaluate'. Every so
|
||||
often, 'Expression::TestAbort' will call 'Expression::DoTestAbort'. If
|
||||
'Expression::DoTestAbort' returns true, and exception is thrown indicating an
|
||||
abort.
|
||||
|
||||
The reason a real test is not conducted each time by 'Expression::TestAbort' is
|
||||
that it can dramatically slow down the expression evaluation, depending how an
|
||||
abort is tested. 'Expression::SetTestAbortCount' controlls how many times
|
||||
'Node::Evaluate' (and therefore 'Expression::TestAbort') gets called before a
|
||||
real abort is tested by 'Expression::DoTestAbort'.
|
||||
|
||||
To add abort testing support, derive a new expression object and override
|
||||
'Expression::DoTestAbort' as follows:
|
||||
|
||||
class MyExpression : public Expression
|
||||
{
|
||||
public:
|
||||
MyExpression(bool *abort) { m_abort = abort; }
|
||||
|
||||
bool DoTestAbort() { return *m_abort; }
|
||||
|
||||
private:
|
||||
bool *m_abort;
|
||||
};
|
||||
|
||||
User Data
|
||||
---------
|
||||
If custom function need to access user data associated with an expression,
|
||||
derive a class from the expression object that stores the user data. Then,
|
||||
access the expression from the function node by using the protected 'm_expr'.
|
||||
|
||||
class MyExpression : public Expression
|
||||
{
|
||||
public:
|
||||
MyExpression(void *userdata);
|
||||
};
|
||||
|
||||
class MyFunctionNode : public FunctionNode
|
||||
{
|
||||
public:
|
||||
...
|
||||
|
||||
double DoEvaluate() { MyExpression *m = (MyExpression*)m_expr; ... }
|
||||
};
|
||||
|
||||
|
||||
Identifiers
|
||||
-----------
|
||||
Functions, variables, and constants are accessed in the expression as
|
||||
identifiers. These identifiers follow a certain form by the parser:
|
||||
|
||||
- An identifier may consist of multiple parts, each seperated by a period('.')
|
||||
- An identifier does not end in a period('.')
|
||||
- Each part begins with a letter or underscore('_'), and may contain letters,
|
||||
digits, or underscores('_').
|
||||
|
||||
The parser recognizes the above as identifiers in an expression. However, no
|
||||
check is made when an application adds a function or value to the lists. It is
|
||||
up to the application to make sure it is named correct.
|
||||
|
||||
The following are valid identifiers:
|
||||
|
||||
color1
|
||||
color1.red
|
||||
color2._rgb._red
|
||||
_x
|
||||
|
||||
The following are invalid identifiers
|
||||
|
||||
1color
|
||||
color.4
|
||||
|
||||
Value Lists
|
||||
-----------
|
||||
Value lists store the constants and values that are used by an expression.
|
||||
A value list is associated with an expression by using 'Expression::SetValueList'
|
||||
Once an expression is parsed, the expression tree stores pointers directly to
|
||||
the values, and so the value list should not be freed while it is in use.
|
||||
|
||||
To add values to the list, use 'Add'. You can also specify the
|
||||
default values and if it is a constant.
|
||||
|
||||
vlist.Add("x");
|
||||
vlist.Add("found", 1.0);
|
||||
vlist.Add("PI", 3.14159, true);
|
||||
|
||||
You can also add external values to the list as follows.
|
||||
|
||||
double x, f, p;
|
||||
vlist.AddAddress("x", &x);
|
||||
vlist.AddAddress("f", &f, 2.2);
|
||||
vlist.AddAddress("p", &p, 3.14, true);
|
||||
|
||||
Sometimes a compiler may optimize code in such a way that problems occur. For
|
||||
instance, the expression can change the values 'x' and 'f' above, but the code
|
||||
below may get optimized:
|
||||
|
||||
x = 1;
|
||||
f = 2.2;
|
||||
|
||||
for(...)
|
||||
{
|
||||
for(...)
|
||||
{
|
||||
e.Evaluate();
|
||||
Use(x, f);
|
||||
}
|
||||
}
|
||||
|
||||
Since it does not appear that 'x' and 'f' are being modified inside the loop,
|
||||
especially in deeply nested loops, the compiler may optimize it by loading the
|
||||
values outside the loop and using the cached values in the loop. If the
|
||||
expression changes the values, they will not be used, but the cached values
|
||||
will be. This is just a problem I have encounted a few times. To solve this
|
||||
problem, change their declarations to be volatile:
|
||||
|
||||
volatile double x, f, p;
|
||||
vlist.AddAddress("x", (double*)&x);
|
||||
vlist.AddAddress("f", (double*)&f, 2.2);
|
||||
vlist.AddAddress("p", (double*)&p, 3.14, true);
|
||||
|
||||
Like this, the compiler must reload the variables from memory each time they
|
||||
are accessed.
|
||||
|
||||
If you use internal storage, you can still get the address of the values and
|
||||
directly manipulate them as such:
|
||||
|
||||
double *x;
|
||||
|
||||
vlist.Add("x");
|
||||
x = vlist.GetAddress("x");
|
||||
|
||||
for(...)
|
||||
{
|
||||
*x = some_value;
|
||||
e.Evaluate();
|
||||
...
|
||||
}
|
||||
|
||||
To initialize default values into the list, use 'AddDefaultValues':
|
||||
|
||||
vlist.AddDefaultValues();
|
||||
vlist.Add("x");
|
||||
vlist.Add("y");
|
||||
...
|
||||
|
||||
When you want to reset all items to their default values, you can call 'Reset'.
|
||||
This will reset internal and external values. Constants will also be reset
|
||||
because, even though an expression can not modify a constant, the application
|
||||
can.
|
||||
|
||||
vlist.Reset();
|
||||
|
||||
You can also clear all items from the list. Do this ONLY when the expression
|
||||
will not be evaluated again or will be reparsed before evaluating, because the
|
||||
expression stores pointers directly to the values, and evaluating the expression
|
||||
if the list is cleared will likely cause an access violation. External values
|
||||
will not be deleted or removed, but the list entry associated with it will be.
|
||||
|
||||
vlist.Clear();
|
||||
e.Parse(...);
|
||||
|
||||
Finally, you can save the state of the value list by enumerating the values:
|
||||
|
||||
ValueList::size_type p, c;
|
||||
|
||||
c = vlist.Count();
|
||||
for(p = 0; p < c; p++)
|
||||
{
|
||||
string name;
|
||||
double value;
|
||||
|
||||
vlist.Item(p, &name, &value);
|
||||
...
|
||||
}
|
||||
|
||||
You can later use this to restore the list. Remember, when adding a value to
|
||||
the list, if it already exists, an exception will the be thrown.
|
||||
|
||||
Function Lists
|
||||
--------------
|
||||
Function lists store the function factories for the expression. A function
|
||||
factory create a function node when needed, and also reports the name used.
|
||||
To create a custom function, first derive a custom function node from
|
||||
'FunctionNode'.
|
||||
|
||||
class MyFunctionNode : public FunctionNode
|
||||
{
|
||||
public:
|
||||
MyFunctionNode(Expression *expr);
|
||||
double DoEvaluate();
|
||||
};
|
||||
|
||||
Set the argument count in the constructor. The first two arguments control
|
||||
the number of normal paramters, the second control the number of reference
|
||||
parameters. A value of -1 is used for any number.
|
||||
|
||||
MyFunctionNode::MyFunctionNode(Expression *expr) : FunctionNode(expr)
|
||||
{
|
||||
SetArgumentCount(
|
||||
0, // Minimum normal parameters
|
||||
2, // Maximum normal parameters
|
||||
2, // Minimum reference parameters
|
||||
-1); // Maximum reference parameters
|
||||
}
|
||||
|
||||
Evaluate a function by overriding 'DoEvaluate'. You can access the normal
|
||||
parameters in 'm_nodes' and the reference parameters in 'm_refs' as follows.
|
||||
When evaluating a node, call 'Evaluate' and NOT 'DoEvaluate'.
|
||||
|
||||
double MyFunctionNode::DoEvaluate()
|
||||
{
|
||||
*m_refs[0] = m_nodes[0]->Evalute();
|
||||
|
||||
return m_nodes[1]->Evaluate();
|
||||
}
|
||||
|
||||
It is up to each function solver how to access and do the job. If you need to
|
||||
iterate over the items, the types are defined as follows:
|
||||
|
||||
std::vector<Node*> - For normal argumnents
|
||||
std::vector<double*> - For reference arguments
|
||||
|
||||
After a function node is created, a function factory must be created to produce
|
||||
the function node:
|
||||
|
||||
class MyFunctionFactory : public FunctionFactory
|
||||
{
|
||||
public:
|
||||
std::string GetName() const;
|
||||
FunctionNode *DoCreate(Expression *expr);
|
||||
};
|
||||
|
||||
std::string MyFunctionFactory::GetName() const
|
||||
{
|
||||
return "myfunction";
|
||||
}
|
||||
|
||||
FunctionNode *MyFunctionFactory::DoCreate(Expression *expr)
|
||||
{
|
||||
return new MyFunctionNode(expr);
|
||||
}
|
||||
|
||||
Finally, the function node needs to be added to function list:
|
||||
|
||||
flist.Add(new MyFunctionFactory());
|
||||
|
||||
To be exception safe, you can also do this:
|
||||
|
||||
auto_ptr<FunctionFactory> p(new MyFunctionFactory());
|
||||
flist.Add(p.get());
|
||||
p.release();
|
||||
|
||||
This way, if 'Add' throws an exception, the function factory will still
|
||||
be deleted.
|
||||
|
||||
The library includes many internal functions. These can be initialized directly
|
||||
into the list:
|
||||
|
||||
flist.AddDefaultFunctions();
|
||||
|
||||
And finally, you can clear the list if you want to. The list is automatically
|
||||
cleared when it is destroyed.
|
||||
|
||||
flist.Clear();
|
||||
|
||||
Expressions
|
||||
-----------
|
||||
The expression is what is used to actually parse and evaluate. After the
|
||||
function and value lists are created, they can be associated with an expression:
|
||||
|
||||
Expression e;
|
||||
e.SetValueList(&vlist);
|
||||
e.SetFunctionList(&flist);
|
||||
e.SetDataList(&dlist);
|
||||
|
||||
An expression can be parsed and used over and over:
|
||||
|
||||
e.Parse(...);
|
||||
|
||||
for(...)
|
||||
{
|
||||
result = e.Evaluate();
|
||||
}
|
||||
|
||||
An expression can be parsed again, it is automatically cleared each time.
|
||||
'Clear' can be called if desired to clear the expression without reparsing or
|
||||
destroying it.
|
||||
|
||||
e.Parse(...);
|
||||
|
||||
for(...)
|
||||
{
|
||||
result = e.Evaluate();
|
||||
}
|
||||
|
||||
e.Parse(...); // Automatically clears
|
||||
|
||||
for(...)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
e.Clear(); // Clear expression, maybe to free memory, without destroying it
|
||||
|
||||
Exceptions
|
||||
----------
|
||||
Exceptions are thrown to indicate a problem. The problem may or may not be
|
||||
an error, depending on the exception, and the application.
|
||||
|
||||
Most exceptions are defined by ExprEval, but some exceptions may occur from
|
||||
C++. The most likely exception to get from C++ is 'bad_alloc' if memory
|
||||
allocation fails.
|
||||
|
||||
ExprEval defines a base exception class 'Exception', which is derived from
|
||||
'std::exception'. All other ExprEval exceptiosn derive from it.
|
||||
|
||||
Exception
|
||||
|
||||
Base ExprEval exception, derived from 'std::exception'. A 'GetValue'
|
||||
method returns the string of where the exception came from, depending
|
||||
on the exception type.
|
||||
|
||||
For some exceptions generated during parsing, A 'GetStart' and 'GetEnd'
|
||||
method return the position in the expression string of the start and
|
||||
end of the error.
|
||||
|
||||
NotFoundException (parsing)
|
||||
|
||||
Thrown when a function is not found. It is also thrown when a value
|
||||
identifer can not be found in a value list and can not be added to the
|
||||
list during a parse, but this will usually not happen because if it
|
||||
can not be added to the list, a 'bad_alloc' will usually be the reason.
|
||||
'ValueList::GetAddress' does not throw this.
|
||||
|
||||
AlreadyExistsException
|
||||
|
||||
A name being added to a function or value list already exists.
|
||||
|
||||
NullPointerException
|
||||
|
||||
A null pointer was passed to a function that should not be null.
|
||||
|
||||
MathException (evaluation)
|
||||
|
||||
A math error occured during an evaluation.
|
||||
|
||||
DivideByZeroException (evaluation)
|
||||
|
||||
A division by zero was attempted during evaluation.
|
||||
|
||||
NoValueListException (parsing)
|
||||
|
||||
An expression is trying to use a value identifier, but no value list
|
||||
is associated with it.
|
||||
|
||||
NoFunctionListException (parsing)
|
||||
|
||||
An expression is trying to use a function identifier, but no value list
|
||||
is associated with it.
|
||||
|
||||
AbortException (evaluation)
|
||||
|
||||
'Expression::DoTestAbort' returned true.
|
||||
|
||||
EmptyExpressionException (parsing, evaluation)
|
||||
|
||||
At parse time, there is no expression. At evaluation time, the expression
|
||||
is not parsed.
|
||||
|
||||
UnknownTokenException (parsing)
|
||||
|
||||
An unknown token was encounted.
|
||||
|
||||
InvalidArgumentCountException (parsing, evaluation)
|
||||
|
||||
An invalid count of arguments was passed to a function. At parse time, this
|
||||
is controlled by 'FunctionNode::SetArgumentCount'. Some functions may take
|
||||
various parameter counts depending on a situation, and may throw this at
|
||||
evaluation time.
|
||||
|
||||
ConstantAssignException (parsing)
|
||||
|
||||
An attempt to assign to a constant occured.
|
||||
|
||||
ConstantReferenceException (parsing)
|
||||
|
||||
An attempt to pass a constant to a function by reference occured.
|
||||
|
||||
SyntaxException (parsing)
|
||||
|
||||
A general syntax exception occured
|
||||
|
||||
UnmatchedParenthesisException (parsing)
|
||||
|
||||
The parenthesis are unmatched or missing the opening or closing parenthesis.
|
||||
|
||||
|
||||
Tricks
|
||||
------
|
||||
|
||||
A single value list can be shared by more than one expression. In this way, each
|
||||
expression shares all values of that list:
|
||||
|
||||
ValueList vlist;
|
||||
Expression e1, e2;
|
||||
|
||||
e1.SetValueList(&vlist);
|
||||
e2.SetValueLIst(&vlist);
|
||||
|
||||
An external value can be shared by several value lists, and can be constant in
|
||||
one and not in another:
|
||||
|
||||
double x;
|
||||
ValueList v1, v2;
|
||||
Expression e1, e2;
|
||||
|
||||
v1.AddAddress("x", &x);
|
||||
v2.AddAddress("x", &x, 0.0, true);
|
||||
|
||||
e1.SetValueList(&v1);
|
||||
e2.SetValueList(&v2);
|
||||
|
||||
An empty expression can be ignored:
|
||||
|
||||
Expression e1, e2;
|
||||
bool eval2;
|
||||
|
||||
// Expression 1 must exist
|
||||
e1.Parse(...);
|
||||
|
||||
// Expression 2 can be blank
|
||||
eval2 = true;
|
||||
try
|
||||
{
|
||||
e2.Parse(...);
|
||||
}
|
||||
catch(EmptyExpresionExceptin &e)
|
||||
{
|
||||
eval2 = false;
|
||||
}
|
||||
|
||||
for(...)
|
||||
{
|
||||
e1.Evaluate();
|
||||
|
||||
if(eval2)
|
||||
e2.Evaluate();
|
||||
}
|
||||
|
||||
|
||||
Internal Values
|
||||
---------------
|
||||
A call to 'ValueList::AddDefaultValues' will add the following values to a
|
||||
value list:
|
||||
|
||||
PI
|
||||
|
||||
The value of PI, equal to 3.14159265358979323846
|
||||
|
||||
E
|
||||
|
||||
The value of e, equal to 2.7182818284590452354
|
||||
|
||||
|
||||
Internal Functions
|
||||
------------------
|
||||
A call to 'FunctionList::AddDefaultFunctions' will add the following functions
|
||||
to a function list:
|
||||
|
||||
abs(x)
|
||||
|
||||
Return the absolute value of 'x'
|
||||
|
||||
mod(x, y)
|
||||
|
||||
Return the remainder of 'x' divided by 'y'
|
||||
|
||||
ipart(x)
|
||||
|
||||
Return the interger portion of 'x'
|
||||
|
||||
fpart(x)
|
||||
|
||||
Return the fraction portion of 'x'
|
||||
|
||||
min(x, y, z, ...)
|
||||
|
||||
Return the value of the smallest parameter
|
||||
|
||||
max(x, y, z, ...)
|
||||
|
||||
Return the value of the largest parameter
|
||||
|
||||
sqrt(x)
|
||||
|
||||
Return the square root of 'x'
|
||||
|
||||
sin(x), cos(x), tan(x)
|
||||
|
||||
Return the sine, cosine, or tangent of 'x'
|
||||
|
||||
sinh(x), cosh(x), tanh(x)
|
||||
|
||||
Return the hyperbolic sine, cosine, or tangent of 'x'
|
||||
|
||||
asin(x), acos(x), atan(x)
|
||||
|
||||
Return the inverse since, cosine, or tangent of 'x'
|
||||
|
||||
atan(y, x)
|
||||
|
||||
Return the inverse tangent of 'y' divided by 'x', with the correct
|
||||
angle for the quadrant of (x, y)
|
||||
|
||||
log(x)
|
||||
|
||||
Return the base 10 logarithm of 'x'
|
||||
|
||||
ln(x)
|
||||
|
||||
Return the natural logarithm of 'x'
|
||||
|
||||
exp(x)
|
||||
|
||||
Return the value of e raised to the power of 'x'
|
||||
|
||||
logn(x, y)
|
||||
|
||||
Return the base 'y' logarithm of 'x'
|
||||
|
||||
ceil(x)
|
||||
|
||||
Return the value of 'x' raised to the nearest integer
|
||||
|
||||
floor(x)
|
||||
|
||||
Return the value of 'x' dropped to the nearest integer
|
||||
|
||||
rand(&seed)
|
||||
|
||||
Return a random number from 0 to 1 inclusive. 'seed' is used to generate
|
||||
the number and is changed for the next number.
|
||||
|
||||
random(min, max, &seed)
|
||||
|
||||
Return a random number from 'min' to 'max'
|
||||
|
||||
randomize(&seed)
|
||||
|
||||
Initialize the seed with a random value, based on the computer time and
|
||||
the number of times randomize has been used.
|
||||
|
||||
deg(x)
|
||||
|
||||
Return 'x' radians converted to degrees
|
||||
|
||||
rad(x)
|
||||
|
||||
Return 'x' degrees converted to radians
|
||||
|
||||
rect2pol(x, y, &distance, &angle)
|
||||
|
||||
Convert rectangular coordinates 'x' and 'y' to polar coordinates and stores
|
||||
the result in 'distance' and 'angle'. Returns distance.
|
||||
|
||||
pol2rect(distance, angle, &x, &y)
|
||||
|
||||
Convert polar coordinates 'distance' and 'angle' to rectangular coordinates
|
||||
and stores the result in 'x' and 'y'. Returns x.
|
||||
|
||||
if(c, t, f)
|
||||
|
||||
If 'c' is not zero, evaluates and returns 't', otherwise evaluates and
|
||||
returns 'f'. Only one of 't' or 'f' is evaluated.
|
||||
|
||||
select(c, n, z), select(c, n, z, p)
|
||||
|
||||
If 'c' is less than zero, evaluates and returns 'n'. If 'c' is zero,
|
||||
evaluates and returns 'z'. If 'c' is greater than zero, evaluates and
|
||||
returns 'z' for three arguments and 'p' for four arguments. Only one of
|
||||
'n', 'z', or 'p' is evaluated.
|
||||
|
||||
equal(x, y)
|
||||
|
||||
Returns 1 if 'x' is equal to 'y', else returns 0
|
||||
|
||||
above(x, y)
|
||||
|
||||
Returns 1 if 'x' is greater than 'y', else returns 0
|
||||
|
||||
below(x, y)
|
||||
|
||||
Returns 1 if 'x' is less than 'y', else returns 0
|
||||
|
||||
clip(x, min, max)
|
||||
|
||||
Clips 'x' to the range 'min' and 'max'
|
||||
|
||||
clamp(x, min, max)
|
||||
|
||||
Clamps 'x' to the range 'min' and 'max', wrapping as needed
|
||||
|
||||
rescale(p, o1, o2, n1, n2)
|
||||
|
||||
Rescales a point 'p' from the range 'o1' - 'o2' to the range 'n1' - 'n2'
|
||||
|
||||
poly(x, ...)
|
||||
|
||||
Calculate the polynomial with the value of 'x' and given terms. The
|
||||
right-most argument is the multiplier for the exponent of zero, and
|
||||
increases to the left.
|
||||
|
||||
poly(4, 3, 5, 2, 8) is 3 * 4 ^ 3 + 5 * 4 ^ 2 + 2 * 4 ^ 1 + 8
|
||||
|
||||
and(x, y)
|
||||
|
||||
Returns 0 if 'x' or 'y' is 0, else returns 1
|
||||
|
||||
or(x, y)
|
||||
|
||||
Returns 0 if 'x' and 'y' is 0, else returns 1
|
||||
|
||||
not(x)
|
||||
|
||||
Returns 1 if 'x' is 0, else returns 0
|
||||
|
||||
|
||||
More Information
|
||||
----------------
|
||||
For more information, view the source code for the library.
|
||||
|
20
3rdparty/expreval/docs/license.txt
vendored
Normal file
20
3rdparty/expreval/docs/license.txt
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
ExprEval - Expression Evaluation Library
|
||||
Version 3.x
|
||||
|
||||
Copyright (C) 2006 Brian Allen Vanderburg II
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
167
3rdparty/expreval/except.cpp
vendored
Normal file
167
3rdparty/expreval/except.cpp
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
// File: except.cpp
|
||||
// Author: Brian Vanderburg II
|
||||
// Purpose: ExprEval exceptions
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Includes
|
||||
#include "except.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ExprEval;
|
||||
|
||||
|
||||
// Default/unknown ExprEval exception
|
||||
//------------------------------------------------------------------------------
|
||||
Exception::Exception() :
|
||||
m_start((string::size_type)-1),
|
||||
m_end((string::size_type)-1)
|
||||
{
|
||||
m_type = Type_Exception;
|
||||
}
|
||||
|
||||
Exception::~Exception() throw()
|
||||
{
|
||||
}
|
||||
|
||||
Exception::Type Exception::GetType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
const string &Exception::GetValue() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
void Exception::SetStart(string::size_type start)
|
||||
{
|
||||
m_start = start;
|
||||
}
|
||||
|
||||
void Exception::SetEnd(string::size_type end)
|
||||
{
|
||||
m_end = end;
|
||||
}
|
||||
|
||||
string::size_type Exception::GetStart() const
|
||||
{
|
||||
return m_start;
|
||||
}
|
||||
|
||||
string::size_type Exception::GetEnd() const
|
||||
{
|
||||
return m_end;
|
||||
}
|
||||
|
||||
// Not found exception
|
||||
//------------------------------------------------------------------------------
|
||||
NotFoundException::NotFoundException(const string &name)
|
||||
{
|
||||
m_type = Type_NotFoundException;
|
||||
m_value = name;
|
||||
}
|
||||
|
||||
// Already exists exception
|
||||
//------------------------------------------------------------------------------
|
||||
AlreadyExistsException::AlreadyExistsException(const string &name)
|
||||
{
|
||||
m_type = Type_AlreadyExistsException;
|
||||
m_value = name;
|
||||
}
|
||||
|
||||
// Null pointer exception
|
||||
//------------------------------------------------------------------------------
|
||||
NullPointerException::NullPointerException(const string &method)
|
||||
{
|
||||
m_type = Type_NullPointerException;
|
||||
m_value = method;
|
||||
}
|
||||
|
||||
// Math error exception
|
||||
//------------------------------------------------------------------------------
|
||||
MathException::MathException(const string &function)
|
||||
{
|
||||
m_type = Type_MathException;
|
||||
m_value = function;
|
||||
}
|
||||
|
||||
// Divide by zero
|
||||
//------------------------------------------------------------------------------
|
||||
DivideByZeroException::DivideByZeroException()
|
||||
{
|
||||
m_type = Type_DivideByZeroException;
|
||||
}
|
||||
|
||||
// No value list found during parsing
|
||||
//------------------------------------------------------------------------------
|
||||
NoValueListException::NoValueListException()
|
||||
{
|
||||
m_type = Type_NoValueListException;
|
||||
}
|
||||
|
||||
// No function list found during parsing
|
||||
//------------------------------------------------------------------------------
|
||||
NoFunctionListException::NoFunctionListException()
|
||||
{
|
||||
m_type = Type_NoFunctionListException;
|
||||
}
|
||||
|
||||
// Expression abort
|
||||
//------------------------------------------------------------------------------
|
||||
AbortException::AbortException()
|
||||
{
|
||||
m_type = Type_AbortException;
|
||||
}
|
||||
|
||||
// Empty expression
|
||||
//------------------------------------------------------------------------------
|
||||
EmptyExpressionException::EmptyExpressionException()
|
||||
{
|
||||
m_type = Type_EmptyExpressionException;
|
||||
}
|
||||
|
||||
// Unknown token found during parsing
|
||||
//------------------------------------------------------------------------------
|
||||
UnknownTokenException::UnknownTokenException()
|
||||
{
|
||||
m_type = Type_UnknownTokenException;
|
||||
}
|
||||
|
||||
// Invalid argument count
|
||||
//------------------------------------------------------------------------------
|
||||
InvalidArgumentCountException::InvalidArgumentCountException(const string &function)
|
||||
{
|
||||
m_type = Type_InvalidArgumentCountException;
|
||||
m_value = function;
|
||||
}
|
||||
|
||||
// Assign to constant
|
||||
//------------------------------------------------------------------------------
|
||||
ConstantAssignException::ConstantAssignException(const string &value)
|
||||
{
|
||||
m_type = Type_ConstantAssignException;
|
||||
m_value = value;
|
||||
}
|
||||
|
||||
// Pass constant by reference
|
||||
//------------------------------------------------------------------------------
|
||||
ConstantReferenceException::ConstantReferenceException(const string &value)
|
||||
{
|
||||
m_type = Type_ConstantReferenceException;
|
||||
m_value = value;
|
||||
}
|
||||
|
||||
// Syntax error exception
|
||||
//------------------------------------------------------------------------------
|
||||
SyntaxException::SyntaxException()
|
||||
{
|
||||
m_type = Type_SyntaxException;
|
||||
}
|
||||
|
||||
// Unmatched parenthesis
|
||||
//------------------------------------------------------------------------------
|
||||
UnmatchedParenthesisException::UnmatchedParenthesisException()
|
||||
{
|
||||
m_type = Type_UnmatchedParenthesisException;
|
||||
}
|
189
3rdparty/expreval/except.h
vendored
Normal file
189
3rdparty/expreval/except.h
vendored
Normal file
@ -0,0 +1,189 @@
|
||||
// File: except.h
|
||||
// Author: Brian Vanderburg II
|
||||
// Purpose: ExprEval exceptions
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __EXPREVAL_EXCEPT_H
|
||||
#define __EXPREVAL_EXCEPT_H
|
||||
|
||||
// Includes
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
// Part of expreval namespace
|
||||
namespace ExprEval
|
||||
{
|
||||
// Forward declarations
|
||||
class Expression;
|
||||
|
||||
// Exception class
|
||||
//--------------------------------------------------------------------------
|
||||
class Exception : public ::std::exception
|
||||
{
|
||||
public:
|
||||
// Types of exceptions (to simplify some error handling)
|
||||
// Each exception must set m_type in the construct
|
||||
// Each exception should have a different type
|
||||
enum Type
|
||||
{
|
||||
Type_Exception = 1,
|
||||
Type_NotFoundException,
|
||||
Type_AlreadyExistsException,
|
||||
Type_NullPointerException,
|
||||
Type_MathException,
|
||||
Type_DivideByZeroException,
|
||||
Type_NoValueListException,
|
||||
Type_NoFunctionListException,
|
||||
Type_AbortException,
|
||||
Type_EmptyExpressionException,
|
||||
Type_UnknownTokenException,
|
||||
Type_InvalidArgumentCountException,
|
||||
Type_ConstantAssignException,
|
||||
Type_ConstantReferenceException,
|
||||
Type_SyntaxException,
|
||||
Type_UnmatchedParenthesisException
|
||||
};
|
||||
|
||||
Exception();
|
||||
virtual ~Exception() throw();
|
||||
|
||||
Type GetType() const;
|
||||
const ::std::string &GetValue() const;
|
||||
|
||||
void SetStart(::std::string::size_type start);
|
||||
void SetEnd(::std::string::size_type end);
|
||||
|
||||
::std::string::size_type GetStart() const;
|
||||
::std::string::size_type GetEnd() const;
|
||||
|
||||
protected:
|
||||
Type m_type;
|
||||
::std::string m_value;
|
||||
::std::string::size_type m_start, m_end;
|
||||
};
|
||||
|
||||
// Not found exception (for functions)
|
||||
//--------------------------------------------------------------------------
|
||||
class NotFoundException : public Exception
|
||||
{
|
||||
public:
|
||||
NotFoundException(const ::std::string &name);
|
||||
};
|
||||
|
||||
// Already exists exception (function or value already exists)
|
||||
//--------------------------------------------------------------------------
|
||||
class AlreadyExistsException : public Exception
|
||||
{
|
||||
public:
|
||||
AlreadyExistsException(const ::std::string &name);
|
||||
};
|
||||
|
||||
// A null pointer was passed
|
||||
//--------------------------------------------------------------------------
|
||||
class NullPointerException : public Exception
|
||||
{
|
||||
public:
|
||||
NullPointerException(const ::std::string &method);
|
||||
};
|
||||
|
||||
// A bad math error occured
|
||||
//--------------------------------------------------------------------------
|
||||
class MathException : public Exception
|
||||
{
|
||||
public:
|
||||
MathException(const ::std::string &function);
|
||||
};
|
||||
|
||||
// Divide by zero exception
|
||||
//--------------------------------------------------------------------------
|
||||
class DivideByZeroException : public Exception
|
||||
{
|
||||
public:
|
||||
DivideByZeroException();
|
||||
};
|
||||
|
||||
// No value list exception (if expression uses variables or constants
|
||||
// but list does not exist) during parsing
|
||||
//--------------------------------------------------------------------------
|
||||
class NoValueListException : public Exception
|
||||
{
|
||||
public:
|
||||
NoValueListException();
|
||||
};
|
||||
|
||||
// No function list exception (if expression uses functions) during parsing
|
||||
//--------------------------------------------------------------------------
|
||||
class NoFunctionListException : public Exception
|
||||
{
|
||||
public:
|
||||
NoFunctionListException();
|
||||
};
|
||||
|
||||
// Abort exception (if DoTestAbort returns true)
|
||||
//--------------------------------------------------------------------------
|
||||
class AbortException : public Exception
|
||||
{
|
||||
public:
|
||||
AbortException();
|
||||
};
|
||||
|
||||
// Empty expression (for parsing or evaluation)
|
||||
//--------------------------------------------------------------------------
|
||||
class EmptyExpressionException : public Exception
|
||||
{
|
||||
public:
|
||||
EmptyExpressionException();
|
||||
};
|
||||
|
||||
// Unknown token in expression string
|
||||
//--------------------------------------------------------------------------
|
||||
class UnknownTokenException : public Exception
|
||||
{
|
||||
public:
|
||||
UnknownTokenException();
|
||||
};
|
||||
|
||||
// Invalid argument count to function
|
||||
//--------------------------------------------------------------------------
|
||||
class InvalidArgumentCountException : public Exception
|
||||
{
|
||||
public:
|
||||
InvalidArgumentCountException(const ::std::string &function);
|
||||
};
|
||||
|
||||
// Assign to a constant
|
||||
//--------------------------------------------------------------------------
|
||||
class ConstantAssignException : public Exception
|
||||
{
|
||||
public:
|
||||
ConstantAssignException(const ::std::string &value);
|
||||
};
|
||||
|
||||
// Pass constant by reference
|
||||
//--------------------------------------------------------------------------
|
||||
class ConstantReferenceException : public Exception
|
||||
{
|
||||
public:
|
||||
ConstantReferenceException(const ::std::string &value);
|
||||
};
|
||||
|
||||
// A general syntax exception
|
||||
//--------------------------------------------------------------------------
|
||||
class SyntaxException : public Exception
|
||||
{
|
||||
public:
|
||||
SyntaxException();
|
||||
};
|
||||
|
||||
// Unmatched parenthesis
|
||||
//--------------------------------------------------------------------------
|
||||
class UnmatchedParenthesisException : public Exception
|
||||
{
|
||||
public:
|
||||
UnmatchedParenthesisException();
|
||||
};
|
||||
|
||||
} // namespace ExprEval
|
||||
|
||||
#endif // __EXPREVAL_EXCEPT_H
|
141
3rdparty/expreval/expr.cpp
vendored
Normal file
141
3rdparty/expreval/expr.cpp
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
// File: expr.cpp
|
||||
// Author: Brian Vanderburg II
|
||||
// Purpose: Expression object
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Includes
|
||||
#include <new>
|
||||
#include <memory>
|
||||
|
||||
#include "defs.h"
|
||||
#include "expr.h"
|
||||
#include "parser.h"
|
||||
#include "node.h"
|
||||
#include "except.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ExprEval;
|
||||
|
||||
|
||||
// Expression object
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constructor
|
||||
Expression::Expression() : m_vlist(0), m_flist(0), m_expr(0)
|
||||
{
|
||||
m_abortcount = 200000;
|
||||
m_abortreset = 200000;
|
||||
}
|
||||
|
||||
// Destructor
|
||||
Expression::~Expression()
|
||||
{
|
||||
// Delete expression nodes
|
||||
delete m_expr;
|
||||
}
|
||||
|
||||
// Set value list
|
||||
void Expression::SetValueList(ValueList *vlist)
|
||||
{
|
||||
m_vlist = vlist;
|
||||
}
|
||||
|
||||
// Get value list
|
||||
ValueList *Expression::GetValueList() const
|
||||
{
|
||||
return m_vlist;
|
||||
}
|
||||
|
||||
// Set function list
|
||||
void Expression::SetFunctionList(FunctionList *flist)
|
||||
{
|
||||
m_flist = flist;
|
||||
}
|
||||
|
||||
// Get function list
|
||||
FunctionList *Expression::GetFunctionList() const
|
||||
{
|
||||
return m_flist;
|
||||
}
|
||||
|
||||
// Test for an abort
|
||||
bool Expression::DoTestAbort()
|
||||
{
|
||||
// Derive a class to test abort
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test for an abort
|
||||
void Expression::TestAbort(bool force)
|
||||
{
|
||||
if(force)
|
||||
{
|
||||
// Test for an abort now
|
||||
if(DoTestAbort())
|
||||
{
|
||||
throw(AbortException());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Test only if abort count is 0
|
||||
if(m_abortcount == 0)
|
||||
{
|
||||
// Reset count
|
||||
m_abortcount = m_abortreset;
|
||||
|
||||
// Test abort
|
||||
if(DoTestAbort())
|
||||
{
|
||||
throw(AbortException());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Decrease abort count
|
||||
m_abortcount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set test abort count
|
||||
void Expression::SetTestAbortCount(unsigned long count)
|
||||
{
|
||||
m_abortreset = count;
|
||||
if(m_abortcount > count)
|
||||
m_abortcount = count;
|
||||
}
|
||||
|
||||
// Parse expression
|
||||
void Expression::Parse(const string &exstr)
|
||||
{
|
||||
// Clear the expression if needed
|
||||
if(m_expr)
|
||||
Clear();
|
||||
|
||||
// Create parser
|
||||
aptr(Parser) p(new Parser(this));
|
||||
|
||||
// Parse the expression
|
||||
m_expr = p->Parse(exstr);
|
||||
}
|
||||
|
||||
// Clear the expression
|
||||
void Expression::Clear()
|
||||
{
|
||||
delete m_expr;
|
||||
m_expr = 0;
|
||||
}
|
||||
|
||||
// Evaluate an expression
|
||||
double Expression::Evaluate()
|
||||
{
|
||||
if(m_expr)
|
||||
{
|
||||
return m_expr->Evaluate();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw(EmptyExpressionException());
|
||||
}
|
||||
}
|
63
3rdparty/expreval/expr.h
vendored
Normal file
63
3rdparty/expreval/expr.h
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
// File: expr.h
|
||||
// Author: Brian Vanderburg II
|
||||
// Purpose: Expression object
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __EXPREVAL_EXPR_H
|
||||
#define __EXPREVAL_EXPR_H
|
||||
|
||||
// Includes
|
||||
#include <string>
|
||||
|
||||
// Part of expreval namespace
|
||||
namespace ExprEval
|
||||
{
|
||||
// Forward declarations
|
||||
class ValueList;
|
||||
class FunctionList;
|
||||
class Node;
|
||||
|
||||
// Expression class
|
||||
//--------------------------------------------------------------------------
|
||||
class Expression
|
||||
{
|
||||
public:
|
||||
Expression();
|
||||
virtual ~Expression();
|
||||
|
||||
// Variable list
|
||||
void SetValueList(ValueList *vlist);
|
||||
ValueList *GetValueList() const;
|
||||
|
||||
// Function list
|
||||
void SetFunctionList(FunctionList *flist);
|
||||
FunctionList *GetFunctionList() const;
|
||||
|
||||
// Abort control
|
||||
virtual bool DoTestAbort();
|
||||
void TestAbort(bool force = false);
|
||||
void SetTestAbortCount(unsigned long count);
|
||||
|
||||
// Parse an expression
|
||||
void Parse(const ::std::string &exstr);
|
||||
|
||||
// Clear an expression
|
||||
void Clear();
|
||||
|
||||
// Evaluate expression
|
||||
double Evaluate();
|
||||
|
||||
protected:
|
||||
ValueList *m_vlist;
|
||||
FunctionList *m_flist;
|
||||
Node *m_expr;
|
||||
unsigned long m_abortcount;
|
||||
unsigned long m_abortreset;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace ExprEval
|
||||
|
||||
#endif // __EXPREVAL_EXPR_H
|
18
3rdparty/expreval/expreval.h
vendored
Normal file
18
3rdparty/expreval/expreval.h
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
// File: expreval.h
|
||||
// Author: Brian Allen Vanderburg II
|
||||
// Purpose: ExprEval 3.x main include file
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef __EXPREVAL_EXPREVAL_H
|
||||
#define __EXPREVAL_EXPREVAL_H
|
||||
|
||||
// Include items
|
||||
#include "vallist.h"
|
||||
#include "funclist.h"
|
||||
#include "expr.h"
|
||||
#include "node.h"
|
||||
#include "parser.h"
|
||||
#include "except.h"
|
||||
|
||||
#endif // __EXPREVAL_EXPREVAL_H
|
||||
|
1644
3rdparty/expreval/func.cpp
vendored
Normal file
1644
3rdparty/expreval/func.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
113
3rdparty/expreval/funclist.cpp
vendored
Normal file
113
3rdparty/expreval/funclist.cpp
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
// File: funclist.cpp
|
||||
// Author: Brian Vanderburg II
|
||||
// Purpose: Function list
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Includes
|
||||
#include <new>
|
||||
|
||||
#include "funclist.h"
|
||||
#include "except.h"
|
||||
#include "node.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ExprEval;
|
||||
|
||||
// Function factory
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constructor
|
||||
FunctionFactory::FunctionFactory()
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
FunctionFactory::~FunctionFactory()
|
||||
{
|
||||
}
|
||||
|
||||
// Create
|
||||
FunctionNode *FunctionFactory::Create(Expression *expr)
|
||||
{
|
||||
FunctionNode *n = DoCreate(expr);
|
||||
if(n)
|
||||
n->m_factory = this;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
// Function list
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constructor
|
||||
FunctionList::FunctionList()
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
FunctionList::~FunctionList()
|
||||
{
|
||||
// Free function factories
|
||||
Clear();
|
||||
}
|
||||
|
||||
// Add factory to list
|
||||
void FunctionList::Add(FunctionFactory *factory)
|
||||
{
|
||||
// Check it
|
||||
if(factory == 0)
|
||||
throw(NullPointerException("FunctionList::Add"));
|
||||
|
||||
// Make sure it does not exist
|
||||
size_type pos;
|
||||
|
||||
for(pos = 0; pos < m_functions.size(); pos++)
|
||||
{
|
||||
if(m_functions[pos]->GetName() == factory->GetName())
|
||||
throw(AlreadyExistsException(factory->GetName()));
|
||||
}
|
||||
|
||||
m_functions.push_back(factory);
|
||||
}
|
||||
|
||||
// Create a node for a function
|
||||
FunctionNode *FunctionList::Create(const string &name, Expression *expr)
|
||||
{
|
||||
// Make sure pointer exists
|
||||
if(expr == 0)
|
||||
throw(NullPointerException("FunctionList::Create"));
|
||||
|
||||
size_type pos;
|
||||
|
||||
for(pos = 0; pos < m_functions.size(); pos++)
|
||||
{
|
||||
if(m_functions[pos]->GetName() == name)
|
||||
{
|
||||
// Found it
|
||||
return m_functions[pos]->Create(expr);
|
||||
}
|
||||
}
|
||||
|
||||
// Not found
|
||||
return 0;
|
||||
}
|
||||
|
||||
// FunctionList::AddDefaultFunctions is located in func.cpp
|
||||
// along with the default function factories
|
||||
|
||||
// Free function list
|
||||
void FunctionList::Clear()
|
||||
{
|
||||
size_type pos;
|
||||
|
||||
for(pos = 0; pos < m_functions.size(); pos++)
|
||||
{
|
||||
delete m_functions[pos];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
64
3rdparty/expreval/funclist.h
vendored
Normal file
64
3rdparty/expreval/funclist.h
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
// File: funclist.h
|
||||
// Author: Brian Vanderburg II
|
||||
// Purpose: Function list
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __EXPREVAL_FUNCLIST_H
|
||||
#define __EXPREVAL_FUNCLIST_H
|
||||
|
||||
// Includes
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Part of expreval namespace
|
||||
namespace ExprEval
|
||||
{
|
||||
// Forward declarations
|
||||
class FunctionNode;
|
||||
class Expression;
|
||||
|
||||
// Function factory
|
||||
//--------------------------------------------------------------------------
|
||||
class FunctionFactory
|
||||
{
|
||||
public:
|
||||
FunctionFactory();
|
||||
virtual ~FunctionFactory();
|
||||
|
||||
virtual ::std::string GetName() const = 0;
|
||||
virtual FunctionNode *DoCreate(Expression *expr) = 0;
|
||||
|
||||
FunctionNode *Create(Expression *expr);
|
||||
};
|
||||
|
||||
// Function list
|
||||
//--------------------------------------------------------------------------
|
||||
class FunctionList
|
||||
{
|
||||
public:
|
||||
typedef ::std::vector<FunctionFactory*>::size_type size_type;
|
||||
|
||||
FunctionList();
|
||||
~FunctionList();
|
||||
|
||||
// Add a function factory to the list
|
||||
void Add(FunctionFactory *factory);
|
||||
|
||||
// Create a node for a function
|
||||
FunctionNode *Create(const ::std::string &name, Expression *expr);
|
||||
|
||||
// Initialize default functions
|
||||
void AddDefaultFunctions();
|
||||
|
||||
// Free items and clear memory
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
::std::vector<FunctionFactory*> m_functions;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __EXPREVAL_FUNCLIST_H
|
||||
|
863
3rdparty/expreval/node.cpp
vendored
Normal file
863
3rdparty/expreval/node.cpp
vendored
Normal file
@ -0,0 +1,863 @@
|
||||
// File: node.cpp
|
||||
// Author: Brian Vanderburg II
|
||||
// Purpose: Expression node
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Includes
|
||||
#include <new>
|
||||
#include <memory>
|
||||
#include <cmath>
|
||||
#include <cerrno>
|
||||
|
||||
#include "defs.h"
|
||||
#include "node.h"
|
||||
#include "expr.h"
|
||||
#include "vallist.h"
|
||||
#include "funclist.h"
|
||||
#include "except.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ExprEval;
|
||||
|
||||
// Node
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constructor
|
||||
Node::Node(Expression *expr) : m_expr(expr)
|
||||
{
|
||||
if(expr == 0)
|
||||
throw(NullPointerException("Node::Node"));
|
||||
}
|
||||
|
||||
// Destructor
|
||||
Node::~Node()
|
||||
{
|
||||
}
|
||||
|
||||
// Evaluate
|
||||
double Node::Evaluate()
|
||||
{
|
||||
m_expr->TestAbort();
|
||||
|
||||
return DoEvaluate();
|
||||
}
|
||||
|
||||
// Function node
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constructor
|
||||
FunctionNode::FunctionNode(Expression *expr) : Node(expr),
|
||||
m_argMin(0), m_argMax(0), m_refMin(0), m_refMax(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
FunctionNode::~FunctionNode()
|
||||
{
|
||||
// Delete child nodes
|
||||
vector<Node*>::size_type pos;
|
||||
|
||||
for(pos = 0; pos < m_nodes.size(); pos++)
|
||||
{
|
||||
delete m_nodes[pos];
|
||||
}
|
||||
}
|
||||
|
||||
// Get name
|
||||
string FunctionNode::GetName() const
|
||||
{
|
||||
return m_factory->GetName();
|
||||
}
|
||||
|
||||
// Set argument count
|
||||
void FunctionNode::SetArgumentCount(long argMin, long argMax, long refMin, long refMax)
|
||||
{
|
||||
m_argMin = argMin;
|
||||
m_argMax = argMax;
|
||||
m_refMin = refMin;
|
||||
m_refMax = refMax;
|
||||
}
|
||||
|
||||
// Parse expression
|
||||
void FunctionNode::Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1)
|
||||
{
|
||||
Parser::size_type pos, last;
|
||||
int plevel = 0;
|
||||
|
||||
// Sanity check (start/end are function parenthesis)
|
||||
if(start >= end)
|
||||
throw(SyntaxException());
|
||||
|
||||
// Look
|
||||
last = start + 1;
|
||||
for(pos = start + 1; pos <= end && start + 1 != end; pos++)
|
||||
{
|
||||
switch(parser[pos].GetType())
|
||||
{
|
||||
case Token::TypeOpenParenthesis:
|
||||
{
|
||||
plevel++;
|
||||
break;
|
||||
};
|
||||
|
||||
case Token::TypeComma:
|
||||
case Token::TypeCloseParenthesis:
|
||||
{
|
||||
// Handle Close parenthesis for all but the last one at the end
|
||||
if(parser[pos].GetType() == Token::TypeCloseParenthesis && pos != end)
|
||||
{
|
||||
plevel--;
|
||||
|
||||
if(plevel < 0)
|
||||
{
|
||||
UnmatchedParenthesisException e;
|
||||
|
||||
e.SetStart(parser[pos].GetStart());
|
||||
e.SetEnd(parser[pos].GetEnd());
|
||||
|
||||
throw(e);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Handle comma, or if it was the ending parenthesis treat it like comma
|
||||
if(plevel == 0)
|
||||
{
|
||||
if(pos > last)
|
||||
{
|
||||
// reference parameter?
|
||||
if(parser[last].GetType() == Token::TypeAmpersand)
|
||||
{
|
||||
// Reference parameter, check position and type of next parameter
|
||||
if(last == pos - 2 && parser[last + 1].GetType() == Token::TypeIdentifier)
|
||||
{
|
||||
// Get value list
|
||||
ValueList *vlist = m_expr->GetValueList();
|
||||
if(vlist == 0)
|
||||
{
|
||||
NoValueListException e;
|
||||
|
||||
e.SetStart(parser[last + 1].GetStart());
|
||||
e.SetEnd(parser[last + 1].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
// Get name
|
||||
string ident = parser[last + 1].GetIdentifier();
|
||||
|
||||
// Make sure it is not a constant
|
||||
if(vlist->IsConstant(ident))
|
||||
{
|
||||
ConstantReferenceException e(ident);
|
||||
|
||||
e.SetStart(parser[last + 1].GetStart());
|
||||
e.SetEnd(parser[last + 1].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
// Get address
|
||||
double *vaddr = vlist->GetAddress(ident);
|
||||
if(vaddr == 0)
|
||||
{
|
||||
// Try to add it and get again
|
||||
vlist->Add(ident);
|
||||
vaddr = vlist->GetAddress(ident);
|
||||
}
|
||||
|
||||
if(vaddr == 0)
|
||||
{
|
||||
NotFoundException e(ident);
|
||||
|
||||
e.SetStart(parser[last + 1].GetStart());
|
||||
e.SetEnd(parser[last + 1].GetEnd());
|
||||
|
||||
throw(e);
|
||||
}
|
||||
|
||||
// Add it
|
||||
m_refs.push_back(vaddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
SyntaxException e;
|
||||
|
||||
e.SetStart(parser[last].GetStart());
|
||||
e.SetEnd(parser[pos].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
} // TypeAmpersand
|
||||
else
|
||||
{
|
||||
// Create node
|
||||
aptr(Node) n(parser.ParseRegion(last, pos - 1));
|
||||
m_nodes.push_back(n.get());
|
||||
n.release();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SyntaxException e;
|
||||
|
||||
e.SetStart(parser[pos].GetStart());
|
||||
e.SetEnd(parser[pos].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
last = pos + 1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// plevel should be zero
|
||||
if(plevel != 0)
|
||||
{
|
||||
UnmatchedParenthesisException e;
|
||||
|
||||
e.SetStart(parser[end].GetStart());
|
||||
e.SetEnd(parser[end].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
|
||||
// Check argument count
|
||||
if(m_argMin != -1 && m_nodes.size() < (vector<Node*>::size_type)m_argMin)
|
||||
{
|
||||
InvalidArgumentCountException e(GetName());
|
||||
|
||||
e.SetStart(parser[start].GetStart());
|
||||
e.SetEnd(parser[end].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
if(m_argMax != -1 && m_nodes.size() > (vector<Node*>::size_type)m_argMax)
|
||||
{
|
||||
InvalidArgumentCountException e(GetName());
|
||||
|
||||
e.SetStart(parser[start].GetStart());
|
||||
e.SetEnd(parser[end].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
if(m_refMin != -1 && m_refs.size() < (vector<double*>::size_type)m_refMin)
|
||||
{
|
||||
InvalidArgumentCountException e(GetName());
|
||||
|
||||
e.SetStart(parser[start].GetStart());
|
||||
e.SetEnd(parser[end].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
if(m_refMax != -1 && m_refs.size() > (vector<double*>::size_type)m_refMax)
|
||||
{
|
||||
InvalidArgumentCountException e(GetName());
|
||||
|
||||
e.SetStart(parser[start].GetStart());
|
||||
e.SetEnd(parser[end].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Multi node
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constructor
|
||||
MultiNode::MultiNode(Expression *expr) : Node(expr)
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
MultiNode::~MultiNode()
|
||||
{
|
||||
// Free child nodes
|
||||
vector<Node*>::size_type pos;
|
||||
|
||||
for(pos = 0; pos < m_nodes.size(); pos++)
|
||||
{
|
||||
delete m_nodes[pos];
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate
|
||||
double MultiNode::DoEvaluate()
|
||||
{
|
||||
vector<Node*>::size_type pos;
|
||||
double result = 0.0;
|
||||
|
||||
for(pos = 0; pos < m_nodes.size(); pos++)
|
||||
{
|
||||
result = m_nodes[pos]->Evaluate();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Parse
|
||||
void MultiNode::Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1)
|
||||
{
|
||||
Parser::size_type pos, last;
|
||||
int plevel = 0;
|
||||
|
||||
// Sanity check
|
||||
if(start >= end)
|
||||
throw(SyntaxException());
|
||||
|
||||
// Look
|
||||
last = start;
|
||||
for(pos = start; pos <= end; pos++)
|
||||
{
|
||||
switch(parser[pos].GetType())
|
||||
{
|
||||
case Token::TypeOpenParenthesis:
|
||||
{
|
||||
plevel++;
|
||||
break;
|
||||
};
|
||||
|
||||
case Token::TypeCloseParenthesis:
|
||||
{
|
||||
plevel--;
|
||||
|
||||
if(plevel < 0)
|
||||
{
|
||||
UnmatchedParenthesisException e;
|
||||
|
||||
e.SetStart(parser[pos].GetStart());
|
||||
e.SetEnd(parser[pos].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Token::TypeSemicolon:
|
||||
{
|
||||
if(plevel == 0)
|
||||
{
|
||||
if(pos > last)
|
||||
{
|
||||
// Everything from last to pos - 1
|
||||
aptr(Node) n(parser.ParseRegion(last, pos - 1));
|
||||
m_nodes.push_back(n.get());
|
||||
n.release();
|
||||
}
|
||||
else
|
||||
{
|
||||
SyntaxException e;
|
||||
|
||||
e.SetStart(parser[last].GetStart());
|
||||
e.SetEnd(parser[pos].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
last = pos + 1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// plevel should be zero
|
||||
if(plevel != 0)
|
||||
{
|
||||
UnmatchedParenthesisException e;
|
||||
|
||||
e.SetStart(parser[pos].GetStart());
|
||||
e.SetEnd(parser[pos].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
// If the end was not a semicolon, test it as well
|
||||
if(last < end + 1)
|
||||
{
|
||||
aptr(Node) n(parser.ParseRegion(last, end));
|
||||
m_nodes.push_back(n.get());
|
||||
n.release();
|
||||
}
|
||||
}
|
||||
|
||||
// Assign node
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constructor
|
||||
AssignNode::AssignNode(Expression *expr) : Node(expr), m_var(0), m_rhs(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
AssignNode::~AssignNode()
|
||||
{
|
||||
// Free child node
|
||||
delete m_rhs;
|
||||
}
|
||||
|
||||
// Evaluate
|
||||
double AssignNode::DoEvaluate()
|
||||
{
|
||||
return (*m_var = m_rhs->Evaluate());
|
||||
}
|
||||
|
||||
// Parse
|
||||
void AssignNode::Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1)
|
||||
{
|
||||
// Check some basic syntax
|
||||
if(v1 != start + 1 || v1 >= end)
|
||||
{
|
||||
SyntaxException e;
|
||||
|
||||
e.SetStart(parser[start].GetStart());
|
||||
e.SetEnd(parser[end].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
// Get the value list
|
||||
ValueList *vlist = m_expr->GetValueList();
|
||||
if(vlist == 0)
|
||||
{
|
||||
NoValueListException e;
|
||||
|
||||
e.SetStart(parser[start].GetStart());
|
||||
e.SetEnd(parser[start].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
// Determine variable name
|
||||
string ident = parser[start].GetIdentifier();
|
||||
|
||||
// Make sure it is not a constant
|
||||
if(vlist->IsConstant(ident))
|
||||
{
|
||||
ConstantAssignException e(ident);
|
||||
|
||||
e.SetStart(parser[start].GetStart());
|
||||
e.SetEnd(parser[v1].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
// Get address
|
||||
double *vaddr = vlist->GetAddress(ident);
|
||||
|
||||
if(vaddr == 0)
|
||||
{
|
||||
// If it does not already exist, try to create it
|
||||
vlist->Add(ident);
|
||||
vaddr = vlist->GetAddress(ident);
|
||||
}
|
||||
|
||||
if(vaddr == 0)
|
||||
{
|
||||
NotFoundException e(ident);
|
||||
|
||||
e.SetStart(parser[start].GetStart());
|
||||
e.SetEnd(parser[start].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
// Parse the node (will throw if it can not parse)
|
||||
aptr(Node) n(parser.ParseRegion(v1 + 1, end));
|
||||
|
||||
// Set data
|
||||
m_var = vaddr;
|
||||
m_rhs = n.release();
|
||||
}
|
||||
|
||||
|
||||
// Add node
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constructor
|
||||
AddNode::AddNode(Expression *expr) : Node(expr), m_lhs(0), m_rhs(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
AddNode::~AddNode()
|
||||
{
|
||||
// Free child nodes
|
||||
delete m_lhs;
|
||||
delete m_rhs;
|
||||
}
|
||||
|
||||
// Evaluate
|
||||
double AddNode::DoEvaluate()
|
||||
{
|
||||
return m_lhs->Evaluate() + m_rhs->Evaluate();
|
||||
}
|
||||
|
||||
// Parse
|
||||
void AddNode::Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1)
|
||||
{
|
||||
// Check some basic syntax
|
||||
if(v1 <= start || v1 >= end)
|
||||
{
|
||||
SyntaxException e;
|
||||
|
||||
e.SetStart(parser[start].GetStart());
|
||||
e.SetEnd(parser[end].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
// Parse sides
|
||||
aptr(Node) left(parser.ParseRegion(start, v1 - 1));
|
||||
aptr(Node) right(parser.ParseRegion(v1 + 1, end));
|
||||
|
||||
m_lhs = left.release();
|
||||
m_rhs = right.release();
|
||||
}
|
||||
|
||||
// Subtract node
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constructor
|
||||
SubtractNode::SubtractNode(Expression *expr) : Node(expr), m_lhs(0), m_rhs(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
SubtractNode::~SubtractNode()
|
||||
{
|
||||
// Free child nodes
|
||||
delete m_lhs;
|
||||
delete m_rhs;
|
||||
}
|
||||
|
||||
// Evaluate
|
||||
double SubtractNode::DoEvaluate()
|
||||
{
|
||||
return m_lhs->Evaluate() - m_rhs->Evaluate();
|
||||
}
|
||||
|
||||
// Parse
|
||||
void SubtractNode::Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1)
|
||||
{
|
||||
// Check some basic syntax
|
||||
if(v1 <= start || v1 >= end)
|
||||
{
|
||||
SyntaxException e;
|
||||
|
||||
e.SetStart(parser[start].GetStart());
|
||||
e.SetEnd(parser[end].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
// Parse sides
|
||||
aptr(Node) left(parser.ParseRegion(start, v1 - 1));
|
||||
aptr(Node) right(parser.ParseRegion(v1 + 1, end));
|
||||
|
||||
m_lhs = left.release();
|
||||
m_rhs = right.release();
|
||||
}
|
||||
|
||||
// Multiply node
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constructor
|
||||
MultiplyNode::MultiplyNode(Expression *expr) : Node(expr), m_lhs(0), m_rhs(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
MultiplyNode::~MultiplyNode()
|
||||
{
|
||||
// Free child nodes
|
||||
delete m_lhs;
|
||||
delete m_rhs;
|
||||
}
|
||||
|
||||
// Evaluate
|
||||
double MultiplyNode::DoEvaluate()
|
||||
{
|
||||
return m_lhs->Evaluate() * m_rhs->Evaluate();
|
||||
}
|
||||
|
||||
// Parse
|
||||
void MultiplyNode::Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1)
|
||||
{
|
||||
// Check some basic syntax
|
||||
if(v1 <= start || v1 >= end)
|
||||
{
|
||||
SyntaxException e;
|
||||
|
||||
e.SetStart(parser[start].GetStart());
|
||||
e.SetEnd(parser[end].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
// Parse sides
|
||||
aptr(Node) left(parser.ParseRegion(start, v1 - 1));
|
||||
aptr(Node) right(parser.ParseRegion(v1 + 1, end));
|
||||
|
||||
m_lhs = left.release();
|
||||
m_rhs = right.release();
|
||||
}
|
||||
|
||||
// Divide node
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constructor
|
||||
DivideNode::DivideNode(Expression *expr) : Node(expr), m_lhs(0), m_rhs(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
DivideNode::~DivideNode()
|
||||
{
|
||||
// Free child nodes
|
||||
delete m_lhs;
|
||||
delete m_rhs;
|
||||
}
|
||||
|
||||
// Evaluate
|
||||
double DivideNode::DoEvaluate()
|
||||
{
|
||||
double r2 = m_rhs->Evaluate();
|
||||
|
||||
if(r2 != 0.0)
|
||||
{
|
||||
return m_lhs->Evaluate() / r2;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw(DivideByZeroException());
|
||||
}
|
||||
}
|
||||
|
||||
// Parse
|
||||
void DivideNode::Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1)
|
||||
{
|
||||
// Check some basic syntax
|
||||
if(v1 <= start || v1 >= end)
|
||||
{
|
||||
SyntaxException e;
|
||||
|
||||
e.SetStart(parser[start].GetStart());
|
||||
e.SetEnd(parser[end].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
// Parse sides
|
||||
aptr(Node) left(parser.ParseRegion(start, v1 - 1));
|
||||
aptr(Node) right(parser.ParseRegion(v1 + 1, end));
|
||||
|
||||
m_lhs = left.release();
|
||||
m_rhs = right.release();
|
||||
}
|
||||
|
||||
// Negate node
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constructor
|
||||
NegateNode::NegateNode(Expression *expr) : Node(expr), m_rhs(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
NegateNode::~NegateNode()
|
||||
{
|
||||
// Free child nodes
|
||||
delete m_rhs;
|
||||
}
|
||||
|
||||
// Evaluate
|
||||
double NegateNode::DoEvaluate()
|
||||
{
|
||||
return -(m_rhs->Evaluate());
|
||||
}
|
||||
|
||||
// Parse
|
||||
void NegateNode::Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1)
|
||||
{
|
||||
// Check some basic syntax
|
||||
if(start != v1 || v1 >= end)
|
||||
{
|
||||
SyntaxException e;
|
||||
|
||||
e.SetStart(parser[start].GetStart());
|
||||
e.SetEnd(parser[end].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
// Parse sides
|
||||
aptr(Node) right(parser.ParseRegion(v1 + 1, end));
|
||||
|
||||
m_rhs = right.release();
|
||||
}
|
||||
|
||||
// Exponent node
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constructor
|
||||
ExponentNode::ExponentNode(Expression *expr) : Node(expr), m_lhs(0), m_rhs(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
ExponentNode::~ExponentNode()
|
||||
{
|
||||
// Free child nodes
|
||||
delete m_lhs;
|
||||
delete m_rhs;
|
||||
}
|
||||
|
||||
// Evaluate
|
||||
double ExponentNode::DoEvaluate()
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
double result = pow(m_lhs->Evaluate(), m_rhs->Evaluate());
|
||||
|
||||
if(errno)
|
||||
throw(MathException("^"));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Parse
|
||||
void ExponentNode::Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1)
|
||||
{
|
||||
// Check some basic syntax
|
||||
if(v1 <= start || v1 >= end)
|
||||
{
|
||||
SyntaxException e;
|
||||
|
||||
e.SetStart(parser[start].GetStart());
|
||||
e.SetEnd(parser[end].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
// Parse sides
|
||||
aptr(Node) left(parser.ParseRegion(start, v1 - 1));
|
||||
aptr(Node) right(parser.ParseRegion(v1 + 1, end));
|
||||
|
||||
m_lhs = left.release();
|
||||
m_rhs = right.release();
|
||||
}
|
||||
|
||||
// Variable node
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constructor
|
||||
VariableNode::VariableNode(Expression *expr) : Node(expr), m_var(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
VariableNode::~VariableNode()
|
||||
{
|
||||
}
|
||||
|
||||
// Evaluate
|
||||
double VariableNode::DoEvaluate()
|
||||
{
|
||||
return *m_var;
|
||||
}
|
||||
|
||||
// Parse
|
||||
void VariableNode::Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1)
|
||||
{
|
||||
// Check some basic syntax
|
||||
if(start != end)
|
||||
{
|
||||
SyntaxException e;
|
||||
|
||||
e.SetStart(parser[start].GetStart());
|
||||
e.SetEnd(parser[end].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
// Get value list
|
||||
ValueList *vlist = m_expr->GetValueList();
|
||||
if(vlist == 0)
|
||||
{
|
||||
NoValueListException e;
|
||||
|
||||
e.SetStart(parser[start].GetStart());
|
||||
e.SetEnd(parser[start].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
// Get name
|
||||
string ident = parser[start].GetIdentifier();
|
||||
|
||||
// Get address
|
||||
double *vaddr = vlist->GetAddress(ident);
|
||||
|
||||
if(vaddr == 0)
|
||||
{
|
||||
// If it does not already exist, try to create it
|
||||
vlist->Add(ident);
|
||||
vaddr = vlist->GetAddress(ident);
|
||||
}
|
||||
|
||||
if(vaddr == 0)
|
||||
{
|
||||
NotFoundException e(ident);
|
||||
|
||||
e.SetStart(parser[start].GetStart());
|
||||
e.SetEnd(parser[start].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
// Set information
|
||||
m_var = vaddr;
|
||||
}
|
||||
|
||||
// Value node
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constructor
|
||||
ValueNode::ValueNode(Expression *expr) : Node(expr), m_val(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
ValueNode::~ValueNode()
|
||||
{
|
||||
}
|
||||
|
||||
// Evaluate
|
||||
double ValueNode::DoEvaluate()
|
||||
{
|
||||
return m_val;
|
||||
}
|
||||
|
||||
// Parse
|
||||
void ValueNode::Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1)
|
||||
{
|
||||
// Check basic syntax
|
||||
if(start != end)
|
||||
{
|
||||
SyntaxException e;
|
||||
|
||||
e.SetStart(parser[start].GetStart());
|
||||
e.SetEnd(parser[end].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
// Set info
|
||||
m_val = parser[start].GetValue();
|
||||
}
|
||||
|
||||
|
||||
|
248
3rdparty/expreval/node.h
vendored
Normal file
248
3rdparty/expreval/node.h
vendored
Normal file
@ -0,0 +1,248 @@
|
||||
// File: node.h
|
||||
// Author: Brian Vanderburg II
|
||||
// Purpose: Expression node
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __EXPREVAL_NODE_H
|
||||
#define __EXPREVAL_NODE_H
|
||||
|
||||
// Includes
|
||||
#include <vector>
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
// Part of expreval namespace
|
||||
namespace ExprEval
|
||||
{
|
||||
// Forward declarations
|
||||
class Expression;
|
||||
class FunctionFactory;
|
||||
|
||||
|
||||
// Node class
|
||||
//--------------------------------------------------------------------------
|
||||
class Node
|
||||
{
|
||||
public:
|
||||
Node(Expression *expr);
|
||||
virtual ~Node();
|
||||
|
||||
virtual double DoEvaluate() = 0;
|
||||
virtual void Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1 = 0) = 0;
|
||||
|
||||
double Evaluate(); // Calls Expression::TestAbort, then DoEvaluate
|
||||
|
||||
protected:
|
||||
Expression *m_expr;
|
||||
};
|
||||
|
||||
// General function node class
|
||||
//--------------------------------------------------------------------------
|
||||
class FunctionNode : public Node
|
||||
{
|
||||
public:
|
||||
FunctionNode(Expression *expr);
|
||||
~FunctionNode();
|
||||
|
||||
// Parse nodes and references
|
||||
void Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1 = 0);
|
||||
|
||||
|
||||
private:
|
||||
// Function factory
|
||||
FunctionFactory *m_factory;
|
||||
|
||||
// Argument count
|
||||
long m_argMin;
|
||||
long m_argMax;
|
||||
long m_refMin;
|
||||
long m_refMax;
|
||||
|
||||
protected:
|
||||
// Set argument count (called in derived constructors)
|
||||
void SetArgumentCount(long argMin = 0, long argMax = 0,
|
||||
long refMin = 0, long refMax = 0);
|
||||
|
||||
// Function name (using factory)
|
||||
::std::string GetName() const;
|
||||
|
||||
// Normal, reference, and data parameters
|
||||
::std::vector<Node*> m_nodes;
|
||||
::std::vector<double*> m_refs;
|
||||
|
||||
friend class FunctionFactory;
|
||||
};
|
||||
|
||||
// Mulit-expression node
|
||||
//--------------------------------------------------------------------------
|
||||
class MultiNode : public Node
|
||||
{
|
||||
public:
|
||||
MultiNode(Expression *expr);
|
||||
~MultiNode();
|
||||
|
||||
double DoEvaluate();
|
||||
void Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1 = 0);
|
||||
|
||||
private:
|
||||
::std::vector<Node*> m_nodes;
|
||||
};
|
||||
|
||||
// Assign node
|
||||
//--------------------------------------------------------------------------
|
||||
class AssignNode : public Node
|
||||
{
|
||||
public:
|
||||
AssignNode(Expression *expr);
|
||||
~AssignNode();
|
||||
|
||||
double DoEvaluate();
|
||||
void Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1 = 0);
|
||||
|
||||
private:
|
||||
double *m_var;
|
||||
Node *m_rhs;
|
||||
};
|
||||
|
||||
// Add node
|
||||
//--------------------------------------------------------------------------
|
||||
class AddNode : public Node
|
||||
{
|
||||
public:
|
||||
AddNode(Expression *expr);
|
||||
~AddNode();
|
||||
|
||||
double DoEvaluate();
|
||||
void Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1 = 0);
|
||||
|
||||
private:
|
||||
Node *m_lhs;
|
||||
Node *m_rhs;
|
||||
};
|
||||
|
||||
// Subtract node
|
||||
//--------------------------------------------------------------------------
|
||||
class SubtractNode : public Node
|
||||
{
|
||||
public:
|
||||
SubtractNode(Expression *expr);
|
||||
~SubtractNode();
|
||||
|
||||
double DoEvaluate();
|
||||
void Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1 = 0);
|
||||
|
||||
private:
|
||||
Node *m_lhs;
|
||||
Node *m_rhs;
|
||||
};
|
||||
|
||||
// Multiply node
|
||||
//--------------------------------------------------------------------------
|
||||
class MultiplyNode : public Node
|
||||
{
|
||||
public:
|
||||
MultiplyNode(Expression *expr);
|
||||
~MultiplyNode();
|
||||
|
||||
double DoEvaluate();
|
||||
void Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1 = 0);
|
||||
|
||||
private:
|
||||
Node *m_lhs;
|
||||
Node *m_rhs;
|
||||
};
|
||||
|
||||
// Divide node
|
||||
//--------------------------------------------------------------------------
|
||||
class DivideNode : public Node
|
||||
{
|
||||
public:
|
||||
DivideNode(Expression *expr);
|
||||
~DivideNode();
|
||||
|
||||
double DoEvaluate();
|
||||
void Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1 = 0);
|
||||
|
||||
private:
|
||||
Node *m_lhs;
|
||||
Node *m_rhs;
|
||||
};
|
||||
|
||||
// Negate node
|
||||
//--------------------------------------------------------------------------
|
||||
class NegateNode : public Node
|
||||
{
|
||||
public:
|
||||
NegateNode(Expression *expr);
|
||||
~NegateNode();
|
||||
|
||||
double DoEvaluate();
|
||||
void Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1 = 0);
|
||||
|
||||
private:
|
||||
Node *m_rhs;
|
||||
};
|
||||
|
||||
// Exponent node
|
||||
//--------------------------------------------------------------------------
|
||||
class ExponentNode : public Node
|
||||
{
|
||||
public:
|
||||
ExponentNode(Expression *expr);
|
||||
~ExponentNode();
|
||||
|
||||
double DoEvaluate();
|
||||
void Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1 = 0);
|
||||
|
||||
private:
|
||||
Node *m_lhs;
|
||||
Node *m_rhs;
|
||||
};
|
||||
|
||||
// Variable node (also used for constants)
|
||||
//--------------------------------------------------------------------------
|
||||
class VariableNode : public Node
|
||||
{
|
||||
public:
|
||||
VariableNode(Expression *expr);
|
||||
~VariableNode();
|
||||
|
||||
double DoEvaluate();
|
||||
void Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1 = 0);
|
||||
|
||||
private:
|
||||
double *m_var;
|
||||
};
|
||||
|
||||
// Value node
|
||||
//--------------------------------------------------------------------------
|
||||
class ValueNode : public Node
|
||||
{
|
||||
public:
|
||||
ValueNode(Expression *expr);
|
||||
~ValueNode();
|
||||
|
||||
double DoEvaluate();
|
||||
void Parse(Parser &parser, Parser::size_type start, Parser::size_type end,
|
||||
Parser::size_type v1 = 0);
|
||||
|
||||
private:
|
||||
double m_val;
|
||||
};
|
||||
|
||||
} // namespace ExprEval
|
||||
|
||||
#endif // __EXPREVAL_NODE_H
|
||||
|
774
3rdparty/expreval/parser.cpp
vendored
Normal file
774
3rdparty/expreval/parser.cpp
vendored
Normal file
@ -0,0 +1,774 @@
|
||||
// File: parser.cpp
|
||||
// Author: Brian Vanderburg II
|
||||
// Purpose: Parser object to help parse expression
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Includes
|
||||
#include <new>
|
||||
#include <memory>
|
||||
|
||||
#include "defs.h"
|
||||
#include "parser.h"
|
||||
#include "node.h"
|
||||
#include "except.h"
|
||||
#include "funclist.h"
|
||||
#include "expr.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace ExprEval;
|
||||
|
||||
// Private functions to solve locale problems
|
||||
// ------------------------------------------
|
||||
namespace
|
||||
{
|
||||
bool expreval_isalpha(char c)
|
||||
{
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||
}
|
||||
|
||||
bool expreval_isdigit(char c)
|
||||
{
|
||||
return (c >= '0' && c <= '9');
|
||||
}
|
||||
|
||||
bool expreval_isalnum(char c)
|
||||
{
|
||||
return expreval_isalpha(c) || expreval_isdigit(c);
|
||||
}
|
||||
|
||||
bool expreval_isspace(char c)
|
||||
{
|
||||
return (c == ' ') || (c == '\t') || (c == '\r') || (c == '\n');
|
||||
}
|
||||
|
||||
double expreval_atof(const char* str)
|
||||
{
|
||||
bool negative = false;
|
||||
long double value = 0.0;
|
||||
|
||||
// Skip space
|
||||
while(expreval_isspace(*str))
|
||||
str++;
|
||||
|
||||
// Check for sign
|
||||
if(*str == '-')
|
||||
{
|
||||
negative = true;
|
||||
str++;
|
||||
}
|
||||
else if(*str == '+')
|
||||
{
|
||||
str++;
|
||||
}
|
||||
|
||||
// The part before the decimal
|
||||
while(*str >= '0' && *str <= '9')
|
||||
{
|
||||
value = (value * 10.0) + (double)(*str - '0');
|
||||
str++;
|
||||
}
|
||||
|
||||
// Decimal, if any
|
||||
if(*str == '.')
|
||||
{
|
||||
long double divisor = 1.0;
|
||||
str++;
|
||||
|
||||
// Part after the decimal, if any
|
||||
while(*str >= '0' && *str <= '9')
|
||||
{
|
||||
value = (value * 10.0) + (double)(*str - '0');
|
||||
divisor *= 10.0;
|
||||
str++;
|
||||
}
|
||||
|
||||
value /= divisor;
|
||||
}
|
||||
|
||||
// The result
|
||||
return negative ? -value : value;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Token
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constructor
|
||||
Token::Token(TokenType type, string::size_type start, string::size_type end) :
|
||||
m_type(type),
|
||||
m_start(start),
|
||||
m_end(end)
|
||||
{
|
||||
}
|
||||
|
||||
// Construct identifier token
|
||||
Token::Token(const string &ident, string::size_type start, string::size_type end) :
|
||||
m_type(Token::TypeIdentifier),
|
||||
m_ident(ident),
|
||||
m_start(start),
|
||||
m_end(end)
|
||||
{
|
||||
}
|
||||
|
||||
// Construct value token
|
||||
Token::Token(double value, string::size_type start, string::size_type end) :
|
||||
m_type(Token::TypeValue),
|
||||
m_value(value),
|
||||
m_start(start),
|
||||
m_end(end)
|
||||
{
|
||||
}
|
||||
|
||||
// Get type
|
||||
Token::TokenType Token::GetType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
// Get identifier
|
||||
const string &Token::GetIdentifier() const
|
||||
{
|
||||
return m_ident;
|
||||
}
|
||||
|
||||
// Get value
|
||||
double Token::GetValue() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
// Get start
|
||||
string::size_type Token::GetStart() const
|
||||
{
|
||||
return m_start;
|
||||
}
|
||||
|
||||
string::size_type Token::GetEnd() const
|
||||
{
|
||||
return m_end;
|
||||
}
|
||||
|
||||
// Parser
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constructor
|
||||
Parser::Parser(Expression *expr) : m_expr(expr)
|
||||
{
|
||||
if(expr == 0)
|
||||
throw(NullPointerException("Parser::Parser"));
|
||||
}
|
||||
|
||||
// Destructor
|
||||
Parser::~Parser()
|
||||
{
|
||||
}
|
||||
|
||||
// Parse an expression string
|
||||
Node *Parser::Parse(const string &exstr)
|
||||
{
|
||||
BuildTokens(exstr);
|
||||
|
||||
// Make sure it is not still empty
|
||||
if(m_tokens.size() == 0)
|
||||
throw(EmptyExpressionException());
|
||||
|
||||
// Parse the range
|
||||
return ParseRegion(0, m_tokens.size() - 1);
|
||||
}
|
||||
|
||||
// Parse a region of tokens
|
||||
Node *Parser::ParseRegion(Parser::size_type start, Parser::size_type end)
|
||||
{
|
||||
size_type pos;
|
||||
size_type fgopen = (size_type)-1;
|
||||
size_type fgclose = (size_type)-1;
|
||||
size_type assignindex = (size_type)-1;
|
||||
size_type addsubindex = (size_type)-1;
|
||||
size_type muldivindex = (size_type)-1;
|
||||
size_type posnegindex = (size_type)-1;
|
||||
size_type expindex = (size_type)-1;
|
||||
bool multiexpr = false;
|
||||
int plevel = 0;
|
||||
|
||||
// Check simple syntax
|
||||
if(start > end)
|
||||
throw(SyntaxException());
|
||||
|
||||
// Scan through tokens
|
||||
for(pos = start; pos <= end; pos++)
|
||||
{
|
||||
switch(m_tokens[pos].GetType())
|
||||
{
|
||||
case Token::TypeOpenParenthesis:
|
||||
{
|
||||
plevel++;
|
||||
|
||||
// Opening of first group?
|
||||
if(plevel == 1 && fgopen == (size_type)-1)
|
||||
fgopen = pos;
|
||||
|
||||
break;
|
||||
};
|
||||
|
||||
case Token::TypeCloseParenthesis:
|
||||
{
|
||||
plevel--;
|
||||
|
||||
// First group closed?
|
||||
if(plevel == 0 && fgclose == (size_type)-1)
|
||||
fgclose = pos;
|
||||
|
||||
if(plevel < 0)
|
||||
{
|
||||
UnmatchedParenthesisException e;
|
||||
|
||||
e.SetStart(m_tokens[pos].GetStart());
|
||||
e.SetEnd(m_tokens[pos].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Token::TypeEqual:
|
||||
{
|
||||
if(plevel == 0)
|
||||
{
|
||||
if(assignindex == (size_type)-1)
|
||||
assignindex = pos;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Token::TypeAsterisk:
|
||||
case Token::TypeForwardSlash:
|
||||
{
|
||||
if(plevel == 0)
|
||||
{
|
||||
muldivindex = pos;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Token::TypeHat:
|
||||
{
|
||||
if(plevel == 0)
|
||||
{
|
||||
expindex = pos;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Token::TypePlus:
|
||||
case Token::TypeHyphen:
|
||||
{
|
||||
if(plevel == 0)
|
||||
{
|
||||
if(pos == start)
|
||||
{
|
||||
// Positive or negative sign
|
||||
if(posnegindex == (size_type)-1)
|
||||
posnegindex = pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
// What is before us
|
||||
switch(m_tokens[pos - 1].GetType())
|
||||
{
|
||||
case Token::TypeEqual:
|
||||
case Token::TypePlus:
|
||||
case Token::TypeHyphen:
|
||||
case Token::TypeAsterisk:
|
||||
case Token::TypeForwardSlash:
|
||||
case Token::TypeHat:
|
||||
// After any of these, we are a positive/negative
|
||||
if(posnegindex == (size_type)-1)
|
||||
posnegindex = pos;
|
||||
break;
|
||||
|
||||
default:
|
||||
// After any other, we are addition/subtration
|
||||
addsubindex = pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Token::TypeSemicolon:
|
||||
{
|
||||
if(plevel == 0)
|
||||
{
|
||||
multiexpr = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// plevel should be 0
|
||||
if(plevel != 0)
|
||||
{
|
||||
UnmatchedParenthesisException e;
|
||||
|
||||
e.SetStart(end);
|
||||
e.SetEnd(end);
|
||||
throw(e);
|
||||
}
|
||||
|
||||
// Parse in certain order to maintain order of operators
|
||||
|
||||
// Multi-expression first
|
||||
if(multiexpr)
|
||||
{
|
||||
aptr(Node) n(new MultiNode(m_expr));
|
||||
n->Parse(*this, start, end);
|
||||
return n.release();
|
||||
}
|
||||
else if(assignindex != (size_type)-1)
|
||||
{
|
||||
// Assignment next
|
||||
aptr(Node) n(new AssignNode(m_expr));
|
||||
n->Parse(*this, start, end, assignindex);
|
||||
return n.release();
|
||||
}
|
||||
else if(addsubindex != (size_type)-1)
|
||||
{
|
||||
// Addition/subtraction next
|
||||
if(m_tokens[addsubindex].GetType() == Token::TypePlus)
|
||||
{
|
||||
// Addition
|
||||
aptr(Node) n(new AddNode(m_expr));
|
||||
n->Parse(*this, start, end, addsubindex);
|
||||
return n.release();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Subtraction
|
||||
aptr(Node) n(new SubtractNode(m_expr));
|
||||
n->Parse(*this, start, end, addsubindex);
|
||||
return n.release();
|
||||
}
|
||||
}
|
||||
else if(muldivindex != (size_type)-1)
|
||||
{
|
||||
// Multiplication/division next
|
||||
|
||||
if(m_tokens[muldivindex].GetType() == Token::TypeAsterisk)
|
||||
{
|
||||
// Multiplication
|
||||
aptr(Node) n(new MultiplyNode(m_expr));
|
||||
n->Parse(*this, start, end, muldivindex);
|
||||
return n.release();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Division
|
||||
aptr(Node) n(new DivideNode(m_expr));
|
||||
n->Parse(*this, start, end, muldivindex);
|
||||
return n.release();
|
||||
}
|
||||
}
|
||||
else if(posnegindex == start)
|
||||
{
|
||||
// Positive/negative next, must be at start and check before exponent
|
||||
if(m_tokens[posnegindex].GetType() == Token::TypePlus)
|
||||
{
|
||||
// Positive
|
||||
return ParseRegion(posnegindex + 1, end);
|
||||
}
|
||||
else
|
||||
{
|
||||
aptr(Node) n(new NegateNode(m_expr));
|
||||
n->Parse(*this, start, end, posnegindex);
|
||||
return n.release();
|
||||
}
|
||||
}
|
||||
else if(expindex != (size_type)-1)
|
||||
{
|
||||
// Exponent
|
||||
aptr(Node) n(new ExponentNode(m_expr));
|
||||
n->Parse(*this, start, end, expindex);
|
||||
return n.release();
|
||||
}
|
||||
else if(posnegindex != (size_type)-1)
|
||||
{
|
||||
// Check pos/neg again. After testing for exponent, a pos/neg
|
||||
// at plevel 0 is syntax error
|
||||
SyntaxException e;
|
||||
|
||||
e.SetStart(m_tokens[posnegindex].GetStart());
|
||||
e.SetEnd(m_tokens[posnegindex].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
else if(fgopen == start)
|
||||
{
|
||||
// Group parenthesis, make sure something in between them
|
||||
if(fgclose == end && fgclose > fgopen + 1)
|
||||
{
|
||||
return ParseRegion(fgopen + 1, fgclose - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
SyntaxException e;
|
||||
|
||||
e.SetStart(m_tokens[fgopen].GetStart());
|
||||
if(fgclose == (size_type)-1)
|
||||
e.SetEnd(m_tokens[fgopen].GetEnd());
|
||||
else
|
||||
e.SetEnd(m_tokens[fgclose].GetEnd());
|
||||
|
||||
throw(e);
|
||||
}
|
||||
}
|
||||
else if(fgopen == start + 1)
|
||||
{
|
||||
// Function
|
||||
if(fgclose == end)
|
||||
{
|
||||
// Find function list
|
||||
FunctionList *flist = m_expr->GetFunctionList();
|
||||
|
||||
if(flist == 0)
|
||||
{
|
||||
NoFunctionListException e;
|
||||
|
||||
e.SetStart(m_tokens[start].GetStart());
|
||||
e.SetEnd(m_tokens[start].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
// Get name
|
||||
string ident = m_tokens[start].GetIdentifier();
|
||||
|
||||
// Create function node
|
||||
aptr(FunctionNode) n(flist->Create(ident, m_expr));
|
||||
|
||||
if(n.get())
|
||||
{
|
||||
n->Parse(*this, fgopen, fgclose);
|
||||
}
|
||||
else
|
||||
{
|
||||
NotFoundException e(ident);
|
||||
|
||||
e.SetStart(m_tokens[start].GetStart());
|
||||
e.SetEnd(m_tokens[start].GetEnd());
|
||||
throw(e);
|
||||
}
|
||||
|
||||
return n.release();
|
||||
}
|
||||
else
|
||||
{
|
||||
SyntaxException e;
|
||||
|
||||
e.SetStart(m_tokens[fgopen].GetStart());
|
||||
if(fgclose == (size_type)-1)
|
||||
e.SetEnd(m_tokens[fgopen].GetEnd());
|
||||
else
|
||||
e.SetEnd(m_tokens[fgclose].GetEnd());
|
||||
|
||||
throw(e);
|
||||
}
|
||||
}
|
||||
else if(start == end)
|
||||
{
|
||||
// Value, variable, or constant
|
||||
|
||||
if(m_tokens[start].GetType() == Token::TypeIdentifier)
|
||||
{
|
||||
// Variable/constant
|
||||
aptr(Node) n(new VariableNode(m_expr));
|
||||
n->Parse(*this, start, end);
|
||||
return n.release();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Value
|
||||
aptr(Node) n(new ValueNode(m_expr));
|
||||
n->Parse(*this, start, end);
|
||||
return n.release();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown, syntax
|
||||
SyntaxException e;
|
||||
|
||||
e.SetStart(m_tokens[pos].GetStart());
|
||||
e.SetEnd(m_tokens[pos].GetEnd());
|
||||
|
||||
throw(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Get a token
|
||||
const Token &Parser::operator[] (Parser::size_type pos) const
|
||||
{
|
||||
return m_tokens[pos];
|
||||
}
|
||||
|
||||
// Build tokens
|
||||
void Parser::BuildTokens(const string &exstr)
|
||||
{
|
||||
m_tokens.clear();
|
||||
|
||||
// Test zero-length expression
|
||||
if(exstr.length() == 0)
|
||||
{
|
||||
throw(EmptyExpressionException());
|
||||
}
|
||||
|
||||
// Search through list
|
||||
string::size_type pos;
|
||||
bool comment = false;
|
||||
|
||||
for(pos = 0; pos < exstr.length(); pos++)
|
||||
{
|
||||
// Take action based on character
|
||||
switch(exstr[pos])
|
||||
{
|
||||
// Comment
|
||||
case '#':
|
||||
{
|
||||
comment = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Newline ends comment
|
||||
case '\r':
|
||||
case '\n':
|
||||
{
|
||||
comment = false;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Open parenthesis
|
||||
case '(':
|
||||
{
|
||||
if(comment == false)
|
||||
{
|
||||
m_tokens.push_back(Token(Token::TypeOpenParenthesis, pos, pos));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Close parenthesis
|
||||
case ')':
|
||||
{
|
||||
if(comment == false)
|
||||
{
|
||||
m_tokens.push_back(Token(Token::TypeCloseParenthesis, pos, pos));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Equal
|
||||
case '=':
|
||||
{
|
||||
if(comment == false)
|
||||
{
|
||||
m_tokens.push_back(Token(Token::TypeEqual, pos, pos));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Plus
|
||||
case '+':
|
||||
{
|
||||
if(comment == false)
|
||||
{
|
||||
m_tokens.push_back(Token(Token::TypePlus, pos, pos));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Hyphen
|
||||
case '-':
|
||||
{
|
||||
if(comment == false)
|
||||
{
|
||||
m_tokens.push_back(Token(Token::TypeHyphen, pos, pos));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Asterisk
|
||||
case '*':
|
||||
{
|
||||
if(comment == false)
|
||||
{
|
||||
m_tokens.push_back(Token(Token::TypeAsterisk, pos, pos));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Forward slash
|
||||
case '/':
|
||||
{
|
||||
if(comment == false)
|
||||
{
|
||||
m_tokens.push_back(Token(Token::TypeForwardSlash, pos, pos));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Hat (exponent)
|
||||
case '^':
|
||||
{
|
||||
if(comment == false)
|
||||
{
|
||||
m_tokens.push_back(Token(Token::TypeHat, pos, pos));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Ampersand
|
||||
case '&':
|
||||
{
|
||||
if(comment == false)
|
||||
{
|
||||
m_tokens.push_back(Token(Token::TypeAmpersand, pos, pos));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Comma
|
||||
case ',':
|
||||
{
|
||||
if(comment == false)
|
||||
{
|
||||
m_tokens.push_back(Token(Token::TypeComma, pos, pos));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Semicolon
|
||||
case ';':
|
||||
{
|
||||
if(comment == false)
|
||||
{
|
||||
m_tokens.push_back(Token(Token::TypeSemicolon, pos, pos));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// None of the above, but it may be an identifier or value
|
||||
default:
|
||||
{
|
||||
if(comment == false)
|
||||
{
|
||||
// First, test for value
|
||||
if(exstr[pos] == '.' || expreval_isdigit(exstr[pos]))
|
||||
{
|
||||
// We are a value
|
||||
string::size_type start = pos;
|
||||
|
||||
// Digits before period
|
||||
while(expreval_isdigit(exstr[pos]))
|
||||
pos++;
|
||||
|
||||
// Period
|
||||
if(exstr[pos] == '.')
|
||||
pos++;
|
||||
|
||||
// Digits after period
|
||||
while(expreval_isdigit(exstr[pos]))
|
||||
pos++;
|
||||
|
||||
// Create token
|
||||
string ident = exstr.substr(start, pos - start);
|
||||
m_tokens.push_back(Token(expreval_atof(ident.c_str()), start, pos - 1));
|
||||
|
||||
// Move pos back so pos++ will set it right
|
||||
pos--;
|
||||
}
|
||||
else if(exstr[pos] == '_' || expreval_isalpha(exstr[pos]))
|
||||
{
|
||||
// We are an identifier
|
||||
string::size_type start = pos;
|
||||
bool foundname = true; // Found name part
|
||||
|
||||
// Search for name, then period, etc
|
||||
// An identifier can be multiple parts. Each part
|
||||
// is formed as an identifier and seperated by a period,
|
||||
// An identifier can not end in a period
|
||||
//
|
||||
// color1.red : 1 identifier token
|
||||
// color1. : color1 is identifier, . begins new token
|
||||
// color1.1red : Not value (part 2 is not right)
|
||||
while(foundname)
|
||||
{
|
||||
// Part before period
|
||||
while(exstr[pos] == '_' || expreval_isalnum(exstr[pos]))
|
||||
pos++;
|
||||
|
||||
// Is there a period
|
||||
if(exstr[pos] == '.')
|
||||
{
|
||||
pos++;
|
||||
|
||||
// There is a period, look for the name again
|
||||
if(exstr[pos] == '_' || expreval_isalpha(exstr[pos]))
|
||||
{
|
||||
foundname = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No name after period
|
||||
foundname = false;
|
||||
|
||||
// Remove period from identifier
|
||||
pos--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No period after name, so no new name
|
||||
foundname = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Create token
|
||||
m_tokens.push_back(Token(exstr.substr(start, pos - start), start, pos - 1));
|
||||
|
||||
// Move pos back so pos++ will set it right
|
||||
pos--;
|
||||
}
|
||||
else if(expreval_isspace(exstr[pos]))
|
||||
{
|
||||
// Do nothing, just ignore white space, but it still
|
||||
// seperates tokens
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown token
|
||||
UnknownTokenException e;
|
||||
e.SetStart(pos);
|
||||
e.SetEnd(pos);
|
||||
|
||||
throw(e);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
96
3rdparty/expreval/parser.h
vendored
Normal file
96
3rdparty/expreval/parser.h
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
// File: parser.h
|
||||
// Author: Brian Vanderburg II
|
||||
// Purpose: Parser object to help parse expression
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __EXPREVAL_PARSER_H
|
||||
#define __EXPREVAL_PARSER_H
|
||||
|
||||
// Includes
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
// Part of expreval namespace
|
||||
namespace ExprEval
|
||||
{
|
||||
// Forward declarations
|
||||
class Expression;
|
||||
class Node;
|
||||
|
||||
// Token class
|
||||
//--------------------------------------------------------------------------
|
||||
class Token
|
||||
{
|
||||
public:
|
||||
|
||||
// Token type
|
||||
enum TokenType
|
||||
{
|
||||
TypeUnknown = 0,
|
||||
|
||||
// Basic types
|
||||
TypeOpenParenthesis, // '('
|
||||
TypeCloseParenthesis, // ')'
|
||||
TypeEqual, // '='
|
||||
TypePlus, // '+'
|
||||
TypeHyphen, // '-'
|
||||
TypeAsterisk, // '*'
|
||||
TypeForwardSlash, // '/'
|
||||
TypeHat, // '^'
|
||||
TypeAmpersand, // '&'
|
||||
TypeComma, // ','
|
||||
TypeSemicolon, // ';'
|
||||
TypeIdentifier, // name
|
||||
TypeValue, // 0.2, .6, 2.1
|
||||
};
|
||||
|
||||
// Constructors
|
||||
Token(TokenType type, ::std::string::size_type start, ::std::string::size_type end);
|
||||
Token(const ::std::string &ident, ::std::string::size_type start, ::std::string::size_type end); // May throw if can not copy string
|
||||
Token(double value, ::std::string::size_type start, ::std::string::size_type end);
|
||||
|
||||
// Information
|
||||
TokenType GetType() const;
|
||||
const ::std::string &GetIdentifier() const;
|
||||
double GetValue() const;
|
||||
|
||||
::std::string::size_type GetStart() const;
|
||||
::std::string::size_type GetEnd() const;
|
||||
|
||||
private:
|
||||
TokenType m_type; // Type of token
|
||||
::std::string m_ident; // If type is Identifier
|
||||
double m_value; // If type is Value
|
||||
|
||||
::std::string::size_type m_start, m_end;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Parser class
|
||||
//--------------------------------------------------------------------------
|
||||
class Parser
|
||||
{
|
||||
public:
|
||||
typedef ::std::vector<Token*>::size_type size_type;
|
||||
|
||||
Parser(Expression *expr);
|
||||
~Parser();
|
||||
|
||||
Node *Parse(const ::std::string &exstr);
|
||||
Node *ParseRegion(size_type start, size_type end);
|
||||
|
||||
const Token &operator[] (size_type pos) const;
|
||||
|
||||
private:
|
||||
|
||||
void BuildTokens(const std::string &exstr);
|
||||
|
||||
Expression *m_expr;
|
||||
::std::vector<Token> m_tokens; // Store token and not pointer to token
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __EXPREVAL_PARSER_H
|
||||
|
208
3rdparty/expreval/vallist.cpp
vendored
Normal file
208
3rdparty/expreval/vallist.cpp
vendored
Normal file
@ -0,0 +1,208 @@
|
||||
// File: vallist.cpp
|
||||
// Author: Brian Vanderburg II
|
||||
// Purpose: Value list used for variable and constants
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Includes
|
||||
#include <new>
|
||||
#include <memory>
|
||||
|
||||
#include "defs.h"
|
||||
#include "vallist.h"
|
||||
#include "except.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ExprEval;
|
||||
|
||||
// ValueListItem
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constructor for internal value
|
||||
ValueListItem::ValueListItem(const string &name, double def, bool constant)
|
||||
{
|
||||
m_name = name;
|
||||
m_constant = constant;
|
||||
m_value = m_def = def;
|
||||
m_ptr = 0;
|
||||
}
|
||||
|
||||
// Constructor for external value
|
||||
ValueListItem::ValueListItem(const string &name, double *ptr, double def, bool constant)
|
||||
{
|
||||
m_name = name;
|
||||
m_constant = constant;
|
||||
m_value = m_def = def;
|
||||
m_ptr = ptr;
|
||||
|
||||
if(m_ptr)
|
||||
*m_ptr = def;
|
||||
else
|
||||
throw(NullPointerException("ValueListItem::ValueListItem"));
|
||||
}
|
||||
|
||||
// Get the name
|
||||
const string &ValueListItem::GetName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
// Return if it is constant
|
||||
bool ValueListItem::IsConstant() const
|
||||
{
|
||||
return m_constant;
|
||||
}
|
||||
|
||||
// Get value address
|
||||
double *ValueListItem::GetAddress()
|
||||
{
|
||||
return m_ptr ? m_ptr : &m_value;
|
||||
}
|
||||
|
||||
// Reset to default value
|
||||
void ValueListItem::Reset()
|
||||
{
|
||||
if(m_ptr)
|
||||
*m_ptr = m_def;
|
||||
else
|
||||
m_value = m_def;
|
||||
}
|
||||
|
||||
|
||||
// ValueList
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Constructor
|
||||
ValueList::ValueList()
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor
|
||||
ValueList::~ValueList()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
// Add value to list
|
||||
void ValueList::Add(const string &name, double def, bool constant)
|
||||
{
|
||||
// Ensure value does not already exist
|
||||
if(GetAddress(name))
|
||||
{
|
||||
throw(AlreadyExistsException(name));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create value
|
||||
aptr(ValueListItem) i(new ValueListItem(name, def ,constant));
|
||||
|
||||
// Add value to list
|
||||
m_values.push_back(i.get());
|
||||
i.release();
|
||||
}
|
||||
}
|
||||
|
||||
// Add an external value to the list
|
||||
void ValueList::AddAddress(const string &name, double *ptr, double def, bool constant)
|
||||
{
|
||||
if(GetAddress(name))
|
||||
{
|
||||
throw(AlreadyExistsException(name));
|
||||
}
|
||||
else if(ptr == 0)
|
||||
{
|
||||
throw(NullPointerException("ValueList::AddAddress"));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create value
|
||||
aptr(ValueListItem) i(new ValueListItem(name, ptr, def, constant));
|
||||
|
||||
// Add value to list
|
||||
m_values.push_back(i.get());
|
||||
i.release();
|
||||
}
|
||||
}
|
||||
|
||||
// Get the address of the value, internal or external
|
||||
double *ValueList::GetAddress(const string &name) const
|
||||
{
|
||||
size_type pos;
|
||||
|
||||
for(pos = 0; pos < m_values.size(); pos++)
|
||||
{
|
||||
if(m_values[pos]->GetName() == name)
|
||||
{
|
||||
// The name matches
|
||||
return m_values[pos]->GetAddress();
|
||||
}
|
||||
}
|
||||
|
||||
// No item found
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Is the value a constant
|
||||
bool ValueList::IsConstant(const string &name) const
|
||||
{
|
||||
size_type pos;
|
||||
|
||||
for(pos = 0; pos < m_values.size(); pos++)
|
||||
{
|
||||
if(m_values[pos]->GetName() == name && m_values[pos]->IsConstant())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Number of values in the list
|
||||
ValueList::size_type ValueList::Count() const
|
||||
{
|
||||
return m_values.size();
|
||||
}
|
||||
|
||||
// Get an item
|
||||
void ValueList::Item(size_type pos, string *name, double *value) const
|
||||
{
|
||||
if(name)
|
||||
*name = m_values[pos]->GetName();
|
||||
|
||||
if(value)
|
||||
*value = *(m_values[pos]->GetAddress());
|
||||
}
|
||||
|
||||
// Add some default values
|
||||
void ValueList::AddDefaultValues()
|
||||
{
|
||||
// Math constant 'e'
|
||||
Add("E", EXPREVAL_E, true);
|
||||
|
||||
// Math constant PI
|
||||
Add("PI", EXPREVAL_PI, true);
|
||||
}
|
||||
|
||||
// Reset values
|
||||
void ValueList::Reset()
|
||||
{
|
||||
size_type pos;
|
||||
|
||||
for(pos = 0; pos < m_values.size(); pos++)
|
||||
{
|
||||
m_values[pos]->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
// Free values
|
||||
void ValueList::Clear()
|
||||
{
|
||||
size_type pos;
|
||||
|
||||
for(pos = 0; pos < m_values.size(); pos++)
|
||||
{
|
||||
delete m_values[pos];
|
||||
}
|
||||
}
|
||||
|
84
3rdparty/expreval/vallist.h
vendored
Normal file
84
3rdparty/expreval/vallist.h
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
// File: vallist.h
|
||||
// Author: Brian Vanderburg II
|
||||
// Purpose: Value list used for variable and constants
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __EXPREVAL_VALLIST_H
|
||||
#define __EXPREVAL_VALLIST_H
|
||||
|
||||
// Includes
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Part of expreval namespace
|
||||
namespace ExprEval
|
||||
{
|
||||
// Value list item
|
||||
//--------------------------------------------------------------------------
|
||||
class ValueListItem
|
||||
{
|
||||
public:
|
||||
ValueListItem(const ::std::string &name, double def = 0.0, bool constant = false);
|
||||
ValueListItem(const ::std::string &name, double *ptr, double def = 0.0, bool constant = false);
|
||||
|
||||
const ::std::string &GetName() const;
|
||||
bool IsConstant() const;
|
||||
|
||||
double *GetAddress();
|
||||
void Reset();
|
||||
|
||||
private:
|
||||
::std::string m_name; // Name of value
|
||||
bool m_constant; // Value is constant
|
||||
|
||||
double m_value; // Internal value (if ptr == 0)
|
||||
double *m_ptr; // Pointer to extern value if not 0
|
||||
|
||||
double m_def; // Default value when reset
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Value list
|
||||
//--------------------------------------------------------------------------
|
||||
class ValueList
|
||||
{
|
||||
public:
|
||||
typedef ::std::vector<ValueListItem*>::size_type size_type;
|
||||
|
||||
ValueList();
|
||||
~ValueList();
|
||||
|
||||
// Add variable or constant to the list
|
||||
void Add(const ::std::string &name, double def = 0.0, bool constant = false);
|
||||
|
||||
// Add an external variable or constant to the list
|
||||
void AddAddress(const ::std::string &name, double *ptr, double def = 0.0, bool constant = false);
|
||||
|
||||
// Get the address of a variable or constant, internal or external
|
||||
double *GetAddress(const ::std::string &name) const;
|
||||
|
||||
// Is the value constant
|
||||
bool IsConstant(const ::std::string &name) const;
|
||||
|
||||
// Enumerate values
|
||||
size_type Count() const;
|
||||
void Item(size_type pos, ::std::string *name = 0, double *value = 0) const;
|
||||
|
||||
// Initialize some default values (math constants)
|
||||
void AddDefaultValues();
|
||||
|
||||
// Reset items to default values (constants are not changed)
|
||||
void Reset();
|
||||
|
||||
// Free items and clear memory
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
::std::vector<ValueListItem*> m_values;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // __EXPREVAL_VALLIST_H
|
||||
|
Loading…
Reference in New Issue
Block a user