summaryrefslogtreecommitdiffstats
path: root/src/evaluator.cpp
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-09 06:41:55 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-09 06:41:55 +0000
commit8bec1dda934fa75cbb1402c58cb879b23305dc40 (patch)
treeb4294963397117f1cf022e7a62452697df996de3 /src/evaluator.cpp
downloadabakus-8bec1dda934fa75cbb1402c58cb879b23305dc40.tar.gz
abakus-8bec1dda934fa75cbb1402c58cb879b23305dc40.zip
Add abakus
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/abakus@1071969 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/evaluator.cpp')
-rw-r--r--src/evaluator.cpp261
1 files changed, 261 insertions, 0 deletions
diff --git a/src/evaluator.cpp b/src/evaluator.cpp
new file mode 100644
index 0000000..4b47d5e
--- /dev/null
+++ b/src/evaluator.cpp
@@ -0,0 +1,261 @@
+/* This file was part of the SpeedCrunch project
+ Copyright (C) 2004 Ariya Hidayat <[email protected]>
+
+ And is now part of abakus.
+ Copyright (c) 2005 Michael Pyne <[email protected]>
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02110-1301, USA.
+ */
+
+#include "evaluator.h"
+#include "function.h"
+#include "node.h" // For parser_yacc.hpp below
+#include "parser_yacc.hpp"
+
+#include <qapplication.h>
+#include <qmap.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qvaluevector.h>
+
+#include <kdebug.h>
+
+//
+// Reimplementation of goodies from Evaluator follows.
+//
+
+Evaluator::Evaluator()
+{
+}
+
+Evaluator::~Evaluator()
+{
+}
+
+void Evaluator::setExpression(const QString &expr)
+{
+ kdError() << k_funcinfo << " not implemented.\n";
+}
+
+QString Evaluator::expression() const
+{
+ kdError() << k_funcinfo << " not implemented.\n";
+ return QString();
+}
+
+void Evaluator::clear()
+{
+ kdError() << k_funcinfo << " not implemented.\n";
+ // Yeah, whatever.
+}
+
+bool Evaluator::isValid() const
+{
+ return true;
+}
+
+Tokens Evaluator::tokens() const
+{
+ kdError() << k_funcinfo << " not implemented.\n";
+ return Tokens();
+}
+
+Tokens Evaluator::scan(const QString &expr)
+{
+ Lexer l(expr);
+ Tokens tokens;
+
+ while(l.hasNext())
+ {
+ int t = l.nextType();
+ Token::Type type = Token::Unknown;
+
+ switch(t)
+ {
+ case POWER:
+ case '*':
+ case '(':
+ case ')':
+ case '-':
+ case '+':
+ case ',':
+ case '=':
+ type = Token::Operator;
+ break;
+
+ case NUM:
+ type = Token::Number;
+ break;
+
+ case SET:
+ case REMOVE:
+ case DERIV:
+ case FN:
+ case ID:
+ type = Token::Identifier;
+ break;
+
+ default:
+ type = Token::Unknown;
+ break;
+ }
+
+ tokens.append(Token(type, l.tokenValue(), l.tokenPos()));
+ }
+
+ return tokens;
+}
+
+QString Evaluator::error() const
+{
+ kdError() << k_funcinfo << " not implemented.\n";
+ return "No Error Yet";
+}
+
+///
+/// ARIYA'S CLASS CODE FOLLOWS
+///
+
+// for null token
+const Token Token::null;
+
+// helper function: return operator of given token text
+// e.g. "*" yields Operator::Asterisk, and so on
+static Token::Op matchOperator( const QString& text )
+{
+ Token::Op result = Token::InvalidOp;
+
+ if( text.length() == 1 )
+ {
+ QChar p = text[0];
+ switch( p.unicode() )
+ {
+ case '+': result = Token::Plus; break;
+ case '-': result = Token::Minus; break;
+ case '*': result = Token::Asterisk; break;
+ case '/': result = Token::Slash; break;
+ case '^': result = Token::Caret; break;
+ case ',': result = Token::Comma; break;
+ case '(': result = Token::LeftPar; break;
+ case ')': result = Token::RightPar; break;
+ case '%': result = Token::Percent; break;
+ case '=': result = Token::Equal; break;
+ default : result = Token::InvalidOp; break;
+ }
+ }
+
+ if( text.length() == 2 )
+ {
+ if( text == "**" ) result = Token::Caret;
+ }
+
+ return result;
+}
+
+// creates a token
+Token::Token( Type type, const QString& text, int pos )
+{
+ m_type = type;
+ m_text = text;
+ m_pos = pos;
+}
+
+// copy constructor
+Token::Token( const Token& token )
+{
+ m_type = token.m_type;
+ m_text = token.m_text;
+ m_pos = token.m_pos;
+}
+
+// assignment operator
+Token& Token::operator=( const Token& token )
+{
+ m_type = token.m_type;
+ m_text = token.m_text;
+ m_pos = token.m_pos;
+ return *this;
+}
+
+Abakus::number_t Token::asNumber() const
+{
+ if( isNumber() )
+ return Abakus::number_t( m_text.latin1() );
+ else
+ return Abakus::number_t();
+}
+
+Token::Op Token::asOperator() const
+{
+ if( isOperator() ) return matchOperator( m_text );
+ else return InvalidOp;
+}
+
+QString Token::description() const
+{
+ QString desc;
+
+ switch (m_type )
+ {
+ case Number: desc = "Number"; break;
+ case Identifier: desc = "Identifier"; break;
+ case Operator: desc = "Operator"; break;
+ default: desc = "Unknown"; break;
+ }
+
+ while( desc.length() < 10 ) desc.prepend( ' ' );
+ desc.prepend( " " );
+ desc.prepend( QString::number( m_pos ) );
+ desc.append( " : " ).append( m_text );
+
+ return desc;
+}
+
+
+QString Evaluator::autoFix( const QString& expr )
+{
+ int par = 0;
+ QString result;
+
+ // strip off all funny characters
+ for( unsigned c = 0; c < expr.length(); c++ )
+ if( expr[c] >= QChar(32) )
+ result.append( expr[c] );
+
+ // automagically close all parenthesis
+ Tokens tokens = Evaluator::scan( result );
+ for( unsigned i=0; i<tokens.count(); i++ )
+ if( tokens[i].asOperator() == Token::LeftPar ) par++;
+ else if( tokens[i].asOperator() == Token::RightPar ) par--;
+ for(; par > 0; par-- )
+ result.append( ')' );
+
+ // special treatment for simple function
+ // e.g. "cos" is regarded as "cos(ans)"
+ if( !result.isEmpty() )
+ {
+ Tokens tokens = Evaluator::scan( result );
+ if( (tokens.count() == 1) &&
+ FunctionManager::instance()->isFunction(tokens[0].text())
+ )
+ {
+ result.append( "(ans)" );
+ }
+ }
+
+ return result;
+}
+
+// vim: set et ts=8 sw=4: