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 }