Home | History | Annotate | Line # | Download | only in dist
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