]> granicus.if.org Git - re2c/commitdiff
Don't loose tags on epsilon-loops in NFA.
authorUlya Trofimovich <skvadrik@gmail.com>
Wed, 11 May 2016 13:48:25 +0000 (14:48 +0100)
committerUlya Trofimovich <skvadrik@gmail.com>
Wed, 11 May 2016 13:48:25 +0000 (14:48 +0100)
re2c/src/ir/dfa/determinization.cc
re2c/src/ir/nfa/nfa.h
re2c/test/tags/nondet_iter.--tags.c [new file with mode: 0644]
re2c/test/tags/nondet_iter.--tags.re [new file with mode: 0644]

index db4d25826a9efaf01a8e8e9b5de6e6b34fe19243..ba9c85d49be853a1d521dd0ffb3eeea380a95fd2 100644 (file)
@@ -66,11 +66,13 @@ struct kitem_t
 static void closure(kitem_t *const kernel, kitem_t *&kend,
        nfa_state_t *n, bool *tags, bool *badtags, size_t ntags)
 {
-       if (n->mark) {
+       // trace the first iteration of each loop:
+       // epsilon-loops may add ney tags and reveal conflicts
+       if (n->loop > 1) {
                return;
        }
 
-       n->mark = true;
+       ++n->loop;
        switch (n->type) {
                case nfa_state_t::ALT:
                        closure(kernel, kend, n->alt.out2, tags, badtags, ntags);
@@ -101,7 +103,7 @@ static void closure(kitem_t *const kernel, kitem_t *&kend,
                        break;
                }
        }
-       n->mark = false;
+       --n->loop;
 }
 
 static size_t find_state(kitem_t *kernel, kitem_t *kend,
index f93d4438d8fca38af073ba22a325222a678088f4..b3e601876c561eab4f1cfb4bfe3ee2f57fc66ab0 100644 (file)
@@ -35,7 +35,7 @@ struct nfa_state_t
                } tag;
        };
        size_t rule;
-       bool mark;
+       uint8_t loop;
 
        void make_alt(size_t r, nfa_state_t *s1, nfa_state_t *s2)
        {
@@ -43,7 +43,7 @@ struct nfa_state_t
                alt.out1 = s1;
                alt.out2 = s2;
                rule = r;
-               mark = false;
+               loop = 0;
        }
        void make_ran(size_t r, nfa_state_t *s, const Range *p)
        {
@@ -51,7 +51,7 @@ struct nfa_state_t
                ran.out = s;
                ran.ran = p;
                rule = r;
-               mark = false;
+               loop = 0;
        }
        void make_tag(size_t r, nfa_state_t *s, size_t i)
        {
@@ -59,13 +59,13 @@ struct nfa_state_t
                tag.out = s;
                tag.info = i;
                rule = r;
-               mark = false;
+               loop = 0;
        }
        void make_fin(size_t r)
        {
                type = FIN;
                rule = r;
-               mark = false;
+               loop = 0;
        }
 };
 
diff --git a/re2c/test/tags/nondet_iter.--tags.c b/re2c/test/tags/nondet_iter.--tags.c
new file mode 100644 (file)
index 0000000..759a4fc
--- /dev/null
@@ -0,0 +1,10 @@
+re2c: error: line 5: tag 'b' is nondeterministic [-Werror-nondeterministic-tags]
+re2c: error: line 6: tag 'e' is nondeterministic [-Werror-nondeterministic-tags]
+re2c: error: line 8: tag 'c' is nondeterministic [-Werror-nondeterministic-tags]
+re2c: error: line 9: tag 'f' is nondeterministic [-Werror-nondeterministic-tags]
+re2c: warning: line 2: rule matches empty string [-Wmatch-empty-string]
+re2c: warning: line 3: rule matches empty string [-Wmatch-empty-string]
+re2c: warning: line 5: rule matches empty string [-Wmatch-empty-string]
+re2c: warning: line 6: rule matches empty string [-Wmatch-empty-string]
+re2c: warning: line 8: rule matches empty string [-Wmatch-empty-string]
+re2c: warning: line 9: rule matches empty string [-Wmatch-empty-string]
diff --git a/re2c/test/tags/nondet_iter.--tags.re b/re2c/test/tags/nondet_iter.--tags.re
new file mode 100644 (file)
index 0000000..6943d58
--- /dev/null
@@ -0,0 +1,10 @@
+/*!re2c
+    ((@a "a")*)* { @a }
+    (("d" @d)*)* { @d }
+
+    (@b "b"*)* { @b }
+    ("e"* @e)* { @e }
+
+    (@c "c"+)* { @c }
+    ("f"+ @f)* { @f }
+*/