AbaKus – a complex calculator
Je kunt niet meer dan 25 onderwerpen selecteren Onderwerpen moeten beginnen met een letter of nummer, kunnen streepjes bevatten ('-') en kunnen maximaal 35 tekens lang zijn.
 
 
 
 

261 regels
5.8 KiB

/* This file was part of the SpeedCrunch project
Copyright (C) 2004 Ariya Hidayat <ariya@kde.org>
And is now part of abakus.
Copyright (c) 2005 Michael Pyne <michael.pyne@kdemail.net>
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 <tqapplication.h>
#include <tqmap.h>
#include <tqstring.h>
#include <tqstringlist.h>
#include <tqvaluevector.h>
#include <kdebug.h>
//
// 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<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: