Visit our Sponsor   Visit our Sponsor
delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
500 Users Online NOW
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback





Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi







Startblatt.de






Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (3)


High speed parserComponent available for this articleFormat this article printer-friendly!Bookmark function is only available for registered users!
Product:
Delphi 6.x (or higher)
Category:
Scientific
Skill Level:
Scoring:
Last Update:
03/31/2003
Search Keys:
delphi delphi3000 article borland vcl code-snippet high speed parser
Times Scored:
1
Visits:
4990
Uploader: Yuriy Pisarev
Company:
Reference: www.pisarev.net
 
Question/Problem/Abstract:
You can download some necessary files from www.pisarev.net
The component is intended for some mathematics and logical calculations. Parser works with the very high speed - about 10000000 operations per 1 - 1.5 seconds for simple mathematics formulas and a little more for logical formulas (these results were reached on the computer with Athlon 1800XP, 512 DDR in Windows XP)
Answer:



The TDataEditor parser

Introduction

The component is intended for some mathematics and logical calculations. Parser contains standard set of mathematics (such as “sin” or “sqrt”) and logical functions (such as “>” or “true”). It also contains standard set of types. But it is possible to create new functions and new types. Parser works with the very high speed - about 10000000 operations per 1 - 1.5 seconds for simple mathematics formulas and a little more for logical formulas (these results were reached on the computer with Athlon 1800XP, 512 DDR in Windows XP). Parser creates binary representation of formula (script) and makes all following calculations by the script. There are no limitations for the formula; it could have any length and any amount of embedded formulas. Embedded formula is expression that is located between brackets and has increased calculation priority.
There are two types of script: logical script (for logical formulas) and mathematics script (for mathematics formulas). Mathematic script could contain inside another mathematic script (embedded formula). Logical script could contain inside both types of script. These scripts have a lot of similar parts. Each script has a header that contains some initial information. Detailed structures of mathematics and logical scripts are in source file (“DataEditor.pas”). It is in constant description section.

Formulas structure

Each formula has to be constructed by some rules. Also it is necessary to know about structure it may have. Functions, types, and other components are in list below:
· Single: type, defines float 32-bit value
· Double: type, defines float 64-bit value
· Int64: type, defines integer signed 64-bit value
· Integer: type, defines integer signed 32-bit value
· Longword: type, defines integer unsigned 32-bit value
· Smallint: type, defines integer signed 16-bit value
· Word: type, defines integer unsigned 16-bit value
· Shortint: type, defines integer signed 8-bit value
· Byte: type, defines integer unsigned 8-bit value
· if: reserved word, defines logical expression
· and: operand,  used for manipulations on logical expressions and executes conjunction operation
· or: operand,  used for manipulations on logical expressions and executes disjunction operation
· xor: operand,  used for manipulations on logical expressions and executes exclusive disjunction operation
· not: operand,  used for manipulations on logical expressions and executes negation operation
· > logical function, returns true if first mathematics expression is greater than second mathematics expression
· <: logical function, returns true if first mathematics expression is less than second mathematics expression
· <>: logical function, returns true if mathematics expressions are not equal
· =>: logical function, returns true if first mathematics expression is equal to or greater than second mathematics expression
· <=: logical function, returns true if first mathematics expression is equal to or less than second mathematics expression
· =: logical function, returns true if mathematics expressions are equal
· Odd: logical function, returns true if mathematic expression is an odd number
· True: logical function, always returns true
· False: logical function, always returns false
· +: operand, executes adding operation
· -: operand, executes subtraction operation
· *: mathematics function, executes multiplying operation
· /: mathematics function, executes division operation
· Sqrt: mathematics functions, root of a number. Root could have any degree
· Div: mathematics functions, executes integer division operation
· Mod: mathematics functions, executes remainder operation
· Int: mathematics function, returns the integer part of a number.
· Frac: mathematics function, returns the fractional part of a number
· Random: mathematics function, returns random number within the range 0 <= value < 1
· Trunc: mathematics function, truncates a number to an integer
· Round: mathematics function, returns the value rounded to the nearest whole number
· Sin: mathematics function, returns the sine of the angle in radians
· ArcSin: mathematics function, returns the inverse sine of a number
· Sinh: mathematics function, returns the hyperbolic sine of an angle
· ArcSinh: mathematics function, returns the inverse hyperbolic sine of a number
· Cos: mathematics function, returns the cosine of the angle in radians
· ArcCos: mathematics function, returns the inverse cosine of a number
· Cosh: mathematics function, returns the hyperbolic cosine of an angle
· ArcCosh: mathematics function, returns the inverse hyperbolic cosine of a number
· Tan: mathematics function, returns the tangent of the angle
· ArcTan: mathematics function, returns the arctangent of a number
· Tanh: mathematics function, returns the hyperbolic tangent of an angle
· ArcTanh: mathematics function, the inverse hyperbolic tangent of a number
· CoTan: mathematics function, returns the cotangent of the angle
· ArcCoTan: mathematics function, returns the inverse cotangent of a number
· CoTanh: mathematics function, returns the hyperbolic cotangent of an angle
· ArcCoTanh: mathematics function, the inverse hyperbolic cotangent of a number
· Sec: mathematics function, returns the secant of an angle
· ArcSec: mathematics function, returns the inverse secant of a number
· Sech: mathematics function, returns the hyperbolic secant of an angle
· ArcSech: mathematics function, returns the inverse hyperbolic secant of a number
· Csc: mathematics function, returns the cosecant of an angle
· ArcCsc: mathematics function, returns the inverse cosecant of a number
· Csch: mathematics function, returns the hyperbolic cosecant of an angle
· ArcCsch: mathematics function, returns the inverse hyperbolic secant of a number
· Abs: mathematics function, returns an absolute value
· Ln: mathematics function, returns the natural log of an expression.
· Lg: mathematics function, returns log base 10
· Log: mathematics function, returns the log of expression for a specified base
· Pi: mathematics function, returns 3.1415926535897932385
· Exp: mathematics function, returns the exponential of  an expression
· !: mathematics function, returns factorial of an expression
· ^: mathematics function, raises expression to any power

