TDAExpressionEvaluator

Overview

The TDAExpressionEvaluator class allows you to use Pascal Script expressions in a script-like approach.

For example: The TDADataTable class uses the TDAExpressionEvaluator in InternalOnCalcFields to do evaluations based on the values of the fields of a current record.

Use Case

You are free to use the functionality of the TDAExpressionEvaluator class for your own purposes. There are some examples of the TDAExpressionEvaluator's usage (please also refer to the TDAStdExpressionEvaluator Use case)):

 
program ExpressionEvaluatorDemo;

{$APPTYPE CONSOLE}

uses
  Classes, SysUtils, Math, Variants, uDAExpressionEvaluator;

type
  TEvaluationContext = class
  public
    procedure ValueSupplier(Sender: TDAExpressionEvaluator; const aIdentifier: string; out aValue: Variant);
    procedure FunctionSupplier (Sender: TDAExpressionEvaluator; const aIdentifier: string; const Args: array of Variant; out aValue: Variant);
  end;

{ TEvaluationContext }

procedure TEvaluationContext.FunctionSupplier(
  Sender: TDAExpressionEvaluator; const aIdentifier: string;
  const Args: array of Variant; out aValue: Variant);
begin
  if aIdentifier = 'FVAL' then begin
    aValue := FutureValue (Args [0], Args [1], Args [2], Args [3], Args [4]);
  end
  else if aIdentifier = 'DDB' then begin
    aValue := DoubleDecliningBalance (Args [0], Args [1], Args [2], Args [3]);
  end
  else if aIdentifier = 'DateToStr' then begin
    aValue := DateToStr (Args [0]);
  end
  else
    raise Exception.Create ('Unknown function ' + QuotedStr (aIdentifier));
end;

procedure TEvaluationContext.ValueSupplier(Sender: TDAExpressionEvaluator;
  const aIdentifier: string; out aValue: Variant);
var
  i     : integer;
  tmp   : TStrings;
begin
  if      aIdentifier = 'null'              then aValue := null
  else if aIdentifier = 'ptEndOfPeriod'     then aValue := ord (ptEndOfPeriod)
  else if aIdentifier = 'ptStartOfPeriod'   then aValue := ord (ptStartOfPeriod)
  else if aIdentifier [1] = '['             then begin
    tmp := TStringList.Create;
    try
      tmp.DelimitedText := Copy (aIdentifier, 2, Length (aIdentifier) - 2);
      aValue := VarArrayCreate([0, tmp.Count -1], varVariant);
      for i := 0 to tmp.Count -1 do 
        aValue [i] := tmp [i];
    finally
      tmp.Free;
    end;
  end
  else
    raise Exception.Create ('Unknown value ' + QuotedStr (aIdentifier));
end;

procedure doCalculation (evaluator : TDAExpressionEvaluator; const expression : string);
begin
  Write (QuotedStr (expression), ' -> ');
  WriteLn (QuotedStr (evaluator.Evaluate (expression)));
end;

procedure doDemo;
var
  evaluator   : TDAExpressionEvaluator;
  context     : TEvaluationContext;
begin
  evaluator := TDAExpressionEvaluator.Create;
  context := TEvaluationContext.Create;

  evaluator.OnGetValue := context.ValueSupplier;
  evaluator.OnUnknownFunctionCall := context.FunctionSupplier;

  doCalculation (evaluator, '((1 + 2) * 3) / 4'); //'2.25'
  doCalculation (evaluator, '31 > $1F'); //'False'
  doCalculation (evaluator, '15 % 4 { % is remainder    (mod)}'); //'3'
  doCalculation (evaluator, '1 in [1, 2, 3]');  //'True'
  doCalculation (evaluator, **abc` LIKE `*c**); //'True'
  doCalculation (evaluator, 'DateToStr (#12/31/2010#)');  //'31.12.2010'
  doCalculation (evaluator, 'FVAL (0.1, 1, 5, 1000, ptStartOfPeriod)'); //'-1105.5'
  doCalculation (evaluator, 'FVAL (0.1, 1, 5, 1000, ptEndOfPeriod)'); //'-1105'
  doCalculation (evaluator, 'DDB (1000, 100, 5, 1)'); //'400'

  evaluator.Free;
  context.Free;
end;

begin
  try
    doDemo;
  except on E : Exception do
    WriteLn ('Exception: ', E.Message);
  end;
end.

Location

  • Unit: uDAExpressionEvaluator.pas


 

constructor Create

Creates a new instance.

constructor Create

Evaluate

Performs Pascal Script from aString (see the Use Case).

function Evaluate(const aString: string): Variant

Parameters:

  • aString: Script text

FunctionList

Holds the set of known functions (see the Use Case).

property FunctionList: TDAEEFunctionList read

OnGetValue

Fires when the script engine encounters an unkown variable (see the Use Case).

property OnGetValue: TDAEEGetValue read write
delegate: procedure OnGetValue(Sender: TDAExpressionEvaluator; const aIdentifier: string; out aValue: Variant)

OnUnknownFunctionCall

Fires when the script engine encounters an unkown a call of an unknown function (not present in FunctionList)(see the Use Case).

property OnUnknownFunctionCall: TDAEEFunctionCall read write
delegate: procedure OnUnknownFunctionCall(Sender: TDAExpressionEvaluator; const aIdentifier: string; const Args: array of Variant; out aValue: Variant)

StringCaseInsensitive

Controls if Pascal rules for identifier name distinguishing is used (True) or not (False, default).

property StringCaseInsensitive: Boolean read write

UseTrueFalseinVariableName

Controls if the name of a variable (True and false) presents a Boolean value (False, default) or a variable (True).

property UseTrueFalseinVariableName: Boolean read write

UseWildcardsInEqual

Controls if a Like style (symbol "*") is used in string comparison (True) or not (False, default).

property UseWildcardsInEqual: Boolean read write

 

FunctionList

Holds the set of known functions (see the Use Case).

property FunctionList: TDAEEFunctionList read

StringCaseInsensitive

Controls if Pascal rules for identifier name distinguishing is used (True) or not (False, default).

property StringCaseInsensitive: Boolean read write

UseTrueFalseinVariableName

Controls if the name of a variable (True and false) presents a Boolean value (False, default) or a variable (True).

property UseTrueFalseinVariableName: Boolean read write

UseWildcardsInEqual

Controls if a Like style (symbol "*") is used in string comparison (True) or not (False, default).

property UseWildcardsInEqual: Boolean read write

 

constructor Create

Creates a new instance.

constructor Create

Evaluate

Performs Pascal Script from aString (see the Use Case).

function Evaluate(const aString: string): Variant

Parameters:

  • aString: Script text

 

OnGetValue

Fires when the script engine encounters an unkown variable (see the Use Case).

property OnGetValue: TDAEEGetValue read write
delegate: procedure OnGetValue(Sender: TDAExpressionEvaluator; const aIdentifier: string; out aValue: Variant)

OnUnknownFunctionCall

Fires when the script engine encounters an unkown a call of an unknown function (not present in FunctionList)(see the Use Case).

property OnUnknownFunctionCall: TDAEEFunctionCall read write
delegate: procedure OnUnknownFunctionCall(Sender: TDAExpressionEvaluator; const aIdentifier: string; const Args: array of Variant; out aValue: Variant)