OSDN Git Service

Automatically align underspecified tasks boundaries on project boundaries when possible.
[tjqt4port/tj2qt4.git] / taskjuggler / ExpressionTree.cpp
index 22d21b3..1280716 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * ExpressionTree.h - TaskJuggler
  *
- * Copyright (c) 2001, 2002 by Chris Schlaeger <cs@suse.de>
+ * Copyright (c) 2001, 2002, 2003, 2004 by Chris Schlaeger <cs@kde.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
  */
 
 #include "ExpressionTree.h"
-#include "CoreAttributes.h"
+#include "Operation.h"
 #include "Project.h"
-#include "Task.h"
-#include "Utility.h"
+#include "Resource.h"
+#include "ExpressionParser.h"
+#include "ExpressionFunctionTable.h"
+#include "TjMessageHandler.h"
+#include "tjlib-internal.h"
 
-// Dummy marco to mark all keywords of taskjuggler syntax
-#define KW(a) a
-
-QDict<int> ExpressionTree::funcArgc;
-
-long
-Operation::evalAsInt(ExpressionTree* et)
+// do not move this into the header, it expands the library image size
+ExpressionTree::ExpressionTree(const Operation* op) :
+    ca(0),
+    symbolTable(),
+    expression(op),
+    evalErrorFlag(false),
+    defFileName(),
+    defLineNo(0)
 {
-       switch (opt)
-       {
-       case Const:
-               return value;
-       case Variable:
-       case Id:
-               return et->resolve(name);
-       case Function:
-               return evalFunction(et);
-       case Date:
-               return value;
-       case Not:
-               return !ops.at(0)->evalAsInt(et);
-       case And:
-               return ops.at(0)->evalAsInt(et) && ops.at(1)->evalAsInt(et);
-       case Or:
-               return ops.at(0)->evalAsInt(et) || ops.at(1)->evalAsInt(et);
-       default:
-               qFatal("Operation::evalAsInt: "
-                          "Unknown opType %d (name: %s)", opt, name.ascii());
-               return 0;
-       }
+    symbolTable.setAutoDelete(true);
 }
 
-time_t
-Operation::evalAsTime(ExpressionTree* et)
+// do not move this into the header, it expands the library image size
+ExpressionTree::ExpressionTree(const ExpressionTree& et) :
+    ca(et.ca),
+    symbolTable(et.symbolTable),
+    expression(new Operation(*et.expression)),
+    evalErrorFlag(false),
+    defFileName(),
+    defLineNo(0)
 {
-       switch(opt)
-       {
-       case Const:
-       case Date:
-               return value;
-       case Variable:
-       case Id:
-               return et->resolve(name);
-       case Function:
-               return evalFunction(et);
-       default:
-               qFatal("Operation::evalAsTime: "
-                          "Unknown opType %d (name: %s)", opt, name.ascii());
-               return 0;
-       }
 }
 
-QString
-Operation::evalAsString(ExpressionTree* et)
+// do not move this into the header, it expands the library image size
+ExpressionTree::ExpressionTree() :
+    ca(0),
+    symbolTable(),
+    expression(0),
+    evalErrorFlag(false),
+    defFileName(),
+    defLineNo(0)
 {
-       switch(opt)
-       {
-       case Const:
-               return QString("%1").arg(value);
-       case Function:
-               return evalFunctionAsString(et);
-       case Date:
-               return time2date(value);
-       case Id:
-               return name;
-       default:
-               qFatal("Operation::evalAsString: "
-                          "Unknown opType %d (name: %s)", opt, name.ascii());
-               return QString::null;
-       }
+    symbolTable.setAutoDelete(true);
 }
 