Logical formulas

Any case the logical formula needs to be started with the reserved word “if”.  It means the current expression is logical. You can use any amount of embedded formulas that are between brackets. Embedded formulas could have any type. Therefore inside of brackets it’s necessary to write reserved word “if” if embedded expression is logical and write nothing if embedded expression if mathematics. For example:
"if (2 log 4) = (4 sqrt 2) or (if (2 * 2) = 4)"
“if true and (if true xor true) or (2 * 2) = 4”
Both expressions return true. You may check this use “SpeedTest” program.
There is each mathematics expression that contains functions needs to be put inside of brackets in the formula. But it’s not necessary for numbers. For example:
“if 1 = 1 or 2 = 2 or 3 =3”
“if (trunk pi) = 3”
What components of formula are mathematics functions - you can clarify using components list above.

Some functions for working with the parser
All operations with the formulas executes object of TDataEditor class. Parser has a lot of methods for registration new functions, types; also it has some methods for translating formulas to scripts and executing these scripts. If you are not going to create new functions, you may skip that paragraph.

procedure RegisterNumFunction(out FunctionID: Integer; const FunctionName: string; RequireValue1, RequireValue2: Boolean); virtual;

Register mathematics function with “FunctionName” name. Parameters RequireValue1 and RequireValue2 mean if parameter needs before or after function accordingly. “FunctionID” is identifier of registered function. If function failed, the “FunctionID” parameter is -1. This parameter will be changed automatically after procedure “SortNumFunctionsData” is called. Registration order is not important, but  always after registration new elements it’s necessary to call sorting procedure. There are three sorting procedures: “SortNumFunctionsData”, “SortBoolFunctionsData” and “SortTypesData” in TDataEditor for sorting mathematics, logical functions and types accordingly. These methods sort registered functions thereby placing the longest functions to the beginning of memory. It’s necessary to remember that after sorting procedure is called all functions identifiers are changed. For example:

...
type
  TForm1 = class(TForm)
  ...
  private
    FLogID: Integer;
    FSinhID: Integer;
      ...
  end;

  ...

  procedure TForm1.FormCreate(Sender: TObject);
  begin
    with DataEditor do begin
      // “Log” and “Sinh” functions already exist like standard functions,
      // but this sample is just hypothetical

      //Function Log needs both parameters:
      RegisterNumFunction(FLogID, 'log', True, True);

      //Function Sinh needs just a second parameter:
      RegisterNumFunction(FSinhID, 'sinh', False, True);

      // It’s possible, that now FLogID = 0 and FSinhID = 1;
      SortNumFunctionsData;
      // Now FLogID = 1 and FSinhID = 0, because of the first function
      // is the longest function
    end;
  ...
  end;
  
  ...

