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);
break;
}
}
- n->mark = false;
+ --n->loop;
}
static size_t find_state(kitem_t *kernel, kitem_t *kend,
} tag;
};
size_t rule;
- bool mark;
+ uint8_t loop;
void make_alt(size_t r, nfa_state_t *s1, nfa_state_t *s2)
{
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)
{
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)
{
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;
}
};
--- /dev/null
+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]
--- /dev/null
+/*!re2c
+ ((@a "a")*)* { @a }
+ (("d" @d)*)* { @d }
+
+ (@b "b"*)* { @b }
+ ("e"* @e)* { @e }
+
+ (@c "c"+)* { @c }
+ ("f"+ @f)* { @f }
+*/