std::fill(used, used + nver, false);
for (size_t t = 0; t < ntag; ++t) {
- used[fins[t]] = !fixed(tags[t]);
+ const tagver_t f = fins[t];
+ used[f] = f != TAGVER_ZERO; // fixed tag or unreachable rule
}
for (size_t i = 0; i < cfg.nbbfall; ++i) {
const cfg_bb_t &b = cfg.bblocks[i];
tagver_t maxver = 0;
for (size_t v = 0; v < nver; ++v) {
- if (used[v]) {
- ver2new[v] = ++maxver;
- }
+ ver2new[v] = used[v] ? ++maxver : TAGVER_ZERO;
}
delete[] used;
tagver_t *fins = cfg.dfa.finvers;
const std::vector<Tag> &tags = cfg.dfa.tags;
for (size_t t = 0; t < tags.size(); ++t) {
- if (!fixed(tags[t])) {
- fins[t] = ver2new[fins[t]];
+ tagver_t &f = fins[t];
+ if (f != TAGVER_ZERO) { // fixed tag or unreachable rule
+ f = ver2new[f];
}
}
}
* Furthermore, fixed tags are fobidden with generic API because it cannot
* express fixed offsets.
*
+ * Tags with history also cannot be fixed.
+ *
* One special case is pre-orbit tags: tags that correspond to the opening
* of capturing group under iteration. We don't need to know the value of
* such tags: we only need the last iteration which is captured by the
case RE::TAG: {
// see note [fixed and variable tags]
Tag &tag = tags[re->tag.idx];
- if (toplevel && dist != Tag::VARDIST) {
+ if (toplevel && dist != Tag::VARDIST && !history(tag)) {
tag.base = base;
tag.dist = dist;
} else if (preorbit(tags, re->tag.idx)) {