TFatExpression 1.0 beta
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.
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 simple 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.
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 then the parser expects, then the missing parameter are treated as zeros.
As you can see in demo, I handle the ADD function via 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.
so... this is the basic info. For more, you should see demo, dig into the source or email me
(in this order).
eof