diff --git a/src/parsers/many.c b/src/parsers/many.c index c439b67..f4829eb 100644 --- a/src/parsers/many.c +++ b/src/parsers/many.c @@ -58,59 +58,58 @@ static bool many_isValidCF(void *env) { static HCFChoice* desugar_many(HAllocator *mm__, void *env) { HRepeat *repeat = (HRepeat*)env; + if(repeat->count > 1) { + assert_message(0, "'h_repeat_n' is not context-free, can't be desugared"); + return NULL; + } + /* many(A) => Ma -> A Mar -> \epsilon (but not if many1/sepBy1 is used) Mar -> Sep A Mar -> \epsilon */ - HCFChoice *ret = h_new(HCFChoice, 1); - ret->type = HCF_CHOICE; - if (repeat->min_p) - ret->seq = h_new(HCFSequence*, 2); /* choice of 1 sequence, A Mar */ - else - ret->seq = h_new(HCFSequence*, 3); /* choice of 2 sequences, A Mar | epsilon */ - ret->seq[0] = h_new(HCFSequence, 1); - ret->seq[0]->items = h_new(HCFChoice*, 2); - + + HCFChoice *a = h_desugar(mm__, repeat->p); + HCFChoice *ma = h_new(HCFChoice, 1); + HCFChoice *mar = h_new(HCFChoice, 1); + HCFChoice *eps = desugar_epsilon(mm__, NULL); + /* create first subrule */ - HCFChoice *ma = h_new(HCFChoice, 3); ma->type = HCF_CHOICE; - ma->seq[0]->items[0] = h_desugar(mm__, repeat->p); + ma->seq = h_new(HCFSequence*, 3); /* enough for 2 productions */ + ma->seq[0] = h_new(HCFSequence, 1); + ma->seq[0]->items = h_new(HCFChoice*, 3); + ma->seq[0]->items[0] = a; + ma->seq[0]->items[1] = mar; + ma->seq[0]->items[2] = NULL; + ma->seq[1] = NULL; + + /* if not many1/sepBy1, attach epsilon */ + if (repeat->count == 0) { + ma->seq[1] = h_new(HCFSequence, 1); + ma->seq[1]->items = h_new(HCFChoice*, 2); + ma->seq[1]->items[0] = eps; + ma->seq[1]->items[1] = NULL; + ma->seq[2] = NULL; + } /* create second subrule */ - HCFChoice *mar = h_new(HCFChoice, 3); mar->type = HCF_CHOICE; - mar->seq = h_new(HCFSequence*, 2); + mar->seq = h_new(HCFSequence*, 3); mar->seq[0] = h_new(HCFSequence, 1); mar->seq[0]->items = h_new(HCFChoice*, 4); mar->seq[0]->items[0] = h_desugar(mm__, repeat->sep); - mar->seq[0]->items[1] = h_desugar(mm__, repeat->p); + mar->seq[0]->items[1] = a; mar->seq[0]->items[2] = mar; // woo recursion! mar->seq[0]->items[3] = NULL; + mar->seq[1] = h_new(HCFSequence, 1); mar->seq[1]->items = h_new(HCFChoice*, 2); - mar->seq[1]->items[0] = desugar_epsilon(mm__, NULL);\ + mar->seq[1]->items[0] = eps; mar->seq[1]->items[1] = NULL; - mar->seq[2]->items = NULL; + mar->seq[2] = NULL; - /* attach second subrule to first subrule */ - ma->seq[0]->items[1] = mar; - ma->seq[0]->items[2] = NULL; - - /* attach first subrule to ret */ - ret->seq[0]->items[0] = ma; - ret->seq[0]->items[1] = NULL; - - /* if not many1/sepBy1, attach epsilon */ - if (repeat->min_p) { - ret->seq[1]->items = NULL; - } else { - ret->seq[1]->items = h_new(HCFChoice*, 2); - ret->seq[1]->items[0] = desugar_epsilon(mm__, NULL); - ret->seq[1]->items[1] = NULL; - ret->seq[2]->items = NULL; - } - return ret; + return ma; } static const HParserVtable many_vt = {