From: Ulya Trofimovich Date: Tue, 19 Feb 2019 21:51:43 +0000 (+0000) Subject: No need to fully unwind tag histories when calculating POSIX precedence. X-Git-Tag: 1.2~144 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=007c44ef3a2be4299c46c7d57683c8eb538f60e3;p=re2c No need to fully unwind tag histories when calculating POSIX precedence. Histories are stored in a trie. Each history is represented by an index to its tail in the trie. In order to compare two histories, we can simply unwind both indices, step by step, until they coincide or root index is reached. Related commits in libre2c: 062da2dca6908c0f6da54711b897e3bafca2628c 2a7158b401d7e925696fc1b0c8da37a59e364dd4 --- diff --git a/re2c/src/dfa/posix_precedence.cc b/re2c/src/dfa/posix_precedence.cc index fc654187..66691f8c 100644 --- a/re2c/src/dfa/posix_precedence.cc +++ b/re2c/src/dfa/posix_precedence.cc @@ -8,104 +8,94 @@ namespace re2c { -static void reconstruct_history(const tag_history_t &, tag_path_t &, hidx_t); - -int32_t precedence(determ_context_t &ctx, - const clos_t &x, const clos_t &y, int32_t &rhox, int32_t &rhoy) +int32_t precedence(determ_context_t &ctx, const clos_t &x, const clos_t &y + , int32_t &prec1, int32_t &prec2) { - const hidx_t xl = x.tlook, yl = y.tlook; - const uint32_t xo = x.origin, yo = y.origin; - const std::vector &tags = ctx.dc_dfa.tags; - const kernel_t *k = NULL; + const int32_t idx1 = x.tlook, idx2 = y.tlook; + const uint32_t orig1 = x.origin, orig2 = y.origin; + int prec = 0; - if (xl == yl && xo == yo) { - rhox = rhoy = MAX_RHO; - return 0; + if (idx1 == idx2 && orig1 == orig2) { + prec1 = prec2 = MAX_RHO; + return prec; } - tag_history_t &thist = ctx.dc_taghistory; - tag_path_t &p1 = ctx.dc_path1, &p2 = ctx.dc_path2; - reconstruct_history(thist, p1, xl); - reconstruct_history(thist, p2, yl); - tag_path_t::const_reverse_iterator - i1 = p1.rbegin(), e1 = p1.rend(), j1 = i1, g1, - i2 = p2.rbegin(), e2 = p2.rend(), j2 = i2, g2; - - DINCCOUNT_CLPREC(ctx); - DINCCOUNT_CLLENGTH(ctx, p1.size() + p2.size()); - - const bool fork_frame = xo == yo; + const std::vector &tags = ctx.dc_dfa.tags; + tag_history_t &hist = ctx.dc_taghistory; - // longest precedence + const bool fork_frame = orig1 == orig2; if (fork_frame) { - // find fork - for (; j1 != e1 && j2 != e2 && *j1 == *j2; ++j1, ++j2); - rhox = rhoy = j1 > i1 - ? tags[(j1 - 1)->idx].height : MAX_RHO; + prec1 = prec2 = MAX_RHO; } else { - // get precedence table and size of the origin state - k = ctx.dc_kernels[ctx.dc_origin]; - rhox = unpack_longest(k->prectbl[xo * k->size + yo]); - rhoy = unpack_longest(k->prectbl[yo * k->size + xo]); + const kernel_t *k = ctx.dc_kernels[ctx.dc_origin]; + prec = unpack_leftmost(k->prectbl[orig1 * k->size + orig2]); + prec1 = unpack_longest(k->prectbl[orig1 * k->size + orig2]); + prec2 = unpack_longest(k->prectbl[orig2 * k->size + orig1]); } - for (g1 = j1; g1 != e1; ++g1) { - rhox = std::min(rhox, tags[g1->idx].height); + + tag_info_t info1, info2; + int32_t i1 = idx1, i2 = idx2; + for (; i1 != i2; ) { + if (i1 > i2) { + info1 = hist.info(i1); + prec1 = std::min(prec1, tags[info1.idx].height); + i1 = hist.pred(i1); + } + else { + info2 = hist.info(i2); + prec2 = std::min(prec2, tags[info2.idx].height); + i2 = hist.pred(i2); + } + DINCCOUNT_CLLENGTH(ctx, 1); } - for (g2 = j2; g2 != e2; ++g2) { - rhoy = std::min(rhoy, tags[g2->idx].height); + if (i1 != HROOT) { + DASSERT(fork_frame); + const int32_t h = tags[hist.info(i1).idx].height; + prec1 = std::min(prec1, h); + prec2 = std::min(prec2, h); } - if (rhox > rhoy) return -1; - if (rhox < rhoy) return 1; + DINCCOUNT_CLPREC(ctx); + + // longest precedence + if (prec1 > prec2) return -1; + if (prec1 < prec2) return 1; // leftmost precedence if (fork_frame) { // equal => not less - if (j1 == e1 && j2 == e2) return 0; + if (i1 == idx1 && i2 == idx2) return 0; // shorter => less - if (j1 == e1) return -1; - if (j2 == e2) return 1; + if (i1 == idx1) return -1; + if (i2 == idx2) return 1; - const uint32_t idx1 = j1->idx, idx2 = j2->idx; - const bool neg1 = j1->neg, neg2 = j2->neg; + const uint32_t tag1 = info1.idx, tag2 = info2.idx; + const bool neg1 = info1.neg, neg2 = info2.neg; // can't be both closing - DASSERT(!(idx1 % 2 == 1 && idx2 % 2 == 1)); + DASSERT(!(tag1 % 2 == 1 && tag2 % 2 == 1)); // closing vs opening: closing wins - if (idx1 % 2 == 1) return -1; - if (idx2 % 2 == 1) return 1; + if (tag1 % 2 == 1) return -1; + if (tag2 % 2 == 1) return 1; // can't be both negative DASSERT(!(neg1 && neg2)); // positive vs negative: positive wins - if (neg1) return 1; + if (neg1) return 1; if (neg2) return -1; // positive vs positive: smaller wins // (this case is only possible because multiple // top-level RE don't have proper negative tags) - if (idx1 < idx2) return -1; - if (idx1 > idx2) return 1; - } - else { - return unpack_leftmost(k->prectbl[xo * k->size + yo]); - } - - // unreachable - DASSERT(false); - return 0; -} + if (tag1 < tag2) return -1; + if (tag1 > tag2) return 1; -void reconstruct_history(const tag_history_t &history, - tag_path_t &path, hidx_t idx) -{ - path.clear(); - for (; idx != HROOT; idx = history.pred(idx)) { - path.push_back(history.info(idx)); + DASSERT(false); // unreachable } + return prec; } int32_t unpack_longest(int32_t packed) diff --git a/re2c/test/debug/closure_stats.i--posix-captures--posix-closure(gor1)--dump-closure-stats.c b/re2c/test/debug/closure_stats.i--posix-captures--posix-closure(gor1)--dump-closure-stats.c index b682ee38..9c70f138 100644 --- a/re2c/test/debug/closure_stats.i--posix-captures--posix-closure(gor1)--dump-closure-stats.c +++ b/re2c/test/debug/closure_stats.i--posix-captures--posix-closure(gor1)--dump-closure-stats.c @@ -112,23 +112,23 @@ } debug/closure_stats.i--posix-captures--posix-closure(gor1)--dump-closure-stats.re:1:32: warning: rule matches empty string [-Wmatch-empty-string] -scans: 47 prec: 3 length: 36 +scans: 47 prec: 3 length: 24 scans: 0 prec: 0 length: 0 debug/closure_stats.i--posix-captures--posix-closure(gor1)--dump-closure-stats.re:2:32: warning: rule matches empty string [-Wmatch-empty-string] -scans: 133 prec: 14 length: 282 +scans: 133 prec: 14 length: 66 scans: 0 prec: 0 length: 0 debug/closure_stats.i--posix-captures--posix-closure(gor1)--dump-closure-stats.re:3:32: warning: rule matches empty string [-Wmatch-empty-string] -scans: 617 prec: 84 length: 3420 +scans: 617 prec: 84 length: 432 scans: 0 prec: 0 length: 0 debug/closure_stats.i--posix-captures--posix-closure(gor1)--dump-closure-stats.re:4:32: warning: rule matches empty string [-Wmatch-empty-string] -scans: 3841 prec: 584 length: 49176 +scans: 3841 prec: 584 length: 4980 scans: 0 prec: 0 length: 0 debug/closure_stats.i--posix-captures--posix-closure(gor1)--dump-closure-stats.re:5:35: warning: rule matches empty string [-Wmatch-empty-string] -scans: 27377 prec: 4368 length: 751536 +scans: 27377 prec: 4368 length: 71004 scans: 0 prec: 0 length: 0 debug/closure_stats.i--posix-captures--posix-closure(gor1)--dump-closure-stats.re:6:35: warning: rule matches empty string [-Wmatch-empty-string] -scans: 207313 prec: 33824 length: 11771232 +scans: 207313 prec: 33824 length: 1086636 scans: 0 prec: 0 length: 0 debug/closure_stats.i--posix-captures--posix-closure(gor1)--dump-closure-stats.re:7:35: warning: rule matches empty string [-Wmatch-empty-string] -scans: 1614737 prec: 266304 length: 186413760 +scans: 1614737 prec: 266304 length: 17060172 scans: 0 prec: 0 length: 0 diff --git a/re2c/test/debug/closure_stats.i--posix-captures--posix-closure(gtop)--dump-closure-stats.c b/re2c/test/debug/closure_stats.i--posix-captures--posix-closure(gtop)--dump-closure-stats.c index 3bab0ed3..aa17bcac 100644 --- a/re2c/test/debug/closure_stats.i--posix-captures--posix-closure(gtop)--dump-closure-stats.c +++ b/re2c/test/debug/closure_stats.i--posix-captures--posix-closure(gtop)--dump-closure-stats.c @@ -112,23 +112,23 @@ } debug/closure_stats.i--posix-captures--posix-closure(gtop)--dump-closure-stats.re:1:32: warning: rule matches empty string [-Wmatch-empty-string] -scans: 24 prec: 3 length: 36 +scans: 24 prec: 3 length: 24 scans: 0 prec: 0 length: 0 debug/closure_stats.i--posix-captures--posix-closure(gtop)--dump-closure-stats.re:2:32: warning: rule matches empty string [-Wmatch-empty-string] -scans: 67 prec: 14 length: 282 +scans: 67 prec: 14 length: 66 scans: 0 prec: 0 length: 0 debug/closure_stats.i--posix-captures--posix-closure(gtop)--dump-closure-stats.re:3:32: warning: rule matches empty string [-Wmatch-empty-string] -scans: 309 prec: 84 length: 3420 +scans: 309 prec: 84 length: 432 scans: 0 prec: 0 length: 0 debug/closure_stats.i--posix-captures--posix-closure(gtop)--dump-closure-stats.re:4:32: warning: rule matches empty string [-Wmatch-empty-string] -scans: 1921 prec: 584 length: 49176 +scans: 1921 prec: 584 length: 4980 scans: 0 prec: 0 length: 0 debug/closure_stats.i--posix-captures--posix-closure(gtop)--dump-closure-stats.re:5:35: warning: rule matches empty string [-Wmatch-empty-string] -scans: 13689 prec: 4368 length: 751536 +scans: 13689 prec: 4368 length: 71004 scans: 0 prec: 0 length: 0 debug/closure_stats.i--posix-captures--posix-closure(gtop)--dump-closure-stats.re:6:35: warning: rule matches empty string [-Wmatch-empty-string] -scans: 103657 prec: 33824 length: 11771232 +scans: 103657 prec: 33824 length: 1086636 scans: 0 prec: 0 length: 0 debug/closure_stats.i--posix-captures--posix-closure(gtop)--dump-closure-stats.re:7:35: warning: rule matches empty string [-Wmatch-empty-string] -scans: 807369 prec: 266304 length: 186413760 +scans: 807369 prec: 266304 length: 17060172 scans: 0 prec: 0 length: 0