qlalr: replace QLinkedList with std::list

This is in preparation of deprecating QLinkedList.

Most is straight-forward, except where operator+ was used on linked-list
iterators. In one case, replaced this with std::next, in the other, with
prefix increments, since the advancement was always equal to the loop
control variable. Since advancing a linked-list iterator is a linear
operation, this removes a source of quadratic complexity.

Another obstacle was the overloaded op< set, which was in the Qt namespace
while the iterator is from std and the payload, as before, was global.
This breaks ADL, so move these operators to namespace std. This violates
the standard, but the functions are tagged with our distinct types, so it
shouldn't cause any trouble.

Change-Id: Ifec0a927bfdabb002838cdf86fb8d23b32a38ff7
Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
bb10
Marc Mutz 2019-05-02 19:56:29 +02:00
parent 13997cccc9
commit dce7dbecb0
5 changed files with 27 additions and 37 deletions

View File

@ -84,7 +84,6 @@ SOURCES += \
../../corelib/tools/qcryptographichash.cpp \
../../corelib/tools/qhash.cpp \
../../corelib/tools/qlist.cpp \
../../corelib/tools/qlinkedlist.cpp \
../../corelib/tools/qlocale.cpp \
../../corelib/tools/qlocale_tools.cpp \
../../corelib/tools/qmap.cpp \

View File

