unit uEvaluadorDeExpresionesSimple;


interface

uses
  Classes, SysUtils, FileUtil,
  SynHighlighterPas, SynEdit, SynCompletion,
  SynPluginSyncroEdit,
  Forms, Controls, Graphics, Dialogs, StdCtrls,
  ufuncionesbasicas,
  {$IFDEF CHEQUEO_MEM}
  heaptrc,
  {$ENDIF}
  uparseadorsupersimple;

type

  { TForm1 }

  TForm1 = class(TForm)
    btEvaluar: TButton;
    CrearDerivada: TButton;
    eExpresion: TMemo;
    eResultado: TMemo;
    SynCompletion1: TSynCompletion;
    SynEdit1: TSynEdit;
    SynFreePascalSyn1: TSynFreePascalSyn;
    SynPluginSyncroEdit1: TSynPluginSyncroEdit;
    procedure btEvaluarClick(Sender: TObject);
    procedure CrearDerivadaClick(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

  { TActor }

  TActor = class(TObject)
    a: double;
    constructor Create( a_: double );
    function LA_FUNCION( x1, x2: double ): double;
    procedure AddDefiniciones( aEvaluador:  TEvaluadorExpresionesSimples );
  end;

  TFuncFonFF =   function ( x1, x2: double ): double of object;

var
  Form1: TForm1;
  af: TFuncFonFF;

implementation

{$R *.lfm}

{ TActor }

constructor TActor.Create(a_: double);
begin
  inherited Create;
  a:= a_;
end;

function TActor.LA_FUNCION(x1, x2: double): double;
begin
  result:= x1 * x2 + a;
end;

procedure TActor.AddDefiniciones(aEvaluador: TEvaluadorExpresionesSimples);
var
  af: TFunc_F_FF_OfObject;
begin
  af:= TFunc_F_FF_OfObject.Create( 'MiFun', La_funcion );
  aEvaluador.CatalogoFuncionesDeUsuario.Add( af );
end;

{ TForm1 }

procedure TForm1.btEvaluarClick(Sender: TObject);
var
  s, st: string;
  tokens: TTokensLst;
  nodo: TNodoToken;
  k: integer;
  aEvaluador: TEvaluadorExpresionesSimples;
  exp: TExpresion;
  aVar: TVar;
  bVar: TVar;
  Actor1: TActor;

  res: double;
  VariablesNoDefinidas: string;

begin
  aEvaluador := TEvaluadorExpresionesSimples.Create;
  st := eExpresion.Text;
  s:= next_sentencia( st );
  exp:= nil;

  while s <> '' do
  begin

   tokens := aEvaluador.tokenParser(s);

   tokens.writeln;

   if exp <> nil then
     exp.free;
   exp := aEvaluador.GetFullExpresion(tokens);
   VariablesNoDefinidas:= aEvaluador.VariablesNoDefinidas;
   if VariablesNoDefinidas <> '' then
      ShowMessage('Variables no definidas: '+ VariablesNoDefinidas );

   tokens.Free;
   exp.evaluar;

   writeln( 's: ', s );
   writeln( 'r: ', exp.ValAsStr );
   s:= next_sentencia( st );
  end;



  aVar:= aEvaluador.FindVar( 'a' );
  bVar:= aEvaluador.FindVar( 'b' );
  eResultado.Lines.Add( 'a: '+aVar.ValAsStr );
  eResultado.Lines.Add( 'b: '+bVar.ValAsStr );

  aVar.val.val_F:=12.12;
  exp.evaluar;
  eResultado.Lines.Add( 'a: '+aVar.ValAsStr );
  eResultado.Lines.Add( 'b: '+bVar.ValAsStr );

  Actor1:= TActor.Create( 1.3 );

  af:= Actor1.LA_FUNCION;

  writeln( 'Hola, : ', af( 2, 3 ) );

  Actor1.AddDefiniciones( aEvaluador );
  s:= 'y:= MiFun( a, b );';
  if aEvaluador.Ejecutar( res, s ) then
    s:= FloatToStr( res )
  else
    s:= 'Error, la expresión no retorna un número real.';
  eResultado.Lines.add( 'y: '+ s );
  Actor1.Free;

  exp.Free;
  aEvaluador.Free;

end;

procedure TForm1.CrearDerivadaClick(Sender: TObject);
var
  s, st: string;
  tokens: TTokensLst;
  nodo: TNodoToken;
  k: integer;
  aEvaluador: TEvaluadorExpresionesSimples;
  exp: TExpresion;
  derivadas:TExprLst;
  variable: TNodoToken;
  aVar: TVar;
  bVar: TVar;
  Actor1: TActor;

  res: double;
begin
  aEvaluador := TEvaluadorExpresionesSimples.Create;
  st := eExpresion.Text;
  s:= next_sentencia( st );
  exp:= nil;

  derivadas:=TExprLst.Create;

  // derivaremos con respecto a x
  variable:=TNodoToken.Create(TTK_Var,'x');

  while s <> '' do
  begin
    tokens := aEvaluador.tokenParser(s);
    if exp <> nil then
      exp.free;
    exp := aEvaluador.GetFullExpresion(tokens);
    tokens.Free;
    derivadas.lst.add(exp.crearDerivada(variable));
    s:= next_sentencia( st );
  end;

  writeln(derivadas.Serialize2);
  writeln();
  writeln(exp.Serialize2);

  exp.Free;
  derivadas.Free;
  variable.Free;
  aEvaluador.Free;

end;



initialization
    {$IFDEF CHEQUEO_MEM}
  if FileExists('C:\basura\heap.trc') then
    DeleteFile('C:\basura\heap.trc');
  heaptrc.SetHeapTraceOutput('C:\basura\heap.trc');
   {$ENDIF}

end.

