]> granicus.if.org Git - re2c/commitdiff
Fixed history comparison in case both latest subhistories are bottoms.
authorUlya Trofimovich <skvadrik@gmail.com>
Tue, 16 May 2017 21:11:55 +0000 (22:11 +0100)
committerUlya Trofimovich <skvadrik@gmail.com>
Tue, 16 May 2017 21:11:55 +0000 (22:11 +0100)
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.

re2c/src/dfa/closure.cc
re2c/test/posix_captures/uncomparable_bottoms.i--posix-captures.c [new file with mode: 0644]
re2c/test/posix_captures/uncomparable_bottoms.i--posix-captures.re [new file with mode: 0644]

index 1f80e180265e3fa05d5c7d74d2360e687aa697b8..c061b8f7d6da7d7d5d8cd841b989c8727f73f94a 100644 (file)
@@ -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 (file)
index 0000000..4458c60
--- /dev/null
@@ -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 (file)
index 0000000..0696df2
--- /dev/null
@@ -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")* {}
+*/