1 |
|
|
/* $OpenBSD: mkpar.c,v 1.18 2014/03/13 00:59:34 tedu Exp $ */ |
2 |
|
|
/* $NetBSD: mkpar.c,v 1.4 1996/03/19 03:21:39 jtc Exp $ */ |
3 |
|
|
|
4 |
|
|
/* |
5 |
|
|
* Copyright (c) 1989 The Regents of the University of California. |
6 |
|
|
* All rights reserved. |
7 |
|
|
* |
8 |
|
|
* This code is derived from software contributed to Berkeley by |
9 |
|
|
* Robert Paul Corbett. |
10 |
|
|
* |
11 |
|
|
* Redistribution and use in source and binary forms, with or without |
12 |
|
|
* modification, are permitted provided that the following conditions |
13 |
|
|
* are met: |
14 |
|
|
* 1. Redistributions of source code must retain the above copyright |
15 |
|
|
* notice, this list of conditions and the following disclaimer. |
16 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
17 |
|
|
* notice, this list of conditions and the following disclaimer in the |
18 |
|
|
* documentation and/or other materials provided with the distribution. |
19 |
|
|
* 3. Neither the name of the University nor the names of its contributors |
20 |
|
|
* may be used to endorse or promote products derived from this software |
21 |
|
|
* without specific prior written permission. |
22 |
|
|
* |
23 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
24 |
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
25 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
26 |
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
27 |
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
28 |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
29 |
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
30 |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
31 |
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
32 |
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
33 |
|
|
* SUCH DAMAGE. |
34 |
|
|
*/ |
35 |
|
|
|
36 |
|
|
#include "defs.h" |
37 |
|
|
|
38 |
|
|
action **parser; |
39 |
|
|
int SRtotal; |
40 |
|
|
int SRexpect = 0; |
41 |
|
|
int RRtotal; |
42 |
|
|
short *SRconflicts; |
43 |
|
|
short *RRconflicts; |
44 |
|
|
short *defred; |
45 |
|
|
short *rules_used; |
46 |
|
|
short nunused; |
47 |
|
|
short final_state; |
48 |
|
|
|
49 |
|
|
static int SRcount; |
50 |
|
|
static int RRcount; |
51 |
|
|
|
52 |
|
|
extern action *parse_actions(); |
53 |
|
|
extern action *get_shifts(); |
54 |
|
|
extern action *add_reductions(); |
55 |
|
|
extern action *add_reduce(); |
56 |
|
|
|
57 |
|
|
short sole_reduction(int); |
58 |
|
|
void free_action_row(action *); |
59 |
|
|
|
60 |
|
|
void find_final_state(void); |
61 |
|
|
void unused_rules(void); |
62 |
|
|
void remove_conflicts(void); |
63 |
|
|
void total_conflicts(void); |
64 |
|
|
void defreds(void); |
65 |
|
|
|
66 |
|
|
|
67 |
|
|
void |
68 |
|
|
make_parser(void) |
69 |
|
21 |
{ |
70 |
|
|
int i; |
71 |
|
|
|
72 |
|
21 |
parser = NEW2(nstates, action *); |
73 |
✓✓ |
4023 |
for (i = 0; i < nstates; i++) |
74 |
|
4002 |
parser[i] = parse_actions(i); |
75 |
|
|
|
76 |
|
21 |
find_final_state(); |
77 |
|
21 |
remove_conflicts(); |
78 |
|
21 |
unused_rules(); |
79 |
✓✓ |
21 |
if (SRtotal + RRtotal > 0) |
80 |
|
1 |
total_conflicts(); |
81 |
|
21 |
defreds(); |
82 |
|
21 |
} |
83 |
|
|
|
84 |
|
|
|
85 |
|
|
action * |
86 |
|
|
parse_actions(int stateno) |
87 |
|
4002 |
{ |
88 |
|
|
action *actions; |
89 |
|
|
|
90 |
|
4002 |
actions = get_shifts(stateno); |
91 |
|
4002 |
actions = add_reductions(stateno, actions); |
92 |
|
4002 |
return (actions); |
93 |
|
|
} |
94 |
|
|
|
95 |
|
|
|
96 |
|
|
action * |
97 |
|
|
get_shifts(int stateno) |
98 |
|
4002 |
{ |
99 |
|
|
action *actions, *temp; |
100 |
|
|
shifts *sp; |
101 |
|
|
short *to_state; |
102 |
|
|
int i, k; |
103 |
|
|
int symbol; |
104 |
|
|
|
105 |
|
4002 |
actions = 0; |
106 |
|
4002 |
sp = shift_table[stateno]; |
107 |
✓✓ |
4002 |
if (sp) { |
108 |
|
2097 |
to_state = sp->shift; |
109 |
✓✓ |
8536 |
for (i = sp->nshifts - 1; i >= 0; i--) { |
110 |
|
6439 |
k = to_state[i]; |
111 |
|
6439 |
symbol = accessing_symbol[k]; |
112 |
✓✓ |
6439 |
if (ISTOKEN(symbol)) { |
113 |
|
4308 |
temp = NEW(action); |
114 |
|
4308 |
temp->next = actions; |
115 |
|
4308 |
temp->symbol = symbol; |
116 |
|
4308 |
temp->number = k; |
117 |
|
4308 |
temp->prec = symbol_prec[symbol]; |
118 |
|
4308 |
temp->action_code = SHIFT; |
119 |
|
4308 |
temp->assoc = symbol_assoc[symbol]; |
120 |
|
4308 |
actions = temp; |
121 |
|
|
} |
122 |
|
|
} |
123 |
|
|
} |
124 |
|
4002 |
return (actions); |
125 |
|
|
} |
126 |
|
|
|
127 |
|
|
action * |
128 |
|
|
add_reductions(int stateno, action * actions) |
129 |
|
4002 |
{ |
130 |
|
|
int i, j, m, n; |
131 |
|
|
int ruleno, tokensetsize; |
132 |
|
|
unsigned *rowp; |
133 |
|
|
|
134 |
|
4002 |
tokensetsize = WORDSIZE(ntokens); |
135 |
|
4002 |
m = lookaheads[stateno]; |
136 |
|
4002 |
n = lookaheads[stateno + 1]; |
137 |
✓✓ |
6447 |
for (i = m; i < n; i++) { |
138 |
|
2445 |
ruleno = LAruleno[i]; |
139 |
|
2445 |
rowp = LA + i * tokensetsize; |
140 |
✓✓ |
191251 |
for (j = ntokens - 1; j >= 0; j--) { |
141 |
✓✓ |
188806 |
if (BIT(rowp, j)) |
142 |
|
31174 |
actions = add_reduce(actions, ruleno, j); |
143 |
|
|
} |
144 |
|
|
} |
145 |
|
4002 |
return (actions); |
146 |
|
|
} |
147 |
|
|
|
148 |
|
|
|
149 |
|
|
action * |
150 |
|
|
add_reduce(action * actions, int ruleno, int symbol) |
151 |
|
31174 |
{ |
152 |
|
|
action *temp, *prev, *next; |
153 |
|
|
|
154 |
|
31174 |
prev = 0; |
155 |
✓✓✓✓
|
36092 |
for (next = actions; next && next->symbol < symbol; next = next->next) |
156 |
|
4918 |
prev = next; |
157 |
|
|
|
158 |
✓✓✓✓ ✓✗ |
31263 |
while (next && next->symbol == symbol && next->action_code == SHIFT) { |
159 |
|
89 |
prev = next; |
160 |
|
89 |
next = next->next; |
161 |
|
|
} |
162 |
|
|
|
163 |
✓✓✗✓ ✗✗✗✗
|
31174 |
while (next && next->symbol == symbol && |
164 |
|
|
next->action_code == REDUCE && next->number < ruleno) { |
165 |
|
|
prev = next; |
166 |
|
|
next = next->next; |
167 |
|
|
} |
168 |
|
|
|
169 |
|
31174 |
temp = NEW(action); |
170 |
|
31174 |
temp->next = next; |
171 |
|
31174 |
temp->symbol = symbol; |
172 |
|
31174 |
temp->number = ruleno; |
173 |
|
31174 |
temp->prec = rprec[ruleno]; |
174 |
|
31174 |
temp->action_code = REDUCE; |
175 |
|
31174 |
temp->assoc = rassoc[ruleno]; |
176 |
|
|
|
177 |
✓✓ |
31174 |
if (prev) |
178 |
|
1292 |
prev->next = temp; |
179 |
|
|
else |
180 |
|
29882 |
actions = temp; |
181 |
|
|
|
182 |
|
31174 |
return (actions); |
183 |
|
|
} |
184 |
|
|
|
185 |
|
|
|
186 |
|
|
void |
187 |
|
|
find_final_state(void) |
188 |
|
21 |
{ |
189 |
|
|
int goal, i; |
190 |
|
|
short *to_state; |
191 |
|
|
shifts *p; |
192 |
|
|
|
193 |
|
21 |
p = shift_table[0]; |
194 |
|
21 |
to_state = p->shift; |
195 |
|
21 |
goal = ritem[1]; |
196 |
✓✗ |
23 |
for (i = p->nshifts - 1; i >= 0; --i) { |
197 |
|
23 |
final_state = to_state[i]; |
198 |
✓✓ |
23 |
if (accessing_symbol[final_state] == goal) |
199 |
|
21 |
break; |
200 |
|
|
} |
201 |
|
21 |
} |
202 |
|
|
|
203 |
|
|
|
204 |
|
|
void |
205 |
|
|
unused_rules(void) |
206 |
|
21 |
{ |
207 |
|
|
int i; |
208 |
|
|
action *p; |
209 |
|
|
|
210 |
|
21 |
rules_used = calloc(nrules, sizeof(short)); |
211 |
✗✓ |
21 |
if (rules_used == NULL) |
212 |
|
|
no_space(); |
213 |
|
|
|
214 |
✓✓ |
4023 |
for (i = 0; i < nstates; ++i) { |
215 |
✓✓ |
39484 |
for (p = parser[i]; p; p = p->next) { |
216 |
✓✓✓✓
|
35482 |
if (p->action_code == REDUCE && p->suppressed == 0) |
217 |
|
31094 |
rules_used[p->number] = 1; |
218 |
|
|
} |
219 |
|
|
} |
220 |
|
|
|
221 |
|
21 |
nunused = 0; |
222 |
✓✓ |
2263 |
for (i = 3; i < nrules; ++i) |
223 |
✗✓ |
2242 |
if (!rules_used[i]) |
224 |
|
|
++nunused; |
225 |
|
|
|
226 |
✗✓ |
21 |
if (nunused) { |
227 |
|
|
if (nunused == 1) |
228 |
|
|
fprintf(stderr, "%s: 1 rule never reduced\n", __progname); |
229 |
|
|
else |
230 |
|
|
fprintf(stderr, "%s: %d rules never reduced\n", __progname, |
231 |
|
|
nunused); |
232 |
|
|
} |
233 |
|
21 |
} |
234 |
|
|
|
235 |
|
|
|
236 |
|
|
void |
237 |
|
|
remove_conflicts(void) |
238 |
|
21 |
{ |
239 |
|
|
int i; |
240 |
|
|
int symbol; |
241 |
|
21 |
action *p, *pref = NULL; |
242 |
|
|
|
243 |
|
21 |
SRtotal = 0; |
244 |
|
21 |
RRtotal = 0; |
245 |
|
21 |
SRconflicts = NEW2(nstates, short); |
246 |
|
21 |
RRconflicts = NEW2(nstates, short); |
247 |
✓✓ |
4023 |
for (i = 0; i < nstates; i++) { |
248 |
|
4002 |
SRcount = 0; |
249 |
|
4002 |
RRcount = 0; |
250 |
|
4002 |
symbol = -1; |
251 |
✓✓ |
39484 |
for (p = parser[i]; p; p = p->next) { |
252 |
✓✓ |
35482 |
if (p->symbol != symbol) { |
253 |
|
35393 |
pref = p; |
254 |
|
35393 |
symbol = p->symbol; |
255 |
✗✓ |
89 |
} else if (i == final_state && symbol == 0) { |
256 |
|
|
SRcount++; |
257 |
|
|
p->suppressed = 1; |
258 |
✓✗ |
89 |
} else if (pref->action_code == SHIFT) { |
259 |
✓✓✓✗
|
89 |
if (pref->prec > 0 && p->prec > 0) { |
260 |
✓✓ |
10 |
if (pref->prec < p->prec) { |
261 |
|
3 |
pref->suppressed = 2; |
262 |
|
3 |
pref = p; |
263 |
✓✓ |
7 |
} else if (pref->prec > p->prec) { |
264 |
|
1 |
p->suppressed = 2; |
265 |
✓✗ |
6 |
} else if (pref->assoc == LEFT) { |
266 |
|
6 |
pref->suppressed = 2; |
267 |
|
6 |
pref = p; |
268 |
|
|
} else if (pref->assoc == RIGHT) { |
269 |
|
|
p->suppressed = 2; |
270 |
|
|
} else { |
271 |
|
|
pref->suppressed = 2; |
272 |
|
|
p->suppressed = 2; |
273 |
|
|
} |
274 |
|
|
} else { |
275 |
|
79 |
SRcount++; |
276 |
|
79 |
p->suppressed = 1; |
277 |
|
|
} |
278 |
|
|
} else { |
279 |
|
|
RRcount++; |
280 |
|
|
p->suppressed = 1; |
281 |
|
|
} |
282 |
|
|
} |
283 |
|
4002 |
SRtotal += SRcount; |
284 |
|
4002 |
RRtotal += RRcount; |
285 |
|
4002 |
SRconflicts[i] = SRcount; |
286 |
|
4002 |
RRconflicts[i] = RRcount; |
287 |
|
|
} |
288 |
|
21 |
} |
289 |
|
|
|
290 |
|
|
|
291 |
|
|
void |
292 |
|
|
total_conflicts(void) |
293 |
|
1 |
{ |
294 |
|
|
/* Warn if s/r != expect or if any r/r */ |
295 |
✗✓✗✗
|
1 |
if ((SRtotal != SRexpect) || RRtotal) { |
296 |
✗✓ |
1 |
if (SRtotal == 1) |
297 |
|
|
fprintf(stderr, "%s: %s finds 1 shift/reduce conflict\n", |
298 |
|
|
input_file_name, __progname); |
299 |
✓✗ |
1 |
else if (SRtotal > 1) |
300 |
|
1 |
fprintf(stderr, "%s: %s finds %d shift/reduce conflicts\n", |
301 |
|
|
input_file_name, __progname, SRtotal); |
302 |
|
|
} |
303 |
✗✓ |
1 |
if (RRtotal == 1) |
304 |
|
|
fprintf(stderr, "%s: %s finds 1 reduce/reduce conflict\n", |
305 |
|
|
input_file_name, __progname); |
306 |
✗✓ |
1 |
else if (RRtotal > 1) |
307 |
|
|
fprintf(stderr, "%s: %s finds %d reduce/reduce conflicts\n", |
308 |
|
|
input_file_name, __progname, RRtotal); |
309 |
|
1 |
} |
310 |
|
|
|
311 |
|
|
|
312 |
|
|
short |
313 |
|
|
sole_reduction(int stateno) |
314 |
|
4002 |
{ |
315 |
|
|
int count; |
316 |
|
|
short ruleno; |
317 |
|
|
action *p; |
318 |
|
|
|
319 |
|
4002 |
count = 0; |
320 |
|
4002 |
ruleno = 0; |
321 |
✓✓ |
33894 |
for (p = parser[stateno]; p; p = p->next) { |
322 |
✓✓✓✓
|
31905 |
if (p->action_code == SHIFT && p->suppressed == 0) |
323 |
|
2002 |
return (0); |
324 |
✓✓✓✗
|
29903 |
else if (p->action_code == REDUCE && p->suppressed == 0) { |
325 |
✓✓✓✓
|
29894 |
if (ruleno > 0 && p->number != ruleno) |
326 |
|
11 |
return (0); |
327 |
✓✓ |
29883 |
if (p->symbol != 1) |
328 |
|
29482 |
++count; |
329 |
|
29883 |
ruleno = p->number; |
330 |
|
|
} |
331 |
|
|
} |
332 |
|
|
|
333 |
✓✓ |
1989 |
if (count == 0) |
334 |
|
2 |
return (0); |
335 |
|
1987 |
return (ruleno); |
336 |
|
|
} |
337 |
|
|
|
338 |
|
|
|
339 |
|
|
void |
340 |
|
|
defreds(void) |
341 |
|
21 |
{ |
342 |
|
|
int i; |
343 |
|
|
|
344 |
|
21 |
defred = NEW2(nstates, short); |
345 |
✓✓ |
4023 |
for (i = 0; i < nstates; i++) |
346 |
|
4002 |
defred[i] = sole_reduction(i); |
347 |
|
21 |
} |
348 |
|
|
|
349 |
|
|
void |
350 |
|
|
free_action_row(action * p) |
351 |
|
4002 |
{ |
352 |
|
|
action *q; |
353 |
|
|
|
354 |
✓✓ |
43486 |
while (p) { |
355 |
|
35482 |
q = p->next; |
356 |
|
35482 |
free(p); |
357 |
|
35482 |
p = q; |
358 |
|
|
} |
359 |
|
4002 |
} |
360 |
|
|
|
361 |
|
|
void |
362 |
|
|
free_parser(void) |
363 |
|
21 |
{ |
364 |
|
|
int i; |
365 |
|
|
|
366 |
✓✓ |
4023 |
for (i = 0; i < nstates; i++) |
367 |
|
4002 |
free_action_row(parser[i]); |
368 |
|
|
|
369 |
|
21 |
free(parser); |
370 |
|
21 |
} |