]> granicus.if.org Git - re2c/commitdiff
Emulate tag calculation when generating paths for skeleton.
authorUlya Trofimovich <skvadrik@gmail.com>
Thu, 10 Nov 2016 15:44:02 +0000 (15:44 +0000)
committerUlya Trofimovich <skvadrik@gmail.com>
Thu, 10 Nov 2016 15:44:02 +0000 (15:44 +0000)
re2c/src/ir/skeleton/generate_data.cc
re2c/src/ir/skeleton/path.h
re2c/src/ir/skeleton/skeleton.cc
re2c/src/ir/skeleton/skeleton.h

index a49f864afa5b36047d33deabb114c0e680c6816b..a9ebec8ff1531e0b84d078d550020727b04e8af8 100644 (file)
@@ -98,6 +98,17 @@ static uint32_t step(uint32_t lower, uint32_t upper)
        return 1 + (upper - lower) / 0x100;
 }
 
+static void apply(size_t *tags, const tcmd_t *cmd, size_t pos)
+{
+       if (!cmd) return;
+       for (const tagsave_t *p = cmd->save; p; p = p->next) {
+               tags[p->ver] = pos;
+       }
+       for (const tagcopy_t *p = cmd->copy; p; p = p->next) {
+               tags[p->lhs] = tags[p->rhs];
+       }
+}
+
 template<typename cunit_t, typename key_t> static cover_size_t cover_one(
        const Skeleton &skel, cover_t &cover)
 {
@@ -125,35 +136,68 @@ template<typename cunit_t, typename key_t> static cover_size_t cover_one(
                * cover_size_t::from64(width);
        if (size.overflow()) return size;
 
-       // input
-       const size_t buffer_size = size.uint32();
+       const size_t
+               nver = skel.ntagver,
+               tags_size = width * nver,
+               buffer_size = size.uint32(),
+               NIL = std::numeric_limits<size_t>::max();
        cunit_t *buffer = new cunit_t [buffer_size];
-       for (size_t i = 0; i < len; ++i) {
+       size_t *tags = new size_t[tags_size];
+
+       // find the last accepting node
+       size_t f = len;
+       for (; f > 0; --f) {
+               if (path.node(skel, f).rule != Rule::NONE) break;
+       }
+       const Node &fin = path.node(skel, f);
 
-               // pick some characters from ranges
-               size_t j = 0;
+       // calculate input characters and tag values
+       std::fill(tags, tags + tags_size, NIL);
+       for (size_t i = 0; i < len; ++i) {
                const Node::arc_t &arc = path.arc(skel, i);
-               for (Node::citer_t a = arc.begin(); a != arc.end(); ++a) {
+               Node::citer_t a = arc.begin();
+
+               for (size_t j = 0; j < width;) {
                        const uint32_t
                                l = a->lower,
                                u = a->upper,
                                d = step(l, u);
-                       for (uint32_t m = l; m < u + d; m += d, ++j) {
+
+                       for (uint32_t m = l; m < u + d && j < width; m += d, ++j) {
                                buffer[j * len + i] = to_le(static_cast<cunit_t>(std::min(m, u)));
+                               if (i < f) {
+                                       apply(&tags[j * nver], a->cmd, i);
+                               }
                        }
-               }
 
-               // fill the rest by rotating picked characters
-               for (const size_t w = j; j < width; ++j) {
-                       buffer[j * len + i] = buffer[(j % w) * len + i];
+                       if (++a == arc.end()) a = arc.begin();
                }
        }
+       for (size_t j = 0; j < width; ++j) {
+               apply(&tags[j * nver], fin.cmd, f);
+       }
+
+       // write input
        fwrite (buffer, sizeof(cunit_t), buffer_size, cover.input);
-       delete[] buffer;
 
-       // keys
-       const key_t match = rule2key<key_t>(path.match(skel), skel.defrule);
-       keygen<key_t>(cover.keys, width, len, path.len_matching(skel), match);
+       // write keys
+       const key_t match = rule2key<key_t>(fin.rule, skel.defrule);
+       size_t len_match = 0;
+       if (fin.rule != Rule::NONE) {
+               const Rule &rule = skel.rules[fin.rule];
+               const size_t trail = rule.trail;
+               if (trail == Tag::NONE) {
+                       len_match = f;
+               } else {
+                       assert(skel.tags[trail].type == Tag::VAR);
+                       len_match = tags[rule.tags[trail]];
+                       assert(len_match != NIL);
+               }
+       }
+       keygen<key_t>(cover.keys, width, len, len_match, match);
+
+       delete[] buffer;
+       delete[] tags;
 
        return size;
 }
index e9b194e1911db614eaf2af7b432cc986825456ea..9c6b5517a5b689a59f59547aad29aa01a839f7b8 100644 (file)
@@ -39,51 +39,9 @@ public:
        {
                return arcs.size() - 1;
        }
-       size_t len_matching(const Skeleton &skel) const
+       const Node& node(const Skeleton &skel, size_t i) const
        {
-               std::vector<size_t>::const_reverse_iterator
-                       tail = arcs.rbegin(),
-                       head = arcs.rend();
-               for (; tail != head; ++tail) {
-                       const Node &node = skel.nodes[*tail];
-                       if (node.rule == Rule::NONE) continue;
-
-                       const Rule &rule = skel.rules[node.rule];
-                       const size_t trail = rule.trail;
-                       if (trail != Tag::NONE) {
-                               assert(skel.tags[trail].type == Tag::VAR);
-
-                               const tagver_t ver = rule.tags[trail];
-                               const tagsave_t *p;
-
-                               for (p = node.cmd->save; p && p->ver != ver; p = p->next);
-                               for (; !p && ++tail != head;) {
-                                       // trailing context is a top-level tag: either all ranges have it
-                                       // or none of them do, so it is sufficient to check the 1st range
-                                       const Node::arc_t &arc = skel.nodes[*tail].arcs[*(tail - 1)];
-                                       for (p = arc[0].cmd->save; p && p->ver != ver; p = p->next);
-                               }
-
-                               assert(p);
-                       }
-
-                       return static_cast<size_t>(head - tail) - 1;
-               }
-
-               return 0;
-       }
-       size_t match(const Skeleton &skel) const
-       {
-               std::vector<size_t>::const_reverse_iterator
-                       tail = arcs.rbegin(),
-                       head = arcs.rend();
-               for (; tail != head; ++tail) {
-                       const size_t rule = skel.nodes[*tail].rule;
-                       if (rule != Rule::NONE) {
-                               return rule;
-                       }
-               }
-               return Rule::NONE;
+               return skel.nodes[arcs[i]];
        }
        const Node::arc_t& arc(const Skeleton &skel, size_t i) const
        {
index bf87743cd171f4d6ea3d929f263fd7ef93ed7857..a9041a1c57c8200dd600ce93d44977231e1c31ff 100644 (file)
@@ -56,6 +56,7 @@ Skeleton::Skeleton(
        , nodes(new Node[nodes_count])
        , sizeof_key(8)
        , defrule(def)
+       , ntagver(static_cast<size_t>(dfa.maxtagver) + 1)
        , rules(dfa.rules)
        , tags(dfa.tags)
 {
index cb5d0231a4e4f3eed1d0df80045a208fc6a5b063..20961beaae7d202f41ad653d8d7885f8a5ed678f 100644 (file)
@@ -65,6 +65,7 @@ struct Skeleton
 
        size_t sizeof_key;
        size_t defrule;
+       size_t ntagver;
        const std::valarray<Rule> &rules;
        const std::valarray<Tag> &tags;