]>
git.saurik.com Git - bison.git/blob - src/LR0.c
   1 /* Generate the nondeterministic finite state machine for bison, 
   2    Copyright 1984, 1986, 1989, 2000 Free Software Foundation, Inc. 
   4    This file is part of Bison, the GNU Compiler Compiler. 
   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) 
  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. 
  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, Inc., 59 Temple Place - Suite 330, 
  19    Boston, MA 02111-1307, USA.  */ 
  22 /* See comments in state.h for the data structures that represent it. 
  23    The entry point is generate_states.  */ 
  35 core 
*first_state 
= NULL
; 
  36 shifts 
*first_shift 
= NULL
; 
  37 reductions 
*first_reduction 
= NULL
; 
  39 static core 
*this_state 
= NULL
; 
  40 static core 
*last_state 
= NULL
; 
  41 static shifts 
*last_shift 
= NULL
; 
  42 static reductions 
*last_reduction 
= NULL
; 
  45 static short *shift_symbol 
= NULL
; 
  47 static short *redset 
= NULL
; 
  48 static short *shiftset 
= NULL
; 
  50 static short **kernel_base 
= NULL
; 
  51 static short **kernel_end 
= NULL
; 
  52 static short *kernel_items 
= NULL
; 
  54 /* hash table for states, to recognize equivalent ones.  */ 
  56 #define STATE_TABLE_SIZE        1009 
  57 static core 
**state_table 
= NULL
; 
  61 allocate_itemsets (void) 
  67   short *symbol_count 
= NULL
; 
  70   symbol_count 
= XCALLOC (short, nsyms
); 
  79           symbol_count
[symbol
]++; 
  84   /* See comments before new_itemsets.  All the vectors of items 
  85      live inside KERNEL_ITEMS.  The number of active items after 
  86      some symbol cannot be more than the number of times that symbol 
  87      appears as an item, which is symbol_count[symbol]. 
  88      We allocate that much space for each symbol.  */ 
  90   kernel_base 
= XCALLOC (short *, nsyms
); 
  92     kernel_items 
= XCALLOC (short, count
); 
  95   for (i 
= 0; i 
< nsyms
; i
++) 
  97       kernel_base
[i
] = kernel_items 
+ count
; 
  98       count 
+= symbol_count
[i
]; 
 101   shift_symbol 
= symbol_count
; 
 102   kernel_end 
= XCALLOC (short *, nsyms
); 
 107 allocate_storage (void) 
 109   allocate_itemsets (); 
 111   shiftset 
= XCALLOC (short, nsyms
); 
 112   redset 
= XCALLOC (short, nrules 
+ 1); 
 113   state_table 
= XCALLOC (core 
*, STATE_TABLE_SIZE
); 
 120   XFREE (shift_symbol
); 
 125   XFREE (kernel_items
); 
 132 /*----------------------------------------------------------------. 
 133 | Find which symbols can be shifted in the current state, and for | 
 134 | each one record which items would be active after that shift.   | 
 135 | Uses the contents of itemset.                                   | 
 137 | shift_symbol is set to a vector of the symbols that can be      | 
 138 | shifted.  For each symbol in the grammar, kernel_base[symbol]   | 
 139 | points to a vector of item numbers activated if that symbol is  | 
 140 | shifted, and kernel_end[symbol] points after the end of that    | 
 142 `----------------------------------------------------------------*/ 
 154   fprintf (stderr
, "Entering new_itemsets\n"); 
 157   for (i 
= 0; i 
< nsyms
; i
++) 
 158     kernel_end
[i
] = NULL
; 
 164   while (isp 
< itemsetend
) 
 170           ksp 
= kernel_end
[symbol
]; 
 174               shift_symbol
[shiftcount
++] = symbol
; 
 175               ksp 
= kernel_base
[symbol
]; 
 179           kernel_end
[symbol
] = ksp
; 
 183   nshifts 
= shiftcount
; 
 188 /*-----------------------------------------------------------------. 
 189 | Subroutine of get_state.  Create a new state for those items, if | 
 191 `-----------------------------------------------------------------*/ 
 194 new_state (int symbol
) 
 203   fprintf (stderr
, "Entering new_state, symbol = %d\n", symbol
); 
 206   if (nstates 
>= MAXSHORT
) 
 207     fatal (_("too many states (max %d)"), MAXSHORT
); 
 209   isp1 
= kernel_base
[symbol
]; 
 210   iend 
= kernel_end
[symbol
]; 
 214     (core 
*) xcalloc ((unsigned) (sizeof (core
) + (n 
- 1) * sizeof (short)), 1); 
 215   p
->accessing_symbol 
= symbol
; 
 223   last_state
->next 
= p
; 
 232 /*--------------------------------------------------------------. 
 233 | Find the state number for the state we would get to (from the | 
 234 | current state) by shifting symbol.  Create a new state if no  | 
 235 | equivalent one exists already.  Used by append_states.         | 
 236 `--------------------------------------------------------------*/ 
 239 get_state (int symbol
) 
 251   fprintf (stderr
, "Entering get_state, symbol = %d\n", symbol
); 
 254   isp1 
