Recent

Author Topic: TFPExpressionParser docs ?  (Read 3657 times)

dbannon

  • Hero Member
  • *****
  • Posts: 2802
    • tomboy-ng, a rewrite of the classic Tomboy
TFPExpressionParser docs ?
« on: January 13, 2019, 12:39:22 pm »
Both wiki and forum (eg  https://forum.lazarus.freepascal.org/index.php/topic,34726.msg228205.html ) mention the existence of a doc file relating to TFPExpressionParser apparently  (linux) /usr/share/fpcsrc/3.0.4/packages/fcl-base/examples/fpexprpars.txt

But not on either of my installs ?   Has this file been removed/moved/renamed  ?

This is a seriously useful package and I'd like to read more ....

Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

Bart

  • Hero Member
  • *****
  • Posts: 5290
    • Bart en Mariska's Webstek
Re: TFPExpressionParser docs ?
« Reply #1 on: January 13, 2019, 12:46:37 pm »
It's there on my Windows.
Did you install Examples (installing this is optional).

I attched it for your convenience.

Bart

wp

  • Hero Member
  • *****
  • Posts: 11923
Re: TFPExpressionParser docs ?
« Reply #2 on: January 13, 2019, 12:53:42 pm »

dbannon

  • Hero Member
  • *****
  • Posts: 2802
    • tomboy-ng, a rewrite of the classic Tomboy
Re: TFPExpressionParser docs ?
« Reply #3 on: January 13, 2019, 01:33:31 pm »
thanks Bart, WP.  I usually build lazarus from src but rely on Ubuntu's package manager for fpc and fpc-src. Looks like that misses examples, strange.

Anyway, all good. I do have it working but I was hoping for a bit more detail but there you go !

Thanks folks !

Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

wp

  • Hero Member
  • *****
  • Posts: 11923
Re: TFPExpressionParser docs ?
« Reply #4 on: January 13, 2019, 02:55:33 pm »
I was hoping for a bit more detail but there you go !
What are you missing? I wrote the wiki article on the basis of all that I had needed the parser for so far.

dbannon

  • Hero Member
  • *****
  • Posts: 2802
    • tomboy-ng, a rewrite of the classic Tomboy
Re: TFPExpressionParser docs ?
« Reply #5 on: January 13, 2019, 11:10:19 pm »
Ah, WP, well, firstly, thanks for the wki article, I used it to get going, and I am going, so its good !

But the spirit of opensource says everything could be improved !  I was looking for another list of the trig functions supported, your wiki page, testing indicated and now the doc Bart sent me confirmed it does not do tan() - that surprised me. I'd like to know if it can do degrees instead of radians and so on.

And if I was being really picky (and I can be) I think the wiki page could do with a simple stand alone example. Your example code is mixed a bit with snippits from the package as you explain how it works internally. A first time reader could be forgiven for thinking the package is a bit harder to use than it really is.

Studying your article, I came up with this -
Code: Pascal  [Select][+][-]
  1. function TEditBoxForm.DoCalculate(CalcStr : string) : string;
  2. var
  3.     FParser: TFPExpressionParser;
  4.     parserResult: TFPExpressionResult;
  5. begin
  6.     result := '';
  7.     FParser := TFPExpressionParser.Create(nil);
  8.     try
  9.         try
  10.             FParser.Builtins := [bcMath];
  11.             FParser.Expression := CalcStr;
  12.             parserResult := FParser.Evaluate;
  13.             case parserResult.ResultType of
  14.                 rtInteger : result := inttostr(parserResult.ResInteger);
  15.                 rtFloat : result := floattostr(parserResult.ResFloat);
  16.             end;
  17.         finally
  18.           FParser.Free;
  19.         end;
  20.     except on E: EExprParser do showmessage(E.Message);
  21.     end;
  22. end;
       
If you don't mind, I'll add it to your article ?

edit : Oh, wish I could learn to read properly, you even have an example of how to add tan() to it. sigh ..... :-[

David
« Last Edit: January 13, 2019, 11:55:20 pm by dbannon »
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

wp

  • Hero Member
  • *****
  • Posts: 11923
Re: TFPExpressionParser docs ?
« Reply #6 on: January 14, 2019, 12:26:03 am »
I was looking for a list of the trig functions supported, testing indicated and the doc Bart sent me confirmed it does not do tan() - that surprised me. I'd like to know if it can do degrees instead of radians and so on.
Built-in functions are only those of the system unit. See http://wiki.lazarus.freepascal.org/How_To_Use_TFPExpressionParser#Built-in_categories for a list of built-in functions. In the last section (http://wiki.lazarus.freepascal.org/How_To_Use_TFPExpressionParser#Adding_user-defined_functions), however, you find instructions how to extend it by any other functions.

The attached demo contains a unit fpexprparser_addon which adds many more function of unit math and fpc's numlib. Just add it to "uses" and you're ready to go. The demo itself prints a table of some arcsin values.

If you don't mind, I'll add it to your article along with a list of the maths functions ?
Feel free to change, I'll change back what I don't like  ;)

As for your code sample, for example, I don't like that it is a snippet of some form method. It would be more versatile if you'd make it a standalone function. And you should not convert the returned value to a string - that's too application-specific. I'd also change the order of the try-finally and try-except blocks:
Code: Pascal  [Select][+][-]
  1. function CalcExpression(CalcStr : string) : Double;
  2. var
  3.   FParser: TFPExpressionParser;
  4. begin
  5.   result := NaN;
  6.   FParser := TFPExpressionParser.Create(nil);
  7.   try
  8.     try
  9.       FParser.Builtins := [bcMath];
  10.       FParser.Expression := CalcStr;
  11.       result := ArbToFloat(FParser.Evaluate);
  12.     except
  13.       on E: EExprParser do showmessage(E.Message);
  14.     end;
  15.   finally
  16.     FParser.Free;
  17.   end;
  18. end;
       

dbannon

  • Hero Member
  • *****
  • Posts: 2802
    • tomboy-ng, a rewrite of the classic Tomboy
Re: TFPExpressionParser docs ?
« Reply #7 on: January 14, 2019, 12:24:59 pm »
Quote
The attached demo contains a unit fpexprparser_addon which adds many more function of unit math and fpc's numlib. Just add it to "uses" and you're ready to go. The demo itself prints a table of some arcsin values.

And very nice too, thanks !

Quote
As for your code sample, for example, I don't like that it is a snippet of some form method. It would be more versatile if you'd make it a standalone function. And you should not convert the returned value to a string - that's too application-specific.

While I see your point, I'd suggest we need note the difference between good code in an application and good 'educational' code a user can easily understand and easily modify for their own specific purposes. Not always the same thing. My code shows how different types might be pushed out by the parser and how to handle that difference.

But more importantly, I admit to often wondering how to use the two different try models together. You reckon catch the exception first, then worry about releasing resources. I initially did that but a few months ago, 'someone' was adamant the 'finally' should be wrapped by the exception. (Cannot find the post....).  Please explain .....

Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: TFPExpressionParser docs ?
« Reply #8 on: January 14, 2019, 02:20:00 pm »
But more importantly, I admit to often wondering how to use the two different try models together. You reckon catch the exception first, then worry about releasing resources. I initially did that but a few months ago, 'someone' was adamant the 'finally' should be wrapped by the exception. (Cannot find the post....).  Please explain .....
Enclosing the try..except inside the try..finally means that when an exception arises you still have the objects in the state they were so recovery--or debugging--is possible. If you first free the ressources your exception-catching is left with nothing to work with but the exception itself.  Also, the finally block is always executed, while the except block may not be, so the finally is considered to go "last".

Of course, it all depends on what you do with exceptoins: if you do nothing more than call p.e. a ShowMessage() it matters little. It's just considered bad practice, in general, to enclose the try..finallly inside a try..except.
« Last Edit: January 14, 2019, 02:22:30 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

metallaro1980

  • New Member
  • *
  • Posts: 36
Re: TFPExpressionParser docs ?
« Reply #9 on: April 16, 2019, 02:53:12 pm »
i re-open this thread
it is possibile with TFPExpressionParser
to add custom functions with 2 or more parameters

 fparser.Identifiers.AddFunction('log2', 'F', 'F', @ExprLog2); 

procedure ExprLog2(var Result: TFPExpressionResult; Const Args: TExprParameterArray);
var
  x: extended;
begin
  x := ArgToFloat(Args[0]);
  Result.resFloat := Log2(x);
end; 

so this calculates the log2 of x
but if i want to calculate the logn(n,x) i need 2 variables.
i also add others functions...  fparser.Identifiers.AddFunction('arcsin', 'F', 'F', @ExprArcSin);
for calculate it i use a tedit with a similar text. arcsin(1) and push a button with .Caption set to '='
but if i want to calculate the logn(n,x) how can i pass these parameters?
thank you very much

wp

  • Hero Member
  • *****
  • Posts: 11923
Re: TFPExpressionParser docs ?
« Reply #10 on: April 16, 2019, 03:46:48 pm »
Define the procedure "ExprLogN" with two input arguments (I am assuming here that N can be a floating point value, too):
Code: Pascal  [Select][+][-]
  1. procedure ExprLogN(var Result: TFPExpressionResult; const Args: TExprParameterArray);
  2. var
  3.   n: Double;
  4.   x: Double;
  5. begin
  6.   n := ArgToFloat(Args[0]);
  7.   x := ArgToFloat(Args[1]);
  8.   Result.resFloat := logn(n, x);
  9. end;

Register this function to the parser:
Code: Pascal  [Select][+][-]
  1.    FParser.Identifiers.AddFunction('logn', 'F', 'FF', @ExprLogN);

Then you can call
Code: Pascal  [Select][+][-]
  1.   FParser.Formula := 'logn(3, 1000)';
  2. // or:
  3.   FParser.Formula := 'logn(3,x)';

Here is a complete example (tested):

Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$MODE objfpc}{$H+}
  4.  
  5. uses
  6.   SysUtils, math, fpexprpars;
  7.  
  8. var
  9.   parser: TFpExpressionParser;
  10.  
  11. procedure ExprLogN(var Result: TFPExpressionResult; const Args: TExprParameterArray);
  12. var
  13.   n: Double;
  14.   x: Double;
  15. begin
  16.   n := ArgToFloat(Args[0]);
  17.   x := ArgToFloat(Args[1]);
  18.   Result.resFloat := logn(n, x);
  19. end;
  20.  
  21. const
  22. //  n = 10;
  23.   n = 3;
  24. var
  25.   FParser: TFPExpressionParser;
  26.   argX: TFPExprIdentifierDef;
  27.   argN: TFPExprIdentifierDef;
  28.   s: string;
  29.   i: Integer;
  30.   x: double;
  31.   f: double;
  32.   fs: TFormatSettings;
  33. begin
  34.   fs := DefaultFormatSettings;
  35.   fs.DecimalSeparator := '.';
  36.  
  37.   FParser := TFPExpressionParser.Create(nil);
  38.   try
  39.     // Enable the use of mathematical expressions
  40.     FParser.BuiltIns := [bcMath];
  41.  
  42.     // Add user-defined function
  43.     FParser.Identifiers.AddFunction('logn', 'F', 'FF', @ExprLogN);
  44.  
  45.     // Add the function arguments
  46.     argX := FParser.Identifiers.AddFloatVariable('x', 0.0);
  47.     argN := FParser.Identifiers.AddFloatVariable('n', 1.0);
  48.  
  49.     // Define the function, using the argument names 'n' and 'x' as defined above
  50.     s := FloatToStr(n, fs);
  51.     FParser.Expression := 'logn(' + s + ',x)';
  52.  
  53.     WriteLn('y = ' + FParser.Expression + ' ...');
  54.     // Calculate some function values
  55.     for i := -5 to 5 do begin
  56.       x := Power(10, i);
  57.       argX.AsFloat := x;                             // Set the function argument value
  58.       argN.AsFloat := n;
  59.       f := FParser.Evaluate.ResFloat;                // Calculate the function value
  60.       s := Format('%.9g', [x], fs);
  61.       WriteLn('logn(', n, ',', s, ') = ', f:0:6);
  62.     end;
  63.  
  64.   finally
  65.     FParser.Free;
  66.   end;
  67. end.

mr-highball

  • Full Member
  • ***
  • Posts: 233
    • Highball Github
Re: TFPExpressionParser docs ?
« Reply #11 on: April 16, 2019, 03:59:47 pm »
First time seeing the expression parser, I must've been living under a rock. Anyways, I just wanted to say it's very cool, and the docs were written very well @wp. I'm going to have go... write some expressions...

metallaro1980

  • New Member
  • *
  • Posts: 36
Re: TFPExpressionParser docs ?
« Reply #12 on: April 16, 2019, 06:45:25 pm »
thank you very much
this is another sample

fparser.Identifiers.AddFunction('EV', 'F', 'FF', @ExprEV);

procedure ExprEV(var Result: TFPExpressionResult; const Args: TExprParameterArray);
var
  av: extended;
  t: extended;
begin
  av := ArgToFloat(Args[0]);
  t := ArgToFloat(Args[1]);
  Result.resFloat := Log2(Power(av,2)/(t));
end; 

 

TinyPortal © 2005-2018