]> granicus.if.org Git - re2c/commitdiff
'save' commands for tags with history may need fallback copies.
authorUlya Trofimovich <skvadrik@gmail.com>
Fri, 7 Apr 2017 15:19:00 +0000 (16:19 +0100)
committerUlya Trofimovich <skvadrik@gmail.com>
Fri, 7 Apr 2017 15:19:00 +0000 (16:19 +0100)
For simple tags without history 'save' command is self-sufficient:
it does not depend on anything. However, for tags with history 'save'
commands depend on history, which may be overwritten on the way from
accepting state to fallback transition. We must take care and backup
such overwritten histories when leaving the accepting state.

If history is not overwritten, we don't need a copy, but we still
have to propagate its liveness forward on all fallthrough paths
outgoing from accepting state.

re2c/src/dfa/cfg/liveanal.cc
re2c/src/dfa/fallback_tags.cc

index f03b37836d3b7d36214c0b3d4d74d43d06438a7a..0a22391aa4c541a6a9faf601ccc1892ffb4e34d4 100644 (file)
@@ -145,6 +145,10 @@ void cfg_t::liveness_analysis(const cfg_t &cfg, bool *live)
                // not the same as backward propagation of liveness through bblock
                for (const tcmd_t *p = b->cmd; p; p = p->next) {
                        buf1[p->lhs] = false;
+                       const tagver_t h = p->pred;
+                       if (h != TAGVER_ZERO) {
+                               buf1[h] = true;
+                       }
                }
                for (const tcmd_t *p = b->cmd; p; p = p->next) {
                        const tagver_t v = p->rhs;
index de36641d6e27ee69b687858f030e940d6028fa3f..a5c4fd0d4687cad5f379999dd011d8684fe8102a 100644 (file)
@@ -49,6 +49,19 @@ void find_overwritten_tags(const dfa_t &dfa, size_t state,
        }
 }
 
+// overwritten tags need 'copy' on all outgoing non-accepting paths
+// ('copy' commands must go first, before potential overwrites)
+static void backup(dfa_t &dfa, dfa_state_t *s, tagver_t l, tagver_t r)
+{
+       for (size_t c = 0; c < dfa.nchars; ++c) {
+               size_t i = s->arcs[c];
+               if (i != dfa_t::NIL && dfa.states[i]->fallthru) {
+                       tcmd_t *&p = s->tcmd[c];
+                       p = dfa.tcpool.make_tcmd(p, l, r, TAGVER_ZERO);
+               }
+       }
+}
+
 // WARNING: this function assumes that falthrough and fallback
 // attributes of DFA states have already been calculated, see
 // note [fallback states]
@@ -74,28 +87,25 @@ void insert_fallback_tags(dfa_t &dfa)
                for (; p; p = p->next) {
                        const tagver_t l = p->lhs, r = p->rhs, v = p->pred;
 
-                       // 'save' commands are the same as for final transition
-                       if (!tcmd_t::iscopy(r)) {
-                               t = pool.make_tcmd(t, l, r, v);
-                               continue;
-                       }
-
-                       // non-overwritten tags need 'copy' on fallback transition
-                       if (!owrt[r]) {
-                               f = pool.make_tcmd(f, l, r, v);
-                               continue;
-                       }
+                       // 'copy' commands
+                       if (tcmd_t::iscopy(r)) {
+                               if (!owrt[r]) {
+                                       f = pool.make_tcmd(f, l, r, v);
+                               } else {
+                                       backup(dfa, s, l, r);
+                               }
 
-                       // overwritten tags need 'copy' on all outgoing non-accepting paths
-                       // ('copy' commands must go first, before potential overwrites)
-                       for (size_t c = 0; c < nsym; ++c) {
-                               size_t j = s->arcs[c];
-                               if (j != dfa_t::NIL && dfa.states[j]->fallthru) {
-                                       tcmd_t *&q = s->tcmd[c];
-                                       q = pool.make_tcmd(q, l, r, v);
+                       // 'save' commands
+                       } else {
+                               if (v == TAGVER_ZERO || !owrt[v]) {
+                                       t = pool.make_tcmd(t, l, r, v);
+                               } else {
+                                       t = pool.make_tcmd(t, l, r, l);
+                                       backup(dfa, s, l, v);
                                }
                        }
                }
+
                // join 'copy' (fallback) and 'save' commands
                for (pf = &f; *pf; pf = &(*pf)->next);
                *pf = t;