This repository has been archived on 2024-12-25. You can view files and clone it, but cannot push or open issues or pull requests.
2023-06-20 21:52:24 +03:00

96 lines
2.5 KiB
ObjectPascal

type
Expr = class
end;
V = auto class(Expr)
name: string;
procedure Deconstruct(var name: string);
begin
name := Self.name
end;
end;
Cons = auto class(Expr)
r: real;
procedure Deconstruct(var r: real);
begin
r := Self.r
end;
end;
Add = auto class(Expr)
left,right: Expr;
procedure Deconstruct(var l,r: Expr);
begin
l := left; r := right;
end;
end;
Mult = auto class(Expr)
left,right: Expr;
procedure Deconstruct(var l,r: Expr);
begin
l := left; r := right;
end;
end;
Neg = auto class(Expr)
ex: Expr;
procedure Deconstruct(var ex: Expr);
begin
ex := Self.ex
end;
end;
function NegC(ex: Expr) := new Neg(ex);
function ConsC(r: real) := new Cons(r);
function AddC(ex1,ex2: Expr) := new Add(ex1,ex2);
function MultC(ex1,ex2: Expr) := new Mult(ex1,ex2);
function VC(name: string) := new V(name);
function Simplify(e: Expr): Expr; forward;
function Simplify1(e: Expr): Expr;
begin
match e with
Mult(Cons(c),Cons(c1)): Result := ConsC(c*c1);
Mult(Cons(c),ex) when c=1: Result := Simplify(ex);
Mult(Cons(c),ex) when c=0: Result := ConsC(0);
Add(Cons(c),ex) when c=0: Result := Simplify(ex);
Add(ex,Cons(c)) when c=0: Result := Simplify(ex);
Add(Cons(c),Cons(c1)): Result := ConsC(c+c1);
Add(Cons(c),ex): Result := AddC(ex,ConsC(c)); // константы - в хвосте!
Mult(Cons(c),ex): Result := MultC(ex,ConsC(c));
Add(Add(ex,Cons(c)),Cons(c1)): Result := AddC(ex,ConsC(c+c1)); // ассоциативность
Mult(Mult(ex,Cons(c)),Cons(c1)): Result := MultC(ex,ConsC(c*c1)); // ассоциативность
Neg(Cons(c)): Result := ConsC(-c);
else Result := e;
end;
end;
function Simplify(e: Expr): Expr;
begin
match e with
Mult(e1,e2): Result := Simplify1(MultC(Simplify(e1),Simplify(e2)));
Add(e1,e2): Result := Simplify1(AddC(Simplify(e1),Simplify(e2)));
Neg(e1): Result := Simplify1(NegC(Simplify(e1)));
else Result := e;
end;
end;
function Str(e: Expr): string;
begin
match e with
Mult(l,r): Result := Str(l) + ' * ' + Str(r);
Add(l,r): Result := Str(l) + ' + ' + Str(r);
Neg(n): Result := '-' + Str(n);
Cons(c): Result := c.ToString;
V(x): Result := x;
end;
end;
begin
// 0 + 1*x + 1 + 0*(2 + a) + 2
var r: Expr := AddC(ConsC(1),AddC(MultC(ConsC(1),VC('x')),ConsC(1)));
r := AddC(r,MultC(ConsC(0),AddC(ConsC(2),VC('a'))));
r := AddC(r,ConsC(2));
Str(r).Println;
r := Simplify(r);
Str(r).Println;
end.