summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--differentiator.cpp56
-rw-r--r--expression_base.cpp4
-rw-r--r--expressions.cpp39
-rw-r--r--include/differentiator.hpp20
-rw-r--r--include/expressions.hpp13
-rw-r--r--include/parser.hpp8
-rw-r--r--lexer.cpp2
-rw-r--r--main.cpp24
-rw-r--r--makefile4
-rw-r--r--parser.cpp49
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<Literal *>(expr->getRight());
-
- return new MultiplicationExpression(new MultiplicationExpression(c->copy(), new PowerExpression(expr->getLeft()->copy(), new Literal(c->getValue() - 1))),
+ Variable *x = dynamic_cast<Variable *>(expr->getLeft());
+
+ /* Si el valor izquierdo no es un número, entonces el derecho
+ lo es. */
+ if(c == NULL) {
+ c = dynamic_cast<Literal *>(expr->getLeft());
+ x = dynamic_cast<Variable *>(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 <cmath>
#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 <string>
-#include <vector>
+#include <deque>
#include "expressions.hpp"
#include "lexer.hpp"
@@ -13,11 +13,11 @@ class Parser{
private:
std::string text;
Lexer tokenizer;
- std::vector<Expression *> tree_stack;
+ std::deque<Expression *> 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;