#include #include #include #include #include #include #include #include #include "expression_parser.hpp" #include "expression_lexer.hpp" extern "C" { #include } //#include "simplify/rules.h" int poincare_expression_yyparse(Poincare::Expression ** expressionOutput); namespace Poincare { static Expression::CircuitBreaker sCircuitBreaker = nullptr; #include Expression * Expression::parse(char const * string) { if (string[0] == 0) { return nullptr; } YY_BUFFER_STATE buf = poincare_expression_yy_scan_string(string); Expression * expression = 0; if (poincare_expression_yyparse(&expression) != 0) { // Parsing failed because of invalid input or memory exhaustion if (expression != nullptr) { delete expression; expression = nullptr; } } poincare_expression_yy_delete_buffer(buf); if (expression) { expression->setParent(nullptr, true); } return expression; } void Expression::setCircuitBreaker(CircuitBreaker cb) { sCircuitBreaker = cb; } bool Expression::shouldStopProcessing() { if (sCircuitBreaker == nullptr) { return false; } return sCircuitBreaker(); } ExpressionLayout * Expression::createLayout(FloatDisplayMode floatDisplayMode, ComplexFormat complexFormat) const { switch (floatDisplayMode) { case FloatDisplayMode::Default: switch (complexFormat) { case ComplexFormat::Default: return privateCreateLayout(Preferences::sharedPreferences()->displayMode(), Preferences::sharedPreferences()->complexFormat()); default: return privateCreateLayout(Preferences::sharedPreferences()->displayMode(), complexFormat); } default: switch (complexFormat) { case ComplexFormat::Default: return privateCreateLayout(floatDisplayMode, Preferences::sharedPreferences()->complexFormat()); default: return privateCreateLayout(floatDisplayMode, complexFormat); } } } void Expression::sort() { if (this->type() == Type::Complex) { // TODO: this case should be useless once complex is a leaf expression! return; } for (int i = 0; i < numberOfOperands(); i++) { ((Expression *)operand(i))->sort(); // TODO: implement an editable operand? } // Second, sort all children together if the expression is commutative if (!isCommutative()) { return; } // TODO: use a heap sort instead of a buble sort for (int i = numberOfOperands()-1; i > 0; i--) { bool isSorted = true; for (int j = 0; j < numberOfOperands()-1; j++) { if (operand(j)->comparesTo(operand(j+1)) > 0) { swapOperands(j, j+1); isSorted = false; } } if (isSorted) { return; } } } int Expression::comparesTo(const Expression * e) const { if (this->nodeComparesTo(e) != 0) { return this->nodeComparesTo(e); } for (int i = 0; i < this->numberOfOperands(); i++) { // The NULL node is the least node type. if (e->numberOfOperands() <= i) { return 1; } if (this->operand(i)->comparesTo(e->operand(i)) != 0) { return this->operand(i)->comparesTo(e->operand(i)); } } // The NULL node is the least node type. if (e->numberOfOperands() > numberOfOperands()) { return -1; } return 0; } template Evaluation * Expression::evaluate(Context& context, AngleUnit angleUnit) const { switch (angleUnit) { case AngleUnit::Default: return privateEvaluate(T(), context, Preferences::sharedPreferences()->angleUnit()); default: return privateEvaluate(T(), context, angleUnit); } } template T Expression::approximate(Context& context, AngleUnit angleUnit) const { Evaluation * evaluation = evaluate(context, angleUnit); T result = evaluation->toScalar(); delete evaluation; return result; } template T Expression::approximate(const char * text, Context& context, AngleUnit angleUnit) { Expression * exp = parse(text); if (exp == nullptr) { return NAN; } Evaluation * evaluation = exp->evaluate(context, angleUnit); delete exp; T result = evaluation->toScalar(); delete evaluation; return result; } /*Expression * Expression::simplify() const { // pre-process: // - remonter les noeuds de matrices en root ou les faire disparaitre // - division and subtraction are turned into multiplication and addition // - oppostive are turned into multiplication // - associative expression are collapsed // Simplify: // - see Romain notes // Post-process: // - pattern a+(-1)*b -> a-b // - pattern a*b^(-1) -> a/b // - pattern (-1)*a -> -a * We make sure that the simplification is deletable. * Indeed, we don't want an expression with some parts deletable and some not * // If we have a leaf node nothing can be simplified. if (this->numberOfOperands()==0) { return this->clone(); } Expression * result = this->clone(); Expression * tmp = nullptr; bool simplification_pass_was_useful = true; while (simplification_pass_was_useful) { * We recursively simplify the children expressions. * Note that we are sure to get the samne number of children as we had before * Expression ** simplifiedOperands = new Expression * [result->numberOfOperands()]; for (int i = 0; i < result->numberOfOperands(); i++) { simplifiedOperands[i] = result->operand(i)->simplify(); } * Note that we don't need to clone the simplified children because they are * already cloned before. * tmp = result->cloneWithDifferentOperands(simplifiedOperands, result->numberOfOperands(), false); delete result; result = tmp; // The table is no longer needed. delete [] simplifiedOperands; simplification_pass_was_useful = false; for (int i=0; isimplify(result); if (simplified != nullptr) { simplification_pass_was_useful = true; delete result; result = simplified; break; } } } return result; }*/ template T Expression::epsilon() { static T epsilon = sizeof(T) == sizeof(double) ? 1E-15 : 1E-7f; return epsilon; } int Expression::nodeComparesTo(const Expression * e) const { if (e->type() == this->type()) { return 0; } if (e->type() > this->type()) { return 1; } return -1; } void Expression::setParent(Expression * parent, bool deep) { if (this == parent) { // TODO: this case should be useless once complex is a leaf expression! return; } m_parent = parent; if (deep) { for (int i=0; isetParent(this, deep); } } } } template Poincare::Evaluation * Poincare::Expression::evaluate(Context& context, AngleUnit angleUnit) const; template Poincare::Evaluation * Poincare::Expression::evaluate(Context& context, AngleUnit angleUnit) const; template double Poincare::Expression::approximate(char const*, Poincare::Context&, Poincare::Expression::AngleUnit); template float Poincare::Expression::approximate(char const*, Poincare::Context&, Poincare::Expression::AngleUnit); template double Poincare::Expression::approximate(Poincare::Context&, Poincare::Expression::AngleUnit) const; template float Poincare::Expression::approximate(Poincare::Context&, Poincare::Expression::AngleUnit) const; template double Poincare::Expression::epsilon(); template float Poincare::Expression::epsilon();