mkpar.c revision 87234
1/* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Robert Paul Corbett. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37#include <sys/cdefs.h> 38 39__FBSDID("$FreeBSD: head/usr.bin/yacc/mkpar.c 87234 2001-12-02 21:24:03Z markm $"); 40 41#ifndef lint 42static char const sccsid[] = "@(#)mkpar.c 5.3 (Berkeley) 1/20/91"; 43#endif 44 45#include <stdlib.h> 46#include "defs.h" 47 48action **parser; 49int SRexpect; 50int SRtotal; 51int RRtotal; 52short *SRconflicts; 53short *RRconflicts; 54short *defred; 55short *rules_used; 56short nunused; 57short final_state; 58 59static int SRcount; 60static int RRcount; 61 62static action *add_reduce __P((action *, int, int)); 63static action *add_reductions __P((int, action *)); 64static void defreds __P((void)); 65static void find_final_state __P((void)); 66static void free_action_row __P((action *)); 67static action *get_shifts __P((int)); 68static action *parse_actions __P((int)); 69static void remove_conflicts __P((void)); 70static int sole_reduction __P((int)); 71static void total_conflicts __P((void)); 72static void unused_rules __P((void)); 73 74 75void 76make_parser() 77{ 78 int i; 79 80 parser = NEW2(nstates, action *); 81 for (i = 0; i < nstates; i++) 82 parser[i] = parse_actions(i); 83 84 find_final_state(); 85 remove_conflicts(); 86 unused_rules(); 87 if (SRtotal + RRtotal > 0) total_conflicts(); 88 defreds(); 89} 90 91 92static action * 93parse_actions(stateno) 94int stateno; 95{ 96 action *actions; 97 98 actions = get_shifts(stateno); 99 actions = add_reductions(stateno, actions); 100 return (actions); 101} 102 103 104static action * 105get_shifts(stateno) 106int stateno; 107{ 108 action *actions, *temp; 109 shifts *sp; 110 short *tostate; 111 int i, k; 112 int symbol; 113 114 actions = 0; 115 sp = shift_table[stateno]; 116 if (sp) 117 { 118 tostate = sp->shift; 119 for (i = sp->nshifts - 1; i >= 0; i--) 120 { 121 k = tostate[i]; 122 symbol = accessing_symbol[k]; 123 if (ISTOKEN(symbol)) 124 { 125 temp = NEW(action); 126 temp->next = actions; 127 temp->symbol = symbol; 128 temp->number = k; 129 temp->prec = symbol_prec[symbol]; 130 temp->action_code = SHIFT; 131 temp->assoc = symbol_assoc[symbol]; 132 actions = temp; 133 } 134 } 135 } 136 return (actions); 137} 138 139static action * 140add_reductions(stateno, actions) 141int stateno; 142action *actions; 143{ 144 int i, j, m, n; 145 int ruleno, tokensetsize; 146 unsigned *rowp; 147 148 tokensetsize = WORDSIZE(ntokens); 149 m = lookaheads[stateno]; 150 n = lookaheads[stateno + 1]; 151 for (i = m; i < n; i++) 152 { 153 ruleno = LAruleno[i]; 154 rowp = LA + i * tokensetsize; 155 for (j = ntokens - 1; j >= 0; j--) 156 { 157 if (BIT(rowp, j)) 158 actions = add_reduce(actions, ruleno, j); 159 } 160 } 161 return (actions); 162} 163 164 165static action * 166add_reduce(actions, ruleno, symbol) 167action *actions; 168int ruleno, symbol; 169{ 170 action *temp, *prev, *next; 171 172 prev = 0; 173 for (next = actions; next && next->symbol < symbol; next = next->next) 174 prev = next; 175 176 while (next && next->symbol == symbol && next->action_code == SHIFT) 177 { 178 prev = next; 179 next = next->next; 180 } 181 182 while (next && next->symbol == symbol && 183 next->action_code == REDUCE && next->number < ruleno) 184 { 185 prev = next; 186 next = next->next; 187 } 188 189 temp = NEW(action); 190 temp->next = next; 191 temp->symbol = symbol; 192 temp->number = ruleno; 193 temp->prec = rprec[ruleno]; 194 temp->action_code = REDUCE; 195 temp->assoc = rassoc[ruleno]; 196 197 if (prev) 198 prev->next = temp; 199 else 200 actions = temp; 201 202 return (actions); 203} 204 205 206static void 207find_final_state() 208{ 209 int goal, i; 210 short *tostate; 211 shifts *p; 212 213 p = shift_table[0]; 214 tostate = p->shift; 215 goal = ritem[1]; 216 for (i = p->nshifts - 1; i >= 0; --i) 217 { 218 final_state = tostate[i]; 219 if (accessing_symbol[final_state] == goal) break; 220 } 221} 222 223 224static void 225unused_rules() 226{ 227 int i; 228 action *p; 229 230 rules_used = (short *) MALLOC(nrules*sizeof(short)); 231 if (rules_used == 0) no_space(); 232 233 for (i = 0; i < nrules; ++i) 234 rules_used[i] = 0; 235 236 for (i = 0; i < nstates; ++i) 237 { 238 for (p = parser[i]; p; p = p->next) 239 { 240 if (p->action_code == REDUCE && p->suppressed == 0) 241 rules_used[p->number] = 1; 242 } 243 } 244 245 nunused = 0; 246 for (i = 3; i < nrules; ++i) 247 if (!rules_used[i]) ++nunused; 248 249 if (nunused) { 250 if (nunused == 1) 251 warnx("1 rule never reduced"); 252 else 253 warnx("%d rules never reduced", nunused); 254 } 255} 256 257 258static void 259remove_conflicts() 260{ 261 int i; 262 int symbol; 263 action *p, *pref = NULL; 264 265 SRtotal = 0; 266 RRtotal = 0; 267 SRconflicts = NEW2(nstates, short); 268 RRconflicts = NEW2(nstates, short); 269 for (i = 0; i < nstates; i++) 270 { 271 SRcount = 0; 272 RRcount = 0; 273 symbol = -1; 274 for (p = parser[i]; p; p = p->next) 275 { 276 if (p->symbol != symbol) 277 { 278 pref = p; 279 symbol = p->symbol; 280 } 281 else if (i == final_state && symbol == 0) 282 { 283 SRcount++; 284 p->suppressed = 1; 285 } 286 else if (pref->action_code == SHIFT) 287 { 288 if (pref->prec > 0 && p->prec > 0) 289 { 290 if (pref->prec < p->prec) 291 { 292 pref->suppressed = 2; 293 pref = p; 294 } 295 else if (pref->prec > p->prec) 296 { 297 p->suppressed = 2; 298 } 299 else if (pref->assoc == LEFT) 300 { 301 pref->suppressed = 2; 302 pref = p; 303 } 304 else if (pref->assoc == RIGHT) 305 { 306 p->suppressed = 2; 307 } 308 else 309 { 310 pref->suppressed = 2; 311 p->suppressed = 2; 312 } 313 } 314 else 315 { 316 SRcount++; 317 p->suppressed = 1; 318 } 319 } 320 else 321 { 322 RRcount++; 323 p->suppressed = 1; 324 } 325 } 326 SRtotal += SRcount; 327 RRtotal += RRcount; 328 SRconflicts[i] = SRcount; 329 RRconflicts[i] = RRcount; 330 } 331} 332 333 334static void 335total_conflicts() 336{ 337 /* Warn if s/r != expect or if any r/r */ 338 if ((SRtotal != SRexpect) || RRtotal) 339 { 340 if (SRtotal == 1) 341 warnx("1 shift/reduce conflict"); 342 else if (SRtotal > 1) 343 warnx("%d shift/reduce conflicts", SRtotal); 344 } 345 346 if (RRtotal == 1) 347 warnx("1 reduce/reduce conflict"); 348 else if (RRtotal > 1) 349 warnx("%d reduce/reduce conflicts", RRtotal); 350} 351 352 353static int 354sole_reduction(stateno) 355int stateno; 356{ 357 int count, ruleno; 358 action *p; 359 360 count = 0; 361 ruleno = 0; 362 for (p = parser[stateno]; p; p = p->next) 363 { 364 if (p->action_code == SHIFT && p->suppressed == 0) 365 return (0); 366 else if (p->action_code == REDUCE && p->suppressed == 0) 367 { 368 if (ruleno > 0 && p->number != ruleno) 369 return (0); 370 if (p->symbol != 1) 371 ++count; 372 ruleno = p->number; 373 } 374 } 375 376 if (count == 0) 377 return (0); 378 return (ruleno); 379} 380 381 382static void 383defreds() 384{ 385 int i; 386 387 defred = NEW2(nstates, short); 388 for (i = 0; i < nstates; i++) 389 defred[i] = sole_reduction(i); 390} 391 392static void 393free_action_row(p) 394action *p; 395{ 396 action *q; 397 398 while (p) 399 { 400 q = p->next; 401 FREE(p); 402 p = q; 403 } 404} 405 406void 407free_parser() 408{ 409 int i; 410 411 for (i = 0; i < nstates; i++) 412 free_action_row(parser[i]); 413 414 FREE(parser); 415} 416