/* 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: