|
|
1.1 ! root 1: /* Generate the nondeterministic finite state machine for bison, ! 2: Copyright (C) 1984, 1986, 1989 Free Software Foundation, Inc. ! 3: ! 4: This file is part of Bison, the GNU Compiler Compiler. ! 5: ! 6: Bison is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 2, or (at your option) ! 9: any later version. ! 10: ! 11: Bison is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with Bison; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: ! 21: /* See comments in state.h for the data structures that represent it. ! 22: The entry point is generate_states. */ ! 23: ! 24: #include <stdio.h> ! 25: #include "system.h" ! 26: #include "machine.h" ! 27: #include "new.h" ! 28: #include "gram.h" ! 29: #include "state.h" ! 30: ! 31: ! 32: extern char *nullable; ! 33: extern short *itemset; ! 34: extern short *itemsetend; ! 35: ! 36: ! 37: int nstates; ! 38: int final_state; ! 39: core *first_state; ! 40: shifts *first_shift; ! 41: reductions *first_reduction; ! 42: ! 43: int get_state(); ! 44: core *new_state(); ! 45: ! 46: void new_itemsets(); ! 47: void append_states(); ! 48: void initialize_states(); ! 49: void save_shifts(); ! 50: void save_reductions(); ! 51: void augment_automaton(); ! 52: void insert_start_shift(); ! 53: extern void initialize_closure(); ! 54: extern void closure(); ! 55: extern void finalize_closure(); ! 56: extern void toomany(); ! 57: ! 58: static core *this_state; ! 59: static core *last_state; ! 60: static shifts *last_shift; ! 61: static reductions *last_reduction; ! 62: ! 63: static int nshifts; ! 64: static short *shift_symbol; ! 65: ! 66: static short *redset; ! 67: static short *shiftset; ! 68: ! 69: static short **kernel_base; ! 70: static short **kernel_end; ! 71: static short *kernel_items; ! 72: ! 73: /* hash table for states, to recognize equivalent ones. */ ! 74: ! 75: #define STATE_TABLE_SIZE 1009 ! 76: static core **state_table; ! 77: ! 78: ! 79: ! 80: void ! 81: allocate_itemsets() ! 82: { ! 83: register short *itemp; ! 84: register int symbol; ! 85: register int i; ! 86: register int count; ! 87: register short *symbol_count; ! 88: ! 89: count = 0; ! 90: symbol_count = NEW2(nsyms, short); ! 91: ! 92: itemp = ritem; ! 93: symbol = *itemp++; ! 94: while (symbol) ! 95: { ! 96: if (symbol > 0) ! 97: { ! 98: count++; ! 99: symbol_count[symbol]++; ! 100: } ! 101: symbol = *itemp++; ! 102: } ! 103: ! 104: /* see comments before new_itemsets. All the vectors of items ! 105: live inside kernel_items. The number of active items after ! 106: some symbol cannot be more than the number of times that symbol ! 107: appears as an item, which is symbol_count[symbol]. ! 108: We allocate that much space for each symbol. */ ! 109: ! 110: kernel_base = NEW2(nsyms, short *); ! 111: kernel_items = NEW2(count, short); ! 112: ! 113: count = 0; ! 114: for (i = 0; i < nsyms; i++) ! 115: { ! 116: kernel_base[i] = kernel_items + count; ! 117: count += symbol_count[i]; ! 118: } ! 119: ! 120: shift_symbol = symbol_count; ! 121: kernel_end = NEW2(nsyms, short *); ! 122: } ! 123: ! 124: ! 125: void ! 126: allocate_storage() ! 127: { ! 128: allocate_itemsets(); ! 129: ! 130: shiftset = NEW2(nsyms, short); ! 131: redset = NEW2(nrules + 1, short); ! 132: state_table = NEW2(STATE_TABLE_SIZE, core *); ! 133: } ! 134: ! 135: ! 136: void ! 137: free_storage() ! 138: { ! 139: FREE(shift_symbol); ! 140: FREE(redset); ! 141: FREE(shiftset); ! 142: FREE(kernel_base); ! 143: FREE(kernel_end); ! 144: FREE(kernel_items); ! 145: FREE(state_table); ! 146: } ! 147: ! 148: ! 149: ! 150: /* compute the nondeterministic finite state machine (see state.h for details) ! 151: from the grammar. */ ! 152: void ! 153: generate_states() ! 154: { ! 155: allocate_storage(); ! 156: initialize_closure(nitems); ! 157: initialize_states(); ! 158: ! 159: while (this_state) ! 160: { ! 161: /* Set up ruleset and itemset for the transitions out of this state. ! 162: ruleset gets a 1 bit for each rule that could reduce now. ! 163: itemset gets a vector of all the items that could be accepted next. */ ! 164: closure(this_state->items, this_state->nitems); ! 165: /* record the reductions allowed out of this state */ ! 166: save_reductions(); ! 167: /* find the itemsets of the states that shifts can reach */ ! 168: new_itemsets(); ! 169: /* find or create the core structures for those states */ ! 170: append_states(); ! 171: ! 172: /* create the shifts structures for the shifts to those states, ! 173: now that the state numbers transitioning to are known */ ! 174: if (nshifts > 0) ! 175: save_shifts(); ! 176: ! 177: /* states are queued when they are created; process them all */ ! 178: this_state = this_state->next; ! 179: } ! 180: ! 181: /* discard various storage */ ! 182: finalize_closure(); ! 183: free_storage(); ! 184: ! 185: /* set up initial and final states as parser wants them */ ! 186: augment_automaton(); ! 187: } ! 188: ! 189: ! 190: ! 191: /* Find which symbols can be shifted in the current state, ! 192: and for each one record which items would be active after that shift. ! 193: Uses the contents of itemset. ! 194: shift_symbol is set to a vector of the symbols that can be shifted. ! 195: For each symbol in the grammar, kernel_base[symbol] points to ! 196: a vector of item numbers activated if that symbol is shifted, ! 197: and kernel_end[symbol] points after the end of that vector. */ ! 198: void ! 199: new_itemsets() ! 200: { ! 201: register int i; ! 202: register int shiftcount; ! 203: register short *isp; ! 204: register short *ksp; ! 205: register int symbol; ! 206: ! 207: #ifdef TRACE ! 208: fprintf(stderr, "Entering new_itemsets\n"); ! 209: #endif ! 210: ! 211: for (i = 0; i < nsyms; i++) ! 212: kernel_end[i] = NULL; ! 213: ! 214: shiftcount = 0; ! 215: ! 216: isp = itemset; ! 217: ! 218: while (isp < itemsetend) ! 219: { ! 220: i = *isp++; ! 221: symbol = ritem[i]; ! 222: if (symbol > 0) ! 223: { ! 224: ksp = kernel_end[symbol]; ! 225: ! 226: if (!ksp) ! 227: { ! 228: shift_symbol[shiftcount++] = symbol; ! 229: ksp = kernel_base[symbol]; ! 230: } ! 231: ! 232: *ksp++ = i + 1; ! 233: kernel_end[symbol] = ksp; ! 234: } ! 235: } ! 236: ! 237: nshifts = shiftcount; ! 238: } ! 239: ! 240: ! 241: ! 242: /* Use the information computed by new_itemsets to find the state numbers ! 243: reached by each shift transition from the current state. ! 244: ! 245: shiftset is set up as a vector of state numbers of those states. */ ! 246: void ! 247: append_states() ! 248: { ! 249: register int i; ! 250: register int j; ! 251: register int symbol; ! 252: ! 253: #ifdef TRACE ! 254: fprintf(stderr, "Entering append_states\n"); ! 255: #endif ! 256: ! 257: /* first sort shift_symbol into increasing order */ ! 258: ! 259: for (i = 1; i < nshifts; i++) ! 260: { ! 261: symbol = shift_symbol[i]; ! 262: j = i; ! 263: while (j > 0 && shift_symbol[j - 1] > symbol) ! 264: { ! 265: shift_symbol[j] = shift_symbol[j - 1]; ! 266: j--; ! 267: } ! 268: shift_symbol[j] = symbol; ! 269: } ! 270: ! 271: for (i = 0; i < nshifts; i++) ! 272: { ! 273: symbol = shift_symbol[i]; ! 274: shiftset[i] = get_state(symbol); ! 275: } ! 276: } ! 277: ! 278: ! 279: ! 280: /* find the state number for the state we would get to ! 281: (from the current state) by shifting symbol. ! 282: Create a new state if no equivalent one exists already. ! 283: Used by append_states */ ! 284: ! 285: int ! 286: get_state(symbol) ! 287: int symbol; ! 288: { ! 289: register int key; ! 290: register short *isp1; ! 291: register short *isp2; ! 292: register short *iend; ! 293: register core *sp; ! 294: register int found; ! 295: ! 296: int n; ! 297: ! 298: #ifdef TRACE ! 299: fprintf(stderr, "Entering get_state, symbol = %d\n", symbol); ! 300: #endif ! 301: ! 302: isp1 = kernel_base[symbol]; ! 303: iend = kernel_end[symbol]; ! 304: n = iend - isp1; ! 305: ! 306: /* add up the target state's active item numbers to get a hash key */ ! 307: key = 0; ! 308: while (isp1 < iend) ! 309: key += *isp1++; ! 310: ! 311: key = key % STATE_TABLE_SIZE; ! 312: ! 313: sp = state_table[key]; ! 314: ! 315: if (sp) ! 316: { ! 317: found = 0; ! 318: while (!found) ! 319: { ! 320: if (sp->nitems == n) ! 321: { ! 322: found = 1; ! 323: isp1 = kernel_base[symbol]; ! 324: isp2 = sp->items; ! 325: ! 326: while (found && isp1 < iend) ! 327: { ! 328: if (*isp1++ != *isp2++) ! 329: found = 0; ! 330: } ! 331: } ! 332: ! 333: if (!found) ! 334: { ! 335: if (sp->link) ! 336: { ! 337: sp = sp->link; ! 338: } ! 339: else /* bucket exhausted and no match */ ! 340: { ! 341: sp = sp->link = new_state(symbol); ! 342: found = 1; ! 343: } ! 344: } ! 345: } ! 346: } ! 347: else /* bucket is empty */ ! 348: { ! 349: state_table[key] = sp = new_state(symbol); ! 350: } ! 351: ! 352: return (sp->number); ! 353: } ! 354: ! 355: ! 356: ! 357: /* subroutine of get_state. create a new state for those items, if necessary. */ ! 358: ! 359: core * ! 360: new_state(symbol) ! 361: int symbol; ! 362: { ! 363: register int n; ! 364: register core *p; ! 365: register short *isp1; ! 366: register short *isp2; ! 367: register short *iend; ! 368: ! 369: #ifdef TRACE ! 370: fprintf(stderr, "Entering new_state, symbol = %d\n", symbol); ! 371: #endif ! 372: ! 373: if (nstates >= MAXSHORT) ! 374: toomany("states"); ! 375: ! 376: isp1 = kernel_base[symbol]; ! 377: iend = kernel_end[symbol]; ! 378: n = iend - isp1; ! 379: ! 380: p = (core *) xmalloc((unsigned) (sizeof(core) + (n - 1) * sizeof(short))); ! 381: p->accessing_symbol = symbol; ! 382: p->number = nstates; ! 383: p->nitems = n; ! 384: ! 385: isp2 = p->items; ! 386: while (isp1 < iend) ! 387: *isp2++ = *isp1++; ! 388: ! 389: last_state->next = p; ! 390: last_state = p; ! 391: ! 392: nstates++; ! 393: ! 394: return (p); ! 395: } ! 396: ! 397: ! 398: void ! 399: initialize_states() ! 400: { ! 401: register core *p; ! 402: /* register unsigned *rp1; JF unused */ ! 403: /* register unsigned *rp2; JF unused */ ! 404: /* register unsigned *rend; JF unused */ ! 405: ! 406: p = (core *) xmalloc((unsigned) (sizeof(core) - sizeof(short))); ! 407: first_state = last_state = this_state = p; ! 408: nstates = 1; ! 409: } ! 410: ! 411: ! 412: void ! 413: save_shifts() ! 414: { ! 415: register shifts *p; ! 416: register short *sp1; ! 417: register short *sp2; ! 418: register short *send; ! 419: ! 420: p = (shifts *) xmalloc((unsigned) (sizeof(shifts) + ! 421: (nshifts - 1) * sizeof(short))); ! 422: ! 423: p->number = this_state->number; ! 424: p->nshifts = nshifts; ! 425: ! 426: sp1 = shiftset; ! 427: sp2 = p->shifts; ! 428: send = shiftset + nshifts; ! 429: ! 430: while (sp1 < send) ! 431: *sp2++ = *sp1++; ! 432: ! 433: if (last_shift) ! 434: { ! 435: last_shift->next = p; ! 436: last_shift = p; ! 437: } ! 438: else ! 439: { ! 440: first_shift = p; ! 441: last_shift = p; ! 442: } ! 443: } ! 444: ! 445: ! 446: ! 447: /* find which rules can be used for reduction transitions from the current state ! 448: and make a reductions structure for the state to record their rule numbers. */ ! 449: void ! 450: save_reductions() ! 451: { ! 452: register short *isp; ! 453: register short *rp1; ! 454: register short *rp2; ! 455: register int item; ! 456: register int count; ! 457: register reductions *p; ! 458: ! 459: short *rend; ! 460: ! 461: /* find and count the active items that represent ends of rules */ ! 462: ! 463: count = 0; ! 464: for (isp = itemset; isp < itemsetend; isp++) ! 465: { ! 466: item = ritem[*isp]; ! 467: if (item < 0) ! 468: { ! 469: redset[count++] = -item; ! 470: } ! 471: } ! 472: ! 473: /* make a reductions structure and copy the data into it. */ ! 474: ! 475: if (count) ! 476: { ! 477: p = (reductions *) xmalloc((unsigned) (sizeof(reductions) + ! 478: (count - 1) * sizeof(short))); ! 479: ! 480: p->number = this_state->number; ! 481: p->nreds = count; ! 482: ! 483: rp1 = redset; ! 484: rp2 = p->rules; ! 485: rend = rp1 + count; ! 486: ! 487: while (rp1 < rend) ! 488: *rp2++ = *rp1++; ! 489: ! 490: if (last_reduction) ! 491: { ! 492: last_reduction->next = p; ! 493: last_reduction = p; ! 494: } ! 495: else ! 496: { ! 497: first_reduction = p; ! 498: last_reduction = p; ! 499: } ! 500: } ! 501: } ! 502: ! 503: ! 504: ! 505: /* Make sure that the initial state has a shift that accepts the ! 506: grammar's start symbol and goes to the next-to-final state, ! 507: which has a shift going to the final state, which has a shift ! 508: to the termination state. ! 509: Create such states and shifts if they don't happen to exist already. */ ! 510: void ! 511: augment_automaton() ! 512: { ! 513: register int i; ! 514: register int k; ! 515: /* register int found; JF unused */ ! 516: register core *statep; ! 517: register shifts *sp; ! 518: register shifts *sp2; ! 519: register shifts *sp1; ! 520: ! 521: sp = first_shift; ! 522: ! 523: if (sp) ! 524: { ! 525: if (sp->number == 0) ! 526: { ! 527: k = sp->nshifts; ! 528: statep = first_state->next; ! 529: ! 530: /* The states reached by shifts from first_state are numbered 1...K. ! 531: Look for one reached by start_symbol. */ ! 532: while (statep->accessing_symbol < start_symbol ! 533: && statep->number < k) ! 534: statep = statep->next; ! 535: ! 536: if (statep->accessing_symbol == start_symbol) ! 537: { ! 538: /* We already have a next-to-final state. ! 539: Make sure it has a shift to what will be the final state. */ ! 540: k = statep->number; ! 541: ! 542: while (sp && sp->number < k) ! 543: { ! 544: sp1 = sp; ! 545: sp = sp->next; ! 546: } ! 547: ! 548: if (sp && sp->number == k) ! 549: { ! 550: sp2 = (shifts *) xmalloc((unsigned) (sizeof(shifts) ! 551: + sp->nshifts * sizeof(short))); ! 552: sp2->number = k; ! 553: sp2->nshifts = sp->nshifts + 1; ! 554: sp2->shifts[0] = nstates; ! 555: for (i = sp->nshifts; i > 0; i--) ! 556: sp2->shifts[i] = sp->shifts[i - 1]; ! 557: ! 558: /* Patch sp2 into the chain of shifts in place of sp, ! 559: following sp1. */ ! 560: sp2->next = sp->next; ! 561: sp1->next = sp2; ! 562: if (sp == last_shift) ! 563: last_shift = sp2; ! 564: FREE(sp); ! 565: } ! 566: else ! 567: { ! 568: sp2 = NEW(shifts); ! 569: sp2->number = k; ! 570: sp2->nshifts = 1; ! 571: sp2->shifts[0] = nstates; ! 572: ! 573: /* Patch sp2 into the chain of shifts between sp1 and sp. */ ! 574: sp2->next = sp; ! 575: sp1->next = sp2; ! 576: if (sp == 0) ! 577: last_shift = sp2; ! 578: } ! 579: } ! 580: else ! 581: { ! 582: /* There is no next-to-final state as yet. */ ! 583: /* Add one more shift in first_shift, ! 584: going to the next-to-final state (yet to be made). */ ! 585: sp = first_shift; ! 586: ! 587: sp2 = (shifts *) xmalloc(sizeof(shifts) ! 588: + sp->nshifts * sizeof(short)); ! 589: sp2->nshifts = sp->nshifts + 1; ! 590: ! 591: /* Stick this shift into the vector at the proper place. */ ! 592: statep = first_state->next; ! 593: for (k = 0, i = 0; i < sp->nshifts; k++, i++) ! 594: { ! 595: if (statep->accessing_symbol > start_symbol && i == k) ! 596: sp2->shifts[k++] = nstates; ! 597: sp2->shifts[k] = sp->shifts[i]; ! 598: statep = statep->next; ! 599: } ! 600: if (i == k) ! 601: sp2->shifts[k++] = nstates; ! 602: ! 603: /* Patch sp2 into the chain of shifts ! 604: in place of sp, at the beginning. */ ! 605: sp2->next = sp->next; ! 606: first_shift = sp2; ! 607: if (last_shift == sp) ! 608: last_shift = sp2; ! 609: ! 610: FREE(sp); ! 611: ! 612: /* Create the next-to-final state, with shift to ! 613: what will be the final state. */ ! 614: insert_start_shift(); ! 615: } ! 616: } ! 617: else ! 618: { ! 619: /* The initial state didn't even have any shifts. ! 620: Give it one shift, to the next-to-final state. */ ! 621: sp = NEW(shifts); ! 622: sp->nshifts = 1; ! 623: sp->shifts[0] = nstates; ! 624: ! 625: /* Patch sp into the chain of shifts at the beginning. */ ! 626: sp->next = first_shift; ! 627: first_shift = sp; ! 628: ! 629: /* Create the next-to-final state, with shift to ! 630: what will be the final state. */ ! 631: insert_start_shift(); ! 632: } ! 633: } ! 634: else ! 635: { ! 636: /* There are no shifts for any state. ! 637: Make one shift, from the initial state to the next-to-final state. */ ! 638: ! 639: sp = NEW(shifts); ! 640: sp->nshifts = 1; ! 641: sp->shifts[0] = nstates; ! 642: ! 643: /* Initialize the chain of shifts with sp. */ ! 644: first_shift = sp; ! 645: last_shift = sp; ! 646: ! 647: /* Create the next-to-final state, with shift to ! 648: what will be the final state. */ ! 649: insert_start_shift(); ! 650: } ! 651: ! 652: /* Make the final state--the one that follows a shift from the ! 653: next-to-final state. ! 654: The symbol for that shift is 0 (end-of-file). */ ! 655: statep = (core *) xmalloc((unsigned) (sizeof(core) - sizeof(short))); ! 656: statep->number = nstates; ! 657: last_state->next = statep; ! 658: last_state = statep; ! 659: ! 660: /* Make the shift from the final state to the termination state. */ ! 661: sp = NEW(shifts); ! 662: sp->number = nstates++; ! 663: sp->nshifts = 1; ! 664: sp->shifts[0] = nstates; ! 665: last_shift->next = sp; ! 666: last_shift = sp; ! 667: ! 668: /* Note that the variable `final_state' refers to what we sometimes call ! 669: the termination state. */ ! 670: final_state = nstates; ! 671: ! 672: /* Make the termination state. */ ! 673: statep = (core *) xmalloc((unsigned) (sizeof(core) - sizeof(short))); ! 674: statep->number = nstates++; ! 675: last_state->next = statep; ! 676: last_state = statep; ! 677: } ! 678: ! 679: ! 680: /* subroutine of augment_automaton. ! 681: Create the next-to-final state, to which a shift has already been made in ! 682: the initial state. */ ! 683: void ! 684: insert_start_shift() ! 685: { ! 686: register core *statep; ! 687: register shifts *sp; ! 688: ! 689: statep = (core *) xmalloc((unsigned) (sizeof(core) - sizeof(short))); ! 690: statep->number = nstates; ! 691: statep->accessing_symbol = start_symbol; ! 692: ! 693: last_state->next = statep; ! 694: last_state = statep; ! 695: ! 696: /* Make a shift from this state to (what will be) the final state. */ ! 697: sp = NEW(shifts); ! 698: sp->number = nstates++; ! 699: sp->nshifts = 1; ! 700: sp->shifts[0] = nstates; ! 701: ! 702: last_shift->next = sp; ! 703: last_shift = sp; ! 704: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.