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.