summaryrefslogtreecommitdiffstats
path: root/util/qlalr/lalr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'util/qlalr/lalr.cpp')
-rw-r--r--util/qlalr/lalr.cpp781
1 files changed, 0 insertions, 781 deletions
diff --git a/util/qlalr/lalr.cpp b/util/qlalr/lalr.cpp
deleted file mode 100644
index c68076477f..0000000000
--- a/util/qlalr/lalr.cpp
+++ /dev/null
@@ -1,781 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the utils of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "lalr.h"
-
-#include <limits.h>
-
-#include <algorithm>
-
-#define QLALR_NO_DEBUG_NULLABLES
-#define QLALR_NO_DEBUG_LOOKBACKS
-#define QLALR_NO_DEBUG_DIRECT_READS
-#define QLALR_NO_DEBUG_READS
-#define QLALR_NO_DEBUG_INCLUDES
-#define QLALR_NO_DEBUG_LOOKAHEADS
-
-QT_BEGIN_NAMESPACE
-QTextStream qerr (stderr, QIODevice::WriteOnly);
-QTextStream qout (stdout, QIODevice::WriteOnly);
-
-bool operator < (Name a, Name b)
-{
- return *a < *b;
-}
-
-bool operator < (ItemPointer a, ItemPointer b)
-{
- return &*a < &*b;
-}
-
-bool operator < (StatePointer a, StatePointer b)
-{
- return &*a < &*b;
-}
-QT_END_NAMESPACE
-
-bool Read::operator < (const Read &other) const
-{
- if (state == other.state)
- return nt < other.nt;
-
- return state < other.state;
-}
-
-bool Include::operator < (const Include &other) const
-{
- if (state == other.state)
- return nt < other.nt;
-
- return state < other.state;
-}
-
-bool Lookback::operator < (const Lookback &other) const
-{
- if (state == other.state)
- return nt < other.nt;
-
- return state < other.state;
-}
-
-QTextStream &operator << (QTextStream &out, const Name &n)
-{
- return out << *n;
-}
-
-QTextStream &operator << (QTextStream &out, const Rule &r)
-{
- out << *r.lhs << " ::=";
-
- for (NameList::const_iterator name = r.rhs.begin (); name != r.rhs.end (); ++name)
- out << " " << **name;
-
- return out;
-}
-
-QTextStream &operator << (QTextStream &out, const NameSet &ns)
-{
- out << "{";
-
- for (NameSet::const_iterator n = ns.begin (); n != ns.end (); ++n)
- {
- if (n != ns.begin ())
- out << ", ";
-
- out << *n;
- }
-
- return out << "}";
-}
-
-Item Item::next () const
-{
- Q_ASSERT (! isReduceItem ());
-
- Item n;
- n.rule = rule;
- n.dot = dot;
- ++n.dot;
-
- return n;
-}
-
-QTextStream &operator << (QTextStream &out, const Item &item)
-{
- RulePointer r = item.rule;
-
- out << *r->lhs << ":";
- for (NameList::iterator name = r->rhs.begin (); name != r->rhs.end (); ++name)
- {
- out << " ";
-
- if (item.dot == name)
- out << ". ";
-
- out << **name;
- }
-
- if (item.isReduceItem ())
- out << " .";
-
- return out;
-}
-
-State::State (Grammar *g):
- defaultReduce (g->rules.end ())
-{
-}
-
-QPair<ItemPointer, bool> State::insert (const Item &item)
-{
- ItemPointer it = std::find (kernel.begin (), kernel.end (), item);
-
- if (it != kernel.end ())
- return qMakePair (it, false);
-
- return qMakePair (kernel.insert (it, item), true);
-}
-
-QPair<ItemPointer, bool> State::insertClosure (const Item &item)
-{
- ItemPointer it = std::find (closure.begin (), closure.end (), item);
-
- if (it != closure.end ())
- return qMakePair (it, false);
-
- return qMakePair (closure.insert (it, item), true);
-}
-
-
-/////////////////////////////////////////////////////////////
-// Grammar
-/////////////////////////////////////////////////////////////
-Grammar::Grammar ():
- start (names.end ())
-{
- expected_shift_reduce = 0;
- expected_reduce_reduce = 0;
- current_prec = 0;
- current_assoc = NonAssoc;
-
- table_name = QLatin1String ("parser_table");
-
- tk_end = intern ("$end");
- terminals.insert (tk_end);
- spells.insert (tk_end, "end of file");
-
- /*tk_error= terminals.insert (intern ("error"))*/;
-}
-
-Name Grammar::intern (const QString &id)
-{
- Name name = std::find (names.begin (), names.end (), id);
-
- if (name == names.end ())
- name = names.insert (names.end (), id);
-
- return name;
-}
-
-void Grammar::buildRuleMap ()
-{
- NameSet undefined;
- for (RulePointer rule = rules.begin (); rule != rules.end (); ++rule)
- {
- for (NameList::iterator it = rule->rhs.begin (); it != rule->rhs.end (); ++it)
- {
- Name name = *it;
- if (isTerminal (name) || declared_lhs.find (name) != declared_lhs.end ()
- || undefined.find (name) != undefined.end ())
- continue;
-
- undefined.insert(name);
- fprintf (stderr, "*** Warning. Symbol `%s' is not defined\n", qPrintable (*name));
- }
-
- rule_map.insert (rule->lhs, rule);
- }
-}
-
-void Grammar::buildExtendedGrammar ()
-{
- accept_symbol = intern ("$accept");
- goal = rules.insert (rules.end (), Rule ());
- goal->lhs = accept_symbol;
- goal->rhs.push_back (start);
- goal->rhs.push_back (tk_end);
-
- non_terminals.insert (accept_symbol);
-}
-
-struct _Nullable: public std::unary_function<Name, bool>
-{
- Automaton *_M_automaton;
-
- _Nullable (Automaton *aut):
- _M_automaton (aut) {}
-
- bool operator () (Name name) const
- { return _M_automaton->nullables.find (name) != _M_automaton->nullables.end (); }
-};
-
-Automaton::Automaton (Grammar *g):
- _M_grammar (g),
- start (states.end ())
-{
-}
-
-int Automaton::id (RulePointer rule)
-{
- return 1 + std::distance (_M_grammar->rules.begin (), rule);
-}
-
-int Automaton::id (Name name)
-{
- return std::distance (_M_grammar->names.begin (), name);
-}
-
-int Automaton::id (StatePointer state)
-{
- return std::distance (states.begin (), state);
-}
-
-void Automaton::build ()
-{
- Item item;
- item.rule = _M_grammar->goal;
- item.dot = _M_grammar->goal->rhs.begin ();
-
- State tmp (_M_grammar);
- tmp.insert (item);
- start = internState (tmp).first;
-
- closure (start);
-
- buildNullables ();
- buildLookbackSets ();
- buildReads ();
- buildIncludesAndFollows ();
- buildLookaheads ();
- buildDefaultReduceActions ();
-}
-
-void Automaton::buildNullables ()
-{
- bool changed = true;
-
- while (changed)
- {
- changed = false;
-
- for (RulePointer rule = _M_grammar->rules.begin (); rule != _M_grammar->rules.end (); ++rule)
- {
- NameList::iterator nn = std::find_if (rule->rhs.begin (), rule->rhs.end (), std::not1 (_Nullable (this)));
-
- if (nn == rule->rhs.end ())
- changed |= nullables.insert (rule->lhs).second;
- }
- }
-
-#ifndef QLALR_NO_DEBUG_NULLABLES
- qerr << "nullables = {" << nullables << endl;
-#endif
-}
-
-QPair<StatePointer, bool> Automaton::internState (const State &state)
-{
- StatePointer it = std::find (states.begin (), states.end (), state);
-
- if (it != states.end ())
- return qMakePair (it, false);
-
- return qMakePair (states.insert (it, state), true);
-}
-
-struct _Bucket
-{
- QLinkedList<ItemPointer> items;
-
- void insert (ItemPointer item)
- { items.push_back (item); }
-
- State toState (Automaton *aut)
- {
- State st (aut->_M_grammar);
-
- for (QLinkedList<ItemPointer>::iterator item = items.begin (); item != items.end (); ++item)
- st.insert ((*item)->next ());
-
- return st;
- }
-};
-
-void Automaton::closure (StatePointer state)
-{
- if (! state->closure.empty ()) // ### not true.
- return;
-
- typedef QMap<Name, _Bucket> bucket_map_type;
-
- bucket_map_type buckets;
- QStack<ItemPointer> working_list;
-
- for (ItemPointer item = state->kernel.begin (); item != state->kernel.end (); ++item)
- working_list.push (item);
-
- state->closure = state->kernel;
-
- while (! working_list.empty ())
- {
- ItemPointer item = working_list.top ();
- working_list.pop ();
-
- if (item->isReduceItem ())
- continue;
-
- buckets [*item->dot].insert (item);
-
- if (_M_grammar->isNonTerminal (*item->dot))
- {
- foreach (RulePointer rule, _M_grammar->rule_map.values (*item->dot))
- {
- Item ii;
- ii.rule = rule;
- ii.dot = rule->rhs.begin ();
-
- QPair<ItemPointer, bool> r = state->insertClosure (ii);
-
- if (r.second)
- working_list.push (r.first);
- }
- }
- }
-
- QList<StatePointer> todo;
-
- for (bucket_map_type::iterator bucket = buckets.begin (); bucket != buckets.end (); ++bucket)
- {
- QPair<StatePointer, bool> r = internState (bucket->toState (this));
-
- StatePointer target = r.first;
-
- if (r.second)
- todo.push_back (target);
-
- state->bundle.insert (bucket.key(), target);
- }
-
- while (! todo.empty ())
- {
- closure (todo.front ());
- todo.pop_front ();
- }
-}
-
-void Automaton::buildLookbackSets ()
-{
- for (StatePointer p = states.begin (); p != states.end (); ++p)
- {
- for (Bundle::iterator a = p->bundle.begin (); a != p->bundle.end (); ++a)
- {
- Name A = a.key ();
-
- if (! _M_grammar->isNonTerminal (A))
- continue;
-
- foreach (RulePointer rule, _M_grammar->rule_map.values (A))
- {
- StatePointer q = p;
-
- for (NameList::iterator dot = rule->rhs.begin (); dot != rule->rhs.end (); ++dot)
- q = q->bundle.value (*dot, states.end ());
-
- Q_ASSERT (q != states.end ());
-
- ItemPointer item = q->closure.begin ();
-
- for (; item != q->closure.end (); ++item)
- {
- if (item->rule == rule && item->dot == item->end_rhs ())
- break;
- }
-
- if (item == q->closure.end ())
- {
- Q_ASSERT (q == p);
- Q_ASSERT (rule->rhs.begin () == rule->rhs.end ());
-
- for (item = q->closure.begin (); item != q->closure.end (); ++item)
- {
- if (item->rule == rule && item->dot == item->end_rhs ())
- break;
- }
- }
-
- Q_ASSERT (item != q->closure.end ());
-
- lookbacks.insert (item, Lookback (p, A));
-
-#ifndef QLALR_NO_DEBUG_LOOKBACKS
- qerr << "*** (" << id (q) << ", " << *rule << ") lookback (" << id (p) << ", " << *A << ")" << endl;
-#endif
- }
- }
- }
-}
-
-void Automaton::buildDirectReads ()
-{
- for (StatePointer q = states.begin (); q != states.end (); ++q)
- {
- for (Bundle::iterator a = q->bundle.begin (); a != q->bundle.end (); ++a)
- {
- if (! _M_grammar->isNonTerminal (a.key ()))
- continue;
-
- StatePointer r = a.value ();
-
- for (Bundle::iterator z = r->bundle.begin (); z != r->bundle.end (); ++z)
- {
- Name sym = z.key ();
-
- if (! _M_grammar->isTerminal (sym))
- continue;
-
- q->reads [a.key ()].insert (sym);
- }
- }
-
-#ifndef QLALR_NO_DEBUG_DIRECT_READS
- for (QMap<Name, NameSet>::iterator dr = q->reads.begin (); dr != q->reads.end (); ++dr)
- qerr << "*** DR(" << id (q) << ", " << dr.key () << ") = " << dr.value () << endl;
-#endif
- }
-}
-
-void Automaton::buildReadsDigraph ()
-{
- for (StatePointer q = states.begin (); q != states.end (); ++q)
- {
- for (Bundle::iterator a = q->bundle.begin (); a != q->bundle.end (); ++a)
- {
- if (! _M_grammar->isNonTerminal (a.key ()))
- continue;
-
- StatePointer r = a.value ();
-
- for (Bundle::iterator z = r->bundle.begin (); z != r->bundle.end (); ++z)
- {
- Name sym = z.key ();
-
- if (! _M_grammar->isNonTerminal(sym) || nullables.find (sym) == nullables.end ())
- continue;
-
- ReadsGraph::iterator source = ReadsGraph::get (Read (q, a.key ()));
- ReadsGraph::iterator target = ReadsGraph::get (Read (r, sym));
-
- source->insertEdge (target);
-
-#ifndef QLALR_NO_DEBUG_READS
- qerr << "*** ";
- dump (qerr, source);
- qerr << " reads ";
- dump (qerr, target);
- qerr << endl;
-#endif
- }
- }
- }
-}
-
-void Automaton::buildReads ()
-{
- buildDirectReads ();
- buildReadsDigraph ();
-
- _M_reads_dfn = 0;
-
- for (ReadsGraph::iterator node = ReadsGraph::begin_nodes (); node != ReadsGraph::end_nodes (); ++node)
- {
- if (! node->root)
- continue;
-
- visitReadNode (node);
- }
-
- for (ReadsGraph::iterator node = ReadsGraph::begin_nodes (); node != ReadsGraph::end_nodes (); ++node)
- visitReadNode (node);
-}
-
-void Automaton::visitReadNode (ReadNode node)
-{
- if (node->dfn != 0)
- return; // nothing to do
-
- int N = node->dfn = ++_M_reads_dfn;
- _M_reads_stack.push (node);
-
-#ifndef QLALR_NO_DEBUG_INCLUDES
- // qerr << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << endl;
-#endif
-
- for (ReadsGraph::edge_iterator edge = node->begin (); edge != node->end (); ++edge)
- {
- ReadsGraph::iterator r = *edge;
-
- visitReadNode (r);
-
- node->dfn = qMin (N, r->dfn);
-
- NameSet &dst = node->data.state->reads [node->data.nt];
- NameSet &src = r->data.state->reads [r->data.nt];
- dst.insert (src.begin (), src.end ());
- }
-
- if (node->dfn == N)
- {
- ReadsGraph::iterator tos = _M_reads_stack.top ();
-
- do {
- tos = _M_reads_stack.top ();
- _M_reads_stack.pop ();
- tos->dfn = INT_MAX;
- } while (tos != node);
- }
-}
-
-void Automaton::buildIncludesAndFollows ()
-{
- for (StatePointer p = states.begin (); p != states.end (); ++p)
- p->follows = p->reads;
-
- buildIncludesDigraph ();
-
- _M_includes_dfn = 0;
-
- for (IncludesGraph::iterator node = IncludesGraph::begin_nodes (); node != IncludesGraph::end_nodes (); ++node)
- {
- if (! node->root)
- continue;
-
- visitIncludeNode (node);
- }
-
- for (IncludesGraph::iterator node = IncludesGraph::begin_nodes (); node != IncludesGraph::end_nodes (); ++node)
- visitIncludeNode (node);
-}
-
-void Automaton::buildIncludesDigraph ()
-{
- for (StatePointer pp = states.begin (); pp != states.end (); ++pp)
- {
- for (Bundle::iterator a = pp->bundle.begin (); a != pp->bundle.end (); ++a)
- {
- Name name = a.key ();
-
- if (! _M_grammar->isNonTerminal (name))
- continue;
-
- foreach (RulePointer rule, _M_grammar->rule_map.values (name))
- {
- StatePointer p = pp;
-
- for (NameList::iterator A = rule->rhs.begin (); A != rule->rhs.end (); ++A)
- {
- NameList::iterator dot = A;
- ++dot;
-
- if (_M_grammar->isNonTerminal (*A) && dot == rule->rhs.end ())
- {
- // found an include edge.
- IncludesGraph::iterator target = IncludesGraph::get (Include (pp, name));
- IncludesGraph::iterator source = IncludesGraph::get (Include (p, *A));
-
- source->insertEdge (target);
-
-#ifndef QLALR_NO_DEBUG_INCLUDES
- qerr << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << endl;
-#endif // QLALR_NO_DEBUG_INCLUDES
-
- continue;
- }
-
- p = p->bundle.value (*A);
-
- if (! _M_grammar->isNonTerminal (*A))
- continue;
-
- NameList::iterator first_not_nullable = std::find_if (dot, rule->rhs.end (), std::not1 (_Nullable (this)));
- if (first_not_nullable != rule->rhs.end ())
- continue;
-
- // found an include edge.
- IncludesGraph::iterator target = IncludesGraph::get (Include (pp, name));
- IncludesGraph::iterator source = IncludesGraph::get (Include (p, *A));
-
- source->insertEdge (target);
-
-#ifndef QLALR_NO_DEBUG_INCLUDES
- qerr << "*** (" << id (p) << ", " << *A << ") includes (" << id (pp) << ", " << *name << ")" << endl;
-#endif // QLALR_NO_DEBUG_INCLUDES
- }
- }
- }
- }
-}
-
-void Automaton::visitIncludeNode (IncludeNode node)
-{
- if (node->dfn != 0)
- return; // nothing to do
-
- int N = node->dfn = ++_M_includes_dfn;
- _M_includes_stack.push (node);
-
-#ifndef QLALR_NO_DEBUG_INCLUDES
- // qerr << "*** Debug. visit node (" << id (node->data.state) << ", " << node->data.nt << ") N = " << N << endl;
-#endif
-
- for (IncludesGraph::edge_iterator edge = node->begin (); edge != node->end (); ++edge)
- {
- IncludesGraph::iterator r = *edge;
-
- visitIncludeNode (r);
-
- node->dfn = qMin (N, r->dfn);
-
-#ifndef QLALR_NO_DEBUG_INCLUDES
- qerr << "*** Merge. follows";
- dump (qerr, node);
- qerr << " += follows";
- dump (qerr, r);
- qerr << endl;
-#endif
-
- NameSet &dst = node->data.state->follows [node->data.nt];
- NameSet &src = r->data.state->follows [r->data.nt];
-
- dst.insert (src.begin (), src.end ());
- }
-
- if (node->dfn == N)
- {
- IncludesGraph::iterator tos = _M_includes_stack.top ();
-
- do {
- tos = _M_includes_stack.top ();
- _M_includes_stack.pop ();
- tos->dfn = INT_MAX;
- } while (tos != node);
- }
-}
-
-void Automaton::buildLookaheads ()
-{
- for (StatePointer p = states.begin (); p != states.end (); ++p)
- {
- for (ItemPointer item = p->closure.begin (); item != p->closure.end (); ++item)
- {
- foreach (Lookback lookback, lookbacks.values (item))
- {
- StatePointer q = lookback.state;
-
-#ifndef QLALR_NO_DEBUG_LOOKAHEADS
- qerr << "(" << id (p) << ", " << *item->rule << ") lookbacks ";
- dump (qerr, lookback);
- qerr << " with follows (" << id (q) << ", " << lookback.nt << ") = " << q->follows [lookback.nt] << endl;
-#endif
-
- lookaheads [item].insert (q->follows [lookback.nt].begin (), q->follows [lookback.nt].end ());
- }
- }
-
- // propagate the lookahead in the kernel
- ItemPointer k = p->kernel.begin ();
- ItemPointer c = p->closure.begin ();
-
- for (; k != p->kernel.end (); ++k, ++c)
- lookaheads [k] = lookaheads [c];
- }
-}
-
-void Automaton::buildDefaultReduceActions ()
-{
- for (StatePointer state = states.begin (); state != states.end (); ++state)
- {
- ItemPointer def = state->closure.end ();
- int size = -1;
-
- for (ItemPointer item = state->closure.begin (); item != state->closure.end (); ++item)
- {
- if (item->dot != item->end_rhs ())
- continue;
-
- int la = lookaheads.value (item).size ();
- if (def == state->closure.end () || la > size)
- {
- def = item;
- size = la;
- }
- }
-
- if (def != state->closure.end ())
- {
- Q_ASSERT (size >= 0);
- state->defaultReduce = def->rule;
- }
- }
-}
-
-void Automaton::dump (QTextStream &out, IncludeNode incl)
-{
- out << "(" << id (incl->data.state) << ", " << incl->data.nt << ")";
-}
-
-void Automaton::dump (QTextStream &out, ReadNode rd)
-{
- out << "(" << id (rd->data.state) << ", " << rd->data.nt << ")";
-}
-
-void Automaton::dump (QTextStream &out, const Lookback &lp)
-{
- out << "(" << id (lp.state) << ", " << lp.nt << ")";
-}