mkpar.c revision 8874
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#ifndef lint 38static char sccsid[] = "@(#)mkpar.c 5.3 (Berkeley) 1/20/91"; 39#endif /* not lint */ 40 41#include "defs.h" 42 43action **parser; 44int SRtotal; 45int RRtotal; 46short *SRconflicts; 47short *RRconflicts; 48short *defred; 49short *rules_used; 50short nunused; 51short final_state; 52 53static int SRcount; 54static int RRcount; 55 56extern action *parse_actions(); 57extern action *get_shifts(); 58extern action *add_reductions(); 59extern action *add_reduce(); 60 61 62make_parser() 63{ 64 register int i; 65 66 parser = NEW2(nstates, action *); 67 for (i = 0; i < nstates; i++) 68 parser[i] = parse_actions(i); 69 70 find_final_state(); 71 remove_conflicts(); 72 unused_rules(); 73 if (SRtotal + RRtotal > 0) total_conflicts(); 74 defreds(); 75} 76 77 78action * 79parse_actions(stateno) 80register int stateno; 81{ 82 register action *actions; 83 84 actions = get_shifts(stateno); 85 actions = add_reductions(stateno, actions); 86 return (actions); 87} 88 89 90action * 91get_shifts(stateno) 92int stateno; 93{ 94 register action *actions, *temp; 95 register shifts *sp; 96 register short *to_state; 97 register int i, k; 98 register int symbol; 99 100 actions = 0; 101 sp = shift_table[stateno]; 102 if (sp) 103 { 104 to_state = sp->shift; 105 for (i = sp->nshifts - 1; i >= 0; i--) 106 { 107 k = to_state[i]; 108 symbol = accessing_symbol[k]; 109 if (ISTOKEN(symbol)) 110 { 111 temp = NEW(action); 112 temp->next = actions; 113 temp->symbol = symbol; 114 temp->number = k; 115 temp->prec = symbol_prec[symbol]; 116 temp->action_code = SHIFT; 117 temp->assoc = symbol_assoc[symbol]; 118 actions = temp; 119 } 120 } 121 } 122 return (actions); 123} 124 125action * 126add_reductions(stateno, actions) 127int stateno; 128register action *actions; 129{ 130 register int i, j, m, n; 131 register int ruleno, tokensetsize; 132 register unsigned *rowp; 133 134 tokensetsize = WORDSIZE(ntokens); 135 m = lookaheads[stateno]; 136 n = lookaheads[stateno + 1]; 137 for (i = m; i < n; i++) 138 { 139 ruleno = LAruleno[i]; 140 rowp = LA + i * tokensetsize; 141 for (j = ntokens - 1; j >= 0; j--) 142 { 143 if (BIT(rowp, j)) 144 actions = add_reduce(actions, ruleno, j); 145 } 146 } 147 return (actions); 148} 149 150 151action * 152add_reduce(actions, ruleno, symbol) 153register action *actions; 154register int ruleno, symbol; 155{ 156 register action *temp, *prev, *next; 157 158 prev = 0; 159 for (next = actions; next && next->symbol < symbol; next = next->next) 160 prev = next; 161 162 while (next && next->symbol == symbol && next->action_code == SHIFT) 163 { 164 prev = next; 165 next = next->next; 166 } 167 168 while (next && next->symbol == symbol && 169 next->action_code == REDUCE && next->number < ruleno) 170 { 171 prev = next; 172 next = next->next; 173 } 174 175 temp = NEW(action); 176 temp->next = next; 177 temp->symbol = symbol; 178 temp->number = ruleno; 179 temp->prec = rprec[ruleno]; 180 temp->action_code = REDUCE; 181 temp->assoc = rassoc[ruleno]; 182 183 if (prev) 184 prev->next = temp; 185 else 186 actions = temp; 187 188 return (actions); 189} 190 191 192find_final_state() 193{ 194 register int goal, i; 195 register short *to_state; 196 register shifts *p; 197 198 p = shift_table[0]; 199 to_state = p->shift; 200 goal = ritem[1]; 201 for (i = p->nshifts - 1; i >= 0; --i) 202 { 203 final_state = to_state[i]; 204 if (accessing_symbol[final_state] == goal) break; 205 } 206} 207 208 209unused_rules() 210{ 211 register int i; 212 register action *p; 213 214 rules_used = (short *) MALLOC(nrules*sizeof(short)); 215 if (rules_used == 0) no_space(); 216 217 for (i = 0; i < nrules; ++i) 218 rules_used[i] = 0; 219 220 for (i = 0; i < nstates; ++i) 221 { 222 for (p = parser[i]; p; p = p->next) 223 { 224 if (p->action_code == REDUCE && p->suppressed == 0) 225 rules_used[p->number] = 1; 226 } 227 } 228 229 nunused = 0; 230 for (i = 3; i < nrules; ++i) 231 if (!rules_used[i]) ++nunused; 232 233 if (nunused) 234 if (nunused == 1) 235 fprintf(stderr, "%s: 1 rule never reduced\n", myname); 236 else 237 fprintf(stderr, "%s: %d rules never reduced\n", myname, nunused); 238} 239 240 241remove_conflicts() 242{ 243 register int i; 244 register int symbol; 245 register action *p, *pref; 246 247 SRtotal = 0; 248 RRtotal = 0; 249 SRconflicts = NEW2(nstates, short); 250 RRconflicts = NEW2(nstates, short); 251 for (i = 0; i < nstates; i++) 252 { 253 SRcount = 0; 254 RRcount = 0; 255 symbol = -1; 256 for (p = parser[i]; p; p = p->next) 257 { 258 if (p->symbol != symbol) 259 { 260 pref = p; 261 symbol = p->symbol; 262 } 263 else if (i == final_state && symbol == 0) 264 { 265 SRcount++; 266 p->suppressed = 1; 267 } 268 else if (pref->action_code == SHIFT) 269 { 270 if (pref->prec > 0 && p->prec > 0) 271 { 272 if (pref->prec < p->prec) 273 { 274 pref->suppressed = 2; 275 pref = p; 276 } 277 else if (pref->prec > p->prec) 278 { 279 p->suppressed = 2; 280 } 281 else if (pref->assoc == LEFT) 282 { 283 pref->suppressed = 2; 284 pref = p; 285 } 286 else if (pref->assoc == RIGHT) 287 { 288 p->suppressed = 2; 289 } 290 else 291 { 292 pref->suppressed = 2; 293 p->suppressed = 2; 294 } 295 } 296 else 297 { 298 SRcount++; 299 p->suppressed = 1; 300 } 301 } 302 else 303 { 304 RRcount++; 305 p->suppressed = 1; 306 } 307 } 308 SRtotal += SRcount; 309 RRtotal += RRcount; 310 SRconflicts[i] = SRcount; 311 RRconflicts[i] = RRcount; 312 } 313} 314 315 316total_conflicts() 317{ 318 fprintf(stderr, "%s: ", myname); 319 if (SRtotal == 1) 320 fprintf(stderr, "1 shift/reduce conflict"); 321 else if (SRtotal > 1) 322 fprintf(stderr, "%d shift/reduce conflicts", SRtotal); 323 324 if (SRtotal && RRtotal) 325 fprintf(stderr, ", "); 326 327 if (RRtotal == 1) 328 fprintf(stderr, "1 reduce/reduce conflict"); 329 else if (RRtotal > 1) 330 fprintf(stderr, "%d reduce/reduce conflicts", RRtotal); 331 332 fprintf(stderr, ".\n"); 333} 334 335 336int 337sole_reduction(stateno) 338int stateno; 339{ 340 register int count, ruleno; 341 register action *p; 342 343 count = 0; 344 ruleno = 0; 345 for (p = parser[stateno]; p; p = p->next) 346 { 347 if (p->action_code == SHIFT && p->suppressed == 0) 348 return (0); 349 else if (p->action_code == REDUCE && p->suppressed == 0) 350 { 351 if (ruleno > 0 && p->number != ruleno) 352 return (0); 353 if (p->symbol != 1) 354 ++count; 355 ruleno = p->number; 356 } 357 } 358 359 if (count == 0) 360 return (0); 361 return (ruleno); 362} 363 364 365defreds() 366{ 367 register int i; 368 369 defred = NEW2(nstates, short); 370 for (i = 0; i < nstates; i++) 371 defred[i] = sole_reduction(i); 372} 373 374free_action_row(p) 375register action *p; 376{ 377 register action *q; 378 379 while (p) 380 { 381 q = p->next; 382 FREE(p); 383 p = q; 384 } 385} 386 387free_parser() 388{ 389 register int i; 390 391 for (i = 0; i < nstates; i++) 392 free_action_row(parser[i]); 393 394 FREE(parser); 395} 396