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