]> granicus.if.org Git - re2c/commitdiff
Moved calculation of fallback states to earlier stage of DFA construction.
authorUlya Trofimovich <skvadrik@gmail.com>
Tue, 15 Mar 2016 08:08:45 +0000 (08:08 +0000)
committerUlya Trofimovich <skvadrik@gmail.com>
Tue, 15 Mar 2016 08:08:45 +0000 (08:08 +0000)
We will need this later, when adding multiple context markers
(liveness analyses during context marker deduplication).

re2c/Makefile.am
re2c/src/ir/adfa/adfa.cc
re2c/src/ir/adfa/adfa.h
re2c/src/ir/adfa/prepare.cc
re2c/src/ir/compile.cc
re2c/src/ir/dfa/dfa.h
re2c/src/ir/dfa/fallback.cc [new file with mode: 0644]

index 1e73e3e36212c665903dde4f88fb3a2ace4fa1e1..0acdfe1c364bc19de6ec4723f5dd3b17d182b7c7 100644 (file)
@@ -83,6 +83,7 @@ SRC = \
        src/ir/adfa/adfa.cc \
        src/ir/adfa/prepare.cc \
        src/ir/dfa/determinization.cc \
+       src/ir/dfa/fallback.cc \
        src/ir/dfa/fillpoints.cc \
        src/ir/dfa/minimization.cc \
        src/ir/regexp/encoding/enc.cc \
index cb41d035107557dbc2f4c93c52a9e5169e8774ae..83aa560af6cd46070a3aeb1c23d5056dc705f7ad 100644 (file)
@@ -16,6 +16,7 @@ namespace re2c
 DFA::DFA
        ( const dfa_t &dfa
        , const std::vector<size_t> &fill
+       , const std::vector<size_t> &fallback
        , Skeleton *skel
        , const charset_t &charset
        , const std::string &n
@@ -73,6 +74,10 @@ DFA::DFA
        }
        *p = NULL;
 
+       for (size_t i = 0; i < fallback.size(); ++i) {
+               i2s[fallback[i]]->fallback = true;
+       }
+
        delete[] i2s;
 }
 
index e4b7e4ab1d6d1b97fe19b86f28fa5a5f5935d9d1..b85b4b2c49217155e847d9bf88c06cbf440df9f6 100644 (file)
@@ -26,6 +26,7 @@ struct State
        const RuleInfo * rule;
        State * next;
        size_t fill;
+       bool fallback;
 
        bool isPreCtxt;
        bool isBase;
@@ -37,6 +38,7 @@ struct State
                , rule (NULL)
                , next (0)
                , fill (0)
+               , fallback (false)
                , isPreCtxt (false)
                , isBase (false)
                , go ()
@@ -74,6 +76,7 @@ public:
 public:
        DFA     ( const dfa_t &dfa
                , const std::vector<size_t> &fill
+               , const std::vector<size_t> &fallback
                , Skeleton *skel
                , const charset_t &charset
                , const std::string &n
index bd51bb90edf3326d1733698d91df8c80a1068834..0856a0c3686e797d65c3a989699d582dbf901d77 100644 (file)
@@ -181,24 +181,15 @@ void DFA::prepare ()
                }
        }
 
-       // find backup states and create accept state (if needed)
-       if (default_state)
-       {
-               for (State * s = head; s; s = s->next)
-               {
-                       if (s->rule)
-                       {
-                               for (uint32_t i = 0; i < s->go.nSpans; ++i)
-                               {
-                                       if (!s->go.span[i].to->rule && s->go.span[i].to->action.type != Action::RULE)
-                                       {
-                                               const uint32_t accept = static_cast<uint32_t> (accepts.find_or_add (rules[s->rule->rank]));
-                                               s->action.set_save (accept);
-                                       }
-                               }
+       // bind save actions to fallback states and create accept state (if needed)
+       if (default_state) {
+               for (State *s = head; s; s = s->next) {
+                       if (s->fallback) {
+                               const uint32_t accept = static_cast<uint32_t>(accepts.find_or_add(rules[s->rule->rank]));
+                               s->action.set_save(accept);
                        }
                }
-               default_state->action.set_accept (&accepts);
+               default_state->action.set_accept(&accepts);
        }
 
        // split ``base'' states into two parts
index 3516df254975d93b93ceca7621b247e47c7832eb..cc058c39d24a6cdf874c8f586a938ee3c6c7b3a4 100644 (file)
@@ -61,8 +61,12 @@ smart_ptr<DFA> compile (Spec & spec, Output & output, const std::string & cond,
        std::vector<size_t> fill;
        fillpoints(dfa, fill);
 
+       // see note [fallback states]
+       std::vector<size_t> fallback;
+       fallback_states(dfa, fallback);
+
        // ADFA stands for 'DFA with actions'
-       DFA *adfa = new DFA(dfa, fill, skeleton, cs, name, cond, line);
+       DFA *adfa = new DFA(dfa, fill, fallback, skeleton, cs, name, cond, line);
 
        /*
         * note [reordering DFA states]
index 32ea6f855c6f78c12d5bb01ad0fdec29db606d6c..f58a0f03409de6b8390a9e476bdd65e47149b5cd 100644 (file)
@@ -52,6 +52,7 @@ enum dfa_minimization_t
 
 void minimization(dfa_t &dfa);
 void fillpoints(const dfa_t &dfa, std::vector<size_t> &fill);
+void fallback_states(const dfa_t &dfa, std::vector<size_t> &fallback);
 
 } // namespace re2c
 
diff --git a/re2c/src/ir/dfa/fallback.cc b/re2c/src/ir/dfa/fallback.cc
new file mode 100644 (file)
index 0000000..8d3835f
--- /dev/null
@@ -0,0 +1,31 @@
+#include "src/ir/dfa/dfa.h"
+
+namespace re2c
+{
+
+/* note [fallback states]
+ *
+ * Find accepting states that may be shadowed by other accepting
+ * states: when the short rule matches, lexer must try to match
+ * longer rules; if this attempt is unsuccessful it must fallback
+ * to the short match.
+ */
+void fallback_states(const dfa_t &dfa, std::vector<size_t> &fallback)
+{
+       const size_t count = dfa.states.size();
+       for (size_t i = 0; i < count; ++i) {
+               dfa_state_t *s = dfa.states[i];
+               if (s->rule != NULL) {
+                       for (size_t c = 0; c < dfa.nchars; ++c) {
+                               const size_t j = s->arcs[c];
+                               if (j != dfa_t::NIL
+                                       && dfa.states[j]->rule == NULL) {
+                                       fallback.push_back(i);
+                               }
+                       }
+               }
+       }
+}
+
+} // namespace re2c
+