-long
-Operation::evalFunction(ExpressionTree* et)
+ExpressionTree::~ExpressionTree()
 {
-       if (name == "istask")
-       {
-               return strcmp(et->getCoreAttributes()->getType(), "Task") == 0
-                       && et->getCoreAttributes()->getId() ==
-                       ops.at(0)->evalAsString(et);
-       }
-       else if (name == "issubtaskof")
-       {
-               if (strcmp(et->getCoreAttributes()->getType(), "Task") != 0)
-                       return 0;
-               Task* p;
-               if ((p = et->getCoreAttributes()->getProject()->getTask
-                        (ops.at(0)->evalAsString(et))) == 0)
-                       return 0;
-               return p->isSubTask((Task*) et->getCoreAttributes());
-       }
-       else if (name == "containstask")
-       {
-               if (strcmp(et->getCoreAttributes()->getType(), "Task") != 0)
-                       return 0;
-               Task* st;
-               if ((st = et->getCoreAttributes()->getProject()->getTask
-                        (ops.at(0)->evalAsString(et))) == 0)
-                       return 0;
-               return ((Task*) et->getCoreAttributes())->isSubTask(st);
-       }
-       else if (name == "ismilestone")
-       {
-               if (strcmp(et->getCoreAttributes()->getType(), "Task") != 0)
-                       return 0;
-               return ((Task*) et->getCoreAttributes())->isMilestone();
-       }
-       else if (name == "isresource")
-       {
-               return strcmp(et->getCoreAttributes()->getType(), "Resource") == 0
-                       && et->getCoreAttributes()->getId() ==
-                       ops.at(0)->evalAsString(et);
-       }
-       else if (name == "isaccount")
-       {
-               return strcmp(et->getCoreAttributes()->getType(), "Account") == 0
-                       && et->getCoreAttributes()->getId() ==
-                       ops.at(0)->evalAsString(et);
-       }
-       else if (name == "isplanallocated")
-       {
-               if (strcmp(et->getCoreAttributes()->getType(), "Resource") != 0)
-                       qFatal("Operation::evalFunction: isplanallocated called for "
-                                  "non-resource");
-               return ((Resource*) et->getCoreAttributes())->isPlanAllocated
-                       (Interval(ops.at(1)->evalAsTime(et), ops.at(2)->evalAsTime(et)), 
-                        ops.at(0)->evalAsString(et));
-       }
-       else if (name == "isactualallocated")
-       {
-               if (strcmp(et->getCoreAttributes()->getType(), "Resource") != 0)
-                       qFatal("Operation::evalFunction: isactualallocated called for "
-                                  "non-resource");
-               return ((Resource*) et->getCoreAttributes())->isActualAllocated
-                       (Interval(ops.at(1)->evalAsTime(et), ops.at(2)->evalAsTime(et)), 
-                        ops.at(0)->evalAsString(et));
-       }
-       else
-               qFatal("Unknown function %s", name.data());     
-
-       return 0;
+    delete expression;
 }
 
-QString
-Operation::evalFunctionAsString(ExpressionTree* )
+bool
+ExpressionTree::setTree(const QString& expr, const Project* proj)
 {
-       // There are no functions yet that return a string.
-       return QString::null;
+    ExpressionParser parser(expr, proj);
+    return (expression = parser.parse()) != 0;
 }
 
-ExpressionTree::ExpressionTree(Operation* op) : expression(op)
+long
+ExpressionTree::evalAsInt(const CoreAttributes* c)
 {
-       symbolTable.setAutoDelete(TRUE);
-       if (funcArgc.isEmpty())
-       {
-               funcArgc.insert(KW("istask"), new int(1));
-               funcArgc.insert(KW("issubtaskof"), new int(1));
-               funcArgc.insert(KW("containstask"), new int(1));
-               funcArgc.insert(KW("ismilestone"), new int(0));
-               funcArgc.insert(KW("isresource"), new int(1));
-               funcArgc.insert(KW("isaccount"), new int(1));
-               funcArgc.insert(KW("isplanallocated"), new int(3));
-               funcArgc.insert(KW("isactualallocated"), new int(3));
-       }
+    evalErrorFlag = false;
+    ca = c;
+    long val = expression->evalAsInt(this);
+
+    return val;
 }
 
 long
 ExpressionTree::resolve(const QString& symbol)
 {
-       return symbolTable[symbol] != 0 ? *(symbolTable[symbol]) : 0;
-}
+    if (!symbolTable[symbol])
+    {
+        errorMessage(i18n("Unknown identifier '%1' in logical expression")
+                     .arg(symbol));
+        return 0;
+    }
 
-bool
-ExpressionTree::isFunction(const QString& name)
-{
-       return funcArgc[name];
+    return *(symbolTable[symbol]);
 }
 
-int
-ExpressionTree::arguments(const QString& name)
+void
+ExpressionTree::errorMessage(const QString& msg)
 {
-       return *funcArgc[name];
+    TJMH.errorMessage(msg, defFileName, defLineNo);
+    evalErrorFlag = true;
 }