From 3f9e0da725963bb27aeccf852bf342a9cce2a34b Mon Sep 17 00:00:00 2001 From: HombreLaser Date: Sun, 17 Apr 2022 11:14:38 -0500 Subject: Añadido código de las reglas, solucionado errores. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- differentiator.cpp | 56 +++++++++++++++++++++++++++++++++++++--------- expression_base.cpp | 4 ++-- expressions.cpp | 39 +++++++++++++++++++++++++++++++- include/differentiator.hpp | 20 +++++++++-------- include/expressions.hpp | 13 +++++++++-- include/parser.hpp | 8 +++---- lexer.cpp | 2 ++ main.cpp | 24 +++++++++++++------- makefile | 4 ++-- parser.cpp | 49 +++++++++++++++++++++++----------------- 10 files changed, 161 insertions(+), 58 deletions(-) diff --git a/differentiator.cpp b/differentiator.cpp index 739c19a..d25366d 100644 --- a/differentiator.cpp +++ b/differentiator.cpp @@ -11,17 +11,17 @@ Differentiator::Differentiator() { } // Regla del constante. f(x)=c, f'(x)=0. -Expression *Differentiator::visit(Literal *expr) { +Expression *Differentiator::visit(Literal *expr) const { return new Literal(0); } // Regla de la variable. f(x)=x, f'(x)=1 -Expression *Differentiator::visit(Variable *expr) { +Expression *Differentiator::visit(Variable *expr) const { return new Literal(1); } // Reglas de funciones trigonométricas. -Expression *Differentiator::visit(Function *expr) { +Expression *Differentiator::visit(Function *expr) const { Expression *diff; switch (expr->getFunctionName()) { @@ -56,22 +56,58 @@ Expression *Differentiator::visit(Function *expr) { } } -Expression *Differentiator::visit(NegationExpression *expr) { - return new NegationExpression(expr->diff(this)); +// Regla de la negación. (La derivada del lado derecho.) +Expression *Differentiator::visit(NegationExpression *expr) const { + return new NegationExpression(expr->getRight()->diff(this)); } -Expression *Differentiator::visit(AddExpression *expr) { +// Regla de la suma (las derivadas del lado izquierdo y derecho). +Expression *Differentiator::visit(AddExpression *expr) const { return new AddExpression(expr->getLeft()->diff(this), expr->getRight()->diff(this)); } -Expression *Differentiator::visit(SubExpression *expr) { +/* Regla de la resta. Igual que la de la suma, pero restando los derivandos + en vez de sumarlos. */ +Expression *Differentiator::visit(SubExpression *expr) const { return new SubExpression(expr->getLeft()->diff(this), expr->getRight()->diff(this)); } // Regla de la potencia. f(x)=x^c, f'(x)=c*x^(c-1)}*f'(x). -Expression *Differentiator::visit(PowerExpression *expr) { +Expression *Differentiator::visit(PowerExpression *expr) const { Literal *c = dynamic_cast(expr->getRight()); - - return new MultiplicationExpression(new MultiplicationExpression(c->copy(), new PowerExpression(expr->getLeft()->copy(), new Literal(c->getValue() - 1))), + Variable *x = dynamic_cast(expr->getLeft()); + + /* Si el valor izquierdo no es un número, entonces el derecho + lo es. */ + if(c == NULL) { + c = dynamic_cast(expr->getLeft()); + x = dynamic_cast(expr->getRight()); + } + + return new MultiplicationExpression(new MultiplicationExpression(c->copy(), new PowerExpression(x->copy(), new Literal(c->getValue() - 1))), expr->getLeft()->diff(this)); } + +// Regla del producto. +Expression *Differentiator::visit(MultiplicationExpression *expr) const { + Expression *u = expr->getLeft(); + Expression *v = expr->getRight(); + + return new AddExpression(new MultiplicationExpression(u->copy(), v->diff(this)), new MultiplicationExpression(v->copy(), u->diff(this))); +} + +// Regla de la división. +Expression *Differentiator::visit(DivisionExpression *expr) const { + Expression *u = expr->getLeft(); + Expression *v = expr->getRight(); + + return new DivisionExpression(new SubExpression(new MultiplicationExpression(v->copy(), u->diff(this)), + new MultiplicationExpression(u->copy(), v->diff(this))), new PowerExpression(v->copy(), new Literal(2))); +} + +// Función wrapper. +Expression *deriv(Expression *to_deriv) { + Differentiator d; + + return to_deriv->diff(&d); +} diff --git a/expression_base.cpp b/expression_base.cpp index 2457571..3829715 100644 --- a/expression_base.cpp +++ b/expression_base.cpp @@ -11,11 +11,11 @@ using std::string; Expression::Expression(Expression *left, Expression *right, token_type type) : left(left), right(right), type(type) {} -const Expression *Expression::getLeft() const { +Expression *Expression::getLeft() { return left; } -const Expression *Expression::getRight() const { +Expression *Expression::getRight() { return right; } diff --git a/expressions.cpp b/expressions.cpp index c7d80e3..72e1e04 100644 --- a/expressions.cpp +++ b/expressions.cpp @@ -3,6 +3,7 @@ #include #include "include/lexer.hpp" #include "include/expressions.hpp" +#include "include/differentiator.hpp" using std::string, std::to_string; @@ -25,6 +26,10 @@ float Literal::eval(int arg) { return getValue(); } +Expression *Literal::diff(const Differentiator *d) { + return d->visit(this); +} + Expression *Literal::copy() { return new Literal(value); } @@ -39,7 +44,7 @@ Function::~Function() { delTree(); } -const Expression *Function::getArg() const { +Expression *Function::getArg() { return arg; } @@ -47,6 +52,10 @@ trig_functions Function::getFunctionName() const { return function_name; } +Expression *Function::diff(const Differentiator *d) { + return d->visit(this); +} + void Function::delTree() { delete arg; } @@ -123,6 +132,10 @@ float Variable::eval(int arg) { return arg; } +Expression *Variable::diff(const Differentiator *d) { + return d->visit(this); +} + Expression *Variable::copy() { return new Variable(name); } @@ -142,6 +155,10 @@ float AddExpression::eval(int arg) { return right_val + left_val; } +Expression *AddExpression::diff(const Differentiator *d) { + return d->visit(this); +} + Expression *AddExpression::copy() { return new AddExpression(left->copy(), right->copy()); } @@ -161,6 +178,10 @@ float SubExpression::eval(int arg) { return right_val - left_val; } +Expression *SubExpression::diff(const Differentiator *d) { + return d->visit(this); +} + Expression *SubExpression::copy() { return new SubExpression(left->copy(), right->copy()); } @@ -184,6 +205,10 @@ float NegationExpression::eval(int arg) { return -1 * expr_value; } +Expression *NegationExpression::diff(const Differentiator *d) { + return d->visit(this); +} + Expression *NegationExpression::copy() { return new NegationExpression(right->copy()); } @@ -203,6 +228,10 @@ float DivisionExpression::eval(int arg) { return left_val / right_val; } +Expression *DivisionExpression::diff(const Differentiator *d) { + return d->visit(this); +} + Expression *DivisionExpression::copy() { return new DivisionExpression(left->copy(), right->copy()); } @@ -223,6 +252,10 @@ float MultiplicationExpression::eval(int arg) { return left_val * right_val; } +Expression *MultiplicationExpression::diff(const Differentiator *d) { + return d->visit(this); +} + Expression *MultiplicationExpression::copy() { return new MultiplicationExpression(left->copy(), right->copy()); } @@ -242,6 +275,10 @@ float PowerExpression::eval(int arg) { return std::pow(left_val, right_val); } +Expression *PowerExpression::diff(const Differentiator *d) { + return d->visit(this); +} + Expression *PowerExpression::copy() { return new PowerExpression(left->copy(), right->copy()); } diff --git a/include/differentiator.hpp b/include/differentiator.hpp index f14f2d5..cef5211 100644 --- a/include/differentiator.hpp +++ b/include/differentiator.hpp @@ -14,15 +14,17 @@ private: Expression *ptr; public: Differentiator(); - Expression *visit(Literal *expr); - Expression *visit(Variable *expr); - Expression *visit(Function *expr); - Expression *visit(NegationExpression *expr); - Expression *visit(AddExpression *expr); - Expression *visit(SubExpression *expr); - Expression *visit(DivisionExpression *expr); - Expression *visit(MultiplicationExpression *expr); - Expression *visit(PowerExpression *expr); + Expression *visit(Literal *expr) const; + Expression *visit(Variable *expr) const; + Expression *visit(Function *expr) const; + Expression *visit(NegationExpression *expr) const; + Expression *visit(AddExpression *expr) const; + Expression *visit(SubExpression *expr) const; + Expression *visit(DivisionExpression *expr) const; + Expression *visit(MultiplicationExpression *expr) const; + Expression *visit(PowerExpression *expr) const; }; +Expression *deriv(Expression *to_deriv); + #endif /* DIFFERENTIATOR_H */ diff --git a/include/expressions.hpp b/include/expressions.hpp index 3191436..a293408 100644 --- a/include/expressions.hpp +++ b/include/expressions.hpp @@ -23,14 +23,14 @@ enum trig_functions { i_ctg }; -class Differentiator; // Forward declaration. +class Differentiator; // Forward declaration class Expression { public: Expression(Expression *left, Expression *right, token_type type); virtual ~Expression() = default; std::string getRepr(); - Expression *diff(const Differentiator *d); + virtual Expression *diff(const Differentiator *d) = 0; Expression *getLeft(); Expression *getRight(); virtual float eval(int arg) = 0; @@ -52,6 +52,7 @@ public: ~Literal(); int getValue(); float eval(int arg) override; + Expression *diff(const Differentiator *d) override; Expression *copy() override; protected: void setRepr() override; @@ -66,6 +67,7 @@ public: ~Function(); Expression *getArg(); float eval(int arg) override; + Expression *diff(const Differentiator *d) override; trig_functions getFunctionName() const; Expression *copy() override; protected: @@ -80,6 +82,7 @@ public: explicit Variable(char name); ~Variable(); float eval(int arg) override; + Expression *diff(const Differentiator *d) override; Expression *copy() override; protected: void setRepr() override; @@ -90,6 +93,7 @@ public: AddExpression(Expression *left, Expression *right); ~AddExpression(); float eval(int arg) override; + Expression *diff(const Differentiator *d) override; Expression *copy() override; }; @@ -99,6 +103,7 @@ public: ~SubExpression(); float eval(int arg) override; Expression *copy() override; + Expression *diff(const Differentiator *d) override; }; class NegationExpression : public Expression { @@ -107,6 +112,7 @@ public: ~NegationExpression(); float eval(int arg) override; Expression *copy() override; + Expression *diff(const Differentiator *d) override; protected: void setRepr() override; }; @@ -117,6 +123,7 @@ public: ~DivisionExpression(); float eval(int arg) override; Expression *copy() override; + Expression *diff(const Differentiator *d) override; }; class MultiplicationExpression : public Expression { @@ -125,6 +132,7 @@ public: ~MultiplicationExpression(); float eval(int arg) override; Expression *copy() override; + Expression *diff(const Differentiator *d) override; }; class PowerExpression : public Expression { @@ -133,6 +141,7 @@ public: ~PowerExpression(); float eval(int arg) override; Expression *copy() override; + Expression *diff(const Differentiator *d) override; }; #endif /* EXPRESSIONS_H */ diff --git a/include/parser.hpp b/include/parser.hpp index 567ef03..a4e11af 100644 --- a/include/parser.hpp +++ b/include/parser.hpp @@ -5,7 +5,7 @@ #ifndef PARSER_H #define PARSER_H #include -#include +#include #include "expressions.hpp" #include "lexer.hpp" @@ -13,11 +13,11 @@ class Parser{ private: std::string text; Lexer tokenizer; - std::vector tree_stack; + std::deque tree_queue; Token var{nil, "{}"}; void panic(); - Expression *popStack(); - Expression *newTree(token_type type); + Expression *popQueue(); + Expression *newTree(token_type type, Expression *left, Expression *right); void setText(std::string text); void parseExpr(); void parsePrimeExpr(); diff --git a/lexer.cpp b/lexer.cpp index a9734d1..26432ae 100644 --- a/lexer.cpp +++ b/lexer.cpp @@ -65,6 +65,8 @@ Token Lexer::match(){ else if(matchFunction("csc")) return Token(function, "csc"); else if(matchFunction("sec")) + return Token(function, "sec"); + else if(matchFunction("ctg")) return Token(function, "ctg"); } diff --git a/main.cpp b/main.cpp index 0d95196..fb8b8df 100644 --- a/main.cpp +++ b/main.cpp @@ -6,6 +6,7 @@ #include "include/parser.hpp" #include "include/expressions.hpp" #include "include/exceptions.hpp" +#include "include/differentiator.hpp" using std::string, std::cin, std::cout, std::getline, std::vector, std::begin, std::end, std::endl; @@ -13,16 +14,23 @@ using std::string, std::cin, std::cout, std::getline, std::vector, int main(){ string input; Parser parser; - + Expression *tree; + Expression *differential = NULL; getline(cin, input); - //try { - Expression *tree = parser.parse(input); - cout << tree->getRepr() << endl; - //} catch(const ParserException &e) { - //cout << e.showMsg() << endl; - //} - delete tree; + try { + tree = parser.parse(input); + cout << tree->getRepr() << '\n'; + } catch(const ParserException &e) { + cout << e.showMsg() << endl; + tree = NULL; + } + + if(tree != NULL) { + differential = deriv(tree); + delete tree; + delete differential; + } return 0; } diff --git a/makefile b/makefile index c8b4e2f..8ec96d2 100644 --- a/makefile +++ b/makefile @@ -1,7 +1,7 @@ CC=g++ CFLAGS= -std=gnu++17 -g -DEPS = include/lexer.hpp include/exceptions.hpp include/parser.hpp include/expressions.hpp -OBJ = expressions.o expression_base.o lexer.o exceptions.o parser.o main.o +DEPS = include/lexer.hpp include/exceptions.hpp include/parser.hpp include/expressions.hpp include/differentiator.hpp +OBJ = expressions.o differentiator.o expression_base.o lexer.o exceptions.o parser.o main.o %.o : %.cpp $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) diff --git a/parser.cpp b/parser.cpp index e1595f3..04f6a50 100644 --- a/parser.cpp +++ b/parser.cpp @@ -8,31 +8,31 @@ using std::string, std::stoi; // De haber habido un error vaciaremos la pila de expresiones. void Parser::panic() { - for(auto ptr = tree_stack.begin(); ptr != tree_stack.end(); ++ptr) + for(auto ptr = tree_queue.begin(); ptr != tree_queue.end(); ++ptr) delete *ptr; throw ParserException("Sintaxis incorrecta."); } -Expression *Parser::popStack() { - Expression *val = tree_stack.back(); - tree_stack.pop_back(); +Expression *Parser::popQueue() { + Expression *val = tree_queue.front(); + tree_queue.pop_front(); return val; } -Expression *Parser::newTree(token_type type) { +Expression *Parser::newTree(token_type type, Expression *left, Expression *right) { switch(type) { case sum: - return new AddExpression(popStack(), popStack()); + return new AddExpression(left, right); case substraction: - return new SubExpression(popStack(), popStack()); + return new SubExpression(left, right); case multiplication: - return new MultiplicationExpression(popStack(), popStack()); + return new MultiplicationExpression(left, right); case division: - return new DivisionExpression(popStack(), popStack()); + return new DivisionExpression(left, right); default: // Potencia. - return new PowerExpression(popStack(), popStack()); + return new PowerExpression(left, right); } } @@ -55,7 +55,7 @@ Expression *Parser::parse(string expr) { if(tokenizer.getCurrentToken().type != nil) panic(); - return popStack(); + return popQueue(); } void Parser::parseExpr() { @@ -65,6 +65,7 @@ void Parser::parseExpr() { void Parser::parsePrimeExpr() { token_type current; + Expression *left, *right; if(tokenizer.getCurrentToken().type == sum || tokenizer.getCurrentToken().type == substraction) { @@ -74,8 +75,10 @@ void Parser::parsePrimeExpr() { if(checkToken()) panic(); + left = popQueue(); parseTerm(); - tree_stack.push_back(newTree(current)); + right = popQueue(); + tree_queue.push_back(newTree(current, left, right)); parsePrimeExpr(); } } @@ -87,6 +90,7 @@ void Parser::parseTerm() { void Parser::parsePrimeTerm() { token_type current; + Expression *left, *right; if(tokenizer.getCurrentToken().type == multiplication || tokenizer.getCurrentToken().type == division) { @@ -96,8 +100,10 @@ void Parser::parsePrimeTerm() { if(checkToken()) panic(); + left = popQueue(); parsePower(); - tree_stack.push_back(newTree(current)); + right = popQueue(); + tree_queue.push_back(newTree(current, left, right)); parsePrimeTerm(); } } @@ -108,16 +114,19 @@ void Parser::parsePower() { } void Parser::parsePrimePower() { + Expression *left, *right; + if(tokenizer.getCurrentToken().type == power) { tokenizer.nextToken(); if(tokenizer.getCurrentToken().type != number) panic(); - tree_stack.push_back(new Literal(stoi(tokenizer.getCurrentToken().value))); + left = popQueue(); + right = new Literal(stoi(tokenizer.getCurrentToken().value)); tokenizer.nextToken(); - - tree_stack.push_back(newTree(power)); + + tree_queue.push_back(newTree(power, left, right)); parsePrimePower(); } } @@ -130,7 +139,7 @@ void Parser::parseFactor() { tokenizer.nextToken(); parseExpr(); - tree_stack.push_back(new NegationExpression(popStack())); + tree_queue.push_back(new NegationExpression(popQueue())); break; case left_parens: @@ -170,7 +179,7 @@ void Parser::parseFactor() { panic(); tokenizer.nextToken(); - tree_stack.push_back(new Function(popStack(), name)); + tree_queue.push_back(new Function(popQueue(), name)); break; case variable: @@ -181,12 +190,12 @@ void Parser::parseFactor() { else panic(); // Se introdujeron dos variables en la expresión. - tree_stack.push_back(new Variable(tokenizer.getCurrentToken().value[0])); + tree_queue.push_back(new Variable(tokenizer.getCurrentToken().value[0])); tokenizer.nextToken(); break; case number: - tree_stack.push_back(new Literal(stoi(tokenizer.getCurrentToken().value))); + tree_queue.push_back(new Literal(stoi(tokenizer.getCurrentToken().value))); tokenizer.nextToken(); break; -- cgit v1.2.3