diff --git a/src/backends/ll.c b/src/backends/ll.c index 5994d929e54e424cf2f10fb1899f83345aad8bae..8ed4d604e13272ea4505fa5b55797f4cedf9920f 100644 --- a/src/backends/ll.c +++ b/src/backends/ll.c @@ -5,23 +5,53 @@ -/* LL parse table and associated data */ +/* Generating the LL parse table */ /* Maps each nonterminal (HCFChoice) of the grammar to another hash table that * maps lookahead tokens (HCFToken) to productions (HCFSequence). */ -typedef HHashTable HLLTable; +typedef struct HLLTable_ { + HHashTable *rows; + HArena *arena; + HAllocator *mm__; +} HLLTable; /* Interface to look up an entry in the parse table. */ const HCFSequence *h_ll_lookup(const HLLTable *table, const HCFChoice *x, HCFToken tok) { - const HHashTable *row = h_hashtable_get(table, x); + const HHashTable *row = h_hashtable_get(table->rows, x); assert(row != NULL); // the table should have one row for each nonterminal const HCFSequence *production = h_hashtable_get(row, (void *)tok); return production; } +/* Allocate a new parse table. */ +HLLTable *h_lltable_new(HAllocator *mm__) +{ + // NB the parse table gets an arena separate from the grammar so we can free + // the latter after table generation. + HArena *arena = h_new_arena(mm__, 0); // default blocksize + assert(arena != NULL); + HHashTable *rows = h_hashtable_new(arena, h_eq_ptr, h_hash_ptr); + assert(rows != NULL); + + HLLTable *table = h_new(HLLTable, 1); + assert(table != NULL); + table->mm__ = mm__; + table->arena = arena; + table->rows = rows; + + return table; +} + +void h_lltable_free(HLLTable *table) +{ + HAllocator *mm__ = table->mm__; + h_delete_arena(table->arena); + h_free(table); +} + /* Compute the predict set of production "A -> rhs". */ HHashSet *h_predict(HCFGrammar *g, const HCFChoice *A, const HCFSequence *rhs) { @@ -38,7 +68,15 @@ HHashSet *h_predict(HCFGrammar *g, const HCFChoice *A, const HCFSequence *rhs) } } -int h_ll_compile(HAllocator* mm__, const HParser* parser, const void* params) +/* Generate the LL parse table from the given grammar. + * Returns -1 on error, 0 on success. + */ +static int fill_table(HCFGrammar *g, HLLTable *table) +{ + return -1; // XXX +} + +int h_ll_compile(HAllocator* mm__, HParser* parser, const void* params) { // Convert parser to a CFG. This can fail as indicated by a NULL return. HCFGrammar *grammar = h_cfgrammar(mm__, parser); @@ -49,11 +87,21 @@ int h_ll_compile(HAllocator* mm__, const HParser* parser, const void* params) // TODO: eliminate left recursion // TODO: avoid conflicts by splitting occurances? - // XXX generate table and store in parser->data. - // XXX any other data structures needed? - // XXX free grammar and its arena + // generate table and store in parser->data. + HLLTable *table = h_lltable_new(mm__); + if(fill_table(grammar, table) < 0) { + // the table was ambiguous + h_cfgrammar_free(grammar); + h_lltable_free(table); + return -1; + } + parser->data = table; + + // free grammar and its arena. + // desugared parsers (HCFChoice and HCFSequence) are unaffected by this. + h_cfgrammar_free(grammar); - return -1; // XXX 0 on success + return 0; }