From: Ulya Trofimovich Date: Thu, 10 Nov 2016 15:44:02 +0000 (+0000) Subject: Emulate tag calculation when generating paths for skeleton. X-Git-Tag: 1.0~39^2~231 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c2fc2a9d51fb3612a998fd738ac8fc1cbd4bba82;p=re2c Emulate tag calculation when generating paths for skeleton. --- diff --git a/re2c/src/ir/skeleton/generate_data.cc b/re2c/src/ir/skeleton/generate_data.cc index a49f864a..a9ebec8f 100644 --- a/re2c/src/ir/skeleton/generate_data.cc +++ b/re2c/src/ir/skeleton/generate_data.cc @@ -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 static cover_size_t cover_one( const Skeleton &skel, cover_t &cover) { @@ -125,35 +136,68 @@ template 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::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(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(path.match(skel), skel.defrule); - keygen(cover.keys, width, len, path.len_matching(skel), match); + // write keys + const key_t match = rule2key(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(cover.keys, width, len, len_match, match); + + delete[] buffer; + delete[] tags; return size; } diff --git a/re2c/src/ir/skeleton/path.h b/re2c/src/ir/skeleton/path.h index e9b194e1..9c6b5517 100644 --- a/re2c/src/ir/skeleton/path.h +++ b/re2c/src/ir/skeleton/path.h @@ -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::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(head - tail) - 1; - } - - return 0; - } - size_t match(const Skeleton &skel) const - { - std::vector::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 { diff --git a/re2c/src/ir/skeleton/skeleton.cc b/re2c/src/ir/skeleton/skeleton.cc index bf87743c..a9041a1c 100644 --- a/re2c/src/ir/skeleton/skeleton.cc +++ b/re2c/src/ir/skeleton/skeleton.cc @@ -56,6 +56,7 @@ Skeleton::Skeleton( , nodes(new Node[nodes_count]) , sizeof_key(8) , defrule(def) + , ntagver(static_cast(dfa.maxtagver) + 1) , rules(dfa.rules) , tags(dfa.tags) { diff --git a/re2c/src/ir/skeleton/skeleton.h b/re2c/src/ir/skeleton/skeleton.h index cb5d0231..20961bea 100644 --- a/re2c/src/ir/skeleton/skeleton.h +++ b/re2c/src/ir/skeleton/skeleton.h @@ -65,6 +65,7 @@ struct Skeleton size_t sizeof_key; size_t defrule; + size_t ntagver; const std::valarray &rules; const std::valarray &tags;