/*
* 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;
}