forked from qt-creator/qt-creator
reorganize AST
turn else, for(), defineTest() and defineReplace() into own node types instead of treating them as magic conditionals/functions. on top of that, introduce a proper branching node type, so finding the alternative code paths can be moved into the parser instead of burdening the evaluator with it.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -51,8 +51,8 @@ class ProFileEvaluator
|
||||
|
||||
public:
|
||||
struct FunctionDefs {
|
||||
QHash<QString, ProBlock *> testFunctions;
|
||||
QHash<QString, ProBlock *> replaceFunctions;
|
||||
QHash<QString, ProFunctionDef *> testFunctions;
|
||||
QHash<QString, ProFunctionDef *> replaceFunctions;
|
||||
};
|
||||
|
||||
enum TemplateType {
|
||||
|
||||
@@ -33,37 +33,55 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
ProBlock::ProBlock()
|
||||
: ProItem(BlockKind)
|
||||
void ProItem::disposeItems(ProItem *nitm)
|
||||
{
|
||||
m_proitems = 0;
|
||||
m_blockKind = 0;
|
||||
m_refCount = 1;
|
||||
for (ProItem *itm; (itm = nitm); ) {
|
||||
nitm = itm->next();
|
||||
switch (itm->kind()) {
|
||||
case ProItem::ConditionKind: delete static_cast<ProCondition *>(itm); break;
|
||||
case ProItem::VariableKind: delete static_cast<ProVariable *>(itm); break;
|
||||
case ProItem::BranchKind: delete static_cast<ProBranch *>(itm); break;
|
||||
case ProItem::LoopKind: delete static_cast<ProLoop *>(itm); break;
|
||||
case ProItem::FunctionDefKind: static_cast<ProFunctionDef *>(itm)->deref(); break;
|
||||
case ProItem::OpNotKind:
|
||||
case ProItem::OpAndKind:
|
||||
case ProItem::OpOrKind:
|
||||
delete itm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProBlock::~ProBlock()
|
||||
ProBranch::~ProBranch()
|
||||
{
|
||||
for (ProItem *itm, *nitm = m_proitems; (itm = nitm); ) {
|
||||
nitm = itm->m_next;
|
||||
switch (itm->kind()) {
|
||||
case BlockKind: static_cast<ProBlock *>(itm)->deref(); break;
|
||||
case ConditionKind: delete static_cast<ProCondition *>(itm); break;
|
||||
case OperatorKind: delete static_cast<ProOperator *>(itm); break;
|
||||
case VariableKind: delete static_cast<ProVariable *>(itm); break;
|
||||
}
|
||||
}
|
||||
disposeItems(m_thenItems);
|
||||
disposeItems(m_elseItems);
|
||||
}
|
||||
|
||||
ProLoop::~ProLoop()
|
||||
{
|
||||
disposeItems(m_proitems);
|
||||
}
|
||||
|
||||
ProFunctionDef::~ProFunctionDef()
|
||||
{
|
||||
disposeItems(m_proitems);
|
||||
}
|
||||
|
||||
ProFile::ProFile(const QString &fileName)
|
||||
: ProBlock()
|
||||
: m_proitems(0),
|
||||
m_refCount(1),
|
||||
m_fileName(fileName)
|
||||
{
|
||||
setBlockKind(ProBlock::ProFileKind);
|
||||
m_fileName = fileName;
|
||||
|
||||
int nameOff = fileName.lastIndexOf(QLatin1Char('/'));
|
||||
m_displayFileName = QString(fileName.constData() + nameOff + 1,
|
||||
fileName.length() - nameOff - 1);
|
||||
m_directoryName = QString(fileName.constData(), nameOff);
|
||||
}
|
||||
|
||||
ProFile::~ProFile()
|
||||
{
|
||||
ProItem::disposeItems(m_proitems);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -40,7 +40,7 @@ typedef QAtomicInt ProItemRefCount;
|
||||
#else
|
||||
class ProItemRefCount {
|
||||
public:
|
||||
ProItemRefCount() : m_cnt(0) {}
|
||||
ProItemRefCount(int cnt = 0) : m_cnt(cnt) {}
|
||||
bool ref() { return ++m_cnt != 0; }
|
||||
bool deref() { return --m_cnt != 0; }
|
||||
ProItemRefCount &operator=(int value) { m_cnt = value; return *this; }
|
||||
@@ -54,9 +54,13 @@ class ProItem
|
||||
public:
|
||||
enum ProItemKind {
|
||||
ConditionKind,
|
||||
OperatorKind,
|
||||
OpNotKind,
|
||||
OpAndKind,
|
||||
OpOrKind,
|
||||
VariableKind,
|
||||
BlockKind
|
||||
BranchKind,
|
||||
LoopKind,
|
||||
FunctionDefKind
|
||||
};
|
||||
|
||||
enum ProItemReturn {
|
||||
@@ -64,8 +68,6 @@ public:
|
||||
ReturnTrue,
|
||||
ReturnBreak,
|
||||
ReturnNext,
|
||||
ReturnLoop,
|
||||
ReturnSkip,
|
||||
ReturnReturn
|
||||
};
|
||||
|
||||
@@ -79,43 +81,12 @@ public:
|
||||
ProItem *next() const { return m_next; }
|
||||
ProItem **nextRef() { return &m_next; }
|
||||
|
||||
static void disposeItems(ProItem *nitm);
|
||||
|
||||
private:
|
||||
ProItem *m_next;
|
||||
ProItemKind m_kind;
|
||||
int m_lineNumber;
|
||||
|
||||
friend class ProBlock; // C++ is braindead ...
|
||||
};
|
||||
|
||||
class ProBlock : public ProItem
|
||||
{
|
||||
public:
|
||||
enum ProBlockKind {
|
||||
NormalKind = 0x00,
|
||||
ScopeKind = 0x01,
|
||||
ScopeContentsKind = 0x02,
|
||||
ProFileKind = 0x08,
|
||||
FunctionBodyKind = 0x10,
|
||||
SingleLine = 0x80
|
||||
};
|
||||
|
||||
ProBlock();
|
||||
~ProBlock();
|
||||
|
||||
void setBlockKind(int blockKind) { m_blockKind = blockKind; }
|
||||
int blockKind() const { return m_blockKind; }
|
||||
|
||||
ProItem *items() const { return m_proitems; }
|
||||
ProItem **itemsRef() { return &m_proitems; }
|
||||
|
||||
void ref() { m_refCount.ref(); }
|
||||
void deref() { if (!m_refCount.deref()) delete this; }
|
||||
|
||||
private:
|
||||
ProItem *m_proitems;
|
||||
int m_blockKind;
|
||||
friend class ProFile; // for the pseudo-virtual d'tor
|
||||
ProItemRefCount m_refCount;
|
||||
};
|
||||
|
||||
class ProVariable : public ProItem
|
||||
@@ -154,35 +125,82 @@ private:
|
||||
QString m_text;
|
||||
};
|
||||
|
||||
class ProOperator : public ProItem
|
||||
class ProBranch : public ProItem
|
||||
{
|
||||
public:
|
||||
enum OperatorKind {
|
||||
OrOperator = 1,
|
||||
NotOperator = 2
|
||||
};
|
||||
ProBranch() : ProItem(BranchKind) {}
|
||||
~ProBranch();
|
||||
|
||||
explicit ProOperator(OperatorKind operatorKind) : ProItem(ProItem::OperatorKind), m_operatorKind(operatorKind) {}
|
||||
void setOperatorKind(OperatorKind operatorKind) { m_operatorKind = operatorKind; }
|
||||
OperatorKind operatorKind() const { return m_operatorKind; }
|
||||
ProItem *thenItems() const { return m_thenItems; }
|
||||
ProItem **thenItemsRef() { return &m_thenItems; }
|
||||
ProItem *elseItems() const { return m_elseItems; }
|
||||
ProItem **elseItemsRef() { return &m_elseItems; }
|
||||
|
||||
private:
|
||||
OperatorKind m_operatorKind;
|
||||
ProItem *m_thenItems;
|
||||
ProItem *m_elseItems;
|
||||
};
|
||||
|
||||
class ProFile : public ProBlock
|
||||
class ProLoop : public ProItem
|
||||
{
|
||||
public:
|
||||
ProLoop(const QString &var, const QString &expr)
|
||||
: ProItem(LoopKind), m_variable(var), m_expression(expr) {}
|
||||
~ProLoop();
|
||||
|
||||
QString variable() const { return m_variable; }
|
||||
QString expression() const { return m_expression; }
|
||||
ProItem *items() const { return m_proitems; }
|
||||
ProItem **itemsRef() { return &m_proitems; }
|
||||
|
||||
private:
|
||||
QString m_variable;
|
||||
QString m_expression;
|
||||
ProItem *m_proitems;
|
||||
};
|
||||
|
||||
class ProFunctionDef : public ProItem
|
||||
{
|
||||
public:
|
||||
enum FunctionType { TestFunction, ReplaceFunction };
|
||||
|
||||
ProFunctionDef(const QString &name, FunctionType type)
|
||||
: ProItem(FunctionDefKind), m_name(name), m_type(type), m_refCount(1) {}
|
||||
~ProFunctionDef();
|
||||
|
||||
QString name() const { return m_name; }
|
||||
FunctionType type() const { return m_type; }
|
||||
ProItem *items() const { return m_proitems; }
|
||||
ProItem **itemsRef() { return &m_proitems; }
|
||||
|
||||
void ref() { m_refCount.ref(); }
|
||||
void deref() { if (!m_refCount.deref()) delete this; }
|
||||
|
||||
private:
|
||||
QString m_name;
|
||||
FunctionType m_type;
|
||||
ProItemRefCount m_refCount;
|
||||
ProItem *m_proitems;
|
||||
};
|
||||
|
||||
class ProFile
|
||||
{
|
||||
public:
|
||||
explicit ProFile(const QString &fileName);
|
||||
~ProFile();
|
||||
|
||||
QString displayFileName() const { return m_displayFileName; }
|
||||
QString fileName() const { return m_fileName; }
|
||||
QString directoryName() const { return m_directoryName; }
|
||||
ProItem *items() const { return m_proitems; }
|
||||
ProItem **itemsRef() { return &m_proitems; }
|
||||
|
||||
// d'tor is not virtual
|
||||
void ref() { m_refCount.ref(); }
|
||||
void deref() { if (!m_refCount.deref()) delete this; }
|
||||
|
||||
private:
|
||||
ProItem *m_proitems;
|
||||
ProItemRefCount m_refCount;
|
||||
QString m_fileName;
|
||||
QString m_displayFileName;
|
||||
QString m_directoryName;
|
||||
|
||||
@@ -84,12 +84,13 @@ void ProWriter::addFiles(ProFile *profile, QStringList *lines,
|
||||
*lines << added;
|
||||
}
|
||||
|
||||
static void findProVariables(ProBlock *block, const QStringList &vars,
|
||||
static void findProVariables(ProItem *item, const QStringList &vars,
|
||||
QList<ProVariable *> *proVars)
|
||||
{
|
||||
for (ProItem *item = block->items(); item; item = item->next()) {
|
||||
if (item->kind() == ProItem::BlockKind) {
|
||||
findProVariables(static_cast<ProBlock*>(item), vars, proVars);
|
||||
for (; item; item = item->next()) {
|
||||
if (item->kind() == ProItem::BranchKind) {
|
||||
findProVariables(static_cast<ProBranch*>(item)->thenItems(), vars, proVars);
|
||||
findProVariables(static_cast<ProBranch*>(item)->elseItems(), vars, proVars);
|
||||
} else if (item->kind() == ProItem::VariableKind) {
|
||||
ProVariable *proVar = static_cast<ProVariable*>(item);
|
||||
if (vars.contains(proVar->variable()))
|
||||
@@ -105,7 +106,7 @@ QStringList ProWriter::removeFiles(ProFile *profile, QStringList *lines,
|
||||
QStringList notChanged = filePaths;
|
||||
|
||||
QList<ProVariable *> proVars;
|
||||
findProVariables(profile, vars, &proVars);
|
||||
findProVariables(profile->items(), vars, &proVars);
|
||||
|
||||
// This is a tad stupid - basically, it can remove only entries which
|
||||
// the above code added.
|
||||
|
||||
Reference in New Issue
Block a user