function UnRegisterNumFunction(…): Boolean;  Deletes registered function by it’s name or identifier.
procedure RegisterBoolFunction(out FunctionID: Integer; const FunctionName: string; RequireValue1, RequireValue2: Boolean); virtua; It has the same sense as method “RegisterNumFunction” above.
procedure RegisterType(out TypeID: Integer; const TypeName: string); overload; virtual; Registers new type and gives new type identifier TypeID. If function failed, the “TypeID” parameter is -1.
function UnRegisterType(…): Boolean; Deletes registered type by it’s name or identifier.
procedure StringToNumScript(const S: string; out Script: TScript; OpenedBracket: Char = '('; ClosedBracket: Char = ')'); overload; virtual; Converts string “S” to the script “Script”. Parameters “OpenedBracket” and “ClosedBracket” contains characters of the beginning and the end of embedded formula.
procedure StringToBoolScript(const S: string; out Script: TScript; OpenedBracket: Char = '('; ClosedBracket: Char = ')'); overload; virtual; It has the same sense as method “StringToNumScript” above.
function ExecuteNumScript(Index: Integer): Double; overload; virtual; Executes mathematics script and returns the execution result. Parameter “Index” defines script address.
function ExecuteNumScript(P: Pointer): Double; overload; virtual; Executes mathematics script and returns the execution result. Parameter “P” defines script address.
function ExecuteNum: Double; overload; virtual; Executes mathematics script that is in the “Script” property of TDataEditor class and returns execution result.
function ExecuteBoolScript(Index: Integer): Boolean;  It has the same sense as method “ExecuteNumScript” above.
function ExecuteBoolScript(P: Pointer): Boolean;  It has the same sense as method “ExecuteNumScript” above.
function ExecuteBool: Boolean; It has the same sense as method “ExecuteNumScript” above.
property Script: TScript; Contains script. Script could have any type.
property Formula: string;  Contains formula.
property Accuracy: TRoundToRange;  Indicates the power of rounding. To be short it’s the second parameter of “Accuracy“ function. It’s necessary just for operations with logical scripts. It has default value -7.
property OnNumFunction: TNumFunctionEvent;
TNumFunctionEvent = function(FunctionID: Integer; TypeID: Integer; var Value1: Double; Value2, Value3: Double): Boolean of object;
This event needs to be processed only if there are new functions in object of TDataEditor class. Otherwise all standard functions execute within “DefaultNumFunction” method. Parameter FunctionID is identifier of the processing function. Parameter TypeID is the current type identifier. This event will appear each time it’s necessary to execute function in script even if it’s just a standard function. Therefore you can change the standard functions behavior. If you want to call default function - you should set function result to True. Parameters Value2 and Value3 are functions parameters, they are valid only if current function was registered (see “RegisterNumFunction” method, parameters RequireValue1 and RequireValue2 above) with necessary instructions. Result of function execution should be placed to Value1 parameter. For example:
...

uses ..., Math;

...
type
  TForm1 = class(TForm)
  ...
  private
    FLogID: Integer;
    FSinhID: Integer;
    function NumFunction(FunctionID: Integer; TypeID: Integer;
      var Value1: Double; Value2, Value3: Double): Boolean;

    ...
  end;

  ...

  procedure TForm1.FormCreate(Sender: TObject);
  begin
    with DataEditor do begin
      // “Log” and “Sinh” functions are already exist like standard functions,
      // but this sample is just hypothetical

      RegisterNumFunction(FLogID, 'log', True, True);
      RegisterNumFunction(FSinhID, 'sinh', False, True);
      SortNumFunctionsData;

    end;
  ...
  end;
  
  function TForm1.NumFunction(FunctionID, TypeID: Integer;
    var Value1: Double; Value2, Value3: Double): Boolean;
  begin

    // Now we check if the current function is not standard,
    // if it’s so then we calculate our function and place result in
    // “Value1” parameter and set Function result to True.
    // Otherwise we set function result to True to call default
    // function:

    if FunctionID = FLogID then Value1 := Value1 := LogN(Value2, Value3)
    else if FucntionID = FSinhID then Value1 := SinH(Value3)
    else begin
      Result := True;
      Exit;
    end;
    Result := False;

  end;
  ...

property OnBoolFunction: TBoolFunctionEvent;

