File indexing completed on 2024-04-28 03:40:46
0001 /************************************************************************************* 0002 * Copyright (C) 2008 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 0019 #include "stringexpressionwriter.h" 0020 #include "value.h" 0021 #include "vector.h" 0022 #include "container.h" 0023 #include <QStringList> 0024 #include "list.h" 0025 #include "variable.h" 0026 #include "apply.h" 0027 #include "analitzautils.h" 0028 #include "matrix.h" 0029 0030 using namespace Analitza; 0031 0032 const double StringExpressionWriter::MIN_PRINTABLE_VALUE = 0.0000000000001; // since the precision we choose for 'G' is 12 0033 0034 template <class T> 0035 QStringList StringExpressionWriter::allValues(T it, const T& itEnd, AbstractExpressionVisitor* writer) 0036 { 0037 QStringList elements; 0038 for(; it!=itEnd; ++it) 0039 elements += (*it)->accept(writer).toString(); 0040 0041 return elements; 0042 } 0043 0044 0045 QMap<Operator::OperatorType, QString> initOperators() 0046 { 0047 QMap<Operator::OperatorType, QString> ret; 0048 ret.insert(Operator::plus, QStringLiteral("+")); 0049 ret.insert(Operator::times, QStringLiteral("*")); 0050 ret.insert(Operator::divide, QStringLiteral("/")); 0051 ret.insert(Operator::eq, QStringLiteral("=")); 0052 ret.insert(Operator::neq, QStringLiteral("!=")); 0053 ret.insert(Operator::lt, QStringLiteral("<")); 0054 ret.insert(Operator::leq, QStringLiteral("<=")); 0055 ret.insert(Operator::gt, QStringLiteral(">")); 0056 ret.insert(Operator::geq, QStringLiteral(">=")); 0057 ret.insert(Operator::power, QStringLiteral("^")); 0058 ret.insert(Operator::minus, QStringLiteral("-")); 0059 return ret; 0060 } 0061 0062 const QMap<Operator::OperatorType, QString> StringExpressionWriter::s_operators=initOperators(); 0063 0064 StringExpressionWriter::StringExpressionWriter(const Object* o) 0065 { 0066 if (o) 0067 m_result=o->accept(this); 0068 } 0069 0070 QVariant StringExpressionWriter::visit(const Ci* var) 0071 { 0072 return var->name(); 0073 } 0074 0075 QVariant StringExpressionWriter::visit(const Operator* op) 0076 { 0077 return op->name(); 0078 } 0079 0080 QVariant StringExpressionWriter::visit(const Vector* vec) 0081 { 0082 return QStringLiteral("vector { %1 }").arg(allValues<Vector::const_iterator>(vec->constBegin(), vec->constEnd(), this).join(QStringLiteral(", "))); 0083 } 0084 0085 QVariant StringExpressionWriter::visit(const Matrix* m) 0086 { 0087 return QStringLiteral("matrix { %1 }").arg(allValues(m->constBegin(), m->constEnd(), this).join(QStringLiteral(", "))); 0088 } 0089 0090 QVariant StringExpressionWriter::visit(const MatrixRow* mr) 0091 { 0092 return QStringLiteral("matrixrow { %1 }").arg(allValues(mr->constBegin(), mr->constEnd(), this).join(QStringLiteral(", "))); 0093 } 0094 0095 QVariant StringExpressionWriter::visit(const List* vec) 0096 { 0097 if(!vec->isEmpty() && vec->at(0)->type()==Object::value && static_cast<Cn*>(vec->at(0))->format()==Cn::Char) 0098 return QVariant::fromValue<QString>(QStringLiteral("\"")+AnalitzaUtils::listToString(vec)+'\"'); 0099 else 0100 return QVariant::fromValue<QString>(QStringLiteral("list { %1 }").arg(allValues<List::const_iterator>(vec->constBegin(), vec->constEnd(), this).join(QStringLiteral(", ")))); 0101 } 0102 0103 QVariant StringExpressionWriter::visit(const Cn* var) 0104 { 0105 if(var->isBoolean()) 0106 return var->isTrue() ? "true" : "false"; 0107 else if(var->isCharacter()) 0108 return QString(var->character()); 0109 else if(var->isComplex()) { 0110 QString realpart; 0111 QString imagpart; 0112 bool realiszero = false; 0113 const auto complex = var->complexValue(); 0114 if (qAbs(complex.real()) > MIN_PRINTABLE_VALUE) 0115 realpart = QString::number(complex.real(), 'g', 12); 0116 else 0117 realiszero = true; 0118 0119 if (!qFuzzyCompare(qAbs(complex.imag()), 1)) { 0120 if (qAbs(complex.imag()) > MIN_PRINTABLE_VALUE) { 0121 if (!realiszero && complex.imag()>0.) 0122 realpart += QLatin1Char('+'); 0123 imagpart = QString::number(complex.imag(), 'g', 12); 0124 imagpart += QStringLiteral("*i"); 0125 } 0126 } else { 0127 if (!realiszero) 0128 realpart += QLatin1Char('+'); 0129 if (qFuzzyCompare(complex.imag(), 1)) 0130 imagpart = QStringLiteral("i"); 0131 else 0132 imagpart = QStringLiteral("-i"); 0133 } 0134 0135 return QVariant::fromValue<QString>(realpart+imagpart); 0136 } 0137 else 0138 return QString::number(var->value(), 'g', 12); 0139 } 0140 0141 int StringExpressionWriter::weight(const Operator* op, int size, int pos) 0142 { 0143 switch(op->operatorType()) { 0144 case Operator::lt: 0145 case Operator::gt: 0146 case Operator::eq: 0147 case Operator::neq: 0148 case Operator::leq: 0149 case Operator::geq: 0150 return 1; 0151 case Operator::plus: 0152 return 2; 0153 case Operator::minus: 0154 return size==1 ? 8 : 3; 0155 case Operator::times: 0156 return 4; 0157 case Operator::divide: 0158 return 5 + (pos>0 ? 0 : 1); 0159 case Operator::_and: 0160 case Operator::_or: 0161 case Operator::_xor: 0162 return 6; 0163 case Operator::power: 0164 return 7 + (pos>0 ? 0 : 1); 0165 default: 0166 return 1000; 0167 } 0168 } 0169 0170 QVariant StringExpressionWriter::visit(const Analitza::Apply* a) 0171 { 0172 Operator op=a->firstOperator(); 0173 QStringList ret; 0174 QString toret; 0175 QString bounds; 0176 QStringList bvars=a->bvarStrings(); 0177 0178 if(a->ulimit() || a->dlimit()) { 0179 bounds += '='; 0180 if(a->dlimit()) 0181 bounds += a->dlimit()->accept(this).toString(); 0182 bounds += QLatin1String(".."); 0183 if(a->ulimit()) 0184 bounds += a->ulimit()->accept(this).toString(); 0185 } 0186 else if(a->domain()) 0187 bounds += '@'+a->domain()->accept(this).toString(); 0188 0189 int i = 0; 0190 foreach(Object* o, a->m_params) { 0191 Object::ObjectType type=o->type(); 0192 switch(type) { 0193 case Object::oper: 0194 Q_ASSERT(false); 0195 break; 0196 case Object::variable: 0197 ret << static_cast<const Ci*>(o)->accept(this).toString(); 0198 break; 0199 case Object::apply: { 0200 const Apply *c = (const Apply*) o; 0201 QString s = c->accept(this).toString(); 0202 if(s_operators.contains(op.operatorType()) && !c->isUnary()) { 0203 Operator child_op = c->firstOperator(); 0204 0205 if(child_op.operatorType() && weight(&op, c->countValues(), -1)>weight(&child_op, c->countValues(), i)) 0206 s=QStringLiteral("(%1)").arg(s); 0207 } 0208 ret << s; 0209 } break; 0210 default: 0211 ret << o->accept(this).toString(); 0212 break; 0213 } 0214 ++i; 0215 } 0216 0217 bool func=op.operatorType()==Operator::function; 0218 if(func) { 0219 QString n = ret.takeFirst(); 0220 if(a->m_params.first()->type()!=Object::variable) 0221 n='('+n+')'; 0222 0223 toret += QStringLiteral("%1(%2)").arg(n, ret.join(QStringLiteral(", "))); 0224 } else if(op.operatorType()==Operator::selector) { 0225 if(a->m_params.last()->isApply()) { 0226 const Apply* a1=static_cast<const Apply*>(a->m_params.last()); 0227 if(s_operators.contains(a1->firstOperator().operatorType())) 0228 ret.last()='('+ret.last()+')'; 0229 } 0230 0231 toret += QStringLiteral("%1[%2]").arg(ret.last(), ret.first()); 0232 } else if(ret.count()>1 && s_operators.contains(op.operatorType())) { 0233 toret += ret.join(s_operators.value(op.operatorType())); 0234 } else if(ret.count()==1 && op.operatorType()==Operator::minus) 0235 toret += '-'+ret[0]; 0236 else { 0237 QString bounding; 0238 if(!bounds.isEmpty() || !bvars.isEmpty()) { 0239 if(bvars.count()!=1) bounding +='('; 0240 bounding += bvars.join(QStringLiteral(", ")); 0241 if(bvars.count()!=1) bounding +=')'; 0242 0243 bounding = ':'+bounding +bounds; 0244 } 0245 0246 toret += QStringLiteral("%1(%2%3)").arg(op.accept(this).toString(), ret.join(QStringLiteral(", ")), bounding); 0247 } 0248 0249 return toret; 0250 } 0251 0252 QVariant StringExpressionWriter::visit(const Container* var) 0253 { 0254 QStringList ret = allValues(var->constBegin(), var->constEnd(), this); 0255 0256 QString toret; 0257 switch(var->containerType()) { 0258 case Container::declare: 0259 toret += ret.join(QStringLiteral(":=")); 0260 break; 0261 case Container::lambda: { 0262 QString last=ret.takeLast(); 0263 QStringList bvars = var->bvarStrings(); 0264 if(bvars.count()!=1) toret +='('; 0265 toret += bvars.join(QStringLiteral(", ")); 0266 if(bvars.count()!=1) toret +=')'; 0267 toret += "->" + last; 0268 } break; 0269 case Container::math: 0270 toret += ret.join(QStringLiteral("; ")); 0271 break; 0272 case Container::uplimit: //x->(n1..n2) is put at the same time 0273 case Container::downlimit: 0274 break; 0275 case Container::bvar: 0276 if(ret.count()>1) toret += '('; 0277 toret += ret.join(QStringLiteral(", ")); 0278 if(ret.count()>1) toret += ')'; 0279 break; 0280 case Container::piece: 0281 toret += ret[1]+" ? "+ret[0]; 0282 break; 0283 case Container::otherwise: 0284 toret += "? "+ret[0]; 0285 break; 0286 default: 0287 toret += var->tagName()+" { "+ret.join(QStringLiteral(", "))+" }"; 0288 break; 0289 } 0290 return toret; 0291 } 0292 0293 QVariant StringExpressionWriter::visit(const CustomObject*) 0294 { 0295 return "CustomObject"; 0296 } 0297 0298 QVariant StringExpressionWriter::visit(const None* ) 0299 { 0300 return QString(); 0301 }