@ -36,6 +36,8 @@
#include <QtCore/qfile.h>
#include <QtCore/qmap.h>
#include <iterator>
namespace {
void generateSeparator(int i, QTextStream &out)
@ -126,7 +128,7 @@ QString CppGenerator::endIncludeGuard(const QString &fileName)
void CppGenerator::operator () ()
{
// action table...
state_count = aut.states.size ();
state_count = static_cast<int>(aut.states.size());
terminal_count = static_cast<int>(grammar.terminals.size());
non_terminal_count = static_cast<int>(grammar.non_terminals.size());
@ -156,7 +158,7 @@ void CppGenerator::operator () ()
if (grammar.isNonTerminal (a.key ()))
{
Q_ASSERT (symbol >= terminal_count && symbol < grammar.names.size ());
Q_ASSERT(symbol >= terminal_count && symbol < static_cast<int>(grammar.names.size()));
GOTO (q, symbol - terminal_count) = r;
}
@ -245,7 +247,7 @@ void CppGenerator::operator () ()
<< Qt::endl;
}
QBitArray used_rules (grammar.rules.count ());
QBitArray used_rules{static_cast<int>(grammar.rules.size())};
int q = 0;
for (StatePointer state = aut.states.begin (); state != aut.states.end (); ++state, ++q)
@ -259,12 +261,11 @@ void CppGenerator::operator () ()
}
}
for (int i = 0; i < used_rules.count (); ++i)
auto rule = grammar.rules.begin();
for (int i = 0; i < used_rules.count (); ++i, ++rule)
{
if (! used_rules.testBit (i))
{
RulePointer rule = grammar.rules.begin () + i;
if (rule != grammar.goal)
qerr() << "*** Warning: Rule ``" << *rule << "'' is useless!" << Qt::endl;
}
@ -280,7 +281,7 @@ void CppGenerator::operator () ()
if (u >= 0)
continue;
RulePointer rule = grammar.rules.begin () + (- u - 1);
RulePointer rule = std::next(grammar.rules.begin(), - u - 1);
if (state->defaultReduce == rule)
u = 0;
@ -619,7 +620,7 @@ void CppGenerator::generateImpl (QTextStream &out)
out << "const int " << grammar.table_name << "::rule_index [] = {";
idx = 0;
int offset = 0;
size_t offset = 0;
for (RulePointer rule = grammar.rules.begin (); rule != grammar.rules.end (); ++rule, ++idx)
{
generateSeparator(idx, out);

View File

@ -51,7 +51,9 @@ QTextStream &qout()
static QTextStream result(stdout, QIODevice::WriteOnly);
return result;
}
QT_END_NAMESPACE
namespace std {
bool operator < (Name a, Name b)
{
return *a < *b;
@ -66,7 +68,7 @@ bool operator < (StatePointer a, StatePointer b)
{
return &*a < &*b;
}
QT_END_NAMESPACE
}
bool Read::operator < (const Read &other) const
{
@ -329,7 +331,7 @@ QPair<StatePointer, bool> Automaton::internState (const State &state)
struct _Bucket
{
QLinkedList<ItemPointer> items;
std::list<ItemPointer> items;
void insert (ItemPointer item)
{ items.push_back (item); }
@ -338,8 +340,8 @@ struct _Bucket
{
State st (aut->_M_grammar);
for (QLinkedList<ItemPointer>::iterator item = items.begin (); item != items.end (); ++item)
st.insert ((*item)->next ());
for (auto &item : items)
st.insert(item->next());
return st;
}

View File

@ -51,34 +51,22 @@ class Automaton;
// names
typedef QLinkedList<QString>::iterator Name;
QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(QLinkedList<QString>::iterator, Q_PRIMITIVE_TYPE);
QT_END_NAMESPACE
typedef QLinkedList<Name> NameList;
typedef std::list<QString>::iterator Name;
typedef std::list<Name> NameList;
typedef std::set<Name> NameSet;
// items
typedef QLinkedList<Item> ItemList;
typedef std::list<Item> ItemList;
typedef ItemList::iterator ItemPointer;
QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(ItemList::iterator, Q_PRIMITIVE_TYPE);
QT_END_NAMESPACE
// rules
typedef QLinkedList<Rule> debug_infot;
typedef std::list<Rule> debug_infot;
typedef debug_infot::iterator RulePointer;
QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(debug_infot::iterator, Q_PRIMITIVE_TYPE);
QT_END_NAMESPACE
typedef QMultiMap<Name, RulePointer> RuleMap;
// states
typedef QLinkedList<State> StateList;
typedef std::list<State> StateList;
typedef StateList::iterator StatePointer;
QT_BEGIN_NAMESPACE
Q_DECLARE_TYPEINFO(StateList::iterator, Q_PRIMITIVE_TYPE);
QT_END_NAMESPACE
// arrows
typedef QMap<Name, StatePointer> Bundle;
@ -175,7 +163,7 @@ class Node
public:
typedef std::set<Node<_Tp> > Repository;
typedef typename Repository::iterator iterator;
typedef typename QLinkedList<iterator>::iterator edge_iterator;
typedef typename std::list<iterator>::iterator edge_iterator;
public:
static iterator get (_Tp data);
@ -213,7 +201,7 @@ public: // attributes
mutable bool root;
mutable int dfn;
mutable _Tp data;
mutable QLinkedList<iterator> outs;
mutable std::list<iterator> outs;
protected:
inline Node () {}
@ -235,7 +223,7 @@ typename Node<_Tp>::iterator Node<_Tp>::get (_Tp data)
}
template <typename _Tp>
QPair<typename QLinkedList<typename Node<_Tp>::iterator>::iterator, bool> Node<_Tp>::insertEdge (typename Node<_Tp>::iterator other) const
QPair<typename std::list<typename Node<_Tp>::iterator>::iterator, bool> Node<_Tp>::insertEdge(typename Node<_Tp>::iterator other) const
{
edge_iterator it = std::find (outs.begin (), outs.end (), other);
@ -272,7 +260,7 @@ public:
QString decl_file_name;
QString impl_file_name;
QString token_prefix;
QLinkedList<QString> names;
std::list<QString> names;
Name start;
NameSet terminals;
NameSet non_terminals;
@ -401,11 +389,11 @@ private:
int _M_includes_dfn;
};
QT_BEGIN_NAMESPACE
namespace std {
bool operator < (Name a, Name b);
bool operator < (StatePointer a, StatePointer b);
bool operator < (ItemPointer a, ItemPointer b);
QT_END_NAMESPACE
}
QTextStream &operator << (QTextStream &out, const Name &n);
QTextStream &operator << (QTextStream &out, const Rule &r);

View File

@ -106,7 +106,7 @@ int main (int argc, char *argv[])
if (! p.parse (file_name))
exit (EXIT_FAILURE);
if (grammar.rules.isEmpty ())
if (grammar.rules.empty())
{
qerr() << "*** Fatal. No rules!" << Qt::endl;
exit (EXIT_FAILURE);