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 are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the University of California, Berkeley. The name of the 14 * University may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 */ 20 21 #ifndef lint 22 static char sccsid[] = "@(#)verbose.c 5.1 (Berkeley) 12/25/89"; 23 #endif /* not lint */ 24 25 #include "defs.h" 26 27 28 static short *null_rules; 29 30 verbose() 31 { 32 register int i; 33 34 if (!vflag) return; 35 36 null_rules = (short *) MALLOC(nrules*sizeof(short)); 37 if (null_rules == 0) no_space(); 38 fprintf(verbose_file, "\f\n"); 39 for (i = 0; i < nstates; i++) 40 print_state(i); 41 FREE(null_rules); 42 43 if (nunused) 44 log_unused(); 45 if (SRtotal || RRtotal) 46 log_conflicts(); 47 48 fprintf(verbose_file, "\n\n%d terminals, %d nonterminals\n", ntokens, 49 nvars); 50 fprintf(verbose_file, "%d grammar rules, %d states\n", nrules - 2, nstates); 51 } 52 53 54 log_unused() 55 { 56 register int i; 57 register short *p; 58 59 fprintf(verbose_file, "\n\nRules never reduced:\n"); 60 for (i = 3; i < nrules; ++i) 61 { 62 if (!rules_used[i]) 63 { 64 fprintf(verbose_file, "\t%s :", symbol_name[rlhs[i]]); 65 for (p = ritem + rrhs[i]; *p >= 0; ++p) 66 fprintf(verbose_file, " %s", symbol_name[*p]); 67 fprintf(verbose_file, " (%d)\n", i - 2); 68 } 69 } 70 } 71 72 73 log_conflicts() 74 { 75 register int i; 76 77 fprintf(verbose_file, "\n\n"); 78 for (i = 0; i < nstates; i++) 79 { 80 if (SRconflicts[i] || RRconflicts[i]) 81 { 82 fprintf(verbose_file, "State %d contains ", i); 83 if (SRconflicts[i] == 1) 84 fprintf(verbose_file, "1 shift/reduce conflict"); 85 else if (SRconflicts[i] > 1) 86 fprintf(verbose_file, "%d shift/reduce conflicts", 87 SRconflicts[i]); 88 if (SRconflicts[i] && RRconflicts[i]) 89 fprintf(verbose_file, ", "); 90 if (RRconflicts[i] == 1) 91 fprintf(verbose_file, "1 reduce/reduce conflict"); 92 else if (RRconflicts[i] > 1) 93 fprintf(verbose_file, "%d reduce/reduce conflicts", 94 RRconflicts[i]); 95 fprintf(verbose_file, ".\n"); 96 } 97 } 98 } 99 100 101 print_state(state) 102 int state; 103 { 104 if (state) 105 fprintf(verbose_file, "\n\n"); 106 if (SRconflicts[state] || RRconflicts[state]) 107 print_conflicts(state); 108 fprintf(verbose_file, "state %d\n", state); 109 print_core(state); 110 print_nulls(state); 111 print_actions(state); 112 } 113 114 115 print_conflicts(state) 116 int state; 117 { 118 register int symbol; 119 register action *p, *q, *r; 120 121 for (p = parser[state]; p; p = q->next) 122 { 123 q = p; 124 if (p->action_code == ERROR || p->suppressed == 2) 125 continue; 126 127 symbol = p->symbol; 128 while (q->next && q->next->symbol == symbol) 129 q = q->next; 130 if (state == final_state && symbol == 0) 131 { 132 r = p; 133 for (;;) 134 { 135 fprintf(verbose_file, "%d: shift/reduce conflict \ 136 (accept, reduce %d) on $end\n", state, r->number - 2); 137 if (r == q) break; 138 r = r->next; 139 } 140 } 141 else if (p != q) 142 { 143 r = p->next; 144 if (p->action_code == SHIFT) 145 { 146 for (;;) 147 { 148 if (r->action_code == REDUCE && p->suppressed != 2) 149 fprintf(verbose_file, "%d: shift/reduce conflict \ 150 (shift %d, reduce %d) on %s\n", state, p->number, r->number - 2, 151 symbol_name[symbol]); 152 if (r == q) break; 153 r = r->next; 154 } 155 } 156 else 157 { 158 for (;;) 159 { 160 if (r->action_code == REDUCE && p->suppressed != 2) 161 fprintf(verbose_file, "%d: reduce/reduce conflict \ 162 (reduce %d, reduce %d) on %s\n", state, p->number - 2, r->number - 2, 163 symbol_name[symbol]); 164 if (r == q) break; 165 r = r->next; 166 } 167 } 168 } 169 } 170 } 171 172 173 print_core(state) 174 int state; 175 { 176 register int i; 177 register int k; 178 register int rule; 179 register core *statep; 180 register short *sp; 181 register short *sp1; 182 183 statep = state_table[state]; 184 k = statep->nitems; 185 186 for (i = 0; i < k; i++) 187 { 188 sp1 = sp = ritem + statep->items[i]; 189 190 while (*sp >= 0) ++sp; 191 rule = -(*sp); 192 fprintf(verbose_file, "\t%s : ", symbol_name[rlhs[rule]]); 193 194 for (sp = ritem + rrhs[rule]; sp < sp1; sp++) 195 fprintf(verbose_file, "%s ", symbol_name[*sp]); 196 197 putc('.', verbose_file); 198 199 while (*sp >= 0) 200 { 201 fprintf(verbose_file, " %s", symbol_name[*sp]); 202 sp++; 203 } 204 fprintf(verbose_file, " (%d)\n", -2 - *sp); 205 } 206 } 207 208 209 print_nulls(state) 210 int state; 211 { 212 register action *p; 213 register int i, j, k, nnulls; 214 215 nnulls = 0; 216 for (p = parser[state]; p; p = p->next) 217 { 218 if (p->action_code == REDUCE && 219 (p->suppressed == 0 || p->suppressed == 1)) 220 { 221 i = p->number; 222 if (rrhs[i] + 1 == rrhs[i+1]) 223 { 224 for (j = 0; j < nnulls && i > null_rules[j]; ++j) 225 continue; 226 227 if (j == nnulls) 228 { 229 ++nnulls; 230 null_rules[j] = i; 231 } 232 else if (i != null_rules[j]) 233 { 234 ++nnulls; 235 for (k = nnulls - 1; k > j; --k) 236 null_rules[k] = null_rules[k-1]; 237 null_rules[j] = i; 238 } 239 } 240 } 241 } 242 243 for (i = 0; i < nnulls; ++i) 244 { 245 j = null_rules[i]; 246 fprintf(verbose_file, "\t%s : . (%d)\n", symbol_name[rlhs[j]], 247 j - 2); 248 } 249 fprintf(verbose_file, "\n"); 250 } 251 252 253 print_actions(stateno) 254 int stateno; 255 { 256 register action *p; 257 register shifts *sp; 258 register int as; 259 260 if (stateno == final_state) 261 fprintf(verbose_file, "\t$end accept\n"); 262 263 p = parser[stateno]; 264 if (p) 265 { 266 print_shifts(p); 267 print_reductions(p, defred[stateno]); 268 } 269 270 sp = shift_table[stateno]; 271 if (sp && sp->nshifts > 0) 272 { 273 as = accessing_symbol[sp->shift[sp->nshifts - 1]]; 274 if (ISVAR(as)) 275 print_gotos(stateno); 276 } 277 } 278 279 280 print_shifts(p) 281 register action *p; 282 { 283 register int count; 284 register action *q; 285 286 count = 0; 287 for (q = p; q; q = q->next) 288 { 289 if (q->suppressed < 2 && q->action_code == SHIFT) 290 ++count; 291 } 292 293 if (count > 0) 294 { 295 for (; p; p = p->next) 296 { 297 if (p->action_code == SHIFT && p->suppressed == 0) 298 fprintf(verbose_file, "\t%s shift %d\n", 299 symbol_name[p->symbol], p->number); 300 } 301 } 302 } 303 304 305 print_reductions(p, defred) 306 register action *p; 307 register int defred; 308 { 309 register int k, anyreds; 310 register action *q; 311 312 anyreds = 0; 313 for (q = p; q ; q = q->next) 314 { 315 if (q->action_code == REDUCE && q->suppressed < 2) 316 { 317 anyreds = 1; 318 break; 319 } 320 } 321 322 if (anyreds == 0) 323 fprintf(verbose_file, "\t. error\n"); 324 else 325 { 326 for (; p; p = p->next) 327 { 328 if (p->action_code == REDUCE && p->number != defred) 329 { 330 k = p->number - 2; 331 if (p->suppressed == 0) 332 fprintf(verbose_file, "\t%s reduce %d\n", 333 symbol_name[p->symbol], k); 334 } 335 } 336 337 if (defred > 0) 338 fprintf(verbose_file, "\t. reduce %d\n", defred - 2); 339 } 340 } 341 342 343 print_gotos(stateno) 344 int stateno; 345 { 346 register int i, k; 347 register int as; 348 register short *to_state; 349 register shifts *sp; 350 351 putc('\n', verbose_file); 352 sp = shift_table[stateno]; 353 to_state = sp->shift; 354 for (i = 0; i < sp->nshifts; ++i) 355 { 356 k = to_state[i]; 357 as = accessing_symbol[k]; 358 if (ISVAR(as)) 359 fprintf(verbose_file, "\t%s goto %d\n", symbol_name[as], k); 360 } 361 } 362