= kernel_base
[symbol
]; 
 255   iend 
= kernel_end
[symbol
]; 
 258   /* add up the target state's active item numbers to get a hash key */ 
 263   key 
= key 
% STATE_TABLE_SIZE
; 
 265   sp 
= state_table
[key
]; 
 275               isp1 
= kernel_base
[symbol
]; 
 278               while (found 
&& isp1 
< iend
) 
 280                   if (*isp1
++ != *isp2
++) 
 291               else              /* bucket exhausted and no match */ 
 293                   sp 
= sp
->link 
= new_state (symbol
); 
 299   else                          /* bucket is empty */ 
 301       state_table
[key
] = sp 
= new_state (symbol
); 
 307 /*------------------------------------------------------------------. 
 308 | Use the information computed by new_itemsets to find the state    | 
 309 | numbers reached by each shift transition from the current state.  | 
 311 | shiftset is set up as a vector of state numbers of those states.  | 
 312 `------------------------------------------------------------------*/ 
 322   fprintf (stderr
, "Entering append_states\n"); 
 325   /* first sort shift_symbol into increasing order */ 
 327   for (i 
= 1; i 
< nshifts
; i
++) 
 329       symbol 
= shift_symbol
[i
]; 
 331       while (j 
> 0 && shift_symbol
[j 
- 1] > symbol
) 
 333           shift_symbol
[j
] = shift_symbol
[j 
- 1]; 
 336       shift_symbol
[j
] = symbol
; 
 339   for (i 
= 0; i 
< nshifts
; i
++) 
 341       symbol 
= shift_symbol
[i
]; 
 342       shiftset
[i
] = get_state (symbol
); 
 352   p 
= (core 
*) xcalloc ((unsigned) (sizeof (core
) - sizeof (short)), 1); 
 353   first_state 
= last_state 
= this_state 
= p
; 
 366   p 
= (shifts 
*) xcalloc ((unsigned) (sizeof (shifts
) + 
 367                                       (nshifts 
- 1) * sizeof (short)), 1); 
 369   p
->number 
= this_state
->number
; 
 370   p
->nshifts 
= nshifts
; 
 374   send 
= shiftset 
+ nshifts
; 
 381       last_shift
->next 
= p
; 
 392 /*------------------------------------------------------------------. 
 393 | Subroutine of augment_automaton.  Create the next-to-final state, | 
 394 | to which a shift has already been made in the initial state.      | 
 395 `------------------------------------------------------------------*/ 
 398 insert_start_shift (void) 
 403   statep 
= (core 
*) xcalloc ((unsigned) (sizeof (core
) - sizeof (short)), 1); 
 404   statep
->number 
= nstates
; 
 405   statep
->accessing_symbol 
= start_symbol
; 
 407   last_state
->next 
= statep
; 
 410   /* Make a shift from this state to (what will be) the final state.  */ 
 411   sp 
= XCALLOC (shifts
, 1); 
 412   sp
->number 
= nstates
++; 
 414   sp
->shifts
[0] = nstates
; 
 416   last_shift
->next 
= sp
; 
 421 /*------------------------------------------------------------------. 
 422 | Make sure that the initial state has a shift that accepts the     | 
 423 | grammar's start symbol and goes to the next-to-final state, which | 
 424 | has a shift going to the final state, which has a shift to the    | 
 425 | termination state.  Create such states and shifts if they don't   | 
 426 | happen to exist already.                                          | 
 427 `------------------------------------------------------------------*/ 
 430 augment_automaton (void) 
 446           statep 
= first_state
->next
; 
 448           /* The states reached by shifts from first_state are numbered 1...K. 
 449              Look for one reached by start_symbol.  */ 
 450           while (statep
->accessing_symbol 
< start_symbol
 
 451                  && statep
->number 
< k
) 
 452             statep 
= statep
->next
; 
 454           if (statep
->accessing_symbol 
== start_symbol
) 
 456               /* We already have a next-to-final state. 
 457                  Make sure it has a shift to what will be the final state.  */ 
 460               while (sp 
&& sp
->number 
< k
) 
 466               if (sp 
&& sp
->number 
== k
) 
 468                   sp2 
