From 36e1f66de0b553fcdf8a6ece368bf8577e002743 Mon Sep 17 00:00:00 2001 From: "Meredith L. Patterson" <mlp@thesmartpolitenerd.com> Date: Tue, 18 Dec 2012 18:10:40 -0500 Subject: [PATCH] Expanded vtable for methods to determine whether a combinator is ok to use with regular or CF grammars. --- src/hammer.h | 2 ++ src/parsers/action.c | 12 ++++++++++++ src/parsers/and.c | 5 +++++ src/parsers/attr_bool.c | 12 ++++++++++++ src/parsers/bits.c | 2 ++ src/parsers/butnot.c | 8 ++++++++ src/parsers/ch.c | 2 ++ src/parsers/charset.c | 2 ++ src/parsers/choice.c | 20 ++++++++++++++++++++ src/parsers/difference.c | 8 ++++++++ src/parsers/end.c | 2 ++ src/parsers/epsilon.c | 2 ++ src/parsers/ignore.c | 12 ++++++++++++ src/parsers/ignoreseq.c | 28 ++++++++++++++++++++++++---- src/parsers/indirect.c | 9 +++++++++ src/parsers/int_range.c | 2 ++ src/parsers/many.c | 16 ++++++++++++++++ src/parsers/not.c | 2 ++ src/parsers/nothing.c | 2 ++ src/parsers/optional.c | 12 ++++++++++++ src/parsers/sequence.c | 20 ++++++++++++++++++++ src/parsers/token.c | 2 ++ src/parsers/unimplemented.c | 2 ++ src/parsers/whitespace.c | 12 ++++++++++++ src/parsers/xor.c | 8 ++++++++ 25 files changed, 200 insertions(+), 4 deletions(-) diff --git a/src/hammer.h b/src/hammer.h index 0791769d..ecb60654 100644 --- a/src/hammer.h +++ b/src/hammer.h @@ -112,6 +112,8 @@ typedef bool (*HPredicate)(HParseResult *p); typedef struct HParserVtable_ { HParseResult* (*parse)(void *env, HParseState *state); + bool (*isValidRegular)(void *env); + bool (*isValidCF)(void *env); } HParserVtable; typedef struct HParser_ { diff --git a/src/parsers/action.c b/src/parsers/action.c index 0f1686f2..33e33bc3 100644 --- a/src/parsers/action.c +++ b/src/parsers/action.c @@ -19,8 +19,20 @@ static HParseResult* parse_action(void *env, HParseState *state) { return NULL; } +static bool action_isValidRegular(void *env) { + HParseAction *a = (HParseAction*)env; + return a->p->vtable->isValidRegular(a->p->env); +} + +static bool action_isValidCF(void *env) { + HParseAction *a = (HParseAction*)env; + return a->p->vtable->isValidCF(a->p->env); +} + static const HParserVtable action_vt = { .parse = parse_action, + .isValidRegular = action_isValidRegular, + .isValidCF = action_isValidCF, }; const HParser* h_action(const HParser* p, const HAction a) { diff --git a/src/parsers/and.c b/src/parsers/and.c index 532cbbaf..ac51be29 100644 --- a/src/parsers/and.c +++ b/src/parsers/and.c @@ -11,6 +11,11 @@ static HParseResult *parse_and(void* env, HParseState* state) { static const HParserVtable and_vt = { .parse = parse_and, + .isValidRegular = h_false, /* TODO: strictly speaking this should be regular, + but it will be a huge amount of work and difficult + to get right, so we're leaving it for a future + revision. --mlp, 18/12/12 */ + .isValidCF = h_false, /* despite TODO above, this remains false. */ }; diff --git a/src/parsers/attr_bool.c b/src/parsers/attr_bool.c index 6fa36f84..bfc4976a 100644 --- a/src/parsers/attr_bool.c +++ b/src/parsers/attr_bool.c @@ -17,8 +17,20 @@ static HParseResult* parse_attr_bool(void *env, HParseState *state) { return NULL; } +static bool ab_isValidRegular(void *env) { + HAttrBool *ab = (HAttrBool*)env; + return ab->p->vtable->isValidRegular(ab->p->env); +} + +static bool ab_isValidCF(void *env) { + HAttrBool *ab = (HAttrBool*)env; + return ab->p->vtable->isValidCF(ab->p->env); +} + static const HParserVtable attr_bool_vt = { .parse = parse_attr_bool, + .isValidRegular = ab_isValidRegular, + .isValidCF = ab_isValidCF, }; diff --git a/src/parsers/bits.c b/src/parsers/bits.c index 196e33bb..c3a40da6 100644 --- a/src/parsers/bits.c +++ b/src/parsers/bits.c @@ -18,6 +18,8 @@ static HParseResult* parse_bits(void* env, HParseState *state) { static const HParserVtable bits_vt = { .parse = parse_bits, + .isValidRegular = h_true, + .isValidCF = h_true, }; const HParser* h_bits(size_t len, bool sign) { return h_bits__m(&system_allocator, len, sign); diff --git a/src/parsers/butnot.c b/src/parsers/butnot.c index 422e0e1f..4d5bf578 100644 --- a/src/parsers/butnot.c +++ b/src/parsers/butnot.c @@ -35,8 +35,16 @@ static HParseResult* parse_butnot(void *env, HParseState *state) { } } +static bool bn_isValidCF(void *env) { + HTwoParsers *tp = (HTwoParsers*)env; + return (tp->p1->vtable->isValidCF(tp->p1->env) && + tp->p2->vtable->isValidCF(tp->p2->env)); +} + static const HParserVtable butnot_vt = { .parse = parse_butnot, + .isValidRegular = h_false, + .isValidCF = bn_isValidCF, }; const HParser* h_butnot(const HParser* p1, const HParser* p2) { diff --git a/src/parsers/ch.c b/src/parsers/ch.c index 032731e9..8b67744e 100644 --- a/src/parsers/ch.c +++ b/src/parsers/ch.c @@ -14,6 +14,8 @@ static HParseResult* parse_ch(void* env, HParseState *state) { static const HParserVtable ch_vt = { .parse = parse_ch, + .isValidRegular = h_true, + .isValidCF = h_true, }; const HParser* h_ch(const uint8_t c) { diff --git a/src/parsers/charset.c b/src/parsers/charset.c index f11715ff..7341e007 100644 --- a/src/parsers/charset.c +++ b/src/parsers/charset.c @@ -34,6 +34,8 @@ static HParseResult* parse_charset(void *env, HParseState *state) { static const HParserVtable charset_vt = { .parse = parse_charset, + .isValidRegular = h_true, + .isValidCF = h_true, }; const HParser* h_ch_range(const uint8_t lower, const uint8_t upper) { diff --git a/src/parsers/choice.c b/src/parsers/choice.c index 73dedde6..d48ed229 100644 --- a/src/parsers/choice.c +++ b/src/parsers/choice.c @@ -21,8 +21,28 @@ static HParseResult* parse_choice(void *env, HParseState *state) { return NULL; } +static bool choice_isValidRegular(void *env) { + HSequence *s = (HSequence*)env; + for (size_t i=0; i<s->len; ++i) { + if (!s->p_array[i]->vtable->isValidRegular(s->p_array[i]->env)) + return false; + } + return true; +} + +static bool choice_isValidCF(void *env) { + HSequence *s = (HSequence*)env; + for (size_t i=0; i<s->len; ++i) { + if (!s->p_array[i]->vtable->isValidCF(s->p_array[i]->env)) + return false; + } + return true; +} + static const HParserVtable choice_vt = { .parse = parse_choice, + .isValidRegular = choice_isValidRegular, + .isValidCF = choice_isValidCF, }; const HParser* h_choice(const HParser* p, ...) { diff --git a/src/parsers/difference.c b/src/parsers/difference.c index c6cc69ce..e3c41ec3 100644 --- a/src/parsers/difference.c +++ b/src/parsers/difference.c @@ -34,8 +34,16 @@ static HParseResult* parse_difference(void *env, HParseState *state) { } } +static bool diff_isValidCF(void *env) { + HTwoParsers *tp = (HTwoParsers*)env; + return (tp->p1->vtable->isValidCF(tp->p1->env) && + tp->p2->vtable->isValidCF(tp->p2->env)); +} + static HParserVtable difference_vt = { .parse = parse_difference, + .isValidRegular = h_false, + .isValidCF = diff_isValidCF, }; const HParser* h_difference(const HParser* p1, const HParser* p2) { diff --git a/src/parsers/end.c b/src/parsers/end.c index 0f0d1c7d..45ba37d9 100644 --- a/src/parsers/end.c +++ b/src/parsers/end.c @@ -12,6 +12,8 @@ static HParseResult* parse_end(void *env, HParseState *state) { static const HParserVtable end_vt = { .parse = parse_end, + .isValidRegular = h_true, + .isValidCF = h_true, }; const HParser* h_end_p() { diff --git a/src/parsers/epsilon.c b/src/parsers/epsilon.c index ae959cd5..5ae91e36 100644 --- a/src/parsers/epsilon.c +++ b/src/parsers/epsilon.c @@ -10,6 +10,8 @@ static HParseResult* parse_epsilon(void* env, HParseState* state) { static const HParserVtable epsilon_vt = { .parse = parse_epsilon, + .isValidRegular = h_true, + .isValidCF = h_true, }; static const HParser epsilon_p = { diff --git a/src/parsers/ignore.c b/src/parsers/ignore.c index 03cdc107..6191eff9 100644 --- a/src/parsers/ignore.c +++ b/src/parsers/ignore.c @@ -10,8 +10,20 @@ static HParseResult* parse_ignore(void* env, HParseState* state) { return res; } +static bool ignore_isValidRegular(void *env) { + HParser *p = (HParser*)env; + return (p->vtable->isValidRegular(p->env)); +} + +static bool ignore_isValidCF(void *env) { + HParser *p = (HParser*)env; + return (p->vtable->isValidCF(p->env)); +} + static const HParserVtable ignore_vt = { .parse = parse_ignore, + .isValidRegular = ignore_isValidRegular, + .isValidCF = ignore_isValidCF, }; const HParser* h_ignore(const HParser* p) { diff --git a/src/parsers/ignoreseq.c b/src/parsers/ignoreseq.c index 228f6357..319f1ebe 100644 --- a/src/parsers/ignoreseq.c +++ b/src/parsers/ignoreseq.c @@ -7,7 +7,7 @@ typedef struct { const HParser **parsers; - size_t count; // how many parsers in 'ps' + size_t len; // how many parsers in 'ps' size_t which; // whose result to return } HIgnoreSeq; @@ -15,7 +15,7 @@ static HParseResult* parse_ignoreseq(void* env, HParseState *state) { const HIgnoreSeq *seq = (HIgnoreSeq*)env; HParseResult *res = NULL; - for (size_t i=0; i < seq->count; ++i) { + for (size_t i=0; i < seq->len; ++i) { HParseResult *tmp = h_do_parse(seq->parsers[i], state); if (!tmp) return NULL; @@ -26,8 +26,28 @@ static HParseResult* parse_ignoreseq(void* env, HParseState *state) { return res; } +static bool is_isValidRegular(void *env) { + HIgnoreSeq *seq = (HIgnoreSeq*)env; + for (size_t i=0; i<seq->len; ++i) { + if (!seq->parsers[i]->vtable->isValidRegular(seq->parsers[i]->env)) + return false; + } + return true; +} + +static bool is_isValidCF(void *env) { + HIgnoreSeq *seq = (HIgnoreSeq*)env; + for (size_t i=0; i<seq->len; ++i) { + if (!seq->parsers[i]->vtable->isValidCF(seq->parsers[i]->env)) + return false; + } + return true; +} + static const HParserVtable ignoreseq_vt = { .parse = parse_ignoreseq, + .isValidRegular = is_isValidRegular, + .isValidCF = is_isValidCF, }; @@ -40,7 +60,7 @@ static const HParser* h_leftright__m(HAllocator* mm__, const HParser* p, const H seq->parsers = h_new(const HParser*, 2); seq->parsers[0] = p; seq->parsers[1] = q; - seq->count = 2; + seq->len = 2; seq->which = which; HParser *ret = h_new(HParser, 1); @@ -73,7 +93,7 @@ const HParser* h_middle__m(HAllocator* mm__, const HParser* p, const HParser* x, seq->parsers[0] = p; seq->parsers[1] = x; seq->parsers[2] = q; - seq->count = 3; + seq->len = 3; seq->which = 1; HParser *ret = h_new(HParser, 1); diff --git a/src/parsers/indirect.c b/src/parsers/indirect.c index 96e2a65d..4415f067 100644 --- a/src/parsers/indirect.c +++ b/src/parsers/indirect.c @@ -3,8 +3,17 @@ static HParseResult* parse_indirect(void* env, HParseState* state) { return h_do_parse(env, state); } + +static bool indirect_isValidCF(void *env) { + HParser *p = (HParser*)env; + HParser *inner = (HParser*)p->env; + return inner->vtable->isValidCF(inner->env); +} + static const HParserVtable indirect_vt = { .parse = parse_indirect, + .isValidRegular = h_false, + .isValidCF = indirect_isValidCF, }; void h_bind_indirect(HParser* indirect, const HParser* inner) { diff --git a/src/parsers/int_range.c b/src/parsers/int_range.c index 2a1db63c..d1920589 100644 --- a/src/parsers/int_range.c +++ b/src/parsers/int_range.c @@ -30,6 +30,8 @@ static HParseResult* parse_int_range(void *env, HParseState *state) { static const HParserVtable int_range_vt = { .parse = parse_int_range, + .isValidRegular = h_true, + .isValidCF = h_true, }; const HParser* h_int_range(const HParser *p, const int64_t lower, const int64_t upper) { diff --git a/src/parsers/many.c b/src/parsers/many.c index 6cb818bc..2c2577ef 100644 --- a/src/parsers/many.c +++ b/src/parsers/many.c @@ -44,8 +44,22 @@ static HParseResult *parse_many(void* env, HParseState *state) { return NULL; } +static bool many_isValidRegular(void *env) { + HRepeat *repeat = (HRepeat*)env; + return (repeat->p->vtable->isValidRegular(repeat->p->env) && + repeat->sep->vtable->isValidRegular(repeat->sep->env)); +} + +static bool many_isValidCF(void *env) { + HRepeat *repeat = (HRepeat*)env; + return (repeat->p->vtable->isValidCF(repeat->p->env) && + repeat->sep->vtable->isValidCF(repeat->sep->env)); +} + static const HParserVtable many_vt = { .parse = parse_many, + .isValidRegular = many_isValidRegular, + .isValidCF = many_isValidCF, }; const HParser* h_many(const HParser* p) { @@ -147,6 +161,8 @@ static HParseResult* parse_length_value(void *env, HParseState *state) { static const HParserVtable length_value_vt = { .parse = parse_length_value, + .isValidRegular = h_false, + .isValidCF = h_false, }; const HParser* h_length_value(const HParser* length, const HParser* value) { diff --git a/src/parsers/not.c b/src/parsers/not.c index 73cf1295..6642d9e8 100644 --- a/src/parsers/not.c +++ b/src/parsers/not.c @@ -12,6 +12,8 @@ static HParseResult* parse_not(void* env, HParseState* state) { static const HParserVtable not_vt = { .parse = parse_not, + .isValidRegular = h_false, /* see and.c for why */ + .isValidCF = h_false, /* also see and.c for why */ }; const HParser* h_not(const HParser* p) { diff --git a/src/parsers/nothing.c b/src/parsers/nothing.c index 120c8ef3..01c029eb 100644 --- a/src/parsers/nothing.c +++ b/src/parsers/nothing.c @@ -8,6 +8,8 @@ static HParseResult* parse_nothing() { static const HParserVtable nothing_vt = { .parse = parse_nothing, + .isValidRegular = h_true, + .isValidCF = h_true, }; const HParser* h_nothing_p() { diff --git a/src/parsers/optional.c b/src/parsers/optional.c index 9625fa0f..0b405e5a 100644 --- a/src/parsers/optional.c +++ b/src/parsers/optional.c @@ -11,8 +11,20 @@ static HParseResult* parse_optional(void* env, HParseState* state) { return make_result(state, ast); } +static bool opt_isValidRegular(void *env) { + HParser *p = (HParser*) env; + return p->vtable->isValidRegular(p->env); +} + +static bool opt_isValidCF(void *env) { + HParser *p = (HParser*) env; + return p->vtable->isValidCF(p->env); +} + static const HParserVtable optional_vt = { .parse = parse_optional, + .isValidRegular = opt_isValidRegular, + .isValidCF = opt_isValidCF, }; const HParser* h_optional(const HParser* p) { diff --git a/src/parsers/sequence.c b/src/parsers/sequence.c index 21ae31d9..f5e19246 100644 --- a/src/parsers/sequence.c +++ b/src/parsers/sequence.c @@ -24,8 +24,28 @@ static HParseResult* parse_sequence(void *env, HParseState *state) { return make_result(state, tok); } +static bool sequence_isValidRegular(void *env) { + HSequence *s = (HSequence*)env; + for (size_t i=0; i<s->len; ++i) { + if (!s->p_array[i]->vtable->isValidRegular(s->p_array[i]->env)) + return false; + } + return true; +} + +static bool sequence_isValidCF(void *env) { + HSequence *s = (HSequence*)env; + for (size_t i=0; i<s->len; ++i) { + if (!s->p_array[i]->vtable->isValidCF(s->p_array[i]->env)) + return false; + } + return true; +} + static const HParserVtable sequence_vt = { .parse = parse_sequence, + .isValidRegular = sequence_isValidRegular, + .isValidCF = sequence_isValidCF, }; const HParser* h_sequence(const HParser* p, ...) { diff --git a/src/parsers/token.c b/src/parsers/token.c index 13bafbb0..f5df9d4c 100644 --- a/src/parsers/token.c +++ b/src/parsers/token.c @@ -22,6 +22,8 @@ static HParseResult* parse_token(void *env, HParseState *state) { const HParserVtable token_vt = { .parse = parse_token, + .isValidRegular = h_true, + .isValidCF = h_true, }; const HParser* h_token(const uint8_t *str, const size_t len) { diff --git a/src/parsers/unimplemented.c b/src/parsers/unimplemented.c index 35ee391c..32838ce5 100644 --- a/src/parsers/unimplemented.c +++ b/src/parsers/unimplemented.c @@ -14,6 +14,8 @@ static HParseResult* parse_unimplemented(void* env, HParseState *state) { static const HParserVtable unimplemented_vt = { .parse = parse_unimplemented, + .isValidRegular = h_false, + .isValidCF = h_false, }; static HParser unimplemented = { diff --git a/src/parsers/whitespace.c b/src/parsers/whitespace.c index 8e009a43..7b2477be 100644 --- a/src/parsers/whitespace.c +++ b/src/parsers/whitespace.c @@ -14,8 +14,20 @@ static HParseResult* parse_whitespace(void* env, HParseState *state) { return h_do_parse((HParser*)env, state); } +static bool ws_isValidRegular(void *env) { + HParser *p = (HParser*)env; + return p->vtable->isValidRegular(p->env); +} + +static bool ws_isValidCF(void *env) { + HParser *p = (HParser*)env; + return p->vtable->isValidCF(p->env); +} + static const HParserVtable whitespace_vt = { .parse = parse_whitespace, + .isValidRegular = ws_isValidRegular, + .isValidCF = ws_isValidCF, }; const HParser* h_whitespace(const HParser* p) { diff --git a/src/parsers/xor.c b/src/parsers/xor.c index a11ad4ae..7679a645 100644 --- a/src/parsers/xor.c +++ b/src/parsers/xor.c @@ -31,8 +31,16 @@ static HParseResult* parse_xor(void *env, HParseState *state) { } } +static bool xor_isValidCF(void *env) { + HTwoParsers *tp = (HTwoParsers*)env; + return (tp->p1->vtable->isValidCF(tp->p1->env) && + tp->p2->vtable->isValidCF(tp->p2->env)); +} + static const HParserVtable xor_vt = { .parse = parse_xor, + .isValidRegular = h_false, + .isValidCF = xor_isValidCF, }; const HParser* h_xor(const HParser* p1, const HParser* p2) { -- GitLab