change sequence variants of first and derives_epsilon to take a
null-terminated array
This commit is contained in:
parent
73a84d17b8
commit
85aaf94332
1 changed files with 14 additions and 20 deletions
|
|
@ -126,13 +126,12 @@ bool h_symbol_derives_epsilon(HCFGrammar *g, const HCFChoice *symbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Does the sentential form given by s derive the empty string? */
|
/* Does the sentential form s derive the empty string? s NULL-terminated. */
|
||||||
bool h_sequence_derives_epsilon(HCFGrammar *g, const HCFSequence *s)
|
bool h_sequence_derives_epsilon(HCFGrammar *g, HCFChoice **s)
|
||||||
{
|
{
|
||||||
// return true iff all symbols in s derive epsilon
|
// return true iff all symbols in s derive epsilon
|
||||||
HCFChoice **x;
|
for(; *s; s++) {
|
||||||
for(x = s->items; *x; x++) {
|
if(!h_symbol_derives_epsilon(g, *s))
|
||||||
if(!h_symbol_derives_epsilon(g, *x))
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -165,7 +164,7 @@ static void collect_geneps(HCFGrammar *g)
|
||||||
// this NT derives epsilon if any of its productions does.
|
// this NT derives epsilon if any of its productions does.
|
||||||
HCFSequence **p;
|
HCFSequence **p;
|
||||||
for(p = symbol->seq; *p != NULL; p++) {
|
for(p = symbol->seq; *p != NULL; p++) {
|
||||||
if(h_sequence_derives_epsilon(g, *p)) {
|
if(h_sequence_derives_epsilon(g, (*p)->items)) {
|
||||||
h_hashset_put(g->nts, symbol);
|
h_hashset_put(g->nts, symbol);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -176,16 +175,11 @@ static void collect_geneps(HCFGrammar *g)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// helper
|
/* Compute first set of sentential form s. s NULL-terminated. */
|
||||||
static HHashSet *first_sequence_(HCFGrammar *g, const HCFChoice **s);
|
HHashSet *h_first_sequence(HCFGrammar *g, HCFChoice **s);
|
||||||
|
|
||||||
static inline HHashSet *h_first_sequence(HCFGrammar *g, const HCFSequence *s)
|
/* Compute first set of symbol x. Memoized. */
|
||||||
{
|
HHashSet *h_first_symbol(HCFGrammar *g, const HCFChoice *x)
|
||||||
// why do I have to cast to a type that's _more_ const?
|
|
||||||
return first_sequence_(g, (const HCFChoice **)s->items);
|
|
||||||
}
|
|
||||||
|
|
||||||
static HHashSet *h_first_symbol(HCFGrammar *g, const HCFChoice *x)
|
|
||||||
{
|
{
|
||||||
HHashSet *ret;
|
HHashSet *ret;
|
||||||
HCFSequence **p;
|
HCFSequence **p;
|
||||||
|
|
@ -218,7 +212,7 @@ static HHashSet *h_first_symbol(HCFGrammar *g, const HCFChoice *x)
|
||||||
// this is a nonterminal
|
// this is a nonterminal
|
||||||
// return the union of the first sets of all productions
|
// return the union of the first sets of all productions
|
||||||
for(p=x->seq; *p; ++p)
|
for(p=x->seq; *p; ++p)
|
||||||
h_hashset_put_all(ret, h_first_sequence(g, *p));
|
h_hashset_put_all(ret, h_first_sequence(g, (*p)->items));
|
||||||
break;
|
break;
|
||||||
default: // should not be reached
|
default: // should not be reached
|
||||||
assert_message(0, "unknown HCFChoice type");
|
assert_message(0, "unknown HCFChoice type");
|
||||||
|
|
@ -227,7 +221,7 @@ static HHashSet *h_first_symbol(HCFGrammar *g, const HCFChoice *x)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HHashSet *first_sequence_(HCFGrammar *g, const HCFChoice **s)
|
HHashSet *h_first_sequence(HCFGrammar *g, HCFChoice **s)
|
||||||
{
|
{
|
||||||
// the first set of the empty sequence is empty
|
// the first set of the empty sequence is empty
|
||||||
if(*s == NULL)
|
if(*s == NULL)
|
||||||
|
|
@ -236,13 +230,13 @@ static HHashSet *first_sequence_(HCFGrammar *g, const HCFChoice **s)
|
||||||
// first(X tail) = first(X) if X does not derive epsilon
|
// first(X tail) = first(X) if X does not derive epsilon
|
||||||
// = first(X) u first(tail) otherwise
|
// = first(X) u first(tail) otherwise
|
||||||
|
|
||||||
const HCFChoice *x = s[0];
|
HCFChoice *x = s[0];
|
||||||
const HCFChoice **tail = s+1;
|
HCFChoice **tail = s+1;
|
||||||
|
|
||||||
HHashSet *first_x = h_first_symbol(g, x);
|
HHashSet *first_x = h_first_symbol(g, x);
|
||||||
if(h_symbol_derives_epsilon(g, x)) {
|
if(h_symbol_derives_epsilon(g, x)) {
|
||||||
// return the union of first(x) and first(tail)
|
// return the union of first(x) and first(tail)
|
||||||
HHashSet *first_tail = first_sequence_(g, tail);
|
HHashSet *first_tail = h_first_sequence(g, tail);
|
||||||
HHashSet *ret = h_hashset_new(g->arena, h_eq_ptr, h_hash_ptr);
|
HHashSet *ret = h_hashset_new(g->arena, h_eq_ptr, h_hash_ptr);
|
||||||
h_hashset_put_all(ret, first_x);
|
h_hashset_put_all(ret, first_x);
|
||||||
h_hashset_put_all(ret, first_tail);
|
h_hashset_put_all(ret, first_tail);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue