diff --git a/lib/tre-parse.c b/lib/tre-parse.c index fa20655..edf97c7 100644 --- a/lib/tre-parse.c +++ b/lib/tre-parse.c @@ -1645,6 +1645,22 @@ tre_parse(tre_parse_ctx_t *ctx) break; } +#ifdef REG_LITERAL + /* In literal mode the branch above is skipped, so an empty + pattern would otherwise fall through without producing an + atom. Emit an empty expression, which matches the empty + string. */ + if ((ctx->cflags & REG_LITERAL) && ctx->re >= ctx->re_end) + { + DPRINT(("tre_parse: literal empty: '%.*" STRF "'\n", + REST(ctx->re))); + result = tre_ast_new_literal(ctx->mem, EMPTY, -1); + if (!result) + return REG_ESPACE; + break; + } +#endif /* REG_LITERAL */ + DPRINT(("tre_parse: literal: '%.*" STRF "'\n", REST(ctx->re))); /* Note that we can't use an tre_isalpha() test here, since there diff --git a/tests/retest.c b/tests/retest.c index 16ccb40..e3fe8ef 100644 --- a/tests/retest.c +++ b/tests/retest.c @@ -633,6 +633,23 @@ main(int argc, char **argv) test_exec("xxxxxx", 0, REG_NOMATCH); #endif + /* + * Literal (REG_LITERAL) patterns. + */ + + /* An empty literal pattern matches the empty string. */ + test_comp("", REG_EXTENDED | REG_LITERAL, 0); + test_exec("abc", 0, REG_OK, 0, 0, END); + test_exec("", 0, REG_OK, 0, 0, END); + + /* Metacharacters lose their meaning in literal mode. */ + test_comp("a.c", REG_EXTENDED | REG_LITERAL, 0); + test_exec("xa.cy", 0, REG_OK, 1, 4, END); + test_exec("abc", 0, REG_NOMATCH); + test_comp("(a|b)*", REG_EXTENDED | REG_LITERAL, 0); + test_exec("x(a|b)*y", 0, REG_OK, 1, 7, END); + test_exec("ababab", 0, REG_NOMATCH); + #ifdef TRE_APPROX /* * Approximate matching tests.