xref: /netbsd/external/bsd/byacc/dist/mkpar.c (revision 9db11b62)
1 /*	$NetBSD: mkpar.c,v 1.13 2021/02/20 22:57:56 christos Exp $	*/
2 
3 /* Id: mkpar.c,v 1.17 2020/09/10 17:37:33 tom Exp  */
4 
5 #include "defs.h"
6 
7 #include <sys/cdefs.h>
8 __RCSID("$NetBSD: mkpar.c,v 1.13 2021/02/20 22:57:56 christos Exp $");
9 
10 #define NotSuppressed(p)	((p)->suppressed == 0)
11 
12 #if defined(YYBTYACC)
13 #define MaySuppress(p)		((backtrack ? ((p)->suppressed <= 1) : (p)->suppressed == 0))
14     /* suppress the preferred action => enable backtracking */
15 #define StartBacktrack(p)	if (backtrack && (p) != NULL && NotSuppressed(p)) (p)->suppressed = 1
16 #else
17 #define MaySuppress(p)		((p)->suppressed == 0)
18 #define StartBacktrack(p)	/*nothing */
19 #endif
20 
21 static action *add_reduce(action *actions, int ruleno, int symbol);
22 static action *add_reductions(int stateno, action *actions);
23 static action *get_shifts(int stateno);
24 static action *parse_actions(int stateno);
25 static int sole_reduction(int stateno);
26 static void defreds(void);
27 static void find_final_state(void);
28 static void free_action_row(action *p);
29 static void remove_conflicts(void);
30 static void total_conflicts(void);
31 static void unused_rules(void);
32 
33 action **parser;
34 
35 int SRexpect;
36 int RRexpect;
37 
38 int SRtotal;
39 int RRtotal;
40 
41 Value_t *SRconflicts;
42 Value_t *RRconflicts;
43 Value_t *defred;
44 Value_t *rules_used;
45 Value_t nunused;
46 Value_t final_state;
47 
48 static Value_t SRcount;
49 static Value_t RRcount;
50 
51 void
make_parser(void)52 make_parser(void)
53 {
54     int i;
55 
56     parser = NEW2(nstates, action *);
57     for (i = 0; i < nstates; i++)
58 	parser[i] = parse_actions(i);
59 
60     find_final_state();
61     remove_conflicts();
62     unused_rules();
63     if (SRtotal + RRtotal > 0)
64 	total_conflicts();
65     defreds();
66 }
67 
68 static action *
parse_actions(int stateno)69 parse_actions(int stateno)
70 {
71     action *actions;
72 
73     actions = get_shifts(stateno);
74     actions = add_reductions(stateno, actions);
75     return (actions);
76 }
77 
78 static action *
get_shifts(int stateno)79 get_shifts(int stateno)
80 {
81     action *actions, *temp;
82     shifts *sp;
83     Value_t *to_state2;
84 
85     actions = 0;
86     sp = shift_table[stateno];
87     if (sp)
88     {
89 	Value_t i;
90 
91 	to_state2 = sp->shift;
92 	for (i = (Value_t)(sp->nshifts - 1); i >= 0; i--)
93 	{
94 	    Value_t k = to_state2[i];
95 	    Value_t symbol = accessing_symbol[k];
96 
97 	    if (ISTOKEN(symbol))
98 	    {
99 		temp = NEW(action);
100 		temp->next = actions;
101 		temp->symbol = symbol;
102 		temp->number = k;
103 		temp->prec = symbol_prec[symbol];
104 		temp->action_code = SHIFT;
105 		temp->assoc = symbol_assoc[symbol];
106 		actions = temp;
107 	    }
108 	}
109     }
110     return (actions);
111 }
112 
113 static action *
add_reductions(int stateno,action * actions)114 add_reductions(int stateno, action *actions)
115 {
116     int i, j, m, n;
117     int tokensetsize;
118 
119     tokensetsize = WORDSIZE(ntokens);
120     m = lookaheads[stateno];
121     n = lookaheads[stateno + 1];
122     for (i = m; i < n; i++)
123     {
124 	int ruleno = LAruleno[i];
125 	unsigned *rowp = LA + i * tokensetsize;
126 
127 	for (j = ntokens - 1; j >= 0; j--)
128 	{
129 	    if (BIT(rowp, j))
130 		actions = add_reduce(actions, ruleno, j);
131 	}
132     }
133     return (actions);
134 }
135 
136 static action *
add_reduce(action * actions,int ruleno,int symbol)137 add_reduce(action *actions,
138 	   int ruleno,
139 	   int symbol)
140 {
141     action *temp, *prev, *next;
142 
143     prev = 0;
144     for (next = actions; next && next->symbol < symbol; next = next->next)
145 	prev = next;
146 
147     while (next && next->symbol == symbol && next->action_code == SHIFT)
148     {
149 	prev = next;
150 	next = next->next;
151     }
152 
153     while (next && next->symbol == symbol &&
154 	   next->action_code == REDUCE && next->number < ruleno)
155     {
156 	prev = next;
157 	next = next->next;
158     }
159 
160     temp = NEW(action);
161     temp->next = next;
162     temp->symbol = (Value_t)symbol;
163     temp->number = (Value_t)ruleno;
164     temp->prec = rprec[ruleno];
165     temp->action_code = REDUCE;
166     temp->assoc = rassoc[ruleno];
167 
168     if (prev)
169 	prev->next = temp;
170     else
171 	actions = temp;
172 
173     return (actions);
174 }
175 
176 static void
find_final_state(void)177 find_final_state(void)
178 {
179     Value_t *to_state2;
180     shifts *p;
181 
182     if ((p = shift_table[0]) != 0)
183     {
184 	int i;
185 	int goal = ritem[1];
186 
187 	to_state2 = p->shift;
188 	for (i = p->nshifts - 1; i >= 0; --i)
189 	{
190 	    final_state = to_state2[i];
191 	    if (accessing_symbol[final_state] == goal)
192 		break;
193 	}
194     }
195 }
196 
197 static void
unused_rules(void)198 unused_rules(void)
199 {
200     int i;
201     action *p;
202 
203     rules_used = TMALLOC(Value_t, nrules);
204     NO_SPACE(rules_used);
205 
206     for (i = 0; i < nrules; ++i)
207 	rules_used[i] = 0;
208 
209     for (i = 0; i < nstates; ++i)
210     {
211 	for (p = parser[i]; p; p = p->next)
212 	{
213 	    if ((p->action_code == REDUCE) && MaySuppress(p))
214 		rules_used[p->number] = 1;
215 	}
216     }
217 
218     nunused = 0;
219     for (i = 3; i < nrules; ++i)
220 	if (!rules_used[i])
221 	    ++nunused;
222 
223     if (nunused)
224     {
225 	if (nunused == 1)
226 	    fprintf(stderr, "%s: 1 rule never reduced\n", myname);
227 	else
228 	    fprintf(stderr, "%s: %d rules never reduced\n", myname, nunused);
229     }
230 }
231 
232 static void
remove_conflicts(void)233 remove_conflicts(void)
234 {
235     int i;
236     action *p, *pref = 0;
237 
238     SRtotal = 0;
239     RRtotal = 0;
240     SRconflicts = NEW2(nstates, Value_t);
241     RRconflicts = NEW2(nstates, Value_t);
242     for (i = 0; i < nstates; i++)
243     {
244 	int symbol = -1;
245 
246 	SRcount = 0;
247 	RRcount = 0;
248 #if defined(YYBTYACC)
249 	pref = NULL;
250 #endif
251 	for (p = parser[i]; p; p = p->next)
252 	{
253 	    if (p->symbol != symbol)
254 	    {
255 		/* the first parse action for each symbol is the preferred action */
256 		pref = p;
257 		symbol = p->symbol;
258 	    }
259 	    /* following conditions handle multiple, i.e., conflicting, parse actions */
260 	    else if (i == final_state && symbol == 0)
261 	    {
262 		SRcount++;
263 		p->suppressed = 1;
264 		StartBacktrack(pref);
265 	    }
266 	    else if (pref != 0 && pref->action_code == SHIFT)
267 	    {
268 		if (pref->prec > 0 && p->prec > 0)
269 		{
270 		    if (pref->prec < p->prec)
271 		    {
272 			pref->suppressed = 2;
273 			pref = p;
274 		    }
275 		    else if (pref->prec > p->prec)
276 		    {
277 			p->suppressed = 2;
278 		    }
279 		    else if (pref->assoc == LEFT)
280 		    {
281 			pref->suppressed = 2;
282 			pref = p;
283 		    }
284 		    else if (pref->assoc == RIGHT)
285 		    {
286 			p->suppressed = 2;
287 		    }
288 		    else
289 		    {
290 			pref->suppressed = 2;
291 			p->suppressed = 2;
292 		    }
293 		}
294 		else
295 		{
296 		    SRcount++;
297 		    p->suppressed = 1;
298 		    StartBacktrack(pref);
299 		}
300 	    }
301 	    else
302 	    {
303 		RRcount++;
304 		p->suppressed = 1;
305 		StartBacktrack(pref);
306 	    }
307 	}
308 	SRtotal += SRcount;
309 	RRtotal += RRcount;
310 	SRconflicts[i] = SRcount;
311 	RRconflicts[i] = RRcount;
312     }
313 }
314 
315 static void
total_conflicts(void)316 total_conflicts(void)
317 {
318     fprintf(stderr, "%s: ", myname);
319     if (SRtotal == 1)
320 	fprintf(stderr, "1 shift/reduce conflict");
321     else if (SRtotal > 1)
322 	fprintf(stderr, "%d shift/reduce conflicts", SRtotal);
323 
324     if (SRtotal && RRtotal)
325 	fprintf(stderr, ", ");
326 
327     if (RRtotal == 1)
328 	fprintf(stderr, "1 reduce/reduce conflict");
329     else if (RRtotal > 1)
330 	fprintf(stderr, "%d reduce/reduce conflicts", RRtotal);
331 
332     fprintf(stderr, ".\n");
333 
334     if (SRexpect >= 0 && SRtotal != SRexpect)
335     {
336 	fprintf(stderr, "%s: ", myname);
337 	fprintf(stderr, "expected %d shift/reduce conflict%s.\n",
338 		SRexpect, PLURAL(SRexpect));
339 	exit_code = EXIT_FAILURE;
340     }
341     if (RRexpect >= 0 && RRtotal != RRexpect)
342     {
343 	fprintf(stderr, "%s: ", myname);
344 	fprintf(stderr, "expected %d reduce/reduce conflict%s.\n",
345 		RRexpect, PLURAL(RRexpect));
346 	exit_code = EXIT_FAILURE;
347     }
348 }
349 
350 static int
sole_reduction(int stateno)351 sole_reduction(int stateno)
352 {
353     int count, ruleno;
354     action *p;
355 
356     count = 0;
357     ruleno = 0;
358     for (p = parser[stateno]; p; p = p->next)
359     {
360 	if (p->action_code == SHIFT && MaySuppress(p))
361 	    return (0);
362 	else if ((p->action_code == REDUCE) && MaySuppress(p))
363 	{
364 	    if (ruleno > 0 && p->number != ruleno)
365 		return (0);
366 	    if (p->symbol != 1)
367 		++count;
368 	    ruleno = p->number;
369 	}
370     }
371 
372     if (count == 0)
373 	return (0);
374     return (ruleno);
375 }
376 
377 static void
defreds(void)378 defreds(void)
379 {
380     int i;
381 
382     defred = NEW2(nstates, Value_t);
383     for (i = 0; i < nstates; i++)
384 	defred[i] = (Value_t)sole_reduction(i);
385 }
386 
387 static void
free_action_row(action * p)388 free_action_row(action *p)
389 {
390     action *q;
391 
392     while (p)
393     {
394 	q = p->next;
395 	FREE(p);
396 	p = q;
397     }
398 }
399 
400 void
free_parser(void)401 free_parser(void)
402 {
403     int i;
404 
405     for (i = 0; i < nstates; i++)
406 	free_action_row(parser[i]);
407 
408     FREE(parser);
409 }
410 
411 #ifdef NO_LEAKS
412 void
mkpar_leaks(void)413 mkpar_leaks(void)
414 {
415     DO_FREE(defred);
416     DO_FREE(rules_used);
417     DO_FREE(SRconflicts);
418     DO_FREE(RRconflicts);
419 }
420 #endif
421