/* PIA - Lenguajes Modernos de Programación * FACULTAD DE CIENCIAS FÍSICO MATEMÁTICAS * Luis Sebastián Martínez Vega - LCC */ #include "include/simplifier.hpp" #include "include/expressions.hpp" #include void Simplifier::simplifyChildren(Expression *root, Expression **left, Expression **right) const { *left = root->getLeft()->simplify(this); *right = root->getRight()->simplify(this); } // Reglas de simplificación. Expression *Simplifier::ruleEval(Expression *expr) const { Literal *left = dynamic_cast (expr->getLeft()); Literal *right = dynamic_cast (expr->getRight()); if(left != NULL && right != NULL) return new Literal(expr->eval()); return NULL; } Expression *Simplifier::ruleMultiplyByOne(MultiplicationExpression *expr) const { Literal *left = dynamic_cast (expr->getLeft()); Literal *right = dynamic_cast (expr->getRight()); if(left != NULL && left->getValue() == 1) return expr->getRight()->copy(); if(right != NULL && right->getValue() == 1) return expr->getLeft()->copy(); return NULL; } Expression *Simplifier::ruleDivideByOne(DivisionExpression *expr) const { Literal *right = dynamic_cast (expr->getRight()); if (right != NULL && right->getValue() == 1) return expr->getLeft()->copy(); return NULL; } Expression *Simplifier::ruleMultiplyByZero(MultiplicationExpression *expr) const { Literal *left = dynamic_cast (expr->getLeft()); Literal *right = dynamic_cast (expr->getRight()); if((left != NULL && left->getValue() == 0) || (right != NULL && right->getValue() == 0)) return new Literal(0); return NULL; } Expression *Simplifier::ruleZeroDivision(DivisionExpression *expr) const { Literal *left = dynamic_cast (expr->getLeft()); if(left != NULL && left->getValue() == 0) return new Literal(0); return NULL; } Expression *Simplifier::ruleOnePower(PowerExpression *expr) const { Literal *right = dynamic_cast (expr->getRight()); if(right != NULL && right->getValue() == 1) return expr->getLeft()->copy(); return NULL; } Expression *Simplifier::ruleZeroPower(PowerExpression *expr) const { Literal *right = dynamic_cast (expr->getRight()); if(right != NULL && right->getValue() == 0) return new Literal(1); return NULL; } Expression *Simplifier::addSubstractZero(Expression *expr) const { Literal *left = dynamic_cast (expr->getLeft()); Literal *right = dynamic_cast (expr->getRight()); if(left != NULL && left->getValue() == 0) return expr->getRight()->copy(); if(right != NULL && right->getValue() == 0) return expr->getLeft()->copy(); return NULL; } // Para variables y constantes sólo devolveremos una copia. Expression *Simplifier::visit(Variable *expr) const { return expr->copy(); } Expression *Simplifier::visit(Literal *expr) const { return expr->copy(); } // Para las funciones sólo simplificaremos su argumento. Expression *Simplifier::visit(Function *expr) const { Expression *simplified = expr->getArg()->simplify(this); return new Function(simplified, expr->getFunctionName()); } // Igual en negaciones. Expression *Simplifier::visit(NegationExpression *expr) const { Expression *simplified = expr->getRight()->simplify(this); return new NegationExpression(simplified); } Expression *Simplifier::visit(AddExpression *expr) const { Expression *left = NULL, *right = NULL, *simplified; AddExpression *root; simplifyChildren(expr, &left, &right); root = new AddExpression(left, right); /* Primera regla: vemos si se puede evaluar. (Los dos nodos hijos son números). */ simplified = ruleEval(root); if(simplified != NULL) { delete root; return simplified; } /* Segunda regla: vemos si uno de los nodos hijo es 0.*/ simplified = addSubstractZero(root); if(simplified != NULL) { delete root; return simplified; } /* No se pudo simplificar más: regresamos un nodo suma con los nodos hijo simplificados.*/ return root; } Expression *Simplifier::visit(SubExpression *expr) const { Expression *left = NULL, *right = NULL, *simplified; SubExpression *root; simplifyChildren(expr, &left, &right); root = new SubExpression(left, right); simplified = ruleEval(root); if(simplified != NULL) { delete root; return simplified; } simplified = addSubstractZero(root); if(simplified != NULL) { delete root; return simplified; } return root; } Expression *Simplifier::visit(MultiplicationExpression *expr) const { Expression *left = NULL, *right = NULL, *simplified; MultiplicationExpression *root; simplifyChildren(expr, &left, &right); root = new MultiplicationExpression(left, right); simplified = ruleEval(root); if(simplified != NULL) { delete root; return simplified; } simplified = ruleMultiplyByOne(root); if(simplified != NULL) { delete root; return simplified; } simplified = ruleMultiplyByZero(root); if(simplified != NULL) { delete root; return simplified; } return root; } Expression *Simplifier::visit(DivisionExpression *expr) const { Expression *left = NULL, *right = NULL, *simplified; DivisionExpression *root; simplifyChildren(expr, &left, &right); root = new DivisionExpression(left, right); simplified = ruleEval(root); if(simplified != NULL) { delete root; return simplified; } simplified = ruleDivideByOne(root); if(simplified != NULL) { delete root; return simplified; } simplified = ruleZeroDivision(root); if(simplified != NULL) { delete root; return simplified; } return root; } Expression *Simplifier::visit(PowerExpression *expr) const { Expression *left = NULL, *right = NULL, *simplified; PowerExpression *root; simplifyChildren(expr, &left, &right); root = new PowerExpression(left, right); simplified = ruleEval(root); if(simplified != NULL) { delete root; return simplified; } simplified = ruleOnePower(expr); if(simplified != NULL) { delete root; return simplified; } simplified = ruleZeroPower(root); if(simplified != NULL) { delete root; return simplified; } return root; } Expression *simplify(Expression *to_simplify) { Simplifier s; return to_simplify->simplify(&s); }