= (shifts 
*) xcalloc ((unsigned) (sizeof (shifts
) 
 473                   sp2
->nshifts 
= sp
->nshifts 
+ 1; 
 474                   sp2
->shifts
[0] = nstates
; 
 475                   for (i 
= sp
->nshifts
; i 
> 0; i
--) 
 476                     sp2
->shifts
[i
] = sp
->shifts
[i 
- 1]; 
 478                   /* Patch sp2 into the chain of shifts in place of sp, 
 480                   sp2
->next 
= sp
->next
; 
 482                   if (sp 
== last_shift
) 
 488                   sp2 
= XCALLOC (shifts
, 1); 
 491                   sp2
->shifts
[0] = nstates
; 
 493                   /* Patch sp2 into the chain of shifts between sp1 and sp.  */ 
 502               /* There is no next-to-final state as yet.  */ 
 503               /* Add one more shift in first_shift, 
 504                  going to the next-to-final state (yet to be made).  */ 
 507               sp2 
= (shifts 
*) xcalloc (sizeof (shifts
) 
 508                                         + sp
->nshifts 
* sizeof (short), 1); 
 509               sp2
->nshifts 
= sp
->nshifts 
+ 1; 
 511               /* Stick this shift into the vector at the proper place.  */ 
 512               statep 
= first_state
->next
; 
 513               for (k 
= 0, i 
= 0; i 
< sp
->nshifts
; k
++, i
++) 
 515                   if (statep
->accessing_symbol 
> start_symbol 
&& i 
== k
) 
 516                     sp2
->shifts
[k
++] = nstates
; 
 517                   sp2
->shifts
[k
] = sp
->shifts
[i
]; 
 518                   statep 
= statep
->next
; 
 521                 sp2
->shifts
[k
++] = nstates
; 
 523               /* Patch sp2 into the chain of shifts 
 524                  in place of sp, at the beginning.  */ 
 525               sp2
->next 
= sp
->next
; 
 527               if (last_shift 
== sp
) 
 532               /* Create the next-to-final state, with shift to 
 533                  what will be the final state.  */ 
 534               insert_start_shift (); 
 539           /* The initial state didn't even have any shifts. 
 540              Give it one shift, to the next-to-final state.  */ 
 541           sp 
= XCALLOC (shifts
, 1); 
 543           sp
->shifts
[0] = nstates
; 
 545           /* Patch sp into the chain of shifts at the beginning.  */ 
 546           sp
->next 
= first_shift
; 
 549           /* Create the next-to-final state, with shift to 
 550              what will be the final state.  */ 
 551           insert_start_shift (); 
 556       /* There are no shifts for any state. 
 557          Make one shift, from the initial state to the next-to-final state.  */ 
 559       sp 
= XCALLOC (shifts
, 1); 
 561       sp
->shifts
[0] = nstates
; 
 563       /* Initialize the chain of shifts with sp.  */ 
 567       /* Create the next-to-final state, with shift to 
 568          what will be the final state.  */ 
 569       insert_start_shift (); 
 572   /* Make the final state--the one that follows a shift from the 
 574      The symbol for that shift is 0 (end-of-file).  */ 
 575   statep 
= (core 
*) xcalloc ((unsigned) (sizeof (core
) - sizeof (short)), 1); 
 576   statep
->number 
= nstates
; 
 577   last_state
->next 
= statep
; 
 580   /* Make the shift from the final state to the termination state.  */ 
 581   sp 
= XCALLOC (shifts
, 1); 
 582   sp
->number 
= nstates
++; 
 584   sp
->shifts
[0] = nstates
; 
 585   last_shift
->next 
= sp
; 
 588   /* Note that the variable `final_state' refers to what we sometimes call 
 589      the termination state.  */ 
 590   final_state 
= nstates
; 
 592   /* Make the termination state.  */ 
 593   statep 
= (core 
*) xcalloc ((unsigned) (sizeof (core
) - sizeof (short)), 1); 
 594   statep
->number 
= nstates
++; 
 595   last_state
->next 
= statep
; 
 600 /*----------------------------------------------------------------. 
 601 | Find which rules can be used for reduction transitions from the | 
 602 | current state and make a reductions structure for the state to  | 
 603 | record their rule numbers.                                      | 
 604 `----------------------------------------------------------------*/ 
 607 save_reductions (void) 
 618   /* Find and count the active items that represent ends of rules. */ 
 621   for (isp 
= itemset
; isp 
< itemsetend
; isp
++) 
 625         redset
[count
++] = -item
; 
 628   /* Make a reductions structure and copy the data into it.  */ 
 632       p 
= (reductions 
*) xcalloc ((unsigned) (sizeof (reductions
) + 
 633                                               (count 
- 1) * sizeof (short)), 1); 
 635       p
->number 
= this_state
->number
; 
 642       for (/* nothing */; rp1 
< rend
; ++rp1
, ++rp2
) 
 647           last_reduction
->next 
= p
; 
 659 /*-------------------------------------------------------------------. 
 660 | Compute the nondeterministic finite state machine (see state.h for | 
 661 | details) from the grammar.                                         | 
 662 `-------------------------------------------------------------------*/ 
 665 generate_states (void) 
 668   new_closure (nitems
); 
 673       /* Set up ruleset and itemset for the transitions out of this 
 674          state.  ruleset gets a 1 bit for each rule that could reduce 
 675          now.  itemset gets a vector of all the items that could be 
 677       closure (this_state
->items
, this_state
->nitems
); 
 678       /* record the reductions allowed out of this state */ 
 680       /* find the itemsets of the states that shifts can reach */ 
 682       /* find or create the core structures for those states */ 
 685       /* create the shifts structures for the shifts to those states, 
 686          now that the state numbers transitioning to are known */ 
 690       /* states are queued when they are created; process them all */ 
 691       this_state 
= this_state
->next
; 
 694   /* discard various storage */ 
 698   /* set up initial and final states as parser wants them */ 
 699   augment_automaton ();