00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdlib.h>
00022 #include <math.h>
00023 #include <float.h>
00024
00025 #include <kdebug.h>
00026
00027 #include <koscript_parser.h>
00028 #include <koscript_util.h>
00029 #include <koscript_func.h>
00030 #include <koscript_synext.h>
00031
00032 #include "kspread_interpreter.h"
00033
00034 #include "kspread_functions.h"
00035 #include "kspread_util.h"
00036 #include "kspread_sheet.h"
00037 #include "kspread_doc.h"
00038 #include "kspread_locale.h"
00039
00040
00041
00042
00043
00044
00045
00046
00050 class KSParseNodeExtraPoint : public KSParseNodeExtra
00051 {
00052 public:
00053 KSParseNodeExtraPoint( const QString& s, KSpreadMap* m, KSpreadSheet* t ) : m_point( s, m, t )
00054 {
00055 }
00056
00057 KSpreadPoint* point() { return &m_point; }
00058
00059 private:
00060 KSpreadPoint m_point;
00061 };
00062
00066 class KSParseNodeExtraRange : public KSParseNodeExtra
00067 {
00068 public:
00069 KSParseNodeExtraRange( const QString& s, KSpreadMap* m, KSpreadSheet* t )
00070 : m_range( s, m, t )
00071 {
00072 }
00073
00074 KSpreadRange* range() { return &m_range; }
00075
00076 private:
00077 KSpreadRange m_range;
00078 };
00079
00080
00081
00082
00083
00084
00085
00086 static bool kspreadfunc_cell( KSContext& context )
00087 {
00088 QValueList<KSValue::Ptr>& args = context.value()->listValue();
00089
00090 if ( !KSUtil::checkArgumentsCount( context, 3, "cell", true ) )
00091 return false;
00092
00093 if ( !KSUtil::checkType( context, args[0], KSValue::ListType, true ) )
00094 return false;
00095 if ( !KSUtil::checkType( context, args[1], KSValue::StringType, true ) )
00096 return false;
00097 if ( !KSUtil::checkType( context, args[2], KSValue::StringType, true ) )
00098 return false;
00099
00100 const QValueList<KSValue::Ptr>& lines = args[0]->listValue();
00101 if ( lines.count() < 2 )
00102 return FALSE;
00103
00104 QValueList<KSValue::Ptr>::ConstIterator it = lines.begin();
00105 if ( !KSUtil::checkType( context, (*it), KSValue::ListType, true ) )
00106 return false;
00107 const QValueList<KSValue::Ptr>& line = (*it)->listValue();
00108 QValueList<KSValue::Ptr>::ConstIterator it2 = line.begin();
00109 int x = 1;
00110 ++it;
00111 ++it2;
00112 for( ; it2 != line.end(); ++it2 )
00113 {
00114 if ( !KSUtil::checkType( context, (*it2), KSValue::StringType, true ) )
00115 return false;
00116 if ( (*it2)->stringValue() == args[1]->stringValue() )
00117 break;
00118 ++x;
00119 }
00120 if ( it2 == line.end() )
00121 return FALSE;
00122
00123 kdDebug(36001) <<"x= "<<x<<endl;
00124 for( ; it != lines.end(); ++it )
00125 {
00126 const QValueList<KSValue::Ptr>& l = (*it)->listValue();
00127 if ( x >= (int)l.count() )
00128 return FALSE;
00129 if ( l[0]->stringValue() == args[2]->stringValue() )
00130 {
00131 context.setValue( new KSValue( *(l[x]) ) );
00132 return TRUE;
00133 }
00134 }
00135
00136 context.setValue( new KSValue( 0.0 ) );
00137 return true;
00138 }
00139
00140 static bool kspreadfunc_select_helper( KSContext& context, QValueList<KSValue::Ptr>& args, QString& result )
00141 {
00142 QValueList<KSValue::Ptr>::Iterator it = args.begin();
00143 QValueList<KSValue::Ptr>::Iterator end = args.end();
00144
00145 for( ; it != end; ++it )
00146 {
00147 if ( KSUtil::checkType( context, *it, KSValue::ListType, false ) )
00148 {
00149 if ( !kspreadfunc_select_helper( context, (*it)->listValue(), result ) )
00150 return false;
00151 }
00152 else if ( !(*it)->toString( context ).isEmpty() )
00153 {
00154 if ( !result.isEmpty() )
00155 result += "\\";
00156 result += (*it)->toString( context );
00157 }
00158 }
00159
00160 return true;
00161 }
00162
00163 static bool kspreadfunc_select( KSContext& context )
00164 {
00165 QString result( "" );
00166 bool b = kspreadfunc_select_helper( context, context.value()->listValue(), result );
00167
00168 if ( b )
00169 context.setValue( new KSValue( result ) );
00170
00171 return b;
00172 }
00173
00174 static KSModule::Ptr kspreadCreateModule_KSpread( KSInterpreter* interp )
00175 {
00176 KSModule::Ptr module = new KSModule( interp, "kspread" );
00177
00178 module->addObject( "CELL", new KSValue( new KSBuiltinFunction( module, "CELL", kspreadfunc_cell ) ) );
00179 module->addObject( "SELECT", new KSValue( new KSBuiltinFunction( module, "SELECT", kspreadfunc_select ) ) );
00180
00181
00182 KSpreadFunctionRepository* repo = KSpreadFunctionRepository::self();
00183 QStringList functionList = repo->regFunctionNames();
00184 for( unsigned i = 0; i < functionList.count(); i++ )
00185 {
00186 QString name = functionList[i];
00187 KSpreadFunction* function = repo->function( name );
00188 if ( function && function->functionPtr )
00189 module->addObject( name, new KSValue( new KSBuiltinFunction( module, name, function->functionPtr ) ) );
00190 }
00191
00192 return module;
00193 }
00194
00195
00196
00197
00198
00199
00200
00201 KSpreadInterpreter::KSpreadInterpreter( KSpreadDoc * doc )
00202 : KSInterpreter(),
00203 m_cell( 0 ),
00204 m_doc( doc ),
00205 m_sheet( 0 )
00206 {
00207 KSModule::Ptr m = kspreadCreateModule_KSpread( this );
00208 m_modules.insert( m->name(), m );
00209
00210
00211 KSNamespace::Iterator it = m->nameSpace()->begin();
00212 KSNamespace::Iterator end = m->nameSpace()->end();
00213 for(; it != end; ++it )
00214 m_global->insert( it.key(), it.data() );
00215 }
00216
00217 bool KSpreadInterpreter::processExtension( KSContext& context, KSParseNode* node )
00218 {
00219 KSParseNodeExtra* extra = node->extra();
00220 if ( !extra )
00221 {
00222 if ( node->getType() == t_cell )
00223 extra = new KSParseNodeExtraPoint( node->getStringLiteral(), m_doc->map(), m_sheet );
00224 else if ( node->getType() == t_range )
00225 extra = new KSParseNodeExtraRange( node->getStringLiteral(), m_doc->map(), m_sheet );
00226 else
00227 return KSInterpreter::processExtension( context, node );
00228 node->setExtra( extra );
00229 }
00230
00231 if ( node->getType() == t_cell )
00232 {
00233 KSParseNodeExtraPoint* p = (KSParseNodeExtraPoint*)extra;
00234 KSpreadPoint* point = p->point();
00235
00236 if ( !point->isValid() )
00237 {
00238 QString tmp( i18n("The expression %1 is not valid") );
00239 tmp = tmp.arg( node->getStringLiteral() );
00240 context.setException( new KSException( "InvalidCellExpression", tmp ) );
00241 return false;
00242 }
00243
00244 KSpreadCell* cell = point->cell();
00245
00246 if ( cell->hasError() )
00247 {
00248 QString tmp( i18n("The cell %1 has an error:\n\n%2") );
00249 tmp = tmp.arg( cell->fullName() );
00250 tmp = tmp.arg( node->getStringLiteral() );
00251 context.setException( new KSException( "ErrorInCell", tmp ) );
00252 return false;
00253 }
00254
00255 if ( cell->isDefault())
00256 context.setValue( new KSValue( 0.0 ) );
00257 else if(cell->isObscured() && cell->isObscuringForced())
00258 context.setValue( new KSValue( 0.0 ) );
00259 else if ( cell->value().isBoolean() )
00260 context.setValue( new KSValue( cell->value().asBoolean() ) );
00261 else if ( cell->isTime() )
00262 context.setValue( new KSValue( cell->value().asTime() ) );
00263 else if ( cell->isDate() )
00264 context.setValue( new KSValue( cell->value().asDate() ) );
00265 else if ( cell->value().isNumber() )
00266 context.setValue( new KSValue( cell->value().asFloat() ) );
00267 else if ( cell->value().asString().isEmpty() )
00268 context.setValue( new KSValue( 0.0 ) );
00269 else
00270 context.setValue( new KSValue( cell->value().asString() ) );
00271 return true;
00272 }
00273
00274 else if ( node->getType() == t_range )
00275 {
00276 KSParseNodeExtraRange* p = (KSParseNodeExtraRange*)extra;
00277 KSpreadRange* r = p->range();
00278
00279
00280 if ( !r->isValid() )
00281 {
00282 QString tmp( i18n("The expression %1 is not valid") );
00283 tmp = tmp.arg( node->getStringLiteral() );
00284 context.setException( new KSException( "InvalidRangeExpression", tmp ) );
00285 return false;
00286 }
00287
00288 if ( r->range.left() == r->range.right()
00289 && r->range.top() == r->range.bottom() )
00290 {
00291 KSpreadCell * cell = r->sheet->cellAt( r->range.x(), r->range.y() );
00292
00293 if ( cell->hasError() )
00294 {
00295 QString tmp( i18n("The cell %1 has an error:\n\n%2") );
00296 tmp = tmp.arg( cell->fullName() );
00297 tmp = tmp.arg( node->getStringLiteral() );
00298 context.setException( new KSException( "ErrorInCell", tmp ) );
00299 return false;
00300 }
00301
00302 if ( cell->isDefault())
00303 context.setValue( new KSValue( 0.0 ) );
00304 else if(cell->isObscured() && cell->isObscuringForced())
00305 context.setValue( new KSValue( 0.0 ) );
00306 else if ( cell->value().isBoolean() )
00307 context.setValue( new KSValue( cell->value().asBoolean() ) );
00308 else if ( cell->isTime() )
00309 context.setValue( new KSValue( cell->value().asTime() ) );
00310 else if ( cell->isDate() )
00311 context.setValue( new KSValue( cell->value().asDate() ) );
00312 else if ( cell->value().isNumber() )
00313 context.setValue( new KSValue( cell->value().asFloat() ) );
00314 else if ( cell->value().asString().isEmpty() )
00315 context.setValue( new KSValue( 0.0 ) );
00316 else
00317 context.setValue( new KSValue( cell->value().asString() ) );
00318
00319 return true;
00320 }
00321
00322
00323 KSValue* v = new KSValue( KSValue::ListType );
00324 for( int y = 0; y < r->range.height(); ++y )
00325 {
00326 KSValue* l = new KSValue( KSValue::ListType );
00327
00328 for( int x = 0; x < r->range.width(); ++x )
00329 {
00330 KSValue* c;
00331 KSpreadCell* cell = r->sheet->cellAt( r->range.x() + x, r->range.y() + y );
00332
00333 if ( cell->hasError() )
00334 {
00335 QString tmp( i18n("The cell %1 has an error:\n\n%2") );
00336 tmp = tmp.arg( cell->fullName() );
00337 tmp = tmp.arg( node->getStringLiteral() );
00338 context.setException( new KSException( "ErrorInCell", tmp ) );
00339 return false;
00340 }
00341
00342 if ( cell->isDefault() )
00343 c = new KSValue( 0.0 );
00344 else if ( cell->value().isNumber() )
00345 c = new KSValue( cell->value().asFloat() );
00346 else if ( cell->value().isBoolean() )
00347 c = new KSValue( cell->value().asBoolean() );
00348 else if ( cell->isDate() )
00349 c = new KSValue( cell->value().asDate() );
00350 else if ( cell->isTime() )
00351 c = new KSValue( cell->value().asTime() );
00352 else if ( cell->value().asString().isEmpty() )
00353 c = new KSValue( 0.0 );
00354 else
00355 c = new KSValue( cell->value().asString() );
00356 if ( !(cell->isObscured() && cell->isObscuringForced()) )
00357 l->listValue().append( c );
00358 }
00359 v->listValue().append( l );
00360 }
00361 context.setValue( v );
00362
00363 return true;
00364 }
00365 else
00366 Q_ASSERT( 0 );
00367
00368
00369 return false;
00370 }
00371
00372 KSParseNode* KSpreadInterpreter::parse( KSContext& context, KSpreadSheet* sheet, const QString& formula )
00373 {
00374
00375 KSParser parser;
00376
00377 if ( !parser.parse( formula.utf8(), KSCRIPT_EXTENSION_KSPREAD, sheet->doc()->locale() ) )
00378 {
00379 context.setException( new KSException( "SyntaxError", parser.errorMessage() ) );
00380 return 0;
00381 }
00382
00383 KSParseNode* n = parser.donateParseTree();
00384
00385 return n;
00386 }
00387
00388 bool KSpreadInterpreter::evaluate( KSContext& context, KSParseNode* node, KSpreadSheet* sheet, KSpreadCell* cell )
00389 {
00390
00391 KSpreadSheet * t = m_sheet;
00392 KSpreadCell * c = m_cell;
00393 m_sheet = sheet;
00394 m_cell = cell;
00395
00396 bool b = node->eval( context );
00397
00398 m_sheet = t;
00399 m_cell = c;
00400
00401 return b;
00402 }