add (untested) follow set computation
This commit is contained in:
parent
85aaf94332
commit
950bed8b8c
1 changed files with 56 additions and 1 deletions
|
|
@ -10,7 +10,8 @@ typedef struct HCFGrammar_ {
|
||||||
HHashSet *nts; // HCFChoices, each representing the alternative
|
HHashSet *nts; // HCFChoices, each representing the alternative
|
||||||
// productions for one nonterminal
|
// productions for one nonterminal
|
||||||
HHashSet *geneps; // set of NTs that can generate the empty string
|
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;
|
HArena *arena;
|
||||||
} HCFGrammar;
|
} 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 */
|
/* LL parse table and associated data */
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue