aboutsummaryrefslogtreecommitdiffstats
path: root/libparser.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libparser.c30
1 files changed, 28 insertions, 2 deletions
diff --git a/libparser.c b/libparser.c
index eec9337..7ef7267 100644
--- a/libparser.c
+++ b/libparser.c
@@ -119,7 +119,7 @@ struct choice {
/**
* The follow-ups
*/
- struct followup *followups;
+ struct followup *followups; /* TODO add memory pool, maybe even use a memory stack */
/**
* The number of follow-ups; this is
@@ -266,6 +266,7 @@ sentence_type_string(enum libparser_sentence_type type)
case LIBPARSER_SENTENCE_TYPE_EXCEPTION: return "EXCEPTION";
case LIBPARSER_SENTENCE_TYPE_EOF: return "EOF";
case LIBPARSER_SENTENCE_TYPE_EPSILON: return "EPSILON";
+ case LIBPARSER_SENTENCE_TYPE_COMMITTED: return "COMMITTED";
default: return "<invalid>";
}
}
@@ -390,6 +391,13 @@ print_sentence(const union libparser_sentence *sentence, int indent)
indent += 1;
break;
+ case LIBPARSER_SENTENCE_TYPE_COMMITTED:
+ fprintf(stderr, "+(");
+ indent = print_sentence(sentence->unary.sentence, indent + 2);
+ fprintf(stderr, ")");
+ indent += 1;
+ break;
+
case LIBPARSER_SENTENCE_TYPE_OPTIONAL:
fprintf(stderr, "[");
indent = print_sentence(sentence->unary.sentence, indent + 1);
@@ -882,6 +890,12 @@ add_unit(const char *rule, const union libparser_sentence *sentence, struct cont
ctx->previous_rejection = ctx->units.count - 1u;
return 1;
+ case LIBPARSER_SENTENCE_TYPE_COMMITTED:
+ if (incomplete(NULL, sentence, start, ctx) ||
+ push(NULL, sentence->unary.sentence, ctx))
+ return -1;
+ return 1;
+
case LIBPARSER_SENTENCE_TYPE_RULE:
for (i = 0; ctx->rules[i]; i++)
if (!strcmp(ctx->rules[i]->name, sentence->rule.rule))
@@ -993,6 +1007,7 @@ make_tree(struct context *ctx, size_t *unit_i, struct libparser_unit **last)
case LIBPARSER_SENTENCE_TYPE_RULE:
case LIBPARSER_SENTENCE_TYPE_OPTIONAL:
case LIBPARSER_SENTENCE_TYPE_ALTERNATION:
+ case LIBPARSER_SENTENCE_TYPE_COMMITTED:
#if PRINT_ACTIONS
fprintf(stderr, "Unary unit: %s: %s [%zu, %zu)\n",
sentence_type_string(unit->sentence->type),
@@ -1164,7 +1179,7 @@ libparser_parse_file(const struct libparser_rule *const rules[], const char *dat
#endif
/* TODO guard against left-side recursion */
- /* TODO make branching opt-in ("?"), and add commit statements ("+") */
+ /* TODO make branching opt-in ("?") */
/* TODO break REPEATED on empty match */
followup:
#if PRINT_ACTIONS
@@ -1234,6 +1249,17 @@ followup:
}
if (!match)
goto mismatch;
+ if (sentence->type == LIBPARSER_SENTENCE_TYPE_COMMITTED) {
+#if PRINT_ACTIONS
+ fprintf(stderr, "Removing interior choices for matched COMMITTED\n");
+#endif
+ j = ctx.followups.followups[i].unit_index;
+ while (ctx.choices.count &&
+ ctx.choices.choices[ctx.choices.count - 1u].unit_index > j) {
+ ctx.choices.next = --ctx.choices.count;
+ free(ctx.choices.choices[ctx.choices.count].followups.followups);
+ }
+ }
#if PRINT_ACTIONS
fprintf(stderr, "Setting end of popped unit to %zu\n", ctx.position);
#endif