From: Ulya Trofimovich Date: Tue, 16 May 2017 21:11:55 +0000 (+0100) Subject: Fixed history comparison in case both latest subhistories are bottoms. X-Git-Tag: 1.0~39^2~50 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e53781621b4dda5e08ced984e9059b6a073eb9d5;p=re2c Fixed history comparison in case both latest subhistories are bottoms. In this case, instead of comparing histories by the leftmost criterion (as it should be, if only one of them is bottom), we should assume that from standpoint of this tag histories are equal and move on to other tags. --- diff --git a/re2c/src/dfa/closure.cc b/re2c/src/dfa/closure.cc index 1f80e180..c061b8f7 100644 --- a/re2c/src/dfa/closure.cc +++ b/re2c/src/dfa/closure.cc @@ -268,23 +268,27 @@ bool better(const clos_t &c1, const clos_t &c2, assert(v1[t] == v2[t]); // open/close capture tag: maximize (on lookahead and versions); - // if either one is bottom, fallback to leftmost disambiguation + // if one is bottom and the other is not, fallback to leftmost + // if both are bottoms, relay comparison to less prioritized tags // we don't use orders for minimize/maximize, because they are // already used for leftmost } else if (capture(tag)) { x = tagtree.last(l1, t); y = tagtree.last(l2, t); - if (x < 0 || y < 0) goto leftmost; + if (x == TAGVER_BOTTOM && y == TAGVER_BOTTOM) continue; + if (x == TAGVER_BOTTOM || y == TAGVER_BOTTOM) goto leftmost; if (x > y) return false; if (x < y) return true; x = tagtree.last(t1, t); y = tagtree.last(t2, t); - if (x < 0 || y < 0) goto leftmost; + if (x == TAGVER_BOTTOM && y == TAGVER_BOTTOM) continue; + if (x == TAGVER_BOTTOM || y == TAGVER_BOTTOM) goto leftmost; if (x > y) return false; if (x < y) return true; x = v1[t]; y = v2[t]; + if (x < 0 && y < 0) continue; if (x < 0 || y < 0) goto leftmost; if (x > y) return false; if (x < y) return true; diff --git a/re2c/test/posix_captures/uncomparable_bottoms.i--posix-captures.c b/re2c/test/posix_captures/uncomparable_bottoms.i--posix-captures.c new file mode 100644 index 00000000..4458c603 --- /dev/null +++ b/re2c/test/posix_captures/uncomparable_bottoms.i--posix-captures.c @@ -0,0 +1,72 @@ +/* Generated by re2c */ +// if two histories are both bottoms (default) for the given tag, +// they are uncomparable from this tag's point of view: decision +// should be relayed on less prioritized tags + + +{ + YYCTYPE yych; + if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); + yych = *YYCURSOR; + switch (yych) { + case 'a': + yyt1 = yyt5 = YYCURSOR; + goto yy3; + case 'b': + yyt2 = yyt5 = NULL; + yyt1 = yyt4 = YYCURSOR; + goto yy4; + default: + yyt2 = yyt3 = yyt4 = yyt5 = NULL; + yyt1 = YYCURSOR; + goto yy2; + } +yy2: + { + const size_t yynmatch = 3; + const YYCTYPE *yypmatch[yynmatch * 2]; + yypmatch[0] = yyt1; + yypmatch[2] = yyt5; + yypmatch[3] = yyt2; + yypmatch[5] = yyt3; + yypmatch[1] = YYCURSOR; + yypmatch[4] = yyt4; + {} + } +yy3: + yych = *++YYCURSOR; + switch (yych) { + case 'b': + yyt2 = yyt4 = YYCURSOR; + goto yy4; + default: + yyt3 = yyt4 = NULL; + yyt2 = YYCURSOR; + goto yy2; + } +yy4: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + switch (yych) { + case 'b': goto yy5; + default: + yyt3 = YYCURSOR; + goto yy2; + } +yy5: + ++YYCURSOR; + if (YYLIMIT <= YYCURSOR) YYFILL(1); + yych = *YYCURSOR; + switch (yych) { + case 'b': + yyt4 = YYCURSOR; + goto yy4; + default: + yyt3 = YYCURSOR; + goto yy2; + } +} + +re2c: warning: line 6: rule matches empty string [-Wmatch-empty-string] +re2c: warning: line 6: trailing context is non-deterministic and induces 2 parallel instances [-Wnondeterministic-tags] diff --git a/re2c/test/posix_captures/uncomparable_bottoms.i--posix-captures.re b/re2c/test/posix_captures/uncomparable_bottoms.i--posix-captures.re new file mode 100644 index 00000000..0696df27 --- /dev/null +++ b/re2c/test/posix_captures/uncomparable_bottoms.i--posix-captures.re @@ -0,0 +1,7 @@ +// if two histories are both bottoms (default) for the given tag, +// they are uncomparable from this tag's point of view: decision +// should be relayed on less prioritized tags + +/*!re2c + ("a")? ("b" | "bb")* {} +*/