From 950bed8b8c7cc1111164038bbb98c1ba59a90368 Mon Sep 17 00:00:00 2001 From: "Sven M. Hallberg" Date: Tue, 30 Apr 2013 20:17:51 +0200 Subject: [PATCH] add (untested) follow set computation --- src/backends/ll.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/src/backends/ll.c b/src/backends/ll.c index 1b9f06b..d1cba42 100644 --- a/src/backends/ll.c +++ b/src/backends/ll.c @@ -10,7 +10,8 @@ typedef struct HCFGrammar_ { HHashSet *nts; // HCFChoices, each representing the alternative // productions for one nonterminal HHashSet *geneps; // set of NTs that can generate the empty string - HHashTable *first; // memoized "first" sets of the grammar's symbols + HHashTable *first; // memoized first sets of the grammar's symbols + HHashTable *follow; // memoized follow sets of the grammar's NTs HArena *arena; } HCFGrammar; @@ -247,6 +248,60 @@ HHashSet *h_first_sequence(HCFGrammar *g, HCFChoice **s) } +/* Compute follow set of symbol x. Memoized. */ +HHashSet *h_follow(HCFGrammar *g, const HCFChoice *x) +{ + // consider all occurances of X in g + // the follow set of X is the union of: + // given a production "A -> alpha X tail": + // if tail derives epsilon: + // first(tail) u follow(A) + // else: + // first(tail) + + HHashSet *ret; + + // memoize via g->follow + assert(g->follow != NULL); + ret = h_hashtable_get(g->follow, x); + if(ret != NULL) + return ret; + ret = h_hashset_new(g->arena, h_eq_ptr, h_hash_ptr); + assert(ret != NULL); + h_hashtable_put(g->follow, x, ret); + + // iterate over g->nts + size_t i; + HHashTableEntry *hte; + for(i=0; i < g->nts->capacity; i++) { + for(hte = &g->nts->contents[i]; hte; hte = hte->next) { + 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; + + // iterate over the productions for A + HCFSequence **p; + for(p=a->seq; *p; p++) { + HCFChoice **s = (*p)->items; // production's right-hand side + + for(; *s; s++) { + if(*s == x) { // occurance found + HCFChoice **tail = s+1; + + h_hashset_put_all(ret, h_first_sequence(g, tail)); + if(h_sequence_derives_epsilon(g, tail)) + h_hashset_put_all(ret, h_follow(g, a)); + } + } + } + } + } + + return ret; +} + + /* LL parse table and associated data */