This is how the generated TDFA does and how it should be done.
Found by slyfox's fuzzer. :)
static void apply(size_t *tags, const tcmd_t *cmd, size_t pos)
{
if (!cmd) return;
- for (const tagsave_t *p = cmd->save; p; p = p->next) {
- tags[p->ver] = p->bottom ? Skeleton::DEFTAG : pos;
- }
for (const tagcopy_t *p = cmd->copy; p; p = p->next) {
tags[p->lhs] = tags[p->rhs];
}
+ for (const tagsave_t *p = cmd->save; p; p = p->next) {
+ tags[p->ver] = p->bottom ? Skeleton::DEFTAG : pos;
+ }
}
static size_t path_width(const path_t &path, const Skeleton &skel)
--- /dev/null
+/* Generated by re2c */
+
+{
+ YYCTYPE yych;
+ if (YYLIMIT <= YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ switch (yych) {
+ case 'a':
+ yyt2 = NULL;
+ yyt1 = YYCURSOR;
+ goto yy3;
+ default:
+ yyt1 = NULL;
+ goto yy2;
+ }
+yy2:
+ p = yyt1;
+ {}
+yy3:
+ ++YYCURSOR;
+ if (YYLIMIT <= YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ switch (yych) {
+ case 'a':
+ yyt2 = yyt1;
+ yyt1 = YYCURSOR;
+ goto yy3;
+ case 'b': goto yy5;
+ default: goto yy2;
+ }
+yy5:
+ YYMARKER = ++YYCURSOR;
+ if (YYLIMIT <= YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ switch (yych) {
+ case 'a': goto yy6;
+ default:
+ yyt1 = yyt2;
+ goto yy2;
+ }
+yy6:
+ ++YYCURSOR;
+ if (YYLIMIT <= YYCURSOR) YYFILL(1);
+ yych = *YYCURSOR;
+ switch (yych) {
+ case 'b': goto yy5;
+ default: goto yy7;
+ }
+yy7:
+ YYCURSOR = YYMARKER;
+ yyt1 = yyt2;
+ goto yy2;
+}
+
+re2c: warning: line 3: rule matches empty string [-Wmatch-empty-string]
+re2c: warning: line 3: tag 'p' is nondeterministic [-Wnondeterministic-tags]
--- /dev/null
+/*!re2c
+
+(@p "a")* "ab"* {}
+
+*/