]> granicus.if.org Git - re2c/commitdiff
Simplified creation of rule states and backup states.
authorUlya Trofimovich <skvadrik@gmail.com>
Mon, 8 Jun 2015 21:25:32 +0000 (22:25 +0100)
committerUlya Trofimovich <skvadrik@gmail.com>
Mon, 8 Jun 2015 21:25:32 +0000 (22:25 +0100)
New simpler implementation uses STL containers instaed of sparse
array. It's less efficient, but the place is not a bottleneck and
simplicity is more important than efficiency.

re2c/Makefile.am
re2c/src/codegen/emit_action.cc
re2c/src/codegen/emit_dfa.cc
re2c/src/codegen/prepare_dfa.cc
re2c/src/dfa/action.h
re2c/src/util/uniq_vector.h [new file with mode: 0644]

index 4937eb6025b1dfd850b5e9a472bc5b912c937563..9edb3cdf48b8b6301c6395213f2a186ef7985222 100644 (file)
@@ -49,6 +49,7 @@ SRC_HDR = \
        src/util/range.h \
        src/util/smart_ptr.h \
        src/util/substr.h \
+       src/util/uniq_vector.h \
        src/util/wrap_iterator.h
 SRC = \
        src/codegen/bitmap.cc \
index c82f8b167063144ddb13366af76325441cb155f6..8658cc912b54f1e85bea65172521da660d482fb7 100644 (file)
@@ -217,14 +217,14 @@ void emit_accept (OutputFile & o, uint32_t ind, bool & readCh, const State * con
                                        genGoTo(o, 0, s, accepts[i], readCh);
                                }
                                o << indent(ind) << "default:\t";
-                               genGoTo(o, 0, s, accepts.back (), readCh);
+                               genGoTo(o, 0, s, accepts[accepts_size - 1], readCh);
                                o << indent(ind) << "}\n";
                        }
                }
                else
                {
                        // no need to write if statement here since there is only case 0.
-                       genGoTo(o, ind, s, accepts.front (), readCh);
+                       genGoTo(o, ind, s, accepts[0], readCh);
                }
        }
 }
index 65148c9af3b9da1f880b9bb21ed3cd5f6bd8ad18..adadafa2fec82870badde6ab2982502e5411b561 100644 (file)
@@ -80,9 +80,9 @@ void DFA::count_used_labels (std::set<label_t> & used, label_t start, label_t in
        {
                s->go.used_labels (used);
        }
-       for (accept_t::const_iterator i = accepts.begin (); i != accepts.end (); ++i)
+       for (uint32_t i = 0; i < accepts.size (); ++i)
        {
-               used.insert ((*i)->label);
+               used.insert (accepts[i]->label);
        }
        // must go last: it needs the set of used labels
        if (used.count (head->label))
index b908c17860445d76eb9f81d0889ee9e39cd3b1ae..b092bfb710813c49cbd0f8a83f98fb6242f52fd6 100644 (file)
@@ -160,8 +160,6 @@ void DFA::prepare(OutputFile & o, uint32_t & max_fill)
        findSCCs();
        head->link = head;
 
-       uint32_t nRules = 0;
-
        for (State * s = head; s; s = s->next)
        {
                s->depth = maxDist(s);
@@ -169,20 +167,15 @@ void DFA::prepare(OutputFile & o, uint32_t & max_fill)
                {
                        max_fill = s->depth;
                }
-               if (s->rule && s->rule->accept >= nRules)
-               {
-                       nRules = s->rule->accept + 1;
-               }
        }
 
        // create rule states
-       State ** rules = new State * [nRules];
-       memset(rules, 0, (nRules)*sizeof(*rules));
+       std::map<uint32_t, State *> rules;
        for (State * s = head; s; s = s->next)
        {
                if (s->rule)
                {
-                       if (!rules[s->rule->accept])
+                       if (rules.find (s->rule->accept) == rules.end ())
                        {
                                State *n = new State;
                                n->action.set_rule (s->rule);
@@ -220,9 +213,6 @@ void DFA::prepare(OutputFile & o, uint32_t & max_fill)
        // find backup states and create accept state (if needed)
        if (default_state)
        {
-               uint32_t nSaves = 0;
-               uint32_t * saves = new uint32_t[nRules];
-               memset(saves, ~0, (nRules)*sizeof(*saves));
                for (State * s = head; s; s = s->next)
                {
                        if (s->rule)
@@ -231,24 +221,18 @@ void DFA::prepare(OutputFile & o, uint32_t & max_fill)
                                {
                                        if (!s->go.span[i].to->rule && s->go.span[i].to->action.type != Action::RULE)
                                        {
-                                               if (saves[s->rule->accept] == ~0u)
-                                               {
-                                                       saves[s->rule->accept] = nSaves++;
-                                                       accepts.push_back (rules[s->rule->accept]);
-                                               }
-                                               s->action.set_save (saves[s->rule->accept]);
+                                               const uint32_t accept = accepts.find_or_add (rules[s->rule->accept]);
+                                               s->action.set_save (accept);
                                        }
                                }
                        }
                }
-               delete [] saves;
                if (accepts.size () > 1)
                {
                        o.set_used_yyaccept ();
                }
                default_state->action.set_accept (&accepts);
        }
-       delete [] rules;
 
        // split ``base'' states into two parts
        for (State * s = head; s; s = s->next)
index 0d33805a9dd4b4112e65e548c4a217b9a801a0cb..d5914817f0e138cc567a55bbf0b1367ea1fe2fa5 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "src/codegen/label.h"
 #include "src/util/c99_stdint.h"
+#include "src/util/uniq_vector.h"
 
 namespace re2c
 {
@@ -24,7 +25,7 @@ struct Initial
        {}
 };
 
-typedef std::vector<const State *> accept_t;
+typedef uniq_vector_t<const State *> accept_t;
 
 class Action
 {
diff --git a/re2c/src/util/uniq_vector.h b/re2c/src/util/uniq_vector.h
new file mode 100644 (file)
index 0000000..0e003a8
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __UNIQ_VECTOR__
+#define __UNIQ_VECTOR__
+
+#include <vector>
+
+#include "src/util/c99_stdint.h"
+
+namespace re2c
+{
+
+// wrapper over std::vector
+// O(n) lookup
+// O(n^2) insertion
+template <typename value_t>
+class uniq_vector_t
+{
+       typedef std::vector<value_t> elems_t;
+       elems_t elems;
+public:
+       uniq_vector_t ()
+               : elems ()
+       {}
+       uint32_t size () const
+       {
+               return elems.size ();
+       }
+       const value_t & operator [] (uint32_t i) const
+       {
+               return elems[i];
+       }
+       uint32_t find_or_add (const value_t & v)
+       {
+               const uint32_t size = elems.size ();
+               for (uint32_t i = 0; i < size; ++i)
+               {
+                       if (elems[i] == v)
+                       {
+                               return i;
+                       }
+               }
+               elems.push_back (v);
+               return size;
+       }
+};
+
+} // namespace re2c
+
+#endif // __UNIQ_VECTOR__