]> git.saurik.com Git - bison.git/blob - src/nullable.c
Work around a bug in bro 0.8, which underparenthesizes its
[bison.git] / src / nullable.c
1 /* Calculate which nonterminals can expand into the null string for Bison.
2
3 Copyright (C) 1984, 1989, 2000, 2001, 2002, 2003, 2004, 2005, 2006
4 Free Software Foundation, Inc.
5
6 This file is part of Bison, the GNU Compiler Compiler.
7
8 Bison is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 Bison is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Bison; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
22
23
24 /* Set up NULLABLE, a vector saying which nonterminals can expand into
25 the null string. NULLABLE[I - NTOKENS] is nonzero if symbol I can
26 do so. */
27
28 #include <config.h>
29 #include "system.h"
30
31 #include "getargs.h"
32 #include "gram.h"
33 #include "nullable.h"
34 #include "reduce.h"
35 #include "symtab.h"
36
37 /* Linked list of rules. */
38 typedef struct rule_list
39 {
40 struct rule_list *next;
41 rule *value;
42 } rule_list;
43
44 bool *nullable = NULL;
45
46 static void
47 nullable_print (FILE *out)
48 {
49 int i;
50 fputs ("NULLABLE\n", out);
51 for (i = ntokens; i < nsyms; i++)
52 fprintf (out, "\t%s: %s\n", symbols[i]->tag,
53 nullable[i - ntokens] ? "yes" : "no");
54 fputs ("\n\n", out);
55 }
56
57 void
58 nullable_compute (void)
59 {
60 rule_number ruleno;
61 symbol_number *s1;
62 symbol_number *s2;
63 rule_list *p;
64
65 symbol_number *squeue = xnmalloc (nvars, sizeof *squeue);
66 size_t *rcount = xcalloc (nrules, sizeof *rcount);
67 /* RITEM contains all the rules, including useless productions.
68 Hence we must allocate room for useless nonterminals too. */
69 rule_list **rsets = xcalloc (nvars, sizeof *rsets);
70 /* This is said to be more elements than we actually use.
71 Supposedly NRITEMS - NRULES is enough. But why take the risk? */
72 rule_list *relts = xnmalloc (nritems + nvars + 1, sizeof *relts);
73
74 nullable = xcalloc (nvars, sizeof *nullable);
75
76 s1 = s2 = squeue;
77 p = relts;
78
79 for (ruleno = 0; ruleno < nrules; ++ruleno)
80 if (rules[ruleno].useful)
81 {
82 rule *rules_ruleno = &rules[ruleno];
83 if (rules_ruleno->rhs[0] >= 0)
84 {
85 /* This rule has a non empty RHS. */
86 item_number *rp = NULL;
87 bool any_tokens = false;
88 for (rp = rules_ruleno->rhs; *rp >= 0; ++rp)
89 if (ISTOKEN (*rp))
90 any_tokens = true;
91
92 /* This rule has only nonterminals: schedule it for the second
93 pass. */
94 if (!any_tokens)
95 for (rp = rules_ruleno->rhs; *rp >= 0; ++rp)
96 {
97 rcount[ruleno]++;
98 p->next = rsets[*rp - ntokens];
99 p->value = rules_ruleno;
100 rsets[*rp - ntokens] = p;
101 p++;
102 }
103 }
104 else
105 {
106 /* This rule has an empty RHS. */
107 assert (item_number_as_rule_number (rules_ruleno->rhs[0])
108 == ruleno);
109 if (rules_ruleno->useful
110 && ! nullable[rules_ruleno->lhs->number - ntokens])
111 {
112 nullable[rules_ruleno->lhs->number - ntokens] = true;
113 *s2++ = rules_ruleno->lhs->number;
114 }
115 }
116 }
117
118 while (s1 < s2)
119 for (p = rsets[*s1++ - ntokens]; p; p = p->next)
120 {
121 rule *r = p->value;
122 if (--rcount[r->number] == 0)
123 if (r->useful && ! nullable[r->lhs->number - ntokens])
124 {
125 nullable[r->lhs->number - ntokens] = true;
126 *s2++ = r->lhs->number;
127 }
128 }
129
130 free (squeue);
131 free (rcount);
132 free (rsets);
133 free (relts);
134
135 if (trace_flag & trace_sets)
136 nullable_print (stderr);
137 }
138
139
140 void
141 nullable_free (void)
142 {
143 free (nullable);
144 }