From 12f748758d0fb4c74cd872a01f96dd48e8242944 Mon Sep 17 00:00:00 2001 From: Ulya Trofimovich Date: Wed, 11 May 2016 14:48:25 +0100 Subject: [PATCH] Don't loose tags on epsilon-loops in NFA. --- re2c/src/ir/dfa/determinization.cc | 8 +++++--- re2c/src/ir/nfa/nfa.h | 10 +++++----- re2c/test/tags/nondet_iter.--tags.c | 10 ++++++++++ re2c/test/tags/nondet_iter.--tags.re | 10 ++++++++++ 4 files changed, 30 insertions(+), 8 deletions(-) create mode 100644 re2c/test/tags/nondet_iter.--tags.c create mode 100644 re2c/test/tags/nondet_iter.--tags.re diff --git a/re2c/src/ir/dfa/determinization.cc b/re2c/src/ir/dfa/determinization.cc index db4d2582..ba9c85d4 100644 --- a/re2c/src/ir/dfa/determinization.cc +++ b/re2c/src/ir/dfa/determinization.cc @@ -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, diff --git a/re2c/src/ir/nfa/nfa.h b/re2c/src/ir/nfa/nfa.h index f93d4438..b3e60187 100644 --- a/re2c/src/ir/nfa/nfa.h +++ b/re2c/src/ir/nfa/nfa.h @@ -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 index 00000000..759a4fc6 --- /dev/null +++ b/re2c/test/tags/nondet_iter.--tags.c @@ -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 index 00000000..6943d58f --- /dev/null +++ b/re2c/test/tags/nondet_iter.--tags.re @@ -0,0 +1,10 @@ +/*!re2c + ((@a "a")*)* { @a } + (("d" @d)*)* { @d } + + (@b "b"*)* { @b } + ("e"* @e)* { @e } + + (@c "c"+)* { @c } + ("f"+ @f)* { @f } +*/ -- 2.40.0