diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-03 02:45:19 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-03 02:45:19 +0000 |
commit | 4e1a5c3eebf50657629e2b4eba13649c2b599598 (patch) | |
tree | 7757743b67ed172d113dad73a3daa5b8aa6f871a /katapult/plugins/catalogs/calculatorcatalog | |
download | katapult-4e1a5c3eebf50657629e2b4eba13649c2b599598.tar.gz katapult-4e1a5c3eebf50657629e2b4eba13649c2b599598.zip |
Added abandoned KDE3 version of katapult
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/katapult@1084407 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'katapult/plugins/catalogs/calculatorcatalog')
14 files changed, 2638 insertions, 0 deletions
diff --git a/katapult/plugins/catalogs/calculatorcatalog/Makefile.am b/katapult/plugins/catalogs/calculatorcatalog/Makefile.am new file mode 100644 index 0000000..c0753c2 --- /dev/null +++ b/katapult/plugins/catalogs/calculatorcatalog/Makefile.am @@ -0,0 +1,20 @@ +# Copyright (C) 2005 Tobi Vollebregt + +# set the include path for X, qt and KDE +INCLUDES = -I$(top_srcdir)/katapult/common $(all_includes) + +# header files +noinst_HEADERS = calculatorcatalog.h expression.h actionevalexpr.h + +# use automoc +METASOURCES = AUTO + +# install xcalc icon +KDE_ICON = xcalc checkmark no + +# our plugin +kde_module_LTLIBRARIES = katapult_calculatorcatalog.la +katapult_calculatorcatalog_la_SOURCES = settings.ui calculatorcatalog.cpp expression.cpp actionevalexpr.cpp parser.cpp +katapult_calculatorcatalog_la_LDFLAGS = -module $(KDE_RPATH) $(KDE_PLUGIN) $(all_libraries) +katapult_calculatorcatalog_la_LIBADD = $(LIB_QT) $(LIB_KDECORE) $(LIB_KDEUI) $(LIB_KIO) $(top_builddir)/katapult/common/libkatapult.la +kde_services_DATA = katapult_calculatorcatalog.desktop diff --git a/katapult/plugins/catalogs/calculatorcatalog/actionevalexpr.cpp b/katapult/plugins/catalogs/calculatorcatalog/actionevalexpr.cpp new file mode 100644 index 0000000..2a786f9 --- /dev/null +++ b/katapult/plugins/catalogs/calculatorcatalog/actionevalexpr.cpp @@ -0,0 +1,161 @@ +/*************************************************************************** + * Copyright (C) 2005 Tobi Vollebregt * + * tobivollebregt@gmail.com * + * * + * Copyright (C) 2005 by Joe Ferris * + * jferris@optimistictech.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include <kapplication.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <krun.h> +#include <kurl.h> +#include <klocale.h> + +#include <qclipboard.h> + +#include "calculatorcatalog.h" +#include "expression.h" +#include "katapultitem.h" +#include "actionevalexpr.h" + + +// Conditional compilation to not bloat the lib if +// KDE already has the following functions. +// Prevents a deprecated function warning too. + +#if !KDE_IS_VERSION(3, 5, 0) + +// Copied some code from KDE 3.5 to make it compile on 3.4. + +// insert (thousands)-"separator"s into the non-fractional part of str +static void _insertSeparator(QString &str, const QString &separator, const QString &decimalSymbol) +{ + // leave fractional part untouched + QString mainPart = str.section(decimalSymbol, 0, 0); + QString fracPart = str.section(decimalSymbol, 1, 1, QString::SectionIncludeLeadingSep); + if (fracPart==decimalSymbol) fracPart=QString(); + for (int pos = mainPart.length() - 3; pos > 0; pos -= 3) + mainPart.insert(pos, separator); + str = mainPart + fracPart; +} + +// This was KLocale::formatNumber(const QString&, bool, int) + +static QString formatNumber(const QString &numStr) +{ + QString tmpString = numStr; + + // Skip the sign (for now) + bool neg = (tmpString[0] == '-'); + if (neg || tmpString[0] == '+') tmpString.remove(0, 1); + + // Split off exponential part (including 'e'-symbol) + QString mantString = tmpString.section('e', 0, 0, QString::SectionCaseInsensitiveSeps); + QString expString = tmpString.section('e', 1, 1, QString::SectionCaseInsensitiveSeps | QString::SectionIncludeLeadingSep); + if (expString.length()==1) expString=QString(); + + // Replace dot with locale decimal separator + mantString.replace(QChar('.'), KGlobal::locale()->decimalSymbol()); + + // Insert the thousand separators + _insertSeparator(mantString, KGlobal::locale()->thousandsSeparator(), KGlobal::locale()->decimalSymbol()); + + // How can we know where we should put the sign? + mantString.prepend(neg?KGlobal::locale()->negativeSign():KGlobal::locale()->positiveSign()); + + return mantString + expString; +} + +#else +// KDE_VERSION >= 3.5.0 + +static QString formatNumber(const QString& numStr) +{ + return KGlobal::locale()->formatNumber(numStr, false, 0); +} + +#endif + + +ActionEvaluateExpression::ActionEvaluateExpression() + : KatapultAction(), _expr(0) +{ +} + +ActionEvaluateExpression::~ActionEvaluateExpression() +{ +} + +QString ActionEvaluateExpression::text() const +{ + if (_expr->parseError()) { + return i18n("Evaluate Expression"); + } else { + // Format result. + int digits = _expr->catalog()->fracDigits(); + QChar f = _expr->catalog()->scientific() ? 'g' : 'f'; + QString num = QString::number(_expr->result(), f, digits); + // Strip trailing zeroes. + if (f == 'f' && digits != 0) { + while (num.endsWith("0")) { + num = num.left(num.length() - 1); + } + if (num.endsWith(".")) { + num = num.left(num.length() - 1); + } + } + // Localize (choose right implementation based on KDE version, see above). + return formatNumber(num); + } +} + +QPixmap ActionEvaluateExpression::icon(int size) const +{ + return KGlobal::iconLoader()->loadIcon("xcalc", KIcon::NoGroup, size); +} + +bool ActionEvaluateExpression::accepts(const KatapultItem* item) const +{ + bool accept = strcmp(item->className(), "Expression") == 0; + if (accept) { + _expr = (const Expression*)item; + } + return accept; +} + +void ActionEvaluateExpression::execute(const KatapultItem* item) const +{ + if (strcmp(item->className(), "Expression") == 0) { + _expr = (const Expression*)item; + + //evaluate expression with assignments enabled + _expr->evaluate(true); + + // Copy calculation and result into clipboard (unless there's a parse error). + if (!_expr->parseError()) { + QClipboard *cb = QApplication::clipboard(); + QString s = _expr->catalog()->formatString(); + s.replace("%1", _expr->text()); + s.replace("%2", text()); + cb->setText(s, QClipboard::Clipboard); + cb->setText(s, QClipboard::Selection); + } + } +} diff --git a/katapult/plugins/catalogs/calculatorcatalog/actionevalexpr.h b/katapult/plugins/catalogs/calculatorcatalog/actionevalexpr.h new file mode 100644 index 0000000..6cf23bf --- /dev/null +++ b/katapult/plugins/catalogs/calculatorcatalog/actionevalexpr.h @@ -0,0 +1,51 @@ +/*************************************************************************** + * Copyright (C) 2005 Tobi Vollebregt * + * tobivollebregt@gmail.com * + * * + * Copyright (C) 2005 by Joe Ferris * + * jferris@optimistictech.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef ACTIONEVALEXPR_H +#define ACTIONEVALEXPR_H + +#include "katapultaction.h" + +class KatapultItem; +class Expression; + +/** +@author Tobi Vollebregt +*/ +class ActionEvaluateExpression : public KatapultAction +{ + public: + ActionEvaluateExpression(); + ~ActionEvaluateExpression(); + + virtual void execute(const KatapultItem*) const; + virtual bool accepts(const KatapultItem*) const; + virtual QString text() const; + virtual QPixmap icon(int) const; + + private: + //_expr needs to be mutable because accepts() is const. + mutable const Expression* _expr; + +}; + +#endif diff --git a/katapult/plugins/catalogs/calculatorcatalog/calculatorcatalog.cpp b/katapult/plugins/catalogs/calculatorcatalog/calculatorcatalog.cpp new file mode 100644 index 0000000..c3c5f6d --- /dev/null +++ b/katapult/plugins/catalogs/calculatorcatalog/calculatorcatalog.cpp @@ -0,0 +1,360 @@ +/*************************************************************************** + * Copyright (C) 2005 Tobi Vollebregt * + * tobivollebregt@gmail.com * + * * + * Copyright (C) 2005 by Joe Ferris * + * jferris@optimistictech.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include <kservicegroup.h> +#include <ksycocaentry.h> +#include <ksycocatype.h> +#include <kapplication.h> +#include <knuminput.h> +#include <kcombobox.h> + +#include <qcheckbox.h> +#include <qbuttongroup.h> +#include <qradiobutton.h> +#include <qregexp.h> + +#include <math.h> + +#include "settings.h" +#include "calculatorcatalog.h" +#include "expression.h" +#include "actionregistry.h" +#include "actionevalexpr.h" +#include "status.h" + + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#ifndef M_E +#define M_E 2.7182818284590452354 +#endif + + +static double frac(double x) +{ + double nowhere; + return modf(x, &nowhere); +} + + +static double deg_sin(double x) { return sin(x * (M_PI / 180.0)); } +static double deg_cos(double x) { return cos(x * (M_PI / 180.0)); } +static double deg_tan(double x) { return tan(x * (M_PI / 180.0)); } +static double deg_asin(double x) { return asin(x) * (180.0 / M_PI); } +static double deg_acos(double x) { return acos(x) * (180.0 / M_PI); } +static double deg_atan(double x) { return atan(x) * (180.0 / M_PI); } +static double deg_sinh(double x) { return sinh(x * (M_PI / 180.0)); } +static double deg_cosh(double x) { return cosh(x * (M_PI / 180.0)); } +static double deg_tanh(double x) { return tanh(x * (M_PI / 180.0)); } +static double deg_asinh(double x) { return asinh(x) * (180.0 / M_PI); } +static double deg_acosh(double x) { return acosh(x) * (180.0 / M_PI); } +static double deg_atanh(double x) { return atanh(x) * (180.0 / M_PI); } + + +const CalculatorCatalog::Function CalculatorCatalog::radiansFunctionTable[] = +{ + { "sin", 3, sin }, + { "cos", 3, cos }, + { "tan", 3, tan }, + { "asin", 4, asin }, + { "acos", 4, acos }, + { "atan", 4, atan }, + { "sinh", 4, sinh }, + { "cosh", 4, cosh }, + { "tanh", 4, tanh }, + { "asinh", 5, asinh }, + { "acosh", 5, acosh }, + { "atanh", 5, atanh }, + { "sqrt", 4, sqrt }, + { "log", 3, log10 }, + { "ln", 2, log }, + { "exp", 3, exp }, + { "abs", 3, fabs }, + { "frac", 4, frac }, + { "round", 5, round }, + { "int", 3, trunc }, + { 0, 0, 0 } +}; + +const CalculatorCatalog::Function CalculatorCatalog::degreesFunctionTable[] = +{ + { "sin", 3, deg_sin }, + { "cos", 3, deg_cos }, + { "tan", 3, deg_tan }, + { "asin", 4, deg_asin }, + { "acos", 4, deg_acos }, + { "atan", 4, deg_atan }, + { "sinh", 4, deg_sinh }, + { "cosh", 4, deg_cosh }, + { "tanh", 4, deg_tanh }, + { "asinh", 5, deg_asinh }, + { "acosh", 5, deg_acosh }, + { "atanh", 5, deg_atanh }, + { "sqrt", 4, sqrt }, + { "log", 3, log10 }, + { "ln", 2, log }, + { "exp", 3, exp }, + { "abs", 3, fabs }, + { "frac", 4, frac }, + { "round", 5, round }, + { "int", 3, trunc }, + { 0, 0, 0 } +}; + + +K_EXPORT_COMPONENT_FACTORY( katapult_calculatorcatalog, + KGenericFactory<CalculatorCatalog>( "katapult_calculatorcatalog" ) ) + +CalculatorCatalog::CalculatorCatalog(QObject*, const char*, const QStringList&): _result(this, QString::null) +{ + ActionRegistry::self()->registerAction(new ActionEvaluateExpression()); + + setVar(getVarID("pi"), M_PI); + setVar(getVarID("e"), M_E); +} + +CalculatorCatalog::~CalculatorCatalog() +{ +} + +void CalculatorCatalog::queryChanged() +{ + int newStatus = 0; + QString cmd = query(); + + if (cmd.isEmpty()) { + reset(); + setBestMatch(Match()); + } else { + if (accepts(cmd)) { + int i, origLength = cmd.length(), length = origLength; + //autocomplete functions + cmd = cmd.lower(); + for (i = length - 1; i >= 0 && cmd[i].isLetter(); --i) { } + if (i != length - 1) { + QString start = cmd.mid(i + 1); + int lengthOfShortest = 9999, shortest = -1; + for (int j = 0; radiansFunctionTable[j].name; ++j) { + if (QString(radiansFunctionTable[j].name).startsWith(start)) { + if (radiansFunctionTable[j].length < lengthOfShortest) { + lengthOfShortest = radiansFunctionTable[j].length; + shortest = j; + } + } + } + if (shortest != -1) { + cmd = cmd.left(i + 1).append(radiansFunctionTable[shortest].name).append("("); + length = cmd.length(); + } + } + //fix parse errors at end of expression, + //ie. close open parentheses, convert operators into NOPs + for (i = length - 1; i >= 0 && (cmd[i] == '(' || cmd[i] == ' '); --i) { } + if (i < 0 || cmd[i] == '+' || cmd[i] == '-') { + cmd.append("0"); + ++length; + } else if (cmd[i] == '*' || cmd[i] == '/' || cmd[i] == '^') { + cmd.append("1"); + ++length; + } else if (cmd[i].isLetter() && (i < length - 1 && cmd[i + 1] == '(')) { + //just add a 0 if it's a function: we don't bother to backpropagate + //through the parse tree (if it existed at all) to figure out a NOP value + //for this particular (chain of) function(s). + cmd.append("0"); + ++length; + } + int openParen = 0; + //use cmd.length() here, it may be > than length. + for (i = 0; i < length; ++i) { + if (cmd[i] == '(') ++openParen; + if (cmd[i] == ')') --openParen; + } + if (openParen > 0) { + char* closeParen = new char[openParen + 1]; + memset(closeParen, ')', openParen); + closeParen[openParen] = 0; + cmd.append(closeParen); + delete[] closeParen; + } + _result.setText(cmd); + setBestMatch(Match(&_result, _result.parseError() ? 10 : 100, origLength)); + //set status. + //add S_Multiple to make sure katapult doesn't auto-exec and close the window + //add S_Active to make sure katapult doesn't start the hideTimer or clearTimer + newStatus = S_HasResults | S_Multiple | S_Active; + } else { + newStatus = 0; + } + } + setStatus(newStatus); +} + +void CalculatorCatalog::reset() +{ + _result.setText(QString::null); +} + +bool CalculatorCatalog::accepts(const QString& str) const +{ + //Heuristic to determine whether the string is an expression or not. + //Accept anything containing [()+\\-/*^=.,0-9]. + return QRegExp("[()+\\-/*^=.,0-9]").search(str) >= 0; +} + +int CalculatorCatalog::getVarID(const char* name) +{ + VarNameToIdMap::iterator it = varNameToId.find(QString(name)); + if (it == varNameToId.end()) { + _pendingVarName = QString(name); + return -1; + } + return *it; +} + +double CalculatorCatalog::getVar(int id) const +{ + return varIdToValue[id]; +} + +double CalculatorCatalog::setVar(int id, double value) +{ + if (id == -1) { + id = varIdToValue.count(); + varNameToId.insert(_pendingVarName, id); + varIdToValue.push_back(value); + } else { + varIdToValue[id] = value; + } + return value; +} + +/* +void CalculatorCatalog::initialize() +{ +} +*/ + +void CalculatorCatalog::readSettings(KConfigBase* config) +{ + _fracDigits = config->readUnsignedNumEntry("FracDigits", 2); + _bScientific = config->readBoolEntry("Scientific", false); + _bDegrees = config->readBoolEntry("Degrees", false); + _bClipboard = config->readBoolEntry("Clipboard", true); + _formatString = config->readEntry("FormatString", "%1 = %2"); +} + +void CalculatorCatalog::writeSettings(KConfigBase* config) +{ + config->writeEntry("FracDigits", fracDigits()); + config->writeEntry("Scientific", scientific()); + config->writeEntry("Degrees", degrees()); + config->writeEntry("Clipboard", clipboard()); + config->writeEntry("FormatString", formatString()); +} + +QWidget * CalculatorCatalog::configure() +{ + CalculatorCatalogSettings* settings = new CalculatorCatalogSettings(); + + settings->fracDigits->setValue(_fracDigits); + connect(settings->fracDigits, SIGNAL(valueChanged(int)), this, SLOT(fracDigitsChanged(int))); + + settings->normal->setChecked(!scientific()); + settings->scientific->setChecked(scientific()); + connect(settings->scientific, SIGNAL(toggled(bool)), this, SLOT(scientificChanged(bool))); + + settings->radians->setChecked(!degrees()); + settings->degrees->setChecked(degrees()); + connect(settings->degrees, SIGNAL(toggled(bool)), this, SLOT(degreesChanged(bool))); + + settings->clipboard->setChecked(clipboard()); + connect(settings->clipboard, SIGNAL(toggled(bool)), this, SLOT(clipboardChanged(bool))); + + settings->formatString->setText(formatString()); + connect(settings->formatString, SIGNAL(textChanged(const QString&)), this, SLOT(formatStringChanged(const QString&))); + + return settings; +} + +void CalculatorCatalog::fracDigitsChanged(int n) +{ + _fracDigits = n; +} + +int CalculatorCatalog::fracDigits() const +{ + return _fracDigits; +} + +void CalculatorCatalog::scientificChanged(bool en) +{ + _bScientific = en; +} + +bool CalculatorCatalog::scientific() const +{ + return _bScientific; +} + +void CalculatorCatalog::degreesChanged(bool en) +{ + _bDegrees = en; +} + +bool CalculatorCatalog::degrees() const +{ + return _bDegrees; +} + +void CalculatorCatalog::formatStringChanged(const QString& fmt) +{ + _formatString = fmt; +} + +QString CalculatorCatalog::formatString() const +{ + return _formatString; +} + +void CalculatorCatalog::clipboardChanged(bool en) +{ + _bClipboard = en; +} + +bool CalculatorCatalog::clipboard() const +{ + return _bClipboard; +} + +const CalculatorCatalog::Function* CalculatorCatalog::functionTable() const +{ + if (degrees()) { + return degreesFunctionTable; + } else { + return radiansFunctionTable; + } +} + +#include "calculatorcatalog.moc" diff --git a/katapult/plugins/catalogs/calculatorcatalog/calculatorcatalog.h b/katapult/plugins/catalogs/calculatorcatalog/calculatorcatalog.h new file mode 100644 index 0000000..88f03cc --- /dev/null +++ b/katapult/plugins/catalogs/calculatorcatalog/calculatorcatalog.h @@ -0,0 +1,122 @@ +/*************************************************************************** + * Copyright (C) 2005 Tobi Vollebregt * + * tobivollebregt@gmail.com * + * * + * Copyright (C) 2005 by Joe Ferris * + * jferris@optimistictech.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef CALCULATORCATALOG_H +#define CALCULATORCATALOG_H + +#include <kgenericfactory.h> + +#include <qmap.h> +#include <qptrlist.h> +#include <qstring.h> +#include <qvaluevector.h> + +#include "expression.h" +#include "katapultcatalog.h" + +class QWidget; + +typedef double (*FunPtr)(double); + +/** +@author Tobi Vollebregt + */ +class CalculatorCatalog : public KatapultCatalog +{ + Q_OBJECT + + public: + + struct ParserControl { + const char* expression; + CalculatorCatalog* catalog; + bool assignments; //are assignments enabled? + double result; + }; + + struct Function { + const char* name; + int length; + FunPtr fptr; + }; + + CalculatorCatalog(QObject*, const char*, const QStringList&); + virtual ~CalculatorCatalog(); + + //virtual void initialize(); + virtual void readSettings(KConfigBase*); + virtual void writeSettings(KConfigBase*); + virtual QWidget* configure(); + + int getVarID(const char*); + double getVar(int) const; + double setVar(int, double); + + int fracDigits() const; + bool scientific() const; + bool degrees() const; + bool clipboard() const; + QString formatString() const; + const Function* functionTable() const; + + protected: + + virtual void queryChanged(); + + private: + + typedef QMap<QString, int> VarNameToIdMap; + typedef QValueVector<double> VarIdToValueVector; + + static const Function radiansFunctionTable[]; + static const Function degreesFunctionTable[]; + + void reset(); + bool accepts(const QString&) const; + + Expression _result; // The one result (there's always one). + + VarNameToIdMap varNameToId; // Maps strings to IDs. + VarIdToValueVector varIdToValue; // Maps IDs to values. + QString _pendingVarName; // Pending while rest of assignment is parsed. + + int _fracDigits; // Number of fractional digits. + bool _bScientific; // Normal or scientific mode? + bool _bDegrees; // Radians or degrees? + bool _bClipboard; // Copy to clipboard? + QString _formatString; // for clipboard copy + + private slots: + + void fracDigitsChanged(int); + void scientificChanged(bool); + void degreesChanged(bool); + void clipboardChanged(bool); + void formatStringChanged(const QString&); + +}; + + +/* from parser.y / parser.cpp: */ +int yyparse(CalculatorCatalog::ParserControl*); + +#endif diff --git a/katapult/plugins/catalogs/calculatorcatalog/expression.cpp b/katapult/plugins/catalogs/calculatorcatalog/expression.cpp new file mode 100644 index 0000000..37e80bc --- /dev/null +++ b/katapult/plugins/catalogs/calculatorcatalog/expression.cpp @@ -0,0 +1,94 @@ +/*************************************************************************** + * Copyright (C) 2005 Tobi Vollebregt * + * tobivollebregt@gmail.com * + * * + * Copyright (C) 2005 by Joe Ferris * + * jferris@optimistictech.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include <kservice.h> +#include <kglobal.h> +#include <kiconloader.h> + +#include "calculatorcatalog.h" +#include "expression.h" + + +Expression::Expression(CalculatorCatalog* catalog, const QString& text): KatapultItem(), _catalog(catalog), _text(text) +{ + evaluate(); +} + +QPixmap Expression::icon(int size) const +{ + const char* icon = "checkmark"; + if (_parseError) { + icon = "no"; + } + return KGlobal::iconLoader()->loadIcon(icon, KIcon::NoGroup, size); +} + +QString Expression::text() const +{ + return _text; +} + +void Expression::setText(const QString& text) +{ + _text = text; + evaluate(); +} + +double Expression::result() const +{ + return _result; +} + +bool Expression::parseError() const +{ + return _parseError; +} + +CalculatorCatalog* Expression::catalog() const +{ + return _catalog; +} + +void Expression::evaluate(bool assignments) const +{ + if (!_text.isEmpty()) { + QString t = _text; + CalculatorCatalog::ParserControl cntrl; + cntrl.expression = t.replace(',', '.').ascii(); + cntrl.catalog = _catalog; + cntrl.assignments = assignments; + if (yyparse(&cntrl) == 0) { + _result = cntrl.result; + _parseError = false; + if (assignments) { + _catalog->setVar(_catalog->getVarID("ans"), _result); + } + } else { + _parseError = true; + } + } else { + _parseError = true; + } +} + +#include "expression.moc" diff --git a/katapult/plugins/catalogs/calculatorcatalog/expression.h b/katapult/plugins/catalogs/calculatorcatalog/expression.h new file mode 100644 index 0000000..6d736f9 --- /dev/null +++ b/katapult/plugins/catalogs/calculatorcatalog/expression.h @@ -0,0 +1,60 @@ +/*************************************************************************** + * Copyright (C) 2005 Tobi Vollebregt * + * tobivollebregt@gmail.com * + * * + * Copyright (C) 2005 by Joe Ferris * + * jferris@optimistictech.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef EXPRESSION_H +#define EXPRESSION_H + +#include <katapultitem.h> + +class CalculatorCatalog; + +/** +@author Tobi Vollebregt +*/ +class Expression : public KatapultItem +{ + Q_OBJECT + public: + Expression(CalculatorCatalog*, const QString&); + + virtual QPixmap icon(int) const; + virtual QString text() const; + + void setText(const QString&); + double result() const; + bool parseError() const; + + //evaluate() must be const, or ActionEvaluateExpression::execute() can't call it. + //It makes sense because evaluate() does _not_ change the expression, + //it just calculates the result and remembers that. + void evaluate(bool assignments = false) const; + + CalculatorCatalog* catalog() const; + + private: + CalculatorCatalog* const _catalog; + QString _text; + mutable double _result; + mutable bool _parseError; +}; + +#endif diff --git a/katapult/plugins/catalogs/calculatorcatalog/hi128-action-checkmark.png b/katapult/plugins/catalogs/calculatorcatalog/hi128-action-checkmark.png Binary files differnew file mode 100644 index 0000000..9854f79 --- /dev/null +++ b/katapult/plugins/catalogs/calculatorcatalog/hi128-action-checkmark.png diff --git a/katapult/plugins/catalogs/calculatorcatalog/hi128-action-no.png b/katapult/plugins/catalogs/calculatorcatalog/hi128-action-no.png Binary files differnew file mode 100644 index 0000000..dae60fe --- /dev/null +++ b/katapult/plugins/catalogs/calculatorcatalog/hi128-action-no.png diff --git a/katapult/plugins/catalogs/calculatorcatalog/hi128-app-xcalc.png b/katapult/plugins/catalogs/calculatorcatalog/hi128-app-xcalc.png Binary files differnew file mode 100644 index 0000000..9330ae7 --- /dev/null +++ b/katapult/plugins/catalogs/calculatorcatalog/hi128-app-xcalc.png diff --git a/katapult/plugins/catalogs/calculatorcatalog/katapult_calculatorcatalog.desktop b/katapult/plugins/catalogs/calculatorcatalog/katapult_calculatorcatalog.desktop new file mode 100644 index 0000000..c528b32 --- /dev/null +++ b/katapult/plugins/catalogs/calculatorcatalog/katapult_calculatorcatalog.desktop @@ -0,0 +1,44 @@ +# Copyright (C) 2005 Tobi Vollebregt +[Desktop Entry] +Name=Calculator Catalog +Name[ar]=مستعرض الآلة الحاسبة ( Calculator Catalog ) +Name[bg]=Каталог на калкулатора +Name[br]=Katalog jederez +Name[da]=Katalogisér beregninger +Name[de]=Rechner-Katalog +Name[el]=Κατάλογος υπολογισμών +Name[es]=Catalogador de calculadora +Name[et]=Kalkulaatorikataloog +Name[fr]=Catalogue calculatrice +Name[gl]=Catálogo de Calculadora +Name[it]=Catalogo calcolatrice +Name[ja]=計算機カタログ +Name[nb]=Kalkulatorkatalog +Name[nl]=Rekenmachinecatalogus +Name[pt]=Catálogo da Calculadora +Name[pt_BR]=Catálogo da Calculadora +Name[sv]=Katalogisera beräkningar +Name[tr]=Hesap Makinesi Kataloğu +Name[uk]=Каталог калькулятора +Comment=Catalogs the set of real numbers for easy calculation through katapult. +Comment[ar]=يستعرض مجموعة ارقامك الحقيقية لعملية الحساب عن طريق katapult. +Comment[bg]=Каталогизира с Katapult набора от числа с цел лесно пресмятане. +Comment[da]=Katalogiserer mængden af reelle tal for nem beregning via Katapult. +Comment[de]=Katalogisiert den Satz reeller Zahlen für einfaches Rechnen mit Katapult +Comment[el]=Δημιουργεί κατάλογο με πραγματικούς αριθμούς για εύκολους υπολογισμούς μέσω του katapult. +Comment[es]=Cataloga un conjunto de números reales para realizar con facilidad cálculos a través de katapult. +Comment[et]=Kataloogib reaalarvud hõlpsaks arvutamiseks Katapulti abil. +Comment[fr]=Cataloguer un ensemble de valeurs pour un calcul facile via Katapult +Comment[gl]=Cataloga os números reais para seren calculados mediante katapult. +Comment[it]=Cataloga l'insieme dei numeri reali per effettuare calcoli facilmente attraverso Katapult. +Comment[ja]=Katapult から簡単に計算できるように実数のセットをカタログ化 +Comment[nb]=Katalogiserer mengden av reelle tall for enkel beregning via Katapult. +Comment[nl]=Catalogiseert een set echte getallen voor eenvoudige berekening via katapult. +Comment[pt]=Cataloga o conjunto de números reais para um cálculo simples através do Katapult. +Comment[pt_BR]=Cataloga o conjunto de números reais para um cálculo simples através do Katapult. +Comment[sv]=Katalogiserar mängden reella tal för enkel beräkning via Katapult. +Comment[uk]=Робить каталог простих чисел для легких підрахунків через Катапульту. +ServiceTypes=Katapult/Catalog +Type=Service +X-KDE-Library=katapult_calculatorcatalog +X-Katapult-ID=Calculator Catalog diff --git a/katapult/plugins/catalogs/calculatorcatalog/parser.cpp b/katapult/plugins/catalogs/calculatorcatalog/parser.cpp new file mode 100644 index 0000000..995cbb2 --- /dev/null +++ b/katapult/plugins/catalogs/calculatorcatalog/parser.cpp @@ -0,0 +1,1387 @@ +/* A Bison parser, made by GNU Bison 2.0. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Written by Richard Stallman by simplifying the original so called + ``semantic'' parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 1 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + NUM = 258, + FUN = 259, + VAR = 260, + NEG = 261 + }; +#endif +#define NUM 258 +#define FUN 259 +#define VAR 260 +#define NEG 261 + + + + +/* Copy the first part of user declarations. */ +#line 5 "plugins/catalogs/calculatorcatalog/parser.y" + +#define YYLEX_PARAM parsercontrol + +#include <math.h> +#include <stdio.h> +#include "calculatorcatalog.h" + +//void yyerror(char const *); +#define yyerror(a,b) + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +#line 22 "plugins/catalogs/calculatorcatalog/parser.y" +typedef union YYSTYPE { + double val; /* For returning numbers. */ + FunPtr fptr; /* For returning function pointers. */ + int id; /* For returning variables. */ +} YYSTYPE; +/* Line 190 of yacc.c. */ +#line 105 "plugins/catalogs/calculatorcatalog/parser.cpp" +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations. */ +#line 39 "plugins/catalogs/calculatorcatalog/parser.y" + +static int yylex(YYSTYPE* lvalp, CalculatorCatalog::ParserControl* parsercontrol); + + +/* Line 213 of yacc.c. */ +#line 120 "plugins/catalogs/calculatorcatalog/parser.cpp" + +#if ! defined (yyoverflow) || YYERROR_VERBOSE + +# ifndef YYFREE +# define YYFREE free +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# endif + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# else +# define YYSTACK_ALLOC alloca +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# endif +#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short int yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined (__GNUC__) && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + register YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined (__STDC__) || defined (__cplusplus) + typedef signed char yysigned_char; +#else + typedef short int yysigned_char; +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 13 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 47 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 15 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 3 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 13 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 28 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 261 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const unsigned char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 13, 14, 9, 8, 2, 7, 2, 10, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 6, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 12, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 11 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const unsigned char yyprhs[] = +{ + 0, 0, 3, 5, 9, 11, 15, 19, 23, 27, + 30, 34, 38, 43 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yysigned_char yyrhs[] = +{ + 16, 0, -1, 17, -1, 5, 6, 17, -1, 3, + -1, 17, 8, 17, -1, 17, 7, 17, -1, 17, + 9, 17, -1, 17, 10, 17, -1, 7, 17, -1, + 17, 12, 17, -1, 13, 17, 14, -1, 4, 13, + 17, 14, -1, 5, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const unsigned char yyrline[] = +{ + 0, 45, 45, 46, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE +/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "NUM", "FUN", "VAR", "'='", "'-'", "'+'", + "'*'", "'/'", "NEG", "'^'", "'('", "')'", "$accept", "line", "exp", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const unsigned short int yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 61, 45, 43, 42, + 47, 261, 94, 40, 41 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const unsigned char yyr1[] = +{ + 0, 15, 16, 16, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const unsigned char yyr2[] = +{ + 0, 2, 1, 3, 1, 3, 3, 3, 3, 2, + 3, 3, 4, 1 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const unsigned char yydefact[] = +{ + 0, 4, 0, 13, 0, 0, 0, 2, 0, 0, + 13, 9, 0, 1, 0, 0, 0, 0, 0, 0, + 3, 11, 6, 5, 7, 8, 10, 12 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yysigned_char yydefgoto[] = +{ + -1, 6, 7 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -12 +static const yysigned_char yypact[] = +{ + 12, -12, -11, 2, 17, 17, 3, 35, 17, 17, + -12, 6, 19, -12, 17, 17, 17, 17, 17, 27, + 35, -12, -3, -3, 6, 6, 6, -12 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yysigned_char yypgoto[] = +{ + -12, -12, -4 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -1 +static const unsigned char yytable[] = +{ + 11, 12, 8, 13, 19, 20, 16, 17, 9, 18, + 22, 23, 24, 25, 26, 1, 2, 3, 18, 4, + 1, 2, 10, 0, 4, 5, 14, 15, 16, 17, + 5, 18, 0, 21, 14, 15, 16, 17, 0, 18, + 0, 27, 14, 15, 16, 17, 0, 18 +}; + +static const yysigned_char yycheck[] = +{ + 4, 5, 13, 0, 8, 9, 9, 10, 6, 12, + 14, 15, 16, 17, 18, 3, 4, 5, 12, 7, + 3, 4, 5, -1, 7, 13, 7, 8, 9, 10, + 13, 12, -1, 14, 7, 8, 9, 10, -1, 12, + -1, 14, 7, 8, 9, 10, -1, 12 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const unsigned char yystos[] = +{ + 0, 3, 4, 5, 7, 13, 16, 17, 13, 6, + 5, 17, 17, 0, 7, 8, 9, 10, 12, 17, + 17, 14, 17, 17, 17, 17, 17, 14 +}; + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (parsercontrol, "syntax error: cannot back up");\ + YYERROR; \ + } \ +while (0) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (N) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (0) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, YYLEX_PARAM) +#else +# define YYLEX yylex (&yylval) +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yysymprint (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_stack_print (short int *bottom, short int *top) +#else +static void +yy_stack_print (bottom, top) + short int *bottom; + short int *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (/* Nothing. */; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_reduce_print (int yyrule) +#else +static void +yy_reduce_print (yyrule) + int yyrule; +#endif +{ + int yyi; + unsigned int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", + yyrule - 1, yylno); + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) + YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); + YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + register const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; +} +# endif +# endif + +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif +{ + register char *yyd = yydest; + register const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +#endif /* !YYERROR_VERBOSE */ + + + +#if YYDEBUG +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) +#else +static void +yysymprint (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + switch (yytype) + { + default: + break; + } + YYFPRINTF (yyoutput, ")"); +} + +#endif /* ! YYDEBUG */ +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM); +# else +int yyparse (); +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int yyparse (CalculatorCatalog::ParserControl* parsercontrol); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM) +# else +int yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int +yyparse (CalculatorCatalog::ParserControl* parsercontrol) +#else +int +yyparse (parsercontrol) + CalculatorCatalog::ParserControl* parsercontrol; +#endif +#endif +{ + /* The look-ahead symbol. */ +int yychar; + +/* The semantic value of the look-ahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + register int yystate; + register int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ + int yytoken = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short int yyssa[YYINITDEPTH]; + short int *yyss = yyssa; + register short int *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + register YYSTYPE *yyvsp; + + + +#define YYPOPSTACK (yyvsp--, yyssp--) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ + int yylen; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + + yyvsp[0] = yylval; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short int *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyoverflowlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyoverflowlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + short int *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyoverflowlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a look-ahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to look-ahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a look-ahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the look-ahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; + + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + yystate = yyn; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: +#line 45 "plugins/catalogs/calculatorcatalog/parser.y" + { parsercontrol->result = (yyvsp[0].val); ;} + break; + + case 3: +#line 46 "plugins/catalogs/calculatorcatalog/parser.y" + { if (parsercontrol->assignments) parsercontrol->catalog->setVar((yyvsp[-2].id), (yyvsp[0].val)); ;} + break; + + case 4: +#line 49 "plugins/catalogs/calculatorcatalog/parser.y" + { (yyval.val) = (yyvsp[0].val); ;} + break; + + case 5: +#line 50 "plugins/catalogs/calculatorcatalog/parser.y" + { (yyval.val) = (yyvsp[-2].val) + (yyvsp[0].val); ;} + break; + + case 6: +#line 51 "plugins/catalogs/calculatorcatalog/parser.y" + { (yyval.val) = (yyvsp[-2].val) - (yyvsp[0].val); ;} + break; + + case 7: +#line 52 "plugins/catalogs/calculatorcatalog/parser.y" + { (yyval.val) = (yyvsp[-2].val) * (yyvsp[0].val); ;} + break; + + case 8: +#line 53 "plugins/catalogs/calculatorcatalog/parser.y" + { (yyval.val) = (yyvsp[-2].val) / (yyvsp[0].val); ;} + break; + + case 9: +#line 54 "plugins/catalogs/calculatorcatalog/parser.y" + { (yyval.val) = -(yyvsp[0].val); ;} + break; + + case 10: +#line 55 "plugins/catalogs/calculatorcatalog/parser.y" + { (yyval.val) = pow((yyvsp[-2].val), (yyvsp[0].val)); ;} + break; + + case 11: +#line 56 "plugins/catalogs/calculatorcatalog/parser.y" + { (yyval.val) = (yyvsp[-1].val); ;} + break; + + case 12: +#line 57 "plugins/catalogs/calculatorcatalog/parser.y" + { (yyval.val) = (*(yyvsp[-3].fptr))((yyvsp[-1].val)); ;} + break; + + case 13: +#line 58 "plugins/catalogs/calculatorcatalog/parser.y" + { if ((yyvsp[0].id) == -1) {yyerror(parsercontrol, "undeclared variable"); YYABORT;} (yyval.val) = parsercontrol->catalog->getVar((yyvsp[0].id)); ;} + break; + + + } + +/* Line 1037 of yacc.c. */ +#line 1098 "plugins/catalogs/calculatorcatalog/parser.cpp" + + yyvsp -= yylen; + yyssp -= yylen; + + + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (YYPACT_NINF < yyn && yyn < YYLAST) + { + YYSIZE_T yysize = 0; + int yytype = YYTRANSLATE (yychar); + const char* yyprefix; + char *yymsg; + int yyx; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 0; + + yyprefix = ", expecting "; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]); + yycount += 1; + if (yycount == 5) + { + yysize = 0; + break; + } + } + yysize += (sizeof ("syntax error, unexpected ") + + yystrlen (yytname[yytype])); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) + { + char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); + yyp = yystpcpy (yyp, yytname[yytype]); + + if (yycount < 5) + { + yyprefix = ", expecting "; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + yyp = yystpcpy (yyp, yyprefix); + yyp = yystpcpy (yyp, yytname[yyx]); + yyprefix = " or "; + } + } + yyerror (parsercontrol, yymsg); + YYSTACK_FREE (yymsg); + } + else + yyerror (parsercontrol, "syntax error; also virtual memory exhausted"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror (parsercontrol, "syntax error"); + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse look-ahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* If at end of input, pop the error token, + then the rest of the stack, then return failure. */ + if (yychar == YYEOF) + for (;;) + { + + YYPOPSTACK; + if (yyssp == yyss) + YYABORT; + yydestruct ("Error: popping", + yystos[*yyssp], yyvsp); + } + } + else + { + yydestruct ("Error: discarding", yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse look-ahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + +#ifdef __GNUC__ + /* Pacify GCC when the user code never invokes YYERROR and the label + yyerrorlab therefore never appears in user code. */ + if (0) + goto yyerrorlab; +#endif + +yyvsp -= yylen; + yyssp -= yylen; + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", yystos[yystate], yyvsp); + YYPOPSTACK; + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yydestruct ("Error: discarding lookahead", + yytoken, &yylval); + yychar = YYEMPTY; + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*----------------------------------------------. +| yyoverflowlab -- parser overflow comes here. | +`----------------------------------------------*/ +yyoverflowlab: + yyerror (parsercontrol, "parser stack overflow"); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} + + +#line 61 "plugins/catalogs/calculatorcatalog/parser.y" + + +/* The lexical analyzer returns a double floating point +number on the stack and the token NUM, or the numeric code +of the character read if not a number. It skips all blanks +and tabs, and returns 0 for end-of-input. */ + +#include <ctype.h> +#include <string.h> + +#define exp (parsercontrol->expression) + +static int yylex(YYSTYPE* lvalp, CalculatorCatalog::ParserControl* parsercontrol) +{ + int c; + + /* Skip white space. */ + while ((c = *(exp++)) == ' ') { + } + /* Return end-of-input. */ + if (c == EOF) { + return 0; + } + /* Process numbers. */ + if (c == '.' || isdigit(c)) { + char *endptr = 0; + lvalp->val = strtod(exp - 1, &endptr); + exp = endptr; + return NUM; + } + /* Process IDs. */ + if (isalpha(c)) { + int length = 0; + char f[128]; + + --exp; + do { + f[length] = tolower(c); + ++length; + } while ((c = exp[length]) != 0 && isalpha(c)); + f[length] = 0; + + /* Process functions. */ + const CalculatorCatalog::Function* const functions = parsercontrol->catalog->functionTable(); + for (int i = 0; functions[i].name; ++i) { + if (length == functions[i].length && strcmp(f, functions[i].name) == 0) { + lvalp->fptr = functions[i].fptr; + exp += length; + return FUN; + } + } + + /* Process variables. */ + lvalp->id = parsercontrol->catalog->getVarID(f); + exp += length; + return VAR; + } + /* Return a single char. */ + return c; +} + + diff --git a/katapult/plugins/catalogs/calculatorcatalog/parser.y b/katapult/plugins/catalogs/calculatorcatalog/parser.y new file mode 100644 index 0000000..b614a70 --- /dev/null +++ b/katapult/plugins/catalogs/calculatorcatalog/parser.y @@ -0,0 +1,120 @@ +/* Author: Tobi Vollebregt */ + +/* Infix notation calculator. */ + +%{ +#define YYLEX_PARAM parsercontrol + +#include <math.h> +#include <stdio.h> +#include "calculatorcatalog.h" + +//void yyerror(char const *); +#define yyerror(a,b) +%} + +/* Be a reentrant parser. */ +%pure_parser + +%parse-param {CalculatorCatalog::ParserControl* parsercontrol} + +/* Bison declarations. */ +%union { + double val; /* For returning numbers. */ + FunPtr fptr; /* For returning function pointers. */ + int id; /* For returning variables. */ +} + +%token <val> NUM /* Simple double precision number. */ +%token <fptr> FUN /* Function. */ +%token <id> VAR /* Variable. */ +%type <val> exp + +%right '=' /* assignment */ +%left '-' '+' +%left '*' '/' +%left NEG /* negation--unary minus */ +%right '^' /* exponentiation */ + +%{ +static int yylex(YYSTYPE* lvalp, CalculatorCatalog::ParserControl* parsercontrol); +%} + +%% /* The grammar follows. */ + +line: exp { parsercontrol->result = $1; } +| VAR '=' exp { if (parsercontrol->assignments) parsercontrol->catalog->setVar($1, $3); } +; + +exp: NUM { $$ = $1; } +| exp '+' exp { $$ = $1 + $3; } +| exp '-' exp { $$ = $1 - $3; } +| exp '*' exp { $$ = $1 * $3; } +| exp '/' exp { $$ = $1 / $3; } +| '-' exp %prec NEG { $$ = -$2; } +| exp '^' exp { $$ = pow($1, $3); } +| '(' exp ')' { $$ = $2; } +| FUN '(' exp ')' { $$ = (*$1)($3); } +| VAR { if ($1 == -1) {yyerror(parsercontrol, "undeclared variable"); YYABORT;} $$ = parsercontrol->catalog->getVar($1); } +; + +%% + +/* The lexical analyzer returns a double floating point +number on the stack and the token NUM, or the numeric code +of the character read if not a number. It skips all blanks +and tabs, and returns 0 for end-of-input. */ + +#include <ctype.h> +#include <string.h> + +#define exp (parsercontrol->expression) + +static int yylex(YYSTYPE* lvalp, CalculatorCatalog::ParserControl* parsercontrol) +{ + int c; + + /* Skip white space. */ + while ((c = *(exp++)) == ' ') { + } + /* Return end-of-input. */ + if (c == EOF) { + return 0; + } + /* Process numbers. */ + if (c == '.' || isdigit(c)) { + char *endptr = 0; + lvalp->val = strtod(exp - 1, &endptr); + exp = endptr; + return NUM; + } + /* Process IDs. */ + if (isalpha(c)) { + int length = 0; + char f[128]; + + --exp; + do { + f[length] = tolower(c); + ++length; + } while ((c = exp[length]) != 0 && isalpha(c)); + f[length] = 0; + + /* Process functions. */ + const CalculatorCatalog::Function* const functions = parsercontrol->catalog->functionTable(); + for (int i = 0; functions[i].name; ++i) { + if (length == functions[i].length && strcmp(f, functions[i].name) == 0) { + lvalp->fptr = functions[i].fptr; + exp += length; + return FUN; + } + } + + /* Process variables. */ + lvalp->id = parsercontrol->catalog->getVarID(f); + exp += length; + return VAR; + } + /* Return a single char. */ + return c; +} diff --git a/katapult/plugins/catalogs/calculatorcatalog/settings.ui b/katapult/plugins/catalogs/calculatorcatalog/settings.ui new file mode 100644 index 0000000..67c0faa --- /dev/null +++ b/katapult/plugins/catalogs/calculatorcatalog/settings.ui @@ -0,0 +1,219 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>CalculatorCatalogSettings</class> +<widget class="QWidget"> + <property name="name"> + <cstring>CalculatorCatalogSettings</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>336</width> + <height>299</height> + </rect> + </property> + <property name="caption"> + <string>Settings</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout13</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Number of fractional digits:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>fracDigits</cstring> + </property> + </widget> + <widget class="KIntSpinBox"> + <property name="name"> + <cstring>fracDigits</cstring> + </property> + <property name="maxValue"> + <number>10</number> + </property> + <property name="minValue"> + <number>0</number> + </property> + <property name="lineStep"> + <number>1</number> + </property> + <property name="whatsThis" stdset="0"> + <string>Katapult will show this number of fractional digits.</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>buttonGroup2</cstring> + </property> + <property name="title"> + <string></string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>normal</cstring> + </property> + <property name="text"> + <string>Normal</string> + </property> + <property name="whatsThis" stdset="0"> + <string>In normal mode, katapult will never show an exponent on a number.</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>scientific</cstring> + </property> + <property name="text"> + <string>Scientific</string> + </property> + <property name="whatsThis" stdset="0"> + <string>In scientific mode, katapult will show an exponent on very large or very small numbers.</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>buttonGroup3</cstring> + </property> + <property name="title"> + <string></string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>radians</cstring> + </property> + <property name="text"> + <string>Radians</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Trigonometric functions expect and return angles in radians (2 pi radians is a full circle).</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>degrees</cstring> + </property> + <property name="text"> + <string>Degrees</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Trigonometric functions expect and return angles in degrees (360 degrees is a full circle).</string> + </property> + </widget> + </vbox> + </widget> + </hbox> + </widget> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>clipboard</cstring> + </property> + <property name="title"> + <string>Copy to clipboard on execute</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="whatsThis" stdset="0"> + <string>katapult can copy the expression or the result of the expression to the clipboard if you press the key assigned to "execute action" (by default, this is Enter).</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout8</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="text"> + <string>Copied text:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>formatString</cstring> + </property> + </widget> + <widget class="QLineEdit"> + <property name="name"> + <cstring>formatString</cstring> + </property> + </widget> + </hbox> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_3</cstring> + </property> + <property name="text"> + <string><i>Hint:</i> %1 is replaced by the expression, %2 is replaced by the result</string> + </property> + </widget> + </vbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<tabstops> + <tabstop>fracDigits</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>knuminput.h</includehint> +</includehints> +</UI> |