File indexing completed on 2024-04-28 03:40:41
0001 /************************************************************************************* 0002 * Copyright (C) 2007 by Aleix Pol <aleixpol@kde.org> * 0003 * * 0004 * This program is free software; you can redistribute it and/or * 0005 * modify it under the terms of the GNU General Public License * 0006 * as published by the Free Software Foundation; either version 2 * 0007 * of the License, or (at your option) any later version. * 0008 * * 0009 * This program is distributed in the hope that it will be useful, * 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0012 * GNU General Public License for more details. * 0013 * * 0014 * You should have received a copy of the GNU General Public License * 0015 * along with this program; if not, write to the Free Software * 0016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 0017 *************************************************************************************/ 0018 #include "expression.h" 0019 0020 #include <QDomElement> 0021 #include <QCoreApplication> 0022 0023 #include "explexer.h" 0024 #include "expressionparser.h" 0025 #include "container.h" 0026 #include "value.h" 0027 #include "vector.h" 0028 #include "variable.h" 0029 #include "stringexpressionwriter.h" 0030 #include "htmlexpressionwriter.h" 0031 #include "mathmlexpressionwriter.h" 0032 #include "mathmlpresentationexpressionwriter.h" 0033 #include "list.h" 0034 #include "analitzautils.h" 0035 #include "apply.h" 0036 #include "customobject.h" 0037 0038 #include "matrix.h" 0039 0040 using namespace Analitza; 0041 0042 class Expression::ExpressionPrivate : public QSharedData 0043 { 0044 public: 0045 ExpressionPrivate(Object* t) : m_tree(t) {} 0046 0047 bool canAdd(const Object* where, const Object* branch); 0048 bool check(const Container* c); 0049 bool check(const Apply* c); 0050 0051 Object* branch(const QDomElement& elem); 0052 0053 template <class T, class Tcontained = Object> 0054 T* addElements(T* v, const QDomElement* elem) 0055 { 0056 QDomNode n = elem->firstChild(); 0057 while(!n.isNull()) { 0058 if(n.isElement()) { 0059 Object* ob= branch(n.toElement()); //TODO: We should do that better 0060 0061 if(ob && canAdd(v, ob)) { 0062 v->appendBranch(static_cast<Tcontained*>(ob)); 0063 } else { 0064 // delete ob; 0065 delete v; 0066 return nullptr; 0067 } 0068 } 0069 n = n.nextSibling(); 0070 } 0071 return v; 0072 } 0073 static List* listFromString(const QString& text); 0074 0075 Object* m_tree; 0076 QStringList m_err; 0077 }; 0078 0079 Expression::Expression() 0080 : d(new ExpressionPrivate(nullptr)) 0081 {} 0082 0083 Expression::Expression(Object * o) 0084 : d(new ExpressionPrivate(o)) 0085 {} 0086 0087 Expression::Expression(const Cn & e) 0088 : d(new ExpressionPrivate(nullptr)) 0089 { 0090 d->m_tree = new Cn(e); 0091 } 0092 0093 Expression::Expression(const Expression & e) 0094 : d(new ExpressionPrivate(nullptr)) 0095 { 0096 d->m_err=e.d->m_err; 0097 if(e.isCorrect() && e.d->m_tree) 0098 d->m_tree = e.d->m_tree->copy(); 0099 } 0100 0101 Expression::Expression(const QString & exp, bool mathml) 0102 : d(new ExpressionPrivate(nullptr)) 0103 { 0104 if(mathml) 0105 setMathML(exp); 0106 else 0107 setText(exp); 0108 } 0109 0110 Expression::~Expression() 0111 { 0112 Q_ASSERT(d); 0113 delete d->m_tree; 0114 } 0115 0116 Expression Expression::operator=(const Expression & e) 0117 { 0118 if(this != &e) { 0119 delete d->m_tree; 0120 0121 if(e.d->m_tree) 0122 d->m_tree = e.d->m_tree->copy(); 0123 else 0124 d->m_tree=nullptr; 0125 0126 d->m_err = e.d->m_err; 0127 } 0128 return *this; 0129 } 0130 0131 bool Expression::setText(const QString & exp) 0132 { 0133 if(exp.isEmpty()) { 0134 delete d->m_tree; 0135 d->m_tree = nullptr; 0136 return true; 0137 } 0138 d->m_err.clear(); 0139 ExpLexer lex(exp); 0140 ExpressionParser parser; 0141 m_comments = parser.comments(); 0142 bool corr=parser.parse(&lex); 0143 0144 if(corr) 0145 setMathML(parser.mathML()); 0146 else 0147 d->m_err << parser.error(); 0148 0149 return corr; 0150 } 0151 0152 bool Expression::ExpressionPrivate::check(const Apply* c) 0153 { 0154 bool ret=true; 0155 Operator op=c->firstOperator(); 0156 Operator::OperatorType opt=op.operatorType(); 0157 int cnt=c->countValues(); 0158 0159 if(((op.nparams()<0 && cnt<=1) || (op.nparams()>-1 && cnt!=op.nparams())) && (opt!=Operator::minus || cnt==0) && opt!=Operator::function) 0160 { 0161 if(op.nparams()<0) 0162 m_err << QCoreApplication::tr("<em>%1</em> needs at least 2 parameters").arg(op.toString()); 0163 else 0164 m_err << QCoreApplication::tr("<em>%1</em> requires %2 parameters") 0165 .arg(op.toString()) 0166 .arg(op.nparams()); 0167 ret=false; 0168 } 0169 0170 if(op.isBounded() && !c->hasBVars()) { 0171 m_err << QCoreApplication::tr("Missing boundary for '%1'").arg(op.toString()); 0172 } else if(!op.isBounded() && c->hasBVars()) { 0173 m_err << QCoreApplication::tr("Unexpected bounding for '%1'").arg(op.toString()); 0174 } 0175 0176 if(op.isBounded() && op!=Operator::diff) { 0177 if(!(c->ulimit() && c->dlimit()) && !c->domain()) { 0178 m_err << QCoreApplication::tr("<em>%1</em> missing bounds on '%2'").arg(c->bvarStrings().join(QStringLiteral(" ")), op.toString()); 0179 } 0180 } 0181 0182 return ret; 0183 } 0184 0185 List* Expression::ExpressionPrivate::listFromString(const QString& text) 0186 { 0187 List* l = new List; 0188 for(int i=0; i<text.size(); ++i) 0189 l->appendBranch(new Cn(text[i])); 0190 return l; 0191 } 0192 0193 bool Expression::ExpressionPrivate::check(const Container* c) 0194 { 0195 bool ret=true; 0196 0197 switch(c->containerType()) { 0198 case Container::declare: 0199 if(c->m_params.size()!=2) { 0200 m_err << QCoreApplication::tr("Wrong declare"); 0201 ret=false; 0202 } 0203 break; 0204 default: 0205 //should never do anything here, 0206 break; 0207 } 0208 0209 if(c->isEmpty() && c->containerType()!=Container::math) { 0210 m_err << QCoreApplication::tr("Empty container: %1").arg(c->tagName()); 0211 ret=false; 0212 } 0213 0214 return ret; 0215 } 0216 0217 bool Expression::ExpressionPrivate::canAdd(const Object* where, const Object* branch) 0218 { 0219 Q_ASSERT(where && branch); 0220 bool correct=true; 0221 0222 if(branch->type()==Object::container) { 0223 const Container* cBranch=static_cast<const Container*>(branch); 0224 if(cBranch->containerType()==Container::piece || cBranch->containerType()==Container::otherwise) { 0225 bool isPiecewise=where->type()==Object::container 0226 && static_cast<const Container*>(where)->containerType()==Container::piecewise; 0227 if(!isPiecewise) { 0228 m_err << QCoreApplication::translate("there was a conditional outside a condition structure", 0229 "We can only have conditionals inside piecewise structures."); 0230 correct=false; 0231 } 0232 } else if(cBranch->containerType()==Container::bvar && (where->isContainer() || where->isApply())) { 0233 //we don't want 2 bvar in the same element 0234 QStringList bvars; 0235 if(where->isContainer()) 0236 bvars=static_cast<const Container*>(where)->bvarStrings(); 0237 else 0238 bvars=static_cast<const Apply*>(where)->bvarStrings(); 0239 0240 const Ci* var= static_cast<const Ci*>(cBranch->m_params.first()); 0241 0242 if(bvars.contains(var->name())) { 0243 correct=false; 0244 m_err << QCoreApplication::tr("Cannot have two parameters with the same name like '%1'.").arg(var->name()); 0245 } 0246 } 0247 } 0248 0249 if(where->type()==Object::container) { 0250 const Container* cWhere=static_cast<const Container*>(where); 0251 0252 if(cWhere->containerType()==Container::piecewise) { 0253 bool isCondition=false; 0254 if(branch->type()==Object::container) { 0255 Container::ContainerType ct=static_cast<const Container*>(branch)->containerType(); 0256 isCondition=ct==Container::piece || ct==Container::otherwise; 0257 0258 if(cWhere->extractType(Container::otherwise)) { 0259 m_err << QCoreApplication::translate("this is an error message. otherwise is the else in a mathml condition", 0260 "The <em>otherwise</em> parameter should be the last one"); 0261 correct=false; 0262 } 0263 0264 } 0265 0266 if(!isCondition) { 0267 m_err << QCoreApplication::translate("there was an element that was not a conditional inside a condition", 0268 "%1 is not a proper condition inside the piecewise").arg(branch->toString()); 0269 correct=false; 0270 } 0271 0272 } else if(cWhere->containerType()==Container::declare && cWhere->isEmpty() && branch->type()!=Object::variable) { 0273 m_err << QCoreApplication::tr("We can only declare variables"); 0274 correct=false; 0275 } 0276 0277 if(cWhere->containerType()==Container::bvar) { 0278 if(branch->type()!=Object::variable) { 0279 m_err << QCoreApplication::tr("We can only have bounded variables"); 0280 correct=false; 0281 } 0282 } 0283 } else 0284 if(where->type()==Object::matrix) { 0285 if(branch->type()==Object::matrixrow) { 0286 const Matrix *matrix = static_cast<const Matrix*>(where); 0287 const MatrixRow *matrixrow = static_cast<const MatrixRow*>(branch); 0288 0289 if (matrixrow->size() == 0) { 0290 m_err << QCoreApplication::tr("Do not want empty matrixrow elements"); 0291 correct=false; 0292 } 0293 0294 if (matrix->rowCount() != 0) 0295 if (static_cast<MatrixRow*>(matrix->rows().at(0))->size() != matrixrow->size()) { 0296 m_err << QCoreApplication::tr("All matrixrow elements must have the same size"); 0297 correct=false; 0298 } 0299 } else { 0300 m_err << QCoreApplication::tr("The matrix must contain only matrixrow elements"); 0301 correct=false; 0302 } 0303 } 0304 0305 Q_ASSERT(correct || !m_err.isEmpty()); 0306 0307 return correct; 0308 } 0309 0310 static void variableDepth(Object* o, int& next, const QMap<QString, int>& scope, const Object* parent=nullptr) 0311 { 0312 Q_ASSERT(o); 0313 switch(o->type()) { 0314 case Object::variable: { 0315 Ci *i = (Ci*) o; 0316 QMap<QString, int>::const_iterator it = scope.constFind(i->name()); 0317 i->setBVarDepth(it==scope.constEnd() 0318 ? -1 0319 : *it); 0320 0321 } break; 0322 case Object::vector: { 0323 Vector *v=(Vector*) o; 0324 for(Vector::const_iterator it=v->constBegin(); it!=v->constEnd(); ++it) 0325 variableDepth(*it, next, scope); 0326 } break; 0327 case Object::matrix: { 0328 Matrix *v=(Matrix*) o; 0329 for(Matrix::const_iterator it=v->constBegin(); it!=v->constEnd(); ++it) 0330 variableDepth(*it, next, scope); 0331 } break; 0332 case Object::matrixrow: { 0333 MatrixRow *v=(MatrixRow*) o; 0334 for(MatrixRow::const_iterator it=v->constBegin(); it!=v->constEnd(); ++it) 0335 variableDepth(*it, next, scope); 0336 } break; 0337 case Object::list: { 0338 List *v=(List*) o; 0339 for(List::const_iterator it=v->constBegin(); it!=v->constEnd(); ++it) 0340 variableDepth(*it, next, scope); 0341 0342 } break; 0343 case Object::container: { 0344 const Container *c = (const Container*) o; 0345 0346 QMap<QString, int> newScope=scope; 0347 0348 Container::const_iterator it=c->m_params.constBegin(), itEnd=c->m_params.constEnd(); 0349 if(c->containerType()==Container::declare) { 0350 Ci* var = static_cast<Ci*>(*it); 0351 ++it; 0352 0353 if((*it)->isContainer() && static_cast<const Container*>(*it)->containerType()==Container::lambda) { 0354 newScope.insert(var->name(), next); 0355 var->setBVarDepth(next++); 0356 } 0357 } else if(c->containerType()==Container::lambda && 0358 !(parent && parent->isContainer() && static_cast<const Container*>(parent)->containerType()==Container::declare)) { 0359 ++next; 0360 } 0361 0362 foreach(Ci* bvar, c->bvarCi()) { 0363 newScope.insert(bvar->name(), next); 0364 bvar->setBVarDepth(next++); 0365 } 0366 0367 for(; it!=itEnd; ++it) 0368 variableDepth(*it, next, newScope, c); 0369 0370 } break; 0371 case Object::apply: { 0372 const Apply *c = (const Apply*) o; 0373 0374 Object* ul=c->ulimit(), *dl=c->dlimit(), *dn=c->domain(); 0375 0376 //uplimit and downlimit are in the parent scope 0377 if(ul) variableDepth(ul, next, scope); 0378 if(dl) variableDepth(dl, next, scope); 0379 if(dn) variableDepth(dn, next, scope); 0380 0381 QMap<QString, int> newScope=scope; 0382 0383 foreach(Ci* bvar, c->bvarCi()) { 0384 newScope.insert(bvar->name(), next); 0385 bvar->setBVarDepth(next++); 0386 } 0387 0388 Apply::const_iterator it = c->firstValue(), itEnd=c->constEnd(); 0389 for(; it!=itEnd; ++it) { 0390 int n=next; 0391 variableDepth(*it, n, newScope, c); 0392 } 0393 } break; 0394 case Object::none: 0395 case Object::value: 0396 case Object::custom: 0397 case Object::oper: 0398 break; 0399 } 0400 } 0401 0402 void Expression::computeDepth(Object* o) 0403 { 0404 if(o) { 0405 QMap<QString, int> scope; 0406 int next=0; 0407 variableDepth(o, next, scope); 0408 } 0409 } 0410 0411 bool Expression::setMathML(const QString & s) 0412 { 0413 d->m_err.clear(); 0414 delete d->m_tree; 0415 0416 QDomDocument doc; 0417 0418 if (!doc.setContent(s)) { 0419 d->m_err << QCoreApplication::tr("Error while parsing: %1").arg(s); 0420 return false; 0421 } 0422 0423 d->m_tree = d->branch(doc.documentElement()); 0424 0425 computeDepth(d->m_tree); 0426 0427 return d->m_tree; 0428 } 0429 0430 Object* Expression::ExpressionPrivate::branch(const QDomElement& elem) 0431 { 0432 Cn *num; Operator *op; 0433 Object* ret=nullptr; 0434 0435 if(elem.tagName()==QLatin1String("cs")) 0436 ret=listFromString(elem.text()); 0437 else switch(whatType(elem.tagName())) { 0438 case Object::container: { 0439 Container::ContainerType t = Container::toContainerType(elem.tagName()); 0440 0441 if(t!=Container::none) { 0442 Container* c=addElements<Container>(new Container(t), &elem); 0443 0444 if(c && !check(c)) { 0445 delete c; 0446 c=nullptr; 0447 } 0448 ret = c; 0449 } else 0450 m_err << QCoreApplication::translate("An error message", "Container unknown: %1").arg(elem.tagName()); 0451 } break; 0452 case Object::value: 0453 num= new Cn(0.); 0454 if(!num->setValue(elem)) { 0455 delete num; 0456 m_err<< QCoreApplication::tr("Cannot codify the %1 value.").arg(elem.text()); 0457 } else 0458 ret = num; 0459 break; 0460 case Object::oper: 0461 if(elem.hasChildNodes()) { 0462 m_err << QCoreApplication::tr("The %1 operator cannot have child contexts.").arg(elem.tagName()); 0463 } else { 0464 Operator::OperatorType type=Operator::toOperatorType(elem.tagName()); 0465 if(type==Operator::none) 0466 m_err << QCoreApplication::tr("The element '%1' is not an operator.").arg(elem.tagName()); 0467 else 0468 ret = op = new Operator(type); 0469 } 0470 break; 0471 case Object::variable: { 0472 Ci* var = new Ci(elem.text()); 0473 var->setFunction(elem.attribute(QStringLiteral("type"))==QLatin1String("function")); 0474 ret=var; 0475 } break; 0476 case Object::vector: { 0477 ret=addElements<Vector>(new Vector(elem.childNodes().count()), &elem); 0478 if(elem.childNodes().count()==0) { 0479 m_err << QCoreApplication::tr("Do not want empty vectors"); 0480 } 0481 // qDebug() << "PEEEEEEU" << v->size(); 0482 } break; 0483 case Object::list: 0484 ret=addElements<List>(new List, &elem); 0485 break; 0486 case Object::matrix: 0487 ret=addElements<Matrix, MatrixRow>(new Matrix, &elem); 0488 if(elem.childNodes().count()==0) { 0489 m_err << QCoreApplication::tr("Do not want empty matrices"); 0490 } 0491 break; 0492 case Object::matrixrow: 0493 ret=addElements<MatrixRow>(new MatrixRow, &elem); 0494 if(elem.childNodes().count()==0) { 0495 m_err << QCoreApplication::tr("Do not want empty matrixrow elements"); 0496 } 0497 break; 0498 case Object::apply: { 0499 Apply *a=addElements<Apply>(new Apply, &elem); 0500 if(a && !check(a)) { 0501 delete a; 0502 a=nullptr; 0503 } 0504 ret=a; 0505 } break; 0506 case Object::none: 0507 case Object::custom: 0508 m_err << QCoreApplication::translate("Error message due to an unrecognized input", 0509 "Not supported/unknown: %1").arg(elem.tagName()); 0510 break; 0511 } 0512 0513 Q_ASSERT(ret || !m_err.isEmpty()); 0514 return ret; 0515 } 0516 0517 QString Expression::toHtml() const 0518 { 0519 Q_ASSERT(isCorrect()); 0520 return HtmlExpressionWriter(d->m_tree).result().toString(); 0521 } 0522 0523 QString Expression::toMathMLPresentation() const 0524 { 0525 Q_ASSERT(isCorrect()); 0526 return MathMLPresentationExpressionWriter(d->m_tree).result().toString(); 0527 } 0528 0529 QString Expression::toMathML() const 0530 { 0531 Q_ASSERT(isCorrect()); 0532 return MathMLExpressionWriter(d->m_tree).result().toString(); 0533 } 0534 0535 QString Expression::toString() const 0536 { 0537 Q_ASSERT(isCorrect()); 0538 StringExpressionWriter s(d->m_tree); 0539 return s.result().toString(); 0540 } 0541 0542 enum Object::ObjectType Expression::whatType(const QString& tag) 0543 { 0544 Object::ObjectType ret=Object::none; 0545 if(tag==QLatin1String("cn")) 0546 ret= Object::value; 0547 else if(tag==QLatin1String("ci")) 0548 ret= Object::variable; 0549 else if(tag==QLatin1String("vector")) 0550 ret= Object::vector; 0551 else if(tag==QLatin1String("list")) 0552 ret= Object::list; 0553 else if(tag==QLatin1String("matrix")) 0554 ret= Object::matrix; 0555 else if(tag==QLatin1String("matrixrow")) 0556 ret= Object::matrixrow; 0557 else if(tag==QLatin1String("apply")) 0558 ret= Object::apply; 0559 else if(Operator::toOperatorType(tag)!=0) 0560 ret= Object::oper; 0561 else if(Container::toContainerType(tag)!=0) 0562 ret= Object::container; 0563 0564 return ret; 0565 } 0566 0567 bool Expression::operator==(const Expression & e) const 0568 { 0569 return AnalitzaUtils::equalTree(e.d->m_tree, d->m_tree); 0570 } 0571 0572 bool Expression::operator!=(const Expression& e) const 0573 { 0574 return !(e==*this); 0575 } 0576 0577 void Expression::clear() 0578 { 0579 delete d->m_tree; 0580 d->m_tree=nullptr; 0581 d->m_err.clear(); 0582 } 0583 0584 bool Expression::isCorrect() const 0585 { 0586 return !(d || d->m_tree) || d->m_err.isEmpty(); 0587 } 0588 0589 QStringList Expression::bvarList() const 0590 { 0591 Q_ASSERT(d->m_tree); 0592 const Object *o = d->m_tree; 0593 0594 if(o->isContainer() && static_cast<const Container*>(o)->containerType()==Container::math) { 0595 if(!static_cast<const Container*>(o)->m_params.isEmpty()) 0596 o = (Container*) static_cast<const Container*>(o)->m_params[0]; 0597 } 0598 0599 if(o->isApply()) 0600 return static_cast<const Apply*>(o)->bvarStrings(); 0601 else if(o->isContainer()) 0602 return static_cast<const Container*>(o)->bvarStrings(); 0603 0604 return QStringList(); 0605 } 0606 0607 Cn Expression::toReal() const 0608 { 0609 Object* tree=d->m_tree; 0610 if(Q_LIKELY(tree && tree->type()==Object::value)) 0611 return *static_cast<Cn*>(tree); 0612 else { 0613 qDebug() << "trying to return not a real value as real:" << (tree ? tree->toString() : QStringLiteral("null")); 0614 return Cn(0.); 0615 } 0616 } 0617 0618 QString Expression::stringValue() const 0619 { 0620 Object* tree=d->m_tree; 0621 if(Q_LIKELY(d->m_tree && d->m_tree->type()==Object::list)) 0622 return AnalitzaUtils::listToString(static_cast<const List*>(tree)); 0623 else { 0624 qDebug() << "trying to return not a string value as string:" << (tree ? tree->toString() : QStringLiteral("null")); 0625 return QString(); 0626 } 0627 } 0628 0629 bool Expression::isString() const 0630 { 0631 return d->m_tree && d->m_tree->type()==Object::list 0632 && !static_cast<const List*>(d->m_tree)->isEmpty() 0633 && static_cast<const List*>(d->m_tree)->at(0)->type()==Object::value 0634 && static_cast<const Cn*>(static_cast<const List*>(d->m_tree)->at(0))->isCharacter(); 0635 } 0636 0637 //if it's a math element, then return the (only) son 0638 Object* actualRoot(Object* o) 0639 { 0640 if(o && o->isContainer()) { 0641 Container* c = (Container*) o; 0642 if(c->containerType()==Container::math) { 0643 return c->m_params[0]; 0644 } 0645 } 0646 return o; 0647 } 0648 0649 bool Expression::isLambda() const 0650 { 0651 Object* o = actualRoot(d->m_tree); 0652 if(o && o->isContainer()) { 0653 Container* c = (Container*) o; 0654 return c->containerType()==Container::lambda; 0655 } 0656 return false; 0657 } 0658 0659 bool Expression::isDeclaration() const 0660 { 0661 Object* o = actualRoot(d->m_tree); 0662 if(o && o->isContainer()) { 0663 Container* c = (Container*) o; 0664 return c->containerType() == Container::declare; 0665 } 0666 return false; 0667 } 0668 0669 QString Expression::name() const 0670 { 0671 Object* o = actualRoot(d->m_tree); 0672 if(o && o->isContainer()) { 0673 Container* c = (Container*) o; 0674 if(c->containerType() == Container::declare) 0675 return static_cast<const Ci*>(c->m_params[0])->name(); 0676 } 0677 return QString(); 0678 } 0679 0680 Expression Expression::declarationValue() const 0681 { 0682 Object* o = actualRoot(d->m_tree); 0683 if(o && o->isContainer()) { 0684 Container* c = (Container*) o; 0685 if(c->containerType() == Container::declare) 0686 return Expression(c->m_params[1]->copy()); 0687 } 0688 return Expression(); 0689 } 0690 0691 bool Expression::isEquation() const 0692 { 0693 Object* o = actualRoot(d->m_tree); 0694 if(o && o->isApply()) { 0695 Apply *c1 = (Apply*) o; 0696 return c1->firstOperator().operatorType()==Operator::eq; 0697 } 0698 return false; 0699 } 0700 0701 Expression Expression::equationToFunction() const 0702 { 0703 Object* o = actualRoot(d->m_tree); 0704 if(o && o->isApply()) { 0705 Apply *c1 = (Apply*) o; 0706 if(c1->firstOperator().operatorType()==Operator::eq) { 0707 Container* c = new Container(Container::math); 0708 Apply* a = new Apply; 0709 a->appendBranch(new Operator(Operator::minus)); 0710 a->appendBranch(c1->at(0)->copy()); 0711 a->appendBranch(c1->at(1)->copy()); 0712 c->appendBranch(a); 0713 return Expression(c); 0714 } 0715 } 0716 return *this; 0717 } 0718 0719 QList<Ci*> Expression::parameters() const 0720 { 0721 QList<Ci*> ret; 0722 Object* o = actualRoot(d->m_tree); 0723 if(o && o->isContainer()) { 0724 Container* c1 = (Container*) o; 0725 return c1->bvarCi(); 0726 } 0727 return ret; 0728 } 0729 0730 Expression Expression::lambdaBody() const 0731 { 0732 Q_ASSERT(isLambda()); 0733 Object* ob = actualRoot(d->m_tree); 0734 if(ob->isContainer()) { 0735 Container* c = (Container*) ob; 0736 Q_ASSERT(c->containerType()==Container::lambda); 0737 Object *ret = c->m_params.last(); 0738 Object* o = ret->copy(); 0739 computeDepth(o); 0740 return Expression(o); 0741 } 0742 return {}; 0743 } 0744 0745 bool Expression::isVector() const 0746 { 0747 Object* o = actualRoot(d->m_tree); 0748 return o && o->type()==Container::vector; 0749 } 0750 0751 bool Expression::isMatrix() const 0752 { 0753 Object* o = actualRoot(d->m_tree); 0754 return o && o->type()==Container::matrix; 0755 } 0756 0757 bool Expression::isList() const 0758 { 0759 Object* o = actualRoot(d->m_tree); 0760 return o && o->type()==Container::list; 0761 } 0762 0763 QList<Expression> Expression::toExpressionList() const 0764 { 0765 bool isvector = isVector(); 0766 if((!isvector && !isList()) || !d->m_tree) 0767 return QList<Expression>(); 0768 0769 QList<Expression> ret; 0770 const Object* o=actualRoot(d->m_tree); 0771 0772 if(isvector) { 0773 const Vector* v = (const Vector*) o; 0774 for(Vector::const_iterator it=v->constBegin(), itEnd=v->constEnd(); it!=itEnd; ++it) { 0775 Object* newelement = (*it)->copy(); 0776 computeDepth(newelement); 0777 ret << Expression(newelement); 0778 } 0779 } else { 0780 const List* v = (const List*) o; 0781 for(List::const_iterator it=v->constBegin(), itEnd=v->constEnd(); it!=itEnd; ++it) { 0782 Object* newelement = (*it)->copy(); 0783 computeDepth(newelement); 0784 ret << Expression(newelement); 0785 } 0786 } 0787 0788 return ret; 0789 } 0790 0791 Expression Expression::elementAt(int position) const 0792 { 0793 Q_ASSERT(isVector()); 0794 Object* o = actualRoot(d->m_tree); 0795 Q_ASSERT(o); 0796 Vector *v=static_cast<Vector*>(o); 0797 0798 return Expression(v->at(position)->copy()); 0799 } 0800 0801 void Expression::setElementAt(int position, const Expression& exp) 0802 { 0803 Q_ASSERT(isVector()); 0804 Object* o = actualRoot(d->m_tree); 0805 Q_ASSERT(o); 0806 Vector *v=static_cast<Vector*>(o); 0807 0808 delete v->at(position); 0809 v->setAt(position, exp.tree()->copy()); 0810 } 0811 0812 QStringList Expression::error() const 0813 { 0814 return d->m_err; 0815 } 0816 0817 void Expression::addError(const QString& error) 0818 { 0819 d->m_err += error; 0820 } 0821 0822 const Object* Expression::tree() const 0823 { 0824 return d->m_tree; 0825 } 0826 0827 Object* Expression::tree() 0828 { 0829 return d->m_tree; 0830 } 0831 0832 Object* Expression::takeTree() 0833 { 0834 Object* ret = d->m_tree; 0835 setTree(Q_NULLPTR); 0836 return ret; 0837 } 0838 0839 void Expression::setTree(Object* o) 0840 { 0841 d->m_tree=o; 0842 } 0843 0844 bool Expression::isReal() const { return d->m_tree && d->m_tree->type()==Object::value; } 0845 bool Expression::isCustomObject() const { return d->m_tree && d->m_tree->type()==Object::custom; } 0846 0847 Expression Expression::constructString(const QString& str) 0848 { 0849 return Expression(ExpressionPrivate::listFromString(str)); 0850 } 0851 0852 Expression Expression::constructList(const QList< Expression >& exps) 0853 { 0854 List* l = new List; 0855 foreach(const Expression& e, exps) 0856 l->appendBranch(e.tree()->copy()); 0857 0858 computeDepth(l); 0859 return Expression(l); 0860 } 0861 0862 #define CHECK_TYPE(type)\ 0863 type* a = (type *) o;\ 0864 \ 0865 type::iterator it=a->begin(), itEnd=a->end();\ 0866 for(; it!=itEnd; ++it) {\ 0867 renameTree(*it, depth, newName);\ 0868 }\ 0869 0870 static void renameTree(Object* o, int depth, const QString& newName) 0871 { 0872 if(!o) 0873 return; 0874 0875 switch(o->type()) { 0876 case Object::variable: { 0877 Ci* var = (Ci*) o; 0878 if(var->depth()==depth) 0879 var->setName(newName); 0880 } break; 0881 case Object::apply: { 0882 CHECK_TYPE(Apply); 0883 renameTree(a->ulimit(), depth, newName); 0884 renameTree(a->dlimit(), depth, newName); 0885 renameTree(a->domain(), depth, newName); 0886 } break; 0887 case Object::container: { CHECK_TYPE(Container); } break; 0888 case Object::list: { CHECK_TYPE(List); } break; 0889 case Object::vector: { CHECK_TYPE(Vector); } break; 0890 case Object::matrix: { CHECK_TYPE(Matrix); } break; 0891 case Object::matrixrow: { CHECK_TYPE(MatrixRow); } break; 0892 0893 case Object::none: 0894 case Object::value: 0895 case Object::oper: 0896 case Object::custom: 0897 break; 0898 } 0899 } 0900 0901 void Expression::renameArgument(int depth, const QString& newName) 0902 { 0903 renameTree(d->m_tree, depth, newName); 0904 computeDepth(d->m_tree); 0905 } 0906 0907 Expression Expression::constructCustomObject(const QVariant& custom, CustomObjectDestructor d) 0908 { 0909 Object* obj = new CustomObject(custom, d); 0910 return Expression(obj); 0911 } 0912 0913 QVariant Expression::customObjectValue() const 0914 { 0915 Object* tree=d->m_tree; 0916 if(Q_LIKELY(tree && tree->type()==Object::custom)) 0917 return static_cast<const CustomObject*>(tree)->value(); 0918 else { 0919 qDebug() << "trying to return as a custom object something that it is not:" << (tree ? tree->toString() : QStringLiteral("null")); 0920 return QVariant(); 0921 } 0922 } 0923 0924 // static void print_dom(const QDomNode& in, int ind) 0925 // { 0926 // QString a; 0927 // 0928 // if(ind >100){ 0929 // qDebug("..."); 0930 // return; 0931 // } 0932 // 0933 // for(int i=0; i<ind; i++) 0934 // a.append("______|"); 0935 // 0936 // if(in.hasChildNodes()) 0937 // qDebug("%s%s(%s) -- %d", qPrintable(a), qPrintable(in.toElement().tagName()), qPrintable(in.toElement().text()), in.childNodes().length()); 0938 // else 0939 // qDebug("%s%s", qPrintable(a), qPrintable(in.toElement().tagName())); 0940 // 0941 // for(int i=0 ; i<in.childNodes().length(); i++){ 0942 // if(in.childNodes().item(i).isElement()) 0943 // print_dom(in.childNodes().item(i), ind+1); 0944 // } 0945 // } 0946 0947 bool Expression::isCompleteExpression(const QString& exp, bool justempty) 0948 { 0949 ExpLexer lex(exp); 0950 return lex.isCompleteExpression(justempty); 0951 } 0952 0953 QStringList Expression::comments() const 0954 { 0955 return m_comments; 0956 } 0957 0958 #include "moc_expression.cpp"