Anyway.
Okay, I just finished writing the main structures to store the parsed equations. Its pretty much as I laid it out; I'll spare you the implementation and just jump to the usage.
Lets take an example expression first -
f() = cos( 5 * 3 )
Now, first we have to create the top-level representation of the expression, which I have dubbed a Statement -
Statement< float, .. > equ;
I'm intentionally omitting the second template argument here because it refers to a variable value table so that we can lookup stuff. And I haven't gotten around to implement that yet, but more than likely its just going to be a string-to-T map.
Okay, so lets start parsing the innermost part of the expression by making some constant value holders -
Value< float, .. >* val1 = new Value< float, .. >( 5 );
Value< float, .. >* val2 = new Value< float, .. >( 3 );
I'm not entirely satisfied with this method of construction, but as it will only be used by parser code I don't feel insensed enough to write factory functions or anything.
Anyway, we now combine the two Values with an Expression construct -
Expression< OP_MUL, float, .. >* expr = new Expression< OP_MUL, float, .. >( val1, val2 );
That should be pretty self explanatory.
Now we can add the expression to our statement. We could have just added the values directly, but that doesn't show everything well.
The statement is managed internally as a cross between a tree and a stack - it maintains a pointer to the head of the tree (which is defaults to a Value< T, .. >( 0 )). It supports two operations - splice and append - whose usage will be explained in a second.
We can take our expression and splice it into the stack with the splice command. Essentially this creates a new Expression with the statement's head as one value and our expression as the other.
Since we left the value of the head as the default - 0 - we should just add in this value (OP_ADD)
equ.splice< OP_ADD >( expr );
Now all we've got left to deal with is the sincos operation. This is easy to apply with the append operation (not aptly named). append creates a new UnaryExpression with the current head as the value and applies the operation to it.
So -
equ.append< OP_COS >();
EDIT: Dcower is a fucking trigonometric nazi. That's right. That's right. Go play with your triangles you silly Nazi, give me a call in 1938 when you forget poland kthx. [sad]
I guess it should be really called apply or transform, but since its technically "appending" a transform onto the list... meh.
Anyway, we want to be able to do something with the final value. We use the eval method to do this -
std::cout << equ.eval( .. ) << std::endl;
Again, I've omitted the variable table stuff. Essentially, you'd pass a reference to the current variable table which would get used by Variable instances in the tree.
And for fun - the operations currently supported -
enum { OP_ADD = 1, OP_SUB, OP_MUL, OP_DIV, OP_POW, OP_LOG, OP_NEG, OP_SIN, OP_COS, OP_TAN, OP_ASIN, OP_ACOS, OP_ATAN};
There are some limitations that I'm secretly hiding, and (in last night's prototype) used template-sex to prevent messes from happening. (think about what happens when you use ints and pass it to an OP_POW which uses pow() internally...)
I'll discuss some of the internals tommorrow night, as well as details on variable tables. And I know no one cares, but that's okay. Because I still care :)