unit Diff;

interface

uses
  SysUtils, Classes, QGraphics, QControls, QForms,
  QDialogs, QStdCtrls, QGrids,CioinaEval;

type
  TfrmDiff = class(TForm)
    Memo1: TMemo;
    Label1: TLabel;
    Button1: TButton;
    Memo2: TMemo;
    Label2: TLabel;
    Edit1: TEdit;
    Label3: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure ExecuteErrorMesssage(Sender: TObject);
    procedure ParseErrorMesssage(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frmDiff: TfrmDiff;
  ev:TCioinaEval;
implementation
{$R *.dfm}
procedure TfrmDiff.ExecuteErrorMesssage(Sender: TObject);
var s,s1:string;
    i   :Integer;
begin
 with Sender as TCioinaEval do
 begin
  i:=Pos(':',ErrorMessageInfo);
  if i>0 then  s1:=' : '+Copy(ErrorMessageInfo,i+1,Length(ErrorMessageInfo)-i) else s1:='';
  if Length(s1)>256 then s1:=Copy(s1,1,256);
  s1:=LowerCase(s1);

  s:='';
  case MathException of
   EX_NONMATH:s:=' : NONMATH';
   EX_Overflow:s:=' : Overflow';
   EX_Underflow:s:=' : Underflow';
   EX_InvalidArgument:s:=' : InvalidArgument';
   EX_ZeroDivide:s:=' : ZeroDivide';
   EX_InvalidOp:s:=' : InvalidOp';
  end;

  case ErrorNumber of
   ERR_NO_MATH_EXPRESSION_WAS_PARSED:           Memo2.Text:=('No math expression was parsed');
   ERR_VARIABLES_AND_VALUES_ARE_DIFFERENT:      Memo2.Text:=('Variable count and value caunt do not corespond');
   ERR_MATH_EXPRESSIONS_ARRAY:                  Memo2.Text:=('Use ''DoVectorOfMathExpressions'' for calculate a vector of math expression');
   ERR_DEF_FUNCTION_STACK_OVERFLOW:             Memo2.Text:=('Stack overflow'+s1);
   ERR_SYSTEM_STACK_OVERFLOW:                   Memo2.Text:=('Fatal error'+s1);
   ERR_EXECUTE:                                 Memo2.Text:=('Execution error'+s1);
   ERR_MULTIPLY:                                Memo2.Text:=('Invalid value for *'+s1+s);
   ERR_DIVISION:                                if MathException=EX_ZeroDivide
                                                then Memo2.Text:=('Division by 0 ')
                                                else Memo2.Text:=('Invalid value for /'+s1+s);
   ERR_PLUS:                                    Memo2.Text:=('Invalid value for +'+s1+s);
   ERR_MINUS:                                   Memo2.Text:=('Invalid value for -'+s1+s);
   ERR_POWER:                                   Memo2.Text:=('Invalid value for ^'+s1+s);
   ERR_EQUAL:                                   Memo2.Text:=('Invalid value for ='+s1+s);
   1..FunCount:
               if s=''
               then Memo2.Text:=('Invalid number of function arguments for: '+ UpperCase(aStr[ErrorNumber]))
               else Memo2.Text:=('Invalid value for '+ UpperCase(aStr[ErrorNumber])+s1+s);
   else if (ErrorNumber>FunCount)and(ErrorNumber<=FunCount+UserFunctionCount)
        then
         if s=''
         then  Memo2.Text:=('Invalid number of function arguments for: '+UpperCase(UserFunctionName[ErrorNumber-FunCount-1]))
         else  Memo2.Text:=('Invalid value for '+ UpperCase(UserFunctionName[ErrorNumber-FunCount-1])+s1+s)
        else Memo2.Text:=(ErrorMessageInfo);
  end;
 end;
end;

procedure TfrmDiff.ParseErrorMesssage(Sender: TObject);
var s,s1:string;
    i:Integer;
begin
 with Sender as TCioinaEval do
 begin
  i:=Pos(':',ErrorMessageInfo);
  if i>0 then  s1:=' : '+Copy(ErrorMessageInfo,i+1,Length(ErrorMessageInfo)-i) else s1:='';
  if Length(s1)>256 then s1:=Copy(s1,1,256);
  s1:=LowerCase(s1);
  s:='';
  case MathException of
   EX_NONMATH:s:=' : NONMATH';
   EX_Overflow:s:=' : Overflow';
   EX_Underflow:s:=' : Underflow';
   EX_InvalidArgument:s:=' : InvalidArgument';
   EX_ZeroDivide:s:=' : ZeroDivide';
   EX_InvalidOp:s:=' : InvalidOp';
  end;

  case ErrorNumber of
   ERR_PARSE:                                   Memo2.Text:=('Invalid expression'+s1);
   ERR_BAD_SYNTAX:                              Memo2.Text:=('Syntax error'+s1);
   ERR_COMMA_SYNTAX:                            Memo2.Text:=('Comma syntax error'+s1);
   ERR_NO_MATH_EXPRESSION_WAS_PARSED:           Memo2.Text:=('No math expression was parsed');
   ERR_PARANTHESES_SYNTAX_ERROR:                Memo2.Text:=('Mismatched parenthesis');
   ERR_INVALID_DERIVATIVE_VARIABLE_NAME:        Memo2.Text:=('Invalid name of derivative variable'+s1);
   ERR_MATH_EXPRESSION_IS_EMPTY:                Memo2.Text:=('Mathematical expression is empty');
   ERR_IDENTIFIER_CANNOT_BE_EMPTY:              Memo2.Text:=('Identifier cannot be empty');
   ERR_IDENTIFIER_LENGTH:                       Memo2.Text:=('Identifier length is too long'+s1);
   ERR_NOT_PASCAL_IDENTIFIER:                   Memo2.Text:=('Invalid identifier'+s1);
   ERR_IDENTIFIER_CANNOT_BE_RESERVED_NAME:      Memo2.Text:=('Identifier cannot be a reserved name'+s1);
   ERR_IDENTIFIER_ALREADY_EXISTS:               Memo2.Text:=('Identifier already exists'+s1);
   ERR_DUBLICATING_USER_IDENTIFIER:             Memo2.Text:=('Dublicating user identifier'+s1);
   ERR_UNKNOWN_EXPRESSION:                      Memo2.Text:=('Unknown expression'+s1);
   ERR_UNKNOWN_FUNCTION:                        Memo2.Text:=('Undefined function'+s1);
   ERR_UNKNOWN_VARIABLE:                        Memo2.Text:=('Undefined variable'+s1);
   ERR_BAD_EXPONENTIAL_FORMAT:                  Memo2.Text:=('Invalid exponent value'+s1);
   ERR_SET_OriginalMathExpressionString_FALSE:  Memo2.Text:=('Set ''OriginalMathExpressionString'' to FALSE for differentiation or for Mathematica 4.1 export');
   ERR_MATH_EXPRESSION_WAS_ERASED:              Memo2.Text:=('Mathematical expression string was erased');
   ERR_USE_VerifySyntaxSemanticsAndDerivation:  Memo2.Text:=('Use ''VerifySyntaxSemanticsAndDerivation'' for differentiation');
   ERR_DERIVATIVE_EXPRESSION_WAS_ERASED:        Memo2.Text:=('Derivative expression string was erased');
   ERR_VARIABLES_AND_VALUES_ARE_DIFFERENT:      Memo2.Text:=('Variable count and value caunt do not corespond');
   ERR_MATH_EXPRESSIONS_ARRAY:                  Memo2.Text:=('Use ''DoVectorOfMathExpressions'' for calculate a vector of math expression');
   ERR_FUNCTION_NUMBER_MUST_BE_LESS:            Memo2.Text:=('Function number must be less'+s1);
   ERR_FUNCTION_ADDRESS_CANNOT_BE_NIL:          Memo2.Text:=('Function address cannot be nil'+s1);
   ERR_PROTECTED_EXPRESSION:                    Memo2.Text:=('Cannot set value for protected expression'+s1);
   ERR_DEF_FUNC_NAME:                           Memo2.Text:=('Invalid function name'+s1);
   ERR_DEF_FUNC_DUBLICATING:                    Memo2.Text:=('Dublicating defined function'+s1);
   ERR_DEF_FUNC_IMPLEMENTING:                   Memo2.Text:=('Defined function was not implimented'+s1);
   ERR_DEF_FUNC_ARG_COUNT:                      Memo2.Text:=('Invalid arguments number for defined function'+s1);
   ERR_DEF_FUNC_ARG_NAME:                       Memo2.Text:=('Invalid argument name for defined function'+s1);
   ERR_DEF_FUNC_ARG_DUBLICATING:                Memo2.Text:=('Dublicating argument name for defined function'+s1);
   ERR_MULTIPLY:                                Memo2.Text:=('Invalid value for *'+s1+s);
   ERR_DIVISION:                                if MathException=EX_ZeroDivide
                                                then Memo2.Text:=('Division by 0')
                                                else Memo2.Text:=('Invalid value for /'+s1+s);
   ERR_PLUS:                                    Memo2.Text:=('Invalid value for +'+s1+s);
   ERR_MINUS:                                   Memo2.Text:=('Invalid value for -'+s1+s);
   ERR_POWER:                                   Memo2.Text:=('Invalid value for ^'+s1+s);
   ERR_EQUAL:                                   Memo2.Text:=('Invalid value for ='+s1+s);
   1..FunCount:
               if s=''
               then Memo2.Text:=('Invalid number of function arguments for: '+ UpperCase(aStr[ErrorNumber]))
               else Memo2.Text:=('Invalid value for '+ UpperCase(aStr[ErrorNumber])+s1+s);
   else if (ErrorNumber>FunCount)and(ErrorNumber<=FunCount+UserFunctionCount)
        then
         if s=''
         then  Memo2.Text:=('Invalid number of function arguments for: '+UpperCase(UserFunctionName[ErrorNumber-FunCount-1]))
         else  Memo2.Text:=('Invalid value for '+ UpperCase(UserFunctionName[ErrorNumber-FunCount-1])+s1+s)
        else Memo2.Text:=(ErrorMessageInfo);
  end;
 end;
end;

procedure TfrmDiff.FormCreate(Sender: TObject);
begin
 DecimalSeparator:='.';
 ev:=TCioinaEval.Create;
 ev.OnVerifySyntaxSemanticsError:=ParseErrorMesssage;
 ev.OnDoMathExpressionError:=ExecuteErrorMesssage;
 frmDiff.Caption:='Differentiate '+TCioinaEval.OwnerInfo;
end;

procedure TfrmDiff.FormDestroy(Sender: TObject);
begin
 ev.Free;
end;

procedure TfrmDiff.Button1Click(Sender: TObject);
var s:string;
begin
 Memo2.Clear;
 s:=StringReplace(Trim(Memo1.Text),''#$D'','',[rfReplaceAll]);
 s:=StringReplace(Trim(s),''#$A'','',[rfReplaceAll]);
 ev.VerifySyntaxSemanticsAndDerivation(s,'',Edit1.Text,true);
 if not(ev.ErrorFlag)
 then Memo2.Text:=ev.DerivativeExpressionString
end;

end.
