1*0a6a1f1dSLionel Sambuc /* $NetBSD: mkpar.c,v 1.8 2015/01/03 23:22:52 christos Exp $ */
284d9c625SLionel Sambuc
3*0a6a1f1dSLionel Sambuc /* Id: mkpar.c,v 1.14 2014/04/01 23:05:37 tom Exp */
44a17663cSThomas Veerman
54a17663cSThomas Veerman #include "defs.h"
64a17663cSThomas Veerman
74a17663cSThomas Veerman #include <sys/cdefs.h>
8*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: mkpar.c,v 1.8 2015/01/03 23:22:52 christos Exp $");
9*0a6a1f1dSLionel Sambuc
10*0a6a1f1dSLionel Sambuc #define NotSuppressed(p) ((p)->suppressed == 0)
11*0a6a1f1dSLionel Sambuc
12*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
13*0a6a1f1dSLionel Sambuc #define MaySuppress(p) ((backtrack ? ((p)->suppressed <= 1) : (p)->suppressed == 0))
14*0a6a1f1dSLionel Sambuc /* suppress the preferred action => enable backtracking */
15*0a6a1f1dSLionel Sambuc #define StartBacktrack(p) if (backtrack && (p) != NULL && NotSuppressed(p)) (p)->suppressed = 1
16*0a6a1f1dSLionel Sambuc #else
17*0a6a1f1dSLionel Sambuc #define MaySuppress(p) ((p)->suppressed == 0)
18*0a6a1f1dSLionel Sambuc #define StartBacktrack(p) /*nothing */
19*0a6a1f1dSLionel Sambuc #endif
204a17663cSThomas Veerman
214a17663cSThomas Veerman static action *add_reduce(action *actions, int ruleno, int symbol);
224a17663cSThomas Veerman static action *add_reductions(int stateno, action *actions);
234a17663cSThomas Veerman static action *get_shifts(int stateno);
244a17663cSThomas Veerman static action *parse_actions(int stateno);
254a17663cSThomas Veerman static int sole_reduction(int stateno);
264a17663cSThomas Veerman static void defreds(void);
274a17663cSThomas Veerman static void find_final_state(void);
284a17663cSThomas Veerman static void free_action_row(action *p);
294a17663cSThomas Veerman static void remove_conflicts(void);
304a17663cSThomas Veerman static void total_conflicts(void);
314a17663cSThomas Veerman static void unused_rules(void);
324a17663cSThomas Veerman
334a17663cSThomas Veerman action **parser;
344a17663cSThomas Veerman
354a17663cSThomas Veerman int SRexpect;
364a17663cSThomas Veerman int RRexpect;
374a17663cSThomas Veerman
384a17663cSThomas Veerman int SRtotal;
394a17663cSThomas Veerman int RRtotal;
404a17663cSThomas Veerman
414a17663cSThomas Veerman Value_t *SRconflicts;
424a17663cSThomas Veerman Value_t *RRconflicts;
434a17663cSThomas Veerman Value_t *defred;
444a17663cSThomas Veerman Value_t *rules_used;
454a17663cSThomas Veerman Value_t nunused;
464a17663cSThomas Veerman Value_t final_state;
474a17663cSThomas Veerman
484a17663cSThomas Veerman static Value_t SRcount;
494a17663cSThomas Veerman static Value_t RRcount;
504a17663cSThomas Veerman
514a17663cSThomas Veerman void
make_parser(void)524a17663cSThomas Veerman make_parser(void)
534a17663cSThomas Veerman {
544a17663cSThomas Veerman int i;
554a17663cSThomas Veerman
564a17663cSThomas Veerman parser = NEW2(nstates, action *);
574a17663cSThomas Veerman for (i = 0; i < nstates; i++)
584a17663cSThomas Veerman parser[i] = parse_actions(i);
594a17663cSThomas Veerman
604a17663cSThomas Veerman find_final_state();
614a17663cSThomas Veerman remove_conflicts();
624a17663cSThomas Veerman unused_rules();
634a17663cSThomas Veerman if (SRtotal + RRtotal > 0)
644a17663cSThomas Veerman total_conflicts();
654a17663cSThomas Veerman defreds();
664a17663cSThomas Veerman }
674a17663cSThomas Veerman
684a17663cSThomas Veerman static action *
parse_actions(int stateno)694a17663cSThomas Veerman parse_actions(int stateno)
704a17663cSThomas Veerman {
714a17663cSThomas Veerman action *actions;
724a17663cSThomas Veerman
734a17663cSThomas Veerman actions = get_shifts(stateno);
744a17663cSThomas Veerman actions = add_reductions(stateno, actions);
754a17663cSThomas Veerman return (actions);
764a17663cSThomas Veerman }
774a17663cSThomas Veerman
784a17663cSThomas Veerman static action *
get_shifts(int stateno)794a17663cSThomas Veerman get_shifts(int stateno)
804a17663cSThomas Veerman {
814a17663cSThomas Veerman action *actions, *temp;
824a17663cSThomas Veerman shifts *sp;
834a17663cSThomas Veerman Value_t *to_state2;
844a17663cSThomas Veerman Value_t i, k;
854a17663cSThomas Veerman Value_t symbol;
864a17663cSThomas Veerman
874a17663cSThomas Veerman actions = 0;
884a17663cSThomas Veerman sp = shift_table[stateno];
894a17663cSThomas Veerman if (sp)
904a17663cSThomas Veerman {
914a17663cSThomas Veerman to_state2 = sp->shift;
924a17663cSThomas Veerman for (i = (Value_t) (sp->nshifts - 1); i >= 0; i--)
934a17663cSThomas Veerman {
944a17663cSThomas Veerman k = to_state2[i];
954a17663cSThomas Veerman symbol = accessing_symbol[k];
964a17663cSThomas Veerman if (ISTOKEN(symbol))
974a17663cSThomas Veerman {
984a17663cSThomas Veerman temp = NEW(action);
994a17663cSThomas Veerman temp->next = actions;
1004a17663cSThomas Veerman temp->symbol = symbol;
1014a17663cSThomas Veerman temp->number = k;
1024a17663cSThomas Veerman temp->prec = symbol_prec[symbol];
1034a17663cSThomas Veerman temp->action_code = SHIFT;
1044a17663cSThomas Veerman temp->assoc = symbol_assoc[symbol];
1054a17663cSThomas Veerman actions = temp;
1064a17663cSThomas Veerman }
1074a17663cSThomas Veerman }
1084a17663cSThomas Veerman }
1094a17663cSThomas Veerman return (actions);
1104a17663cSThomas Veerman }
1114a17663cSThomas Veerman
1124a17663cSThomas Veerman static action *
add_reductions(int stateno,action * actions)1134a17663cSThomas Veerman add_reductions(int stateno, action *actions)
1144a17663cSThomas Veerman {
1154a17663cSThomas Veerman int i, j, m, n;
1164a17663cSThomas Veerman int ruleno, tokensetsize;
1174a17663cSThomas Veerman unsigned *rowp;
1184a17663cSThomas Veerman
1194a17663cSThomas Veerman tokensetsize = WORDSIZE(ntokens);
1204a17663cSThomas Veerman m = lookaheads[stateno];
1214a17663cSThomas Veerman n = lookaheads[stateno + 1];
1224a17663cSThomas Veerman for (i = m; i < n; i++)
1234a17663cSThomas Veerman {
1244a17663cSThomas Veerman ruleno = LAruleno[i];
1254a17663cSThomas Veerman rowp = LA + i * tokensetsize;
1264a17663cSThomas Veerman for (j = ntokens - 1; j >= 0; j--)
1274a17663cSThomas Veerman {
1284a17663cSThomas Veerman if (BIT(rowp, j))
1294a17663cSThomas Veerman actions = add_reduce(actions, ruleno, j);
1304a17663cSThomas Veerman }
1314a17663cSThomas Veerman }
1324a17663cSThomas Veerman return (actions);
1334a17663cSThomas Veerman }
1344a17663cSThomas Veerman
1354a17663cSThomas Veerman static action *
add_reduce(action * actions,int ruleno,int symbol)1364a17663cSThomas Veerman add_reduce(action *actions,
1374a17663cSThomas Veerman int ruleno,
1384a17663cSThomas Veerman int symbol)
1394a17663cSThomas Veerman {
1404a17663cSThomas Veerman action *temp, *prev, *next;
1414a17663cSThomas Veerman
1424a17663cSThomas Veerman prev = 0;
1434a17663cSThomas Veerman for (next = actions; next && next->symbol < symbol; next = next->next)
1444a17663cSThomas Veerman prev = next;
1454a17663cSThomas Veerman
1464a17663cSThomas Veerman while (next && next->symbol == symbol && next->action_code == SHIFT)
1474a17663cSThomas Veerman {
1484a17663cSThomas Veerman prev = next;
1494a17663cSThomas Veerman next = next->next;
1504a17663cSThomas Veerman }
1514a17663cSThomas Veerman
1524a17663cSThomas Veerman while (next && next->symbol == symbol &&
1534a17663cSThomas Veerman next->action_code == REDUCE && next->number < ruleno)
1544a17663cSThomas Veerman {
1554a17663cSThomas Veerman prev = next;
1564a17663cSThomas Veerman next = next->next;
1574a17663cSThomas Veerman }
1584a17663cSThomas Veerman
1594a17663cSThomas Veerman temp = NEW(action);
1604a17663cSThomas Veerman temp->next = next;
1614a17663cSThomas Veerman temp->symbol = (Value_t) symbol;
1624a17663cSThomas Veerman temp->number = (Value_t) ruleno;
1634a17663cSThomas Veerman temp->prec = rprec[ruleno];
1644a17663cSThomas Veerman temp->action_code = REDUCE;
1654a17663cSThomas Veerman temp->assoc = rassoc[ruleno];
1664a17663cSThomas Veerman
1674a17663cSThomas Veerman if (prev)
1684a17663cSThomas Veerman prev->next = temp;
1694a17663cSThomas Veerman else
1704a17663cSThomas Veerman actions = temp;
1714a17663cSThomas Veerman
1724a17663cSThomas Veerman return (actions);
1734a17663cSThomas Veerman }
1744a17663cSThomas Veerman
1754a17663cSThomas Veerman static void
find_final_state(void)1764a17663cSThomas Veerman find_final_state(void)
1774a17663cSThomas Veerman {
1784a17663cSThomas Veerman int goal, i;
1794a17663cSThomas Veerman Value_t *to_state2;
1804a17663cSThomas Veerman shifts *p;
1814a17663cSThomas Veerman
1824a17663cSThomas Veerman p = shift_table[0];
1834a17663cSThomas Veerman to_state2 = p->shift;
1844a17663cSThomas Veerman goal = ritem[1];
1854a17663cSThomas Veerman for (i = p->nshifts - 1; i >= 0; --i)
1864a17663cSThomas Veerman {
1874a17663cSThomas Veerman final_state = to_state2[i];
1884a17663cSThomas Veerman if (accessing_symbol[final_state] == goal)
1894a17663cSThomas Veerman break;
1904a17663cSThomas Veerman }
1914a17663cSThomas Veerman }
1924a17663cSThomas Veerman
1934a17663cSThomas Veerman static void
unused_rules(void)1944a17663cSThomas Veerman unused_rules(void)
1954a17663cSThomas Veerman {
1964a17663cSThomas Veerman int i;
1974a17663cSThomas Veerman action *p;
1984a17663cSThomas Veerman
19984d9c625SLionel Sambuc rules_used = TMALLOC(Value_t, nrules);
2004a17663cSThomas Veerman NO_SPACE(rules_used);
2014a17663cSThomas Veerman
2024a17663cSThomas Veerman for (i = 0; i < nrules; ++i)
2034a17663cSThomas Veerman rules_used[i] = 0;
2044a17663cSThomas Veerman
2054a17663cSThomas Veerman for (i = 0; i < nstates; ++i)
2064a17663cSThomas Veerman {
2074a17663cSThomas Veerman for (p = parser[i]; p; p = p->next)
2084a17663cSThomas Veerman {
209*0a6a1f1dSLionel Sambuc if ((p->action_code == REDUCE) && MaySuppress(p))
2104a17663cSThomas Veerman rules_used[p->number] = 1;
2114a17663cSThomas Veerman }
2124a17663cSThomas Veerman }
2134a17663cSThomas Veerman
2144a17663cSThomas Veerman nunused = 0;
2154a17663cSThomas Veerman for (i = 3; i < nrules; ++i)
2164a17663cSThomas Veerman if (!rules_used[i])
2174a17663cSThomas Veerman ++nunused;
2184a17663cSThomas Veerman
2194a17663cSThomas Veerman if (nunused)
2204a17663cSThomas Veerman {
2214a17663cSThomas Veerman if (nunused == 1)
2224a17663cSThomas Veerman fprintf(stderr, "%s: 1 rule never reduced\n", myname);
2234a17663cSThomas Veerman else
2244a17663cSThomas Veerman fprintf(stderr, "%s: %d rules never reduced\n", myname, nunused);
2254a17663cSThomas Veerman }
2264a17663cSThomas Veerman }
2274a17663cSThomas Veerman
2284a17663cSThomas Veerman static void
remove_conflicts(void)2294a17663cSThomas Veerman remove_conflicts(void)
2304a17663cSThomas Veerman {
2314a17663cSThomas Veerman int i;
2324a17663cSThomas Veerman int symbol;
2334a17663cSThomas Veerman action *p, *pref = 0;
2344a17663cSThomas Veerman
2354a17663cSThomas Veerman SRtotal = 0;
2364a17663cSThomas Veerman RRtotal = 0;
2374a17663cSThomas Veerman SRconflicts = NEW2(nstates, Value_t);
2384a17663cSThomas Veerman RRconflicts = NEW2(nstates, Value_t);
2394a17663cSThomas Veerman for (i = 0; i < nstates; i++)
2404a17663cSThomas Veerman {
2414a17663cSThomas Veerman SRcount = 0;
2424a17663cSThomas Veerman RRcount = 0;
2434a17663cSThomas Veerman symbol = -1;
244*0a6a1f1dSLionel Sambuc #if defined(YYBTYACC)
245*0a6a1f1dSLionel Sambuc pref = NULL;
246*0a6a1f1dSLionel Sambuc #endif
2474a17663cSThomas Veerman for (p = parser[i]; p; p = p->next)
2484a17663cSThomas Veerman {
2494a17663cSThomas Veerman if (p->symbol != symbol)
2504a17663cSThomas Veerman {
251*0a6a1f1dSLionel Sambuc /* the first parse action for each symbol is the preferred action */
2524a17663cSThomas Veerman pref = p;
2534a17663cSThomas Veerman symbol = p->symbol;
2544a17663cSThomas Veerman }
255*0a6a1f1dSLionel Sambuc /* following conditions handle multiple, i.e., conflicting, parse actions */
2564a17663cSThomas Veerman else if (i == final_state && symbol == 0)
2574a17663cSThomas Veerman {
2584a17663cSThomas Veerman SRcount++;
2594a17663cSThomas Veerman p->suppressed = 1;
260*0a6a1f1dSLionel Sambuc StartBacktrack(pref);
2614a17663cSThomas Veerman }
2624a17663cSThomas Veerman else if (pref != 0 && pref->action_code == SHIFT)
2634a17663cSThomas Veerman {
2644a17663cSThomas Veerman if (pref->prec > 0 && p->prec > 0)
2654a17663cSThomas Veerman {
2664a17663cSThomas Veerman if (pref->prec < p->prec)
2674a17663cSThomas Veerman {
2684a17663cSThomas Veerman pref->suppressed = 2;
2694a17663cSThomas Veerman pref = p;
2704a17663cSThomas Veerman }
2714a17663cSThomas Veerman else if (pref->prec > p->prec)
2724a17663cSThomas Veerman {
2734a17663cSThomas Veerman p->suppressed = 2;
2744a17663cSThomas Veerman }
2754a17663cSThomas Veerman else if (pref->assoc == LEFT)
2764a17663cSThomas Veerman {
2774a17663cSThomas Veerman pref->suppressed = 2;
2784a17663cSThomas Veerman pref = p;
2794a17663cSThomas Veerman }
2804a17663cSThomas Veerman else if (pref->assoc == RIGHT)
2814a17663cSThomas Veerman {
2824a17663cSThomas Veerman p->suppressed = 2;
2834a17663cSThomas Veerman }
2844a17663cSThomas Veerman else
2854a17663cSThomas Veerman {
2864a17663cSThomas Veerman pref->suppressed = 2;
2874a17663cSThomas Veerman p->suppressed = 2;
2884a17663cSThomas Veerman }
2894a17663cSThomas Veerman }
2904a17663cSThomas Veerman else
2914a17663cSThomas Veerman {
2924a17663cSThomas Veerman SRcount++;
2934a17663cSThomas Veerman p->suppressed = 1;
294*0a6a1f1dSLionel Sambuc StartBacktrack(pref);
2954a17663cSThomas Veerman }
2964a17663cSThomas Veerman }
2974a17663cSThomas Veerman else
2984a17663cSThomas Veerman {
2994a17663cSThomas Veerman RRcount++;
3004a17663cSThomas Veerman p->suppressed = 1;
301*0a6a1f1dSLionel Sambuc StartBacktrack(pref);
3024a17663cSThomas Veerman }
3034a17663cSThomas Veerman }
3044a17663cSThomas Veerman SRtotal += SRcount;
3054a17663cSThomas Veerman RRtotal += RRcount;
3064a17663cSThomas Veerman SRconflicts[i] = SRcount;
3074a17663cSThomas Veerman RRconflicts[i] = RRcount;
3084a17663cSThomas Veerman }
3094a17663cSThomas Veerman }
3104a17663cSThomas Veerman
3114a17663cSThomas Veerman static void
total_conflicts(void)3124a17663cSThomas Veerman total_conflicts(void)
3134a17663cSThomas Veerman {
3144a17663cSThomas Veerman fprintf(stderr, "%s: ", myname);
3154a17663cSThomas Veerman if (SRtotal == 1)
3164a17663cSThomas Veerman fprintf(stderr, "1 shift/reduce conflict");
3174a17663cSThomas Veerman else if (SRtotal > 1)
3184a17663cSThomas Veerman fprintf(stderr, "%d shift/reduce conflicts", SRtotal);
3194a17663cSThomas Veerman
3204a17663cSThomas Veerman if (SRtotal && RRtotal)
3214a17663cSThomas Veerman fprintf(stderr, ", ");
3224a17663cSThomas Veerman
3234a17663cSThomas Veerman if (RRtotal == 1)
3244a17663cSThomas Veerman fprintf(stderr, "1 reduce/reduce conflict");
3254a17663cSThomas Veerman else if (RRtotal > 1)
3264a17663cSThomas Veerman fprintf(stderr, "%d reduce/reduce conflicts", RRtotal);
3274a17663cSThomas Veerman
3284a17663cSThomas Veerman fprintf(stderr, ".\n");
3294a17663cSThomas Veerman
3304a17663cSThomas Veerman if (SRexpect >= 0 && SRtotal != SRexpect)
3314a17663cSThomas Veerman {
3324a17663cSThomas Veerman fprintf(stderr, "%s: ", myname);
3334a17663cSThomas Veerman fprintf(stderr, "expected %d shift/reduce conflict%s.\n",
3344a17663cSThomas Veerman SRexpect, PLURAL(SRexpect));
3354a17663cSThomas Veerman exit_code = EXIT_FAILURE;
3364a17663cSThomas Veerman }
3374a17663cSThomas Veerman if (RRexpect >= 0 && RRtotal != RRexpect)
3384a17663cSThomas Veerman {
3394a17663cSThomas Veerman fprintf(stderr, "%s: ", myname);
3404a17663cSThomas Veerman fprintf(stderr, "expected %d reduce/reduce conflict%s.\n",
3414a17663cSThomas Veerman RRexpect, PLURAL(RRexpect));
3424a17663cSThomas Veerman exit_code = EXIT_FAILURE;
3434a17663cSThomas Veerman }
3444a17663cSThomas Veerman }
3454a17663cSThomas Veerman
3464a17663cSThomas Veerman static int
sole_reduction(int stateno)3474a17663cSThomas Veerman sole_reduction(int stateno)
3484a17663cSThomas Veerman {
3494a17663cSThomas Veerman int count, ruleno;
3504a17663cSThomas Veerman action *p;
3514a17663cSThomas Veerman
3524a17663cSThomas Veerman count = 0;
3534a17663cSThomas Veerman ruleno = 0;
3544a17663cSThomas Veerman for (p = parser[stateno]; p; p = p->next)
3554a17663cSThomas Veerman {
356*0a6a1f1dSLionel Sambuc if (p->action_code == SHIFT && MaySuppress(p))
3574a17663cSThomas Veerman return (0);
358*0a6a1f1dSLionel Sambuc else if ((p->action_code == REDUCE) && MaySuppress(p))
3594a17663cSThomas Veerman {
3604a17663cSThomas Veerman if (ruleno > 0 && p->number != ruleno)
3614a17663cSThomas Veerman return (0);
3624a17663cSThomas Veerman if (p->symbol != 1)
3634a17663cSThomas Veerman ++count;
3644a17663cSThomas Veerman ruleno = p->number;
3654a17663cSThomas Veerman }
3664a17663cSThomas Veerman }
3674a17663cSThomas Veerman
3684a17663cSThomas Veerman if (count == 0)
3694a17663cSThomas Veerman return (0);
3704a17663cSThomas Veerman return (ruleno);
3714a17663cSThomas Veerman }
3724a17663cSThomas Veerman
3734a17663cSThomas Veerman static void
defreds(void)3744a17663cSThomas Veerman defreds(void)
3754a17663cSThomas Veerman {
3764a17663cSThomas Veerman int i;
3774a17663cSThomas Veerman
3784a17663cSThomas Veerman defred = NEW2(nstates, Value_t);
3794a17663cSThomas Veerman for (i = 0; i < nstates; i++)
3804a17663cSThomas Veerman defred[i] = (Value_t) sole_reduction(i);
3814a17663cSThomas Veerman }
3824a17663cSThomas Veerman
3834a17663cSThomas Veerman static void
free_action_row(action * p)3844a17663cSThomas Veerman free_action_row(action *p)
3854a17663cSThomas Veerman {
3864a17663cSThomas Veerman action *q;
3874a17663cSThomas Veerman
3884a17663cSThomas Veerman while (p)
3894a17663cSThomas Veerman {
3904a17663cSThomas Veerman q = p->next;
3914a17663cSThomas Veerman FREE(p);
3924a17663cSThomas Veerman p = q;
3934a17663cSThomas Veerman }
3944a17663cSThomas Veerman }
3954a17663cSThomas Veerman
3964a17663cSThomas Veerman void
free_parser(void)3974a17663cSThomas Veerman free_parser(void)
3984a17663cSThomas Veerman {
3994a17663cSThomas Veerman int i;
4004a17663cSThomas Veerman
4014a17663cSThomas Veerman for (i = 0; i < nstates; i++)
4024a17663cSThomas Veerman free_action_row(parser[i]);
4034a17663cSThomas Veerman
4044a17663cSThomas Veerman FREE(parser);
4054a17663cSThomas Veerman }
4064a17663cSThomas Veerman
4074a17663cSThomas Veerman #ifdef NO_LEAKS
4084a17663cSThomas Veerman void
mkpar_leaks(void)4094a17663cSThomas Veerman mkpar_leaks(void)
4104a17663cSThomas Veerman {
4114a17663cSThomas Veerman DO_FREE(defred);
4124a17663cSThomas Veerman DO_FREE(rules_used);
4134a17663cSThomas Veerman DO_FREE(SRconflicts);
4144a17663cSThomas Veerman DO_FREE(RRconflicts);
4154a17663cSThomas Veerman }
4164a17663cSThomas Veerman #endif
417