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:
|
public:
|
||||||
struct FunctionDefs {
|
struct FunctionDefs {
|
||||||
QHash<QString, ProBlock *> testFunctions;
|
QHash<QString, ProFunctionDef *> testFunctions;
|
||||||
QHash<QString, ProBlock *> replaceFunctions;
|
QHash<QString, ProFunctionDef *> replaceFunctions;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum TemplateType {
|
enum TemplateType {
|
||||||
|
|||||||
@@ -33,37 +33,55 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
ProBlock::ProBlock()
|
void ProItem::disposeItems(ProItem *nitm)
|
||||||
: ProItem(BlockKind)
|
|
||||||
{
|
{
|
||||||
m_proitems = 0;
|
for (ProItem *itm; (itm = nitm); ) {
|
||||||
m_blockKind = 0;
|
nitm = itm->next();
|
||||||
m_refCount = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProBlock::~ProBlock()
|
|
||||||
{
|
|
||||||
for (ProItem *itm, *nitm = m_proitems; (itm = nitm); ) {
|
|
||||||
nitm = itm->m_next;
|
|
||||||
switch (itm->kind()) {
|
switch (itm->kind()) {
|
||||||
case BlockKind: static_cast<ProBlock *>(itm)->deref(); break;
|
case ProItem::ConditionKind: delete static_cast<ProCondition *>(itm); break;
|
||||||
case ConditionKind: delete static_cast<ProCondition *>(itm); break;
|
case ProItem::VariableKind: delete static_cast<ProVariable *>(itm); break;
|
||||||
case OperatorKind: delete static_cast<ProOperator *>(itm); break;
|
case ProItem::BranchKind: delete static_cast<ProBranch *>(itm); break;
|
||||||
case VariableKind: delete static_cast<ProVariable *>(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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProFile::ProFile(const QString &fileName)
|
ProBranch::~ProBranch()
|
||||||
: ProBlock()
|
|
||||||
{
|
{
|
||||||
setBlockKind(ProBlock::ProFileKind);
|
disposeItems(m_thenItems);
|
||||||
m_fileName = fileName;
|
disposeItems(m_elseItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProLoop::~ProLoop()
|
||||||
|
{
|
||||||
|
disposeItems(m_proitems);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProFunctionDef::~ProFunctionDef()
|
||||||
|
{
|
||||||
|
disposeItems(m_proitems);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProFile::ProFile(const QString &fileName)
|
||||||
|
: m_proitems(0),
|
||||||
|
m_refCount(1),
|
||||||
|
m_fileName(fileName)
|
||||||
|
{
|
||||||
int nameOff = fileName.lastIndexOf(QLatin1Char('/'));
|
int nameOff = fileName.lastIndexOf(QLatin1Char('/'));
|
||||||
m_displayFileName = QString(fileName.constData() + nameOff + 1,
|
m_displayFileName = QString(fileName.constData() + nameOff + 1,
|
||||||
fileName.length() - nameOff - 1);
|
fileName.length() - nameOff - 1);
|
||||||
m_directoryName = QString(fileName.constData(), nameOff);
|
m_directoryName = QString(fileName.constData(), nameOff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProFile::~ProFile()
|
||||||
|
{
|
||||||
|
ProItem::disposeItems(m_proitems);
|
||||||
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ typedef QAtomicInt ProItemRefCount;
|
|||||||
#else
|
#else
|
||||||
class ProItemRefCount {
|
class ProItemRefCount {
|
||||||
public:
|
public:
|
||||||
ProItemRefCount() : m_cnt(0) {}
|
ProItemRefCount(int cnt = 0) : m_cnt(cnt) {}
|
||||||
bool ref() { return ++m_cnt != 0; }
|
bool ref() { return ++m_cnt != 0; }
|
||||||
bool deref() { return --m_cnt != 0; }
|
bool deref() { return --m_cnt != 0; }
|
||||||
ProItemRefCount &operator=(int value) { m_cnt = value; return *this; }
|
ProItemRefCount &operator=(int value) { m_cnt = value; return *this; }
|
||||||
@@ -54,9 +54,13 @@ class ProItem
|
|||||||
public:
|
public:
|
||||||
enum ProItemKind {
|
enum ProItemKind {
|
||||||
ConditionKind,
|
ConditionKind,
|
||||||
OperatorKind,
|
OpNotKind,
|
||||||
|
OpAndKind,
|
||||||
|
OpOrKind,
|
||||||
VariableKind,
|
VariableKind,
|
||||||
BlockKind
|
BranchKind,
|
||||||
|
LoopKind,
|
||||||
|
FunctionDefKind
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ProItemReturn {
|
enum ProItemReturn {
|
||||||
@@ -64,8 +68,6 @@ public:
|
|||||||
ReturnTrue,
|
ReturnTrue,
|
||||||
ReturnBreak,
|
ReturnBreak,
|
||||||
ReturnNext,
|
ReturnNext,
|
||||||
ReturnLoop,
|
|
||||||
ReturnSkip,
|
|
||||||
ReturnReturn
|
ReturnReturn
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -79,43 +81,12 @@ public:
|
|||||||
ProItem *next() const { return m_next; }
|
ProItem *next() const { return m_next; }
|
||||||
ProItem **nextRef() { return &m_next; }
|
ProItem **nextRef() { return &m_next; }
|
||||||
|
|
||||||
|
static void disposeItems(ProItem *nitm);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ProItem *m_next;
|
ProItem *m_next;
|
||||||
ProItemKind m_kind;
|
ProItemKind m_kind;
|
||||||
int m_lineNumber;
|
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
|
class ProVariable : public ProItem
|
||||||
@@ -154,35 +125,82 @@ private:
|
|||||||
QString m_text;
|
QString m_text;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ProOperator : public ProItem
|
class ProBranch : public ProItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum OperatorKind {
|
ProBranch() : ProItem(BranchKind) {}
|
||||||
OrOperator = 1,
|
~ProBranch();
|
||||||
NotOperator = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit ProOperator(OperatorKind operatorKind) : ProItem(ProItem::OperatorKind), m_operatorKind(operatorKind) {}
|
ProItem *thenItems() const { return m_thenItems; }
|
||||||
void setOperatorKind(OperatorKind operatorKind) { m_operatorKind = operatorKind; }
|
ProItem **thenItemsRef() { return &m_thenItems; }
|
||||||
OperatorKind operatorKind() const { return m_operatorKind; }
|
ProItem *elseItems() const { return m_elseItems; }
|
||||||
|
ProItem **elseItemsRef() { return &m_elseItems; }
|
||||||
|
|
||||||
private:
|
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:
|
public:
|
||||||
explicit ProFile(const QString &fileName);
|
explicit ProFile(const QString &fileName);
|
||||||
|
~ProFile();
|
||||||
|
|
||||||
QString displayFileName() const { return m_displayFileName; }
|
QString displayFileName() const { return m_displayFileName; }
|
||||||
QString fileName() const { return m_fileName; }
|
QString fileName() const { return m_fileName; }
|
||||||
QString directoryName() const { return m_directoryName; }
|
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; }
|
void deref() { if (!m_refCount.deref()) delete this; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ProItem *m_proitems;
|
||||||
|
ProItemRefCount m_refCount;
|
||||||
QString m_fileName;
|
QString m_fileName;
|
||||||
QString m_displayFileName;
|
QString m_displayFileName;
|
||||||
QString m_directoryName;
|
QString m_directoryName;
|
||||||
|
|||||||
@@ -84,12 +84,13 @@ void ProWriter::addFiles(ProFile *profile, QStringList *lines,
|
|||||||
*lines << added;
|
*lines << added;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void findProVariables(ProBlock *block, const QStringList &vars,
|
static void findProVariables(ProItem *item, const QStringList &vars,
|
||||||
QList<ProVariable *> *proVars)
|
QList<ProVariable *> *proVars)
|
||||||
{
|
{
|
||||||
for (ProItem *item = block->items(); item; item = item->next()) {
|
for (; item; item = item->next()) {
|
||||||
if (item->kind() == ProItem::BlockKind) {
|
if (item->kind() == ProItem::BranchKind) {
|
||||||
findProVariables(static_cast<ProBlock*>(item), vars, proVars);
|
findProVariables(static_cast<ProBranch*>(item)->thenItems(), vars, proVars);
|
||||||
|
findProVariables(static_cast<ProBranch*>(item)->elseItems(), vars, proVars);
|
||||||
} else if (item->kind() == ProItem::VariableKind) {
|
} else if (item->kind() == ProItem::VariableKind) {
|
||||||
ProVariable *proVar = static_cast<ProVariable*>(item);
|
ProVariable *proVar = static_cast<ProVariable*>(item);
|
||||||
if (vars.contains(proVar->variable()))
|
if (vars.contains(proVar->variable()))
|
||||||
@@ -105,7 +106,7 @@ QStringList ProWriter::removeFiles(ProFile *profile, QStringList *lines,
|
|||||||
QStringList notChanged = filePaths;
|
QStringList notChanged = filePaths;
|
||||||
|
|
||||||
QList<ProVariable *> proVars;
|
QList<ProVariable *> proVars;
|
||||||
findProVariables(profile, vars, &proVars);
|
findProVariables(profile->items(), vars, &proVars);
|
||||||
|
|
||||||
// This is a tad stupid - basically, it can remove only entries which
|
// This is a tad stupid - basically, it can remove only entries which
|
||||||
// the above code added.
|
// the above code added.
|
||||||
|
|||||||
Reference in New Issue
Block a user