File indexing completed on 2024-05-12 15:26:32
0001 /*************************************************************************** 0002 File : VariableParser.h 0003 Project : LabPlot 0004 Description : Variable parser for different CAS backends 0005 -------------------------------------------------------------------- 0006 Copyright : (C) 2015 Garvit Khatri (garvitdelhi@gmail.com) 0007 Copyright : (C) 2016 by Alexander Semke (alexander.semke@web.de) 0008 0009 ***************************************************************************/ 0010 0011 /*************************************************************************** 0012 * * 0013 * This program is free software; you can redistribute it and/or modify * 0014 * it under the terms of the GNU General Public License as published by * 0015 * the Free Software Foundation; either version 2 of the License, or * 0016 * (at your option) any later version. * 0017 * * 0018 * This program is distributed in the hope that it will be useful, * 0019 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0021 * GNU General Public License for more details. * 0022 * * 0023 * You should have received a copy of the GNU General Public License * 0024 * along with this program; if not, write to the Free Software * 0025 * Foundation, Inc., 51 Franklin Street, Fifth Floor, * 0026 * Boston, MA 02110-1301 USA * 0027 * * 0028 ***************************************************************************/ 0029 0030 #include "VariableParser.h" 0031 #include <QStringList> 0032 #include "backend/lib/trace.h" 0033 #include <cmath> // NAN 0034 0035 VariableParser::VariableParser(QString name, QString value) 0036 : m_backendName(std::move(name)), m_string(std::move(value)) { 0037 0038 PERFTRACE("parsing variable"); 0039 if (m_backendName.compare(QStringLiteral("Maxima"), Qt::CaseInsensitive) == 0) 0040 parseMaximaValues(); 0041 else if ( (m_backendName.compare(QStringLiteral("Python"), Qt::CaseInsensitive) == 0) 0042 || (m_backendName.compare(QStringLiteral("Python 3"), Qt::CaseInsensitive) == 0) 0043 || (m_backendName.compare(QStringLiteral("Python 2"), Qt::CaseInsensitive) == 0) ) 0044 parsePythonValues(); 0045 else if (m_backendName.compare(QStringLiteral("Sage"), Qt::CaseInsensitive) == 0) 0046 parsePythonValues(); 0047 else if (m_backendName.compare(QStringLiteral("R"), Qt::CaseInsensitive) == 0) 0048 parseRValues(); 0049 else if (m_backendName.compare(QStringLiteral("Julia"), Qt::CaseInsensitive) == 0) 0050 parsePythonValues(); 0051 else if (m_backendName.compare(QStringLiteral("Octave"), Qt::CaseInsensitive) == 0) 0052 parseOctaveValues(); 0053 } 0054 0055 void VariableParser::parseMaximaValues() { 0056 if (m_string.count(QStringLiteral("[")) < 2) { 0057 m_string = m_string.replace(QStringLiteral("["), QString()); 0058 m_string = m_string.replace(QStringLiteral("]"), QString()); 0059 m_string = m_string.trimmed(); 0060 0061 const QStringList valueStringList = m_string.split(QStringLiteral(",")); 0062 parseValues(valueStringList); 0063 } 0064 } 0065 0066 void VariableParser::parsePythonValues() { 0067 QStringList valueStringList; 0068 m_string = m_string.trimmed(); 0069 if (m_string.startsWith(QStringLiteral("array"))) { 0070 //parse numpy arrays, string representation like array([1,2,3,4,5]) 0071 m_string = m_string.replace(QStringLiteral("array(["), QString()); 0072 m_string = m_string.replace(QStringLiteral("])"), QString()); 0073 } else if (m_string.startsWith(QStringLiteral("["))) { 0074 //parse python's lists 0075 m_string = m_string.replace(QStringLiteral("["), QString()); 0076 m_string = m_string.replace(QStringLiteral("]"), QString()); 0077 } else if (m_string.startsWith(QStringLiteral("("))) { 0078 //parse python's tuples 0079 m_string = m_string.replace(QStringLiteral("("), QString()); 0080 m_string = m_string.replace(QStringLiteral(")"), QString()); 0081 } else { 0082 return; 0083 } 0084 0085 if (m_string.count(QStringLiteral(","))>1) 0086 valueStringList = m_string.split(QStringLiteral(",")); 0087 else 0088 valueStringList = m_string.split(QStringLiteral(" ")); 0089 0090 parseValues(valueStringList); 0091 } 0092 0093 void VariableParser::parseRValues() { 0094 m_string = m_string.trimmed(); 0095 const QStringList valueStringList = m_string.split(QStringLiteral(", ")); 0096 parseValues(valueStringList); 0097 } 0098 0099 void VariableParser::parseOctaveValues() { 0100 m_string = m_string.trimmed(); 0101 0102 QStringList valueStringList; 0103 const QStringList tempStringList = m_string.split(QLatin1Char('\n')); 0104 for (const QString& values : tempStringList) { 0105 //TODO: in newer version of Cantor the rows with "Columns..." were removed already. 0106 //we can stop looking for this substring in some point in time later. 0107 if (!values.isEmpty() && !values.trimmed().startsWith(QStringLiteral("Columns"))) 0108 valueStringList << values.split(QLatin1Char(' ')); 0109 } 0110 0111 valueStringList.removeAll(QString()); 0112 parseValues(valueStringList); 0113 } 0114 0115 bool VariableParser::isParsed() { 0116 return m_parsed; 0117 } 0118 0119 QVector< double > VariableParser::values() { 0120 return m_values; 0121 } 0122 0123 void VariableParser::parseValues(const QStringList& values) { 0124 PERFTRACE("parsing variable values string list"); 0125 for (const QString& v : values) { 0126 bool isNumber = false; 0127 double value = v.trimmed().toDouble(&isNumber); 0128 0129 //accept the variable only if there is at least one numerical value in the array. 0130 if (isNumber) { 0131 if (!m_parsed) 0132 m_parsed = true; 0133 } else { 0134 value = NAN; 0135 } 0136 0137 m_values << value; 0138 } 0139 }