/* This file was part of the SpeedCrunch project Copyright (C) 2004 Ariya Hidayat And is now part of abakus. Copyright (c) 2005 Michael Pyne 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 "evaluator.h" #include "function.h" #include "node.h" // For parser_yacc.hpp below #include "parser.h" #include #include #include #include #include #include // // Reimplementation of goodies from Evaluator follows. // Evaluator::Evaluator() { } Evaluator::~Evaluator() { } void Evaluator::setExpression(const TQString &expr) { kdError() << k_funcinfo << " not implemented.\n"; } TQString Evaluator::expression() const { kdError() << k_funcinfo << " not implemented.\n"; return TQString(); } 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 TQString &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; } TQString 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 TQString& text ) { Token::Op result = Token::InvalidOp; if( text.length() == 1 ) { TQChar 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 TQString& 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; } TQString Token::description() const { TQString 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( TQString::number( m_pos ) ); desc.append( " : " ).append( m_text ); return desc; } TQString Evaluator::autoFix( const TQString& expr ) { int par = 0; TQString result; // strip off all funny characters for( unsigned c = 0; c < expr.length(); c++ ) if( expr[c] >= TQChar(32) ) result.append( expr[c] ); // automagically close all parenthesis Tokens tokens = Evaluator::scan( result ); for( unsigned i=0; i 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; }