46 |
void |
void |
47 |
set_nullable (void) |
set_nullable (void) |
48 |
{ |
{ |
49 |
short *r; |
int ruleno; |
50 |
short *s1; |
short *s1; |
51 |
short *s2; |
short *s2; |
52 |
shorts *p; |
shorts *p; |
53 |
|
|
54 |
short *squeue; |
short *squeue = XCALLOC (short, nvars); |
55 |
short *rcount; |
short *rcount = XCALLOC (short, nrules + 1); |
56 |
shorts **rsets; |
/* RITEM contains all the rules, including useless productions. |
57 |
shorts *relts; |
Hence we must allocate room for useless nonterminals too. */ |
58 |
|
shorts **rsets = XCALLOC (shorts *, nvars) - ntokens; |
59 |
|
/* This is said to be more elements than we actually use. |
60 |
|
Supposedly nitems - nrules is enough. But why take the risk? */ |
61 |
|
shorts *relts = XCALLOC (shorts, nitems + nvars + 1); |
62 |
|
|
63 |
if (trace_flag) |
if (trace_flag) |
64 |
fprintf (stderr, "Entering set_nullable\n"); |
fprintf (stderr, "Entering set_nullable\n"); |
65 |
|
|
66 |
nullable = XCALLOC (char, nvars) - ntokens; |
nullable = XCALLOC (char, nvars) - ntokens; |
67 |
|
|
|
squeue = XCALLOC (short, nvars); |
|
68 |
s1 = s2 = squeue; |
s1 = s2 = squeue; |
|
|
|
|
rcount = XCALLOC (short, nrules + 1); |
|
|
|
|
|
/* RITEM contains all the rules, including useless productions. |
|
|
Hence we must allocate room for useless nonterminals too. */ |
|
|
rsets = XCALLOC (shorts *, nvars + nuseless_nonterminals) - ntokens; |
|
|
/* This is said to be more elements than we actually use. |
|
|
Supposedly nitems - nrules is enough. |
|
|
But why take the risk? */ |
|
|
relts = XCALLOC (shorts, nitems + nvars + nuseless_nonterminals + 1); |
|
69 |
p = relts; |
p = relts; |
70 |
|
|
71 |
for (r = ritem; *r; ++r) |
for (ruleno = 1; ruleno < nrules + 1; ++ruleno) |
72 |
{ |
if (ritem[rule_table[ruleno].rhs] > 0) |
73 |
/* Walk RITEM to find (i), if there are any tokens in the |
{ |
74 |
RHS, and (ii), to find RULENO. */ |
/* This rule has a non empty RHS. */ |
75 |
int ruleno; |
short *r; |
76 |
int any_tokens = 0; |
int any_tokens = 0; |
77 |
short *r1; |
for (r = ritem + rule_table[ruleno].rhs; *r > 0; ++r) |
78 |
for (r1 = r; *r1 > 0; ++r1) |
if (ISTOKEN (*r)) |
79 |
if (ISTOKEN (*r1)) |
any_tokens = 1; |
80 |
any_tokens = 1; |
|
81 |
ruleno = -*r1; |
/* This rule has only nonterminals: schedule it for the second |
82 |
|
pass. */ |
83 |
/* Examine the RHS of the rule. */ |
if (!any_tokens) |
84 |
if (!any_tokens) |
for (r = ritem + rule_table[ruleno].rhs; *r > 0; ++r) |
85 |
for (/* Nothing. */; *r > 0; ++r) |
{ |
86 |
|
rcount[ruleno]++; |
87 |
|
p->next = rsets[*r]; |
88 |
|
p->value = ruleno; |
89 |
|
rsets[*r] = p; |
90 |
|
p++; |
91 |
|
} |
92 |
|
} |
93 |
|
else |
94 |
|
{ |
95 |
|
/* This rule has an empty RHS. */ |
96 |
|
assert (ritem[rule_table[ruleno].rhs] == -ruleno); |
97 |
|
if (rule_table[ruleno].useful && !nullable[rule_table[ruleno].lhs]) |
98 |
{ |
{ |
99 |
rcount[ruleno]++; |
nullable[rule_table[ruleno].lhs] = 1; |
100 |
p->next = rsets[*r]; |
*s2++ = rule_table[ruleno].lhs; |
|
p->value = ruleno; |
|
|
rsets[*r] = p; |
|
|
p++; |
|
101 |
} |
} |
102 |
|
} |
|
/* Examine its LHS. */ |
|
|
if (rule_table[ruleno].useful && !nullable[rule_table[ruleno].lhs]) |
|
|
{ |
|
|
nullable[rule_table[ruleno].lhs] = 1; |
|
|
*s2++ = rule_table[ruleno].lhs; |
|
|
} |
|
|
} |
|
103 |
|
|
104 |
while (s1 < s2) |
while (s1 < s2) |
105 |
for (p = rsets[*s1++]; p; p = p->next) |
for (p = rsets[*s1++]; p; p = p->next) |
106 |
{ |
{ |
107 |
int ruleno = p->value; |
ruleno = p->value; |
108 |
if (--rcount[ruleno] == 0) |
if (--rcount[ruleno] == 0) |
109 |
if (rule_table[ruleno].useful && !nullable[rule_table[ruleno].lhs]) |
if (rule_table[ruleno].useful && !nullable[rule_table[ruleno].lhs]) |
110 |
{ |
{ |