TBoolFunctionEvent = function(FunctionID: Integer; TypeID: Integer; var Value1: Boolean; Value2, Value3: Double): Boolean of object;
It has the same sense as property “OnNumFunction” above.
Samples
GraphX
For the first sample of using TDataEditor I’ve made an ActiveX object which builds functions graphs. I guess it fully demonstrates parser possibilities. Now I’d like to describe some methods and properties of TGraphBldr component. I’ve made the TGraphBldr component to use it in ActiveX object - it’s descendent of TCustomControl class. So, here are some properties and methods of TGraphBldr:
function XCoord(X: Double): Double; returns X coordinate on a scale of graph. Parameter X should be indicated on scale of a component.
function YCoord(Y: Double): Double; returns Y coordinate on a scale of graph. Parameter Y should be indicated on scale of a component.
function Coordinates(X, Y: Double): TCoord;
TCoord = record
  X, Y: Double;
end;
return coordinates on a scale of graph. Parameters  X and Y should be indicated on a scale of component.
property Picture: TBitmap; contains graph image.
property DetailLevel: Integer; Regulates graph detail level.  This property indicates the points amount that will be calculated from the minimum to maximum values of axes X. If you increase the points amount on axis X then occurs accordingly increase the points amount on axis Y. Therefore the effect of increase this property is more noticeable on graphs with the predominated vertical lines, like “tan x” or  “sec x”. So, it’s practically senselessly to increase detail level on such graphs like “sin x” or “cos x”. Component creates points array that will be exposed by filtration. Filtration is necessary because of there are many points with the same coordinates - it’s the side effect of overweening detail level.
property FramePen: TPen; defines object for graph frame line drawing
property GraphPen: TPen; defines object for graph line drawing
property GridPen: TPen; defines object for graph grid line drawing
property HorzSpacing: Double; defines horizontal cell size of a graph grid
property ShowAxis: Boolean; defines if graph axes are visible
property ShowFrame: Boolean; defines if graph frame is visible
property ShowGrid: Boolean; defines if graph grid is visible
property ShowText: Boolean; defines if formula text is visible on graph
property Text: string; contains formula
property TracePen: TPen; defines object for trace lines drawing
property Tracing: Boolean; defines if graph is traceable
property VertSpacing: Double; defines vertical cell size of a graph grid
property XMaxValue: Integer; maximum value of axis X
property YMaxValue: Integer; maximum value of axis Y
property OnTrace: TTraceEvent; TTraceEvent = procedure(Sender: TObject; X, Y: Double) of object; This event will appear each time user moves mouse cursor on a component if Tracing is True. “X” and “Y” parameters are mouse cursor coordinates on a scale of graph.


There is another one sample, more powerful than GraphX. It names Graph and it’s an application.

SpeedTest

This program is for speed testing of TDataEditor component. You can regulate amount of formula execution. Like you’ll see, there is some difference between time of execution simple and complex formulas in program. Also program demonstrates script length and structure. Structure is displayed by four byte numbers and by one byte number.

Generator

This program is intended for testing the execution of huge formulas. “Generator” program generates and executes a long length mathematics formula:

To generate new text press F8 key, or choose Service|Generate menu item. You can write your own formulas directly in program and execute them by pressing F9 key. Elements count trackbar regulates approximate amount of elements in formula. Elements are numbers and functions. Embeddings power regulates the power of embeddings appearance in generated text. Unfortunately, it’s almost impossible to get a valid result of generated text if we use all registered functions (if amount of elements in formula is set to maximum). But we can use simplest functions to get a valid result with the longest formula. It’s possible to choose some functions sets in program.

DrawX

It draws picture using formulas which are on the left side of program. These formulas are in “Drawing.dat”. You can write there your own formulas. “X” function defines X-coordinate of current pixel, “Y” defines Y-coordinate of the pixel and “Index” is index of the pixel. For picture calculation we need at least three formulas, since we use 24-bit picture. Each time the program use three random formulas. There could appear a really interesting pictures!





Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment
new version
    Yuriy Pisarev (Sep 19 2002 5:38PM)

a new version of comonent is available by address: http://www.delphi3000.com/articles/article_3374.asp
Respond

Hard to download
    Richard Winston (Jun 24 2002 8:20PM)

From the description, it looks interesting. However, even though I have a high-speed internet connection, and the file is small, it looks like it is going to take about 7 hours to download. I think the problem is that the server has a slow connection. I suggest you submit it to the Delphi Super page where it will be possible for others to get it more quickly.
Respond

RE: Hard to download
Yuriy Pisarev (Jul 4 2002 11:39AM)

I've placed the archive on new web-site. Now you can go to www.ypdata.boom.ru and select file you need to download.
Respond














 
Sign up to consume product discounts for Bronze memberships !

read more


  Visit our Sponsor

 

  Community Ad of
A. B. Talal
 
   














 







     
  Copyright © 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)