aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2021-10-02 12:38:42 -0700
committerBruce Hill <bruce@bruce-hill.com>2021-10-02 12:38:42 -0700
commit486fe98a9c7f751998aeb6837dabfea7ac33938d (patch)
tree20de27fdeb9b6b6a11d3963363ba53fbeaddce91
parent304d5c35a8718b2b0f190e53dece6362d14df1b4 (diff)
Fix for left recursion error due to wrong context
-rw-r--r--match.c11
-rw-r--r--pattern.h3
2 files changed, 8 insertions, 6 deletions
diff --git a/match.c b/match.c
index 17f88bb..461148d 100644
--- a/match.c
+++ b/match.c
@@ -335,10 +335,10 @@ static match_t *match(match_ctx_t *ctx, const char *str, pat_t *pat)
// point, it can be handled with normal recursion.
// See: left-recursion.md for more details.
if (str == pat->args.leftrec.at) {
- ++pat->args.leftrec.visits;
+ pat->args.leftrec.visited = true;
return clone_match(pat->args.leftrec.match);
} else {
- return match(ctx, str, pat->args.leftrec.fallback);
+ return match(pat->args.leftrec.ctx, str, pat->args.leftrec.fallback);
}
}
case BP_ANYCHAR: {
@@ -631,9 +631,10 @@ static match_t *match(match_ctx_t *ctx, const char *str, pat_t *pat)
.min_matchlen = 0, .max_matchlen = -1,
.args.leftrec = {
.match = NULL,
- .visits = 0,
+ .visited = false,
.at = str,
- .fallback = ref,
+ .fallback = pat,
+ .ctx = (void*)ctx,
},
};
match_ctx_t ctx2 = *ctx;
@@ -652,7 +653,7 @@ static match_t *match(match_ctx_t *ctx, const char *str, pat_t *pat)
match_t *m = match(&ctx2, str, ref);
// If left recursion was involved, keep retrying while forward progress can be made:
- if (m && rec_op.args.leftrec.visits > 0) {
+ if (m && rec_op.args.leftrec.visited) {
while (1) {
const char *prev = m->end;
rec_op.args.leftrec.match = m;
diff --git a/pattern.h b/pattern.h
index a1f7043..dd763d5 100644
--- a/pattern.h
+++ b/pattern.h
@@ -83,9 +83,10 @@ typedef struct pat_s {
} capture;
struct {
struct match_s *match;
- unsigned int visits;
const char *at;
struct pat_s *fallback;
+ void *ctx;
+ bool visited;
} leftrec;
struct {
const char *start, *end, *msg;