1 /* $OpenBSD: mkpar.c,v 1.19 2017/05/25 20:11:03 tedu Exp $ */
2 /* $NetBSD: mkpar.c,v 1.4 1996/03/19 03:21:39 jtc Exp $ */
5 * Copyright (c) 1989 The Regents of the University of California.
8 * This code is derived from software contributed to Berkeley by
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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
52 extern action
*parse_actions(int);
53 extern action
*get_shifts(int);
54 extern action
*add_reductions(int, action
*);
55 extern action
*add_reduce(action
*, int, int);
57 short sole_reduction(int);
58 void free_action_row(action
*);
60 void find_final_state(void);
61 void unused_rules(void);
62 void remove_conflicts(void);
63 void total_conflicts(void);
72 parser
= NEW2(nstates
, action
*);
73 for (i
= 0; i
< nstates
; i
++)
74 parser
[i
] = parse_actions(i
);
79 if (SRtotal
+ RRtotal
> 0)
86 parse_actions(int stateno
)
90 actions
= get_shifts(stateno
);
91 actions
= add_reductions(stateno
, actions
);
97 get_shifts(int stateno
)
99 action
*actions
, *temp
;
106 sp
= shift_table
[stateno
];
108 tto_state
= sp
->shift
;
109 for (i
= sp
->nshifts
- 1; i
>= 0; i
--) {
111 symbol
= accessing_symbol
[k
];
112 if (ISTOKEN(symbol
)) {
114 temp
->next
= actions
;
115 temp
->symbol
= symbol
;
117 temp
->prec
= symbol_prec
[symbol
];
118 temp
->action_code
= SHIFT
;
119 temp
->assoc
= symbol_assoc
[symbol
];
128 add_reductions(int stateno
, action
* actions
)
131 int ruleno
, tokensetsize
;
134 tokensetsize
= WORDSIZE(ntokens
);
135 m
= lookaheads
[stateno
];
136 n
= lookaheads
[stateno
+ 1];
137 for (i
= m
; i
< n
; i
++) {
138 ruleno
= LAruleno
[i
];
139 rowp
= LA
+ i
* tokensetsize
;
140 for (j
= ntokens
- 1; j
>= 0; j
--) {
142 actions
= add_reduce(actions
, ruleno
, j
);
150 add_reduce(action
* actions
, int ruleno
, int symbol
)
152 action
*temp
, *prev
, *next
;
155 for (next
= actions
; next
&& next
->symbol
< symbol
; next
= next
->next
)
158 while (next
&& next
->symbol
== symbol
&& next
->action_code
== SHIFT
) {
163 while (next
&& next
->symbol
== symbol
&&
164 next
->action_code
== REDUCE
&& next
->number
< ruleno
) {
171 temp
->symbol
= symbol
;
172 temp
->number
= ruleno
;
173 temp
->prec
= rprec
[ruleno
];
174 temp
->action_code
= REDUCE
;
175 temp
->assoc
= rassoc
[ruleno
];
187 find_final_state(void)
194 tto_state
= p
->shift
;
196 for (i
= p
->nshifts
- 1; i
>= 0; --i
) {
197 final_state
= tto_state
[i
];
198 if (accessing_symbol
[final_state
] == goal
)
210 rules_used
= calloc(nrules
, sizeof(short));
211 if (rules_used
== NULL
)
214 for (i
= 0; i
< nstates
; ++i
) {
215 for (p
= parser
[i
]; p
; p
= p
->next
) {
216 if (p
->action_code
== REDUCE
&& p
->suppressed
== 0)
217 rules_used
[p
->number
] = 1;
222 for (i
= 3; i
< nrules
; ++i
)
228 fprintf(stderr
, "%s: 1 rule never reduced\n", __progname
);
230 fprintf(stderr
, "%s: %d rules never reduced\n", __progname
,
237 remove_conflicts(void)
241 action
*p
, *pref
= NULL
;
245 SRconflicts
= NEW2(nstates
, short);
246 RRconflicts
= NEW2(nstates
, short);
247 for (i
= 0; i
< nstates
; i
++) {
251 for (p
= parser
[i
]; p
; p
= p
->next
) {
252 if (p
->symbol
!= symbol
) {
255 } else if (i
== final_state
&& symbol
== 0) {
258 } else if (pref
->action_code
== SHIFT
) {
259 if (pref
->prec
> 0 && p
->prec
> 0) {
260 if (pref
->prec
< p
->prec
) {
261 pref
->suppressed
= 2;
263 } else if (pref
->prec
> p
->prec
) {
265 } else if (pref
->assoc
== LEFT
) {
266 pref
->suppressed
= 2;
268 } else if (pref
->assoc
== RIGHT
) {
271 pref
->suppressed
= 2;
285 SRconflicts
[i
] = SRcount
;
286 RRconflicts
[i
] = RRcount
;
292 total_conflicts(void)
294 /* Warn if s/r != expect or if any r/r */
295 if ((SRtotal
!= SRexpect
) || RRtotal
) {
297 fprintf(stderr
, "%s: %s finds 1 shift/reduce conflict\n",
298 input_file_name
, __progname
);
299 else if (SRtotal
> 1)
300 fprintf(stderr
, "%s: %s finds %d shift/reduce conflicts\n",
301 input_file_name
, __progname
, SRtotal
);
304 fprintf(stderr
, "%s: %s finds 1 reduce/reduce conflict\n",
305 input_file_name
, __progname
);
306 else if (RRtotal
> 1)
307 fprintf(stderr
, "%s: %s finds %d reduce/reduce conflicts\n",
308 input_file_name
, __progname
, RRtotal
);
313 sole_reduction(int stateno
)
321 for (p
= parser
[stateno
]; p
; p
= p
->next
) {
322 if (p
->action_code
== SHIFT
&& p
->suppressed
== 0)
324 else if (p
->action_code
== REDUCE
&& p
->suppressed
== 0) {
325 if (ruleno
> 0 && p
->number
!= ruleno
)
344 defred
= NEW2(nstates
, short);
345 for (i
= 0; i
< nstates
; i
++)
346 defred
[i
] = sole_reduction(i
);
350 free_action_row(action
* p
)
366 for (i
= 0; i
< nstates
; i
++)
367 free_action_row(parser
[i
]);