diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-09 06:41:55 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-09 06:41:55 +0000 |
commit | 8bec1dda934fa75cbb1402c58cb879b23305dc40 (patch) | |
tree | b4294963397117f1cf022e7a62452697df996de3 /src/evaluator.cpp | |
download | abakus-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.cpp | 261 |
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: |