TFatExpression 1.0

a component by Gasper Kozak, June 2001
This component is completely free for any (ab)use. I do not promise any support or new updates. The component probably includes bugs. If you find any, please let me know.
check for a new version on Delphi pages.

this is an expression-calculation component. Simply by passing an string-expression to it, you can evaluate its value. It uses a very simple parser and a syntax-tree approach.

FEATURES
operations: + - * / ^ !
parenthesis: ( )
functions:
In the TFatExpression component, there is a Functions: TStringList property, which holds a list of user-defined functions. These can be entered at design-time, or assigned at run-time (see demo). Functions without parameters can also serve as constants (see bellow for function Pi).
the function format is as follows:
function = function_name [ "(" argument_name [";" argument_name ... ] ")" ] "=" expression
valid function_name (and also argument_name) consists of:
 first character      = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_
 every next character = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_$#@&0123456789
here are a few examples of valid functions:
no parameter: Pi=3.14
one parameter: f(t) = 4*t*t + 2*t + 1
one parameter: sqr(x)=x*x
one parameter: sqrt(x)=x^(1/2)
see how functions can include each other
one parameter: circle_area(radius)=Pi*sqr(radius)
two parameters: add(x;y)=x + y
note: in function definition and also in expression, multiple parameters must be separated with a ";" character.
When calculating, you would use some of these functions like this:
FatExpression1.Text := 'sqr(2) + sqrt(16) + add(4; 4)';
in this case, function FatExpression1.Value should return 16

Another type of function-implementing is available. If the component, while evaluating the expression, comes along an unknown function, it generates an OnEvaluate event. It passes the function name, argument count and argument list to the event, expecting the programer to provide it's result value. This can be used for variables, arrays and constants that are application-dependant.
Here is some code showing how you could make the "add(x;y)=x+x" function the other way, by not adding it to the Functions property.
The event handler first checks the Eval argument, and if is the right function (add), it returns a result of "first argument plus second argument" to the Value. Argument list is zero-based, meaning the first argument is Args[0], second is Args[1], ... and the last is Args[ArgCount - 1]. ArgCount tells you how many arguments are in the Args array.
procedure TForm1.FatExpression1Evaluate(Sender: TObject; Eval: String; 
  Args: array of Double; ArgCount: Integer; var Value: Double);
begin
  if UpperCase(Eval) = 'ADD' then
    Value := Args[0] + Args[1];
end;
This code is equal to writing "add(x;y)=x+y" function in the Functions property, although it is probably faster, since it is compiled and optimized by Delphi. There is also one big advantage using this approach. it has a dynamic number of arguments.
Imagine this:
you add this function to the FatExpression1.Functions property: "add(a;b;c;d;e;f;g;h)=a+b+c+d+e+f+g+h".
In expression, you can pass less or more arguments (than there are specified in the function-definition) to the function-call, for example:
FatExpression1.Text := 'add(1;2;3)'; // returns 6
FatExpression1.Text := 'add(1;1;1;1;1;1;1;1;1;1;1;1;1)'; // returns 8, because the function definition only includes 8 parameters
If you pass less arguments, than the parser expects, the missing parameter are treated as zeros.
As you can see in demo, I handle the ADD function through OnEvaluate event. This way, I can take care of any number of arguments passed to the function-call:
  var I: Integer;

  if UpperCase(Eval) = 'ADD' then
    for I := 0 to ArgCount - 1 do
      Value := Value + Args[I];
This code will add any number of arguments and return the value. So now, a call to
FatExpression1.Text := 'add(1;1;1;1;1;1;1;1;1;1;1;1;1)';
returns 13.

Function-calls in expression can also be nested within each other:
add(add(1; 1); add(1; 1))
add(add(add(add(1); 1); 1); 1))
add(add(add(add(4))))
All these functions return 4.


properties
events



so... this is the basic info. For more, you should see demo, dig into the source or email me (in this order).
eof