diff --git a/src/backends/llk.c b/src/backends/llk.c index 72b39bbbcfb8bfed1db466aa8674c1392c7fba3f..228e85b88339fccea7eb2d7d31dcd53ca87922f1 100644 --- a/src/backends/llk.c +++ b/src/backends/llk.c @@ -113,6 +113,7 @@ static int fill_table(HCFGrammar *g, HLLkTable *table) if(hte->key == NULL) continue; const HCFChoice *a = hte->key; // production's left-hand symbol + assert(a->type == HCF_CHOICE); // create table row for this nonterminal HHashTable *row = h_hashtable_new(table->arena, h_eq_ptr, h_hash_ptr); diff --git a/src/cfgrammar.c b/src/cfgrammar.c index 684a39c8663156239a9f8e7ae3e52268c27f1b83..b4a3aef368d4e5017039e554680d1674b4404d98 100644 --- a/src/cfgrammar.c +++ b/src/cfgrammar.c @@ -100,6 +100,8 @@ static void collect_nts(HCFGrammar *grammar, HCFChoice *symbol) break; // it's a terminal symbol, nothing to do case HCF_CHARSET: + break; // NB charsets are considered terminal, too + case HCF_CHOICE: // exploiting the fact that HHashSet is also a HHashTable to number the // nonterminals. @@ -107,13 +109,11 @@ static void collect_nts(HCFGrammar *grammar, HCFChoice *symbol) h_hashtable_put(grammar->nts, symbol, (void *)(uintptr_t)grammar->nts->used); - if(symbol->type == HCF_CHOICE) { - // each element s of symbol->seq (HCFSequence) represents the RHS of - // a production. call self on all symbols (HCFChoice) in s. - for(s = symbol->seq; *s != NULL; s++) { - for(x = (*s)->items; *x != NULL; x++) { - collect_nts(grammar, *x); - } + // each element s of symbol->seq (HCFSequence) represents the RHS of + // a production. call self on all symbols (HCFChoice) in s. + for(s = symbol->seq; *s != NULL; s++) { + for(x = (*s)->items; *x != NULL; x++) { + collect_nts(grammar, *x); } } break; @@ -172,10 +172,7 @@ static void collect_geneps(HCFGrammar *g) if(hte->key == NULL) continue; const HCFChoice *symbol = hte->key; - - // only "choice" nonterminals can derive epsilon. - if(symbol->type != HCF_CHOICE) - continue; + assert(symbol->type == HCF_CHOICE); // this NT derives epsilon if any of its productions does. HCFSequence **p; @@ -298,9 +295,7 @@ HHashSet *h_follow(HCFGrammar *g, const HCFChoice *x) if(hte->key == NULL) continue; const HCFChoice *a = hte->key; // production's left-hand symbol - - // X can only occur in a proper HCF_CHOICE - if(a->type != HCF_CHOICE) continue; + assert(a->type == HCF_CHOICE); // iterate over the productions for A HCFSequence **p; @@ -412,6 +407,8 @@ static void pprint_symbol(FILE *f, const HCFGrammar *g, const HCFChoice *x) case HCF_END: fputc('$', f); break; + case HCF_CHARSET: + pprint_charset(f, x->charset); default: fputs(nonterminal_name(g, x), f); } @@ -456,24 +453,14 @@ void pprint_ntrules(FILE *f, const HCFGrammar *g, const HCFChoice *nt, for(; i<column; i++) fputc(' ', f); fputs(" ->", f); - HCFSequence **p; - switch(nt->type) { - case HCF_CHARSET: - pprint_charset(f, nt->charset); - break; - case HCF_CHOICE: - p = nt->seq; - if(*p == NULL) break; // shouldn't happen - pprint_sequence(f, g, *p++); // print first production on the same line - for(; *p; p++) { // print the rest below with "or" bars - for(i=0; i<column; i++) fputc(' ', f); // indent - fputs(" |", f); - pprint_sequence(f, g, *p); - } - break; - default: // should not be reached - fputs(" ???\n", f); - assert_message(0, "unexpected nonterminal type"); + assert(nt->type == HCF_CHOICE); + HCFSequence **p = nt->seq; + if(*p == NULL) return; // shouldn't happen + pprint_sequence(f, g, *p++); // print first production on the same line + for(; *p; p++) { // print the rest below with "or" bars + for(i=0; i<column; i++) fputc(' ', f); // indent + fputs(" |", f); + pprint_sequence(f, g, *p); } } @@ -495,6 +482,7 @@ void h_pprint_grammar(FILE *file, const HCFGrammar *g, int indent) if(hte->key == NULL) continue; const HCFChoice *a = hte->key; // production's left-hand symbol + assert(a->type == HCF_CHOICE); pprint_ntrules(file, g, a, indent, len); }