home *** CD-ROM | disk | FTP | other *** search
- /* $Id: spacetab.c,v 1.2 1999/11/04 14:02:23 shields Exp $ */
- /*
- This software is subject to the terms of the IBM Jikes Compiler
- License Agreement available at the following URL:
- http://www.ibm.com/research/jikes.
- Copyright (C) 1983, 1999, International Business Machines Corporation
- and others. All Rights Reserved.
- You must accept the terms of that agreement to use this software.
- */
- static char hostfile[] = __FILE__;
-
- #include <string.h>
- #include "common.h"
- #include "space.h"
- #include "header.h"
-
- static struct node **new_state_element_reduce_nodes;
-
- static long total_bytes,
- num_table_entries;
-
- static int top,
- empty_root,
- single_root,
- multi_root;
-
- static short *row_size,
- *frequency_symbol,
- *frequency_count;
-
- static BOOLEAN *shift_on_error_symbol;
-
- /****************************************************************************/
- /* REMAP_NON_TERMINALS: */
- /****************************************************************************/
- /* REMAP_NON_TERMINALS remaps the non-terminal symbols and states based on */
- /* frequency of entries. */
- /****************************************************************************/
- static void remap_non_terminals(void)
- {
- short *frequency_symbol,
- *frequency_count,
- *row_size;
-
- struct goto_header_type go_to;
-
- int i,
- state_no,
- symbol;
-
- /**********************************************************************/
- /* The variable FREQUENCY_SYMBOL is used to hold the non-terminals */
- /* in the grammar, and FREQUENCY_COUNT is used correspondingly to */
- /* hold the number of actions defined on each non-terminal. */
- /* ORDERED_STATE and ROW_SIZE are used in a similar fashion for states*/
- /**********************************************************************/
- frequency_symbol = Allocate_short_array(num_non_terminals);
- frequency_symbol -= (num_terminals + 1);
- frequency_count = Allocate_short_array(num_non_terminals);
- frequency_count -= (num_terminals + 1);
- row_size = Allocate_short_array(num_states + 1);
-
- for ALL_NON_TERMINALS(i)
- {
- frequency_symbol[i] = i;
- frequency_count[i] = 0;
- }
- for ALL_STATES(state_no)
- {
- ordered_state[state_no] = state_no;
- row_size[state_no] = 0;
- go_to = statset[state_no].go_to;
- for (i = 1; i <= go_to.size; i++)
- {
- row_size[state_no]++;
- symbol = GOTO_SYMBOL(go_to, i);
- frequency_count[symbol]++;
- }
- }
-
- /**********************************************************************/
- /* The non-terminals are sorted in descending order based on the */
- /* number of actions defined on then, and they are remapped based on */
- /* the new arrangement obtained by the sorting. */
- /**********************************************************************/
- sortdes(frequency_symbol, frequency_count,
- num_terminals + 1, num_symbols, num_states);
-
- for ALL_NON_TERMINALS(i)
- symbol_map[frequency_symbol[i]] = i;
-
- /**********************************************************************/
- /* All non-terminal entries in the state automaton are updated */
- /* accordingly. We further subtract NUM_TERMINALS from each */
- /* non-terminal to make them fall in the range [1..NUM_NON_TERMINLS] */
- /* instead of [NUM_TERMINALS+1..NUM_SYMBOLS]. */
- /**********************************************************************/
- for ALL_STATES(state_no)
- {
- go_to = statset[state_no].go_to;
- for (i = 1; i <= go_to.size; i++)
- GOTO_SYMBOL(go_to, i) =
- symbol_map[GOTO_SYMBOL(go_to, i)] - num_terminals;
- }
-
- /**********************************************************************/
- /* If Goto-Default was requested, we find out how many non-terminals */
- /* were eliminated as a result, and adjust the GOTO-DEFAULT map, */
- /* based on the new mapping of the non-terminals. */
- /**********************************************************************/
- if (goto_default_bit)
- {
- short *temp_goto_default;
-
- temp_goto_default = Allocate_short_array(num_non_terminals);
- temp_goto_default -= (num_terminals + 1);
-
- for (last_symbol = num_symbols;
- last_symbol > num_terminals; last_symbol--)
- if (frequency_count[last_symbol] != 0)
- break;
- last_symbol -= num_terminals;
- sprintf(msg_line, "Number of non-terminals eliminated: %d",
- num_non_terminals - last_symbol);
- PRNT(msg_line);
-
- /**************************************************************/
- /* Remap the GOTO-DEFAULT map. */
- /* to hold the original map. */
- /**************************************************************/
- for ALL_NON_TERMINALS(symbol)
- temp_goto_default[symbol_map[symbol]] = gotodef[symbol];
- gotodef += (num_terminals + 1);
- ffree(gotodef);
- gotodef = temp_goto_default;
- }
- else
- last_symbol = num_non_terminals;
-
- /**********************************************************************/
- /* The states are sorted in descending order based on the number of */
- /* actions defined on them, and they are remapped based on the new */
- /* arrangement obtained by the sorting. */
- /**********************************************************************/
- sortdes(ordered_state, row_size, 1, num_states, last_symbol);
-
- frequency_symbol += (num_terminals + 1);
- ffree(frequency_symbol);
- frequency_count += (num_terminals + 1);
- ffree(frequency_count);
- ffree(row_size);
-
- return;
- }
-
-
- /****************************************************************************/
- /* OVERLAP_NT_ROWS: */
- /****************************************************************************/
- /* We now overlap the non-terminal table, or more precisely, we compute the */
- /* starting position in a vector where each of its rows may be placed */
- /* without clobbering elements in another row. The starting positions are */
- /* stored in the vector STATE_INDEX. */
- /****************************************************************************/
- static void overlap_nt_rows(void)
- {
- struct goto_header_type go_to;
-
- int max_indx,
- indx,
- k,
- j,
- i,
- k_bytes,
- percentage,
- state_no,
- symbol;
-
- long num_bytes;
-
- num_table_entries = num_gotos + num_goto_reduces + num_states;
- increment_size = MAX((num_table_entries / 100 * increment),
- (last_symbol + 1));
- table_size = MIN((num_table_entries + increment_size), MAX_TABLE_SIZE);
-
- /*************************************************************************/
- /* Allocate space for table, and initlaize the AVAIL_POOL list. The */
- /* variable FIRST_INDEX keeps track of the first element in the doubly- */
- /* linked list, and LAST_ELEMENT keeps track of the last element in the */
- /* list. */
- /* The variable MAX_INDX is used to keep track of the maximum starting */
- /* position for a row that has been used. */
- /*************************************************************************/
- next = Allocate_int_array(table_size + 1);
- previous = Allocate_int_array(table_size + 1);
-
- first_index = 1;
- previous[first_index] = NIL;
- next[first_index] = first_index + 1;
- for (indx = 2; indx < (int) table_size; indx++)
- {
- next[indx] = indx + 1;
- previous[indx] = indx - 1;
- }
- last_index = table_size;
- previous[last_index] = last_index - 1;
- next[last_index] = NIL;
-
- max_indx = first_index;
-
- /*******************************************************************/
- /* We now iterate over all the states in their new sorted order as */
- /* indicated by the variable STATE_NO, and determine an "overlap" */
- /* position for them. */
- /*******************************************************************/
- for ALL_STATES(k)
- {
- state_no = ordered_state[k];
-
- /****************************************************************/
- /* INDX is set to the beginning of the list of available slots */
- /* and we try to determine if it might be a valid starting */
- /* position. If not, INDX is moved to the next element, and we */
- /* repeat the process until a valid position is found. */
- /****************************************************************/
- go_to = statset[state_no].go_to;
- indx = first_index;
-
- look_for_match_in_base_table:
- if (indx == NIL)
- indx = table_size + 1;
- if (indx + last_symbol > table_size)
- reallocate();
- for (i = 1; i <= go_to.size; i++)
- {
- if (next[indx + GOTO_SYMBOL(go_to, i)] == OMEGA)
- {
- indx = next[indx];
- goto look_for_match_in_base_table;
- }
- }
-
- /*****************************************************************/
- /* At this stage, a position(INDX), was found to overlay the row */
- /* in question. Remove elements associated with all positions */
- /* that will be taken by row from the doubly-linked list. */
- /* NOTE tha since SYMBOLs start at 1, the first index can never */
- /* be a candidate (==> I = INDX + SYMBOL) in this loop. */
- /*****************************************************************/
- for (j = 1; j <= go_to.size; j++)
- {
- symbol = GOTO_SYMBOL(go_to, j);
- i = indx + symbol;
- if (i == last_index)
- {
- last_index = previous[last_index];
- next[last_index] = NIL;
- }
- else
- {
- next[previous[i]] = next[i];
- previous[next[i]] = previous[i];
- }
- next[i] = OMEGA;
- }
-
- if (first_index == last_index)
- first_index = NIL;
- else if (indx == first_index)
- {
- first_index = next[first_index];
- previous[first_index] = NIL;
- }
- else if (indx == last_index)
- {
- last_index = previous[last_index];
- next[last_index] = NIL;
- }
- else
- {
- next[previous[indx]] = next[indx];
- previous[next[indx]] = previous[indx];
- }
- next[indx] = OMEGA;
- if (indx > max_indx)
- max_indx = indx;
- state_index[state_no] = indx;
- }
-
- if (goto_default_bit || nt_check_bit)
- check_size = max_indx + num_non_terminals;
- else
- check_size = 0;
-
- for (action_size = max_indx + last_symbol;
- action_size >= max_indx; action_size--)
- if (next[action_size] == OMEGA)
- break;
-
- accept_act = max_indx + num_rules + 1;
- error_act = accept_act + 1;
-
- printf("\n");
- if (goto_default_bit || nt_check_bit)
- {
- sprintf(msg_line,"Length of base Check Table: %d", check_size);
- PRNT(msg_line);
- }
-
- sprintf(msg_line,"Length of base Action Table: %ld", action_size);
- PRNT(msg_line);
-
- sprintf(msg_line,"Number of entries in base Action Table: %d",
- num_table_entries);
- PRNT(msg_line);
-
- percentage = ((action_size - num_table_entries) * 1000)
- / num_table_entries;
- sprintf(msg_line, "Percentage of increase: %d.%d%%",
- percentage / 10, percentage % 10);
- PRNT(msg_line);
-
- if (byte_bit)
- {
- num_bytes = 2 * action_size + check_size;
- if (goto_default_bit || nt_check_bit)
- {
- if (last_symbol > 255)
- num_bytes += check_size;
- }
- }
- else
- num_bytes = 2 * (action_size + check_size);
-
- if (goto_default_bit)
- num_bytes += ((long) 2 * num_non_terminals);
- total_bytes = num_bytes;
-
- k_bytes = (num_bytes / 1024) + 1;
-
- sprintf(msg_line,"Storage required for base Tables: %ld Bytes, %dK",
- num_bytes, k_bytes);
- PRNT(msg_line);
- num_bytes = (long) 4 * num_rules;
- if (byte_bit)
- {
- num_bytes -= num_rules;
- if (num_non_terminals < 256)
- num_bytes -= num_rules;
- }
- sprintf(msg_line, "Storage required for Rules: %ld Bytes", num_bytes);
- PRNT(msg_line);
-
- return;
- }
-
-
- /*********************************************************************/
- /* MERGE_SIMILAR_T_ROWS: */
- /*********************************************************************/
- /* We now try to merge states in the terminal table that are similar.*/
- /* Two states S1 and S2 are said to be similar if they contain the */
- /* same shift actions and they reduce to the same set of rules. In */
- /* addition, there must not exist a terminal symbol "t" such that: */
- /* REDUCE(S1, t) and REDUCE(S2, t) are defined, and */
- /* REDUCE(S1, t) ^= REDUCE(S2, t) */
- /*********************************************************************/
- static void merge_similar_t_rows(void)
- {
- struct shift_header_type sh;
- struct reduce_header_type red;
-
- short *table;
-
- int i,
- j,
- rule_no,
- state_no;
-
- unsigned long hash_address;
-
- struct node *q,
- *r,
- *tail,
- *reduce_root;
-
- table = Allocate_short_array(num_shift_maps + 1);
-
- empty_root = NIL;
- single_root = NIL;
- multi_root = NIL;
- top = 0;
-
- for (i = 1; i <= (int) max_la_state; i++)
- shift_on_error_symbol[i] = FALSE;
-
- for (i = 0; i <= num_shift_maps; i++)
- table[i] = NIL;
-
- /*********************************************************************/
- /* We now hash all the states into TABLE, based on their shift map */
- /* number. */
- /* The rules in the range of the REDUCE MAP are placed in sorted */
- /* order in a linear linked list headed by REDUCE_ROOT. */
- /*********************************************************************/
- for (state_no = 1; state_no <= (int) max_la_state; state_no++)
- {
- reduce_root = NULL;
- if (state_no > (int) num_states)
- red = lastats[state_no].reduce;
- else
- red = reduce[state_no];
-
- for (i = 1; i <= red.size; i++)
- {
- rule_no = REDUCE_RULE_NO(red, i);
-
- for (q = reduce_root; q != NULL; tail = q, q = q -> next)
- { /* Is it or not in REDUCE_ROOT list? */
- if (q -> value == rule_no)
- goto continue_traverse_reduce_map;
- if (q -> value > rule_no)
- break;
- }
-
- r = Allocate_node(); /* Add element to REDUCE_ROOT list */
- r -> value = rule_no;
- if (q == reduce_root)
- {
- r -> next = reduce_root;
- reduce_root = r;
- }
- else
- {
- r -> next = q;
- tail -> next = r;
- }
- continue_traverse_reduce_map:;
- }
-
- /*********************************************************************/
- /* We compute the HASH_ADDRESS, mark if the state has a shift */
- /* action on the ERROR symbol, and search the hash TABLE to see if a */
- /* state matching the description is already in there. */
- /*********************************************************************/
- if (state_no > (int) num_states)
- hash_address = lastats[state_no].shift_number;
- else
- {
- if (default_opt == 5)
- {
- sh = shift[statset[state_no].shift_number];
- for (j = 1; (j <= sh.size) &&
- (! shift_on_error_symbol[state_no]); j++)
- shift_on_error_symbol[state_no] =
- (SHIFT_SYMBOL(sh, j) == error_image);
- }
- hash_address = statset[state_no].shift_number;
- }
-
- for (i = table[hash_address]; i != NIL; i = new_state_element[i].link)
- {
- for (r = reduce_root, q = new_state_element_reduce_nodes[i];
- (r != NULL) && (q != NULL);
- r = r -> next, q = q -> next)
- {
- if (r -> value != q -> value)
- break;
- }
-
- if (r == q)
- break;
- }
-
- /*********************************************************************/
- /* If the state is a new state to be inserted in the table, we now */
- /* do so, and place it in the proper category based on its reduces, */
- /* In any case, the IMAGE field is updated, and so is the relevant */
- /* STATE_LIST element. */
- /* */
- /* If the state contains a shift action on the error symbol and also */
- /* contains reduce actions, we allocate a new element for it and */
- /* place it in the list headed by MULTI_ROOT. Such states are not */
- /* merged, because we do not take default reductions in them. */
- /*********************************************************************/
- if (shift_on_error_symbol[state_no] && (reduce_root != NULL))
- {
- top++;
- if (i == NIL)
- {
- new_state_element[top].link = table[hash_address];
- table[hash_address] = top;
- }
-
- new_state_element[top].thread = multi_root;
- multi_root = top;
-
- new_state_element[top].shift_number = hash_address;
- new_state_element_reduce_nodes[top] = reduce_root;
- state_list[state_no] = NIL;
- new_state_element[top].image = state_no;
- }
- else if (i == NIL)
- {
- top++;
- new_state_element[top].link = table[hash_address];
- table[hash_address] = top;
- if (reduce_root == NULL)
- {
- new_state_element[top].thread = empty_root;
- empty_root = top;
- }
- else if (reduce_root -> next == NULL)
- {
- new_state_element[top].thread = single_root;
- single_root = top;
- }
- else
- {
- new_state_element[top].thread = multi_root;
- multi_root = top;
- }
- new_state_element[top].shift_number = hash_address;
- new_state_element_reduce_nodes[top] = reduce_root;
- state_list[state_no] = NIL;
- new_state_element[top].image = state_no;
- }
- else
- {
- state_list[state_no] = new_state_element[i].image;
- new_state_element[i].image = state_no;
-
- for (r = reduce_root; r != NULL; tail = r, r = r -> next)
- ;
- if (reduce_root != NULL)
- free_nodes(reduce_root, tail);
- }
- }
-
- ffree(table);
-
- return;
- }
-
-
- /*********************************************************************/
- /* MERGE_SHIFT_DOMAINS: */
- /*********************************************************************/
- /* If shift-default actions are requested, the shift actions */
- /* associated with each state are factored out of the Action matrix */
- /* and all identical rows are merged. This merged matrix is used to */
- /* create a boolean vector that may be used to confirm whether or not*/
- /* there is a shift action in a given state S on a given symbol t. */
- /* If we can determine that there is a shift action on a pair (S, t) */
- /* we can apply shift default to the Shift actions just like we did */
- /* for the Goto actions. */
- /*********************************************************************/
- static void merge_shift_domains(void)
- {
- short *shift_domain_link,
- *ordered_shift,
- *terminal_list,
- *temp_shift_default;
-
- short shift_domain_table[SHIFT_TABLE_SIZE];
-
- struct shift_header_type sh;
- struct reduce_header_type red;
-
- BOOLEAN *shift_symbols;
-
- unsigned long hash_address;
-
- int i,
- j,
- indx,
- max_indx,
- k_bytes,
- old_table_size,
- k,
- percentage,
- shift_size,
- shift_no,
- symbol,
- state_no;
-
- long num_bytes;
-
- /*********************************************************************/
- /* Some of the rows in the shift action map have already been merged */
- /* by the merging of compatible states... We simply need to increase */
- /* the size of the granularity by merging these new terminal states */
- /* based only on their shift actions. */
- /* */
- /* The array SHIFT_DOMAIN_TABLE is used as the base for a hash table.*/
- /* Each submap represented by a row of the shift action map is hashed*/
- /* into this table by summing the terminal symbols in its domain. */
- /* The submap is then entered in the hash table and assigned a unique*/
- /* number if such a map was not already placed in the hash table. */
- /* Otherwise, the number assigned to the previous submap is also */
- /* associated with the new submap. */
- /* */
- /* The vector SHIFT_IMAGE is used to keep track of the unique number */
- /* associated with each unique shift submap. */
- /* The vector REAL_SHIFT_NUMBER is the inverse of SHIFT_IMAGE. It is */
- /* used to associate each unique number to its shift submap. */
- /* The integer NUM_TABLE_ENTRIES is used to count the number of */
- /* elements in the new merged shift map. */
- /* */
- /* The arrays ORDERED_SHIFT and ROW_SIZE are also initialized here. */
- /* They are used to sort the rows of the shift actions map later... */
- /*********************************************************************/
- shift_domain_link = Allocate_short_array(num_terminal_states + 1);
- ordered_shift = Allocate_short_array(num_shift_maps + 1);
- terminal_list = Allocate_short_array(num_terminals + 1);
- shift_image = Allocate_short_array(max_la_state + 1);
- real_shift_number = Allocate_short_array(num_shift_maps + 1);
- shift_symbols = Allocate_boolean_array(num_terminals + 1);
-
- shift_check_index = Allocate_int_array(num_shift_maps + 1);
-
- for (i = 0; i <= SHIFT_TABLE_UBOUND; i++)
- shift_domain_table[i] = NIL;
-
- num_table_entries = 0;
- shift_domain_count = 0;
-
- for (state_no = 1; state_no <= num_terminal_states; state_no++)
- {
- shift_no = new_state_element[state_no].shift_number;
- for (i = 1; i <=num_terminals; i++)
- shift_symbols[i] = FALSE;
-
- sh = shift[shift_no];
- shift_size = sh.size;
- hash_address = shift_size;
- for (i = 1; i <= shift_size; i++)
- {
- symbol = SHIFT_SYMBOL(sh, i);
- hash_address += symbol;
- shift_symbols[symbol] = TRUE;
- }
-
- hash_address %= SHIFT_TABLE_SIZE;
-
- for (i = shift_domain_table[hash_address];
- i != NIL; i = shift_domain_link[i])
- {
- sh = shift[new_state_element[i].shift_number];
- if (sh.size == shift_size)
- {
- for (j = 1; j <= shift_size; j++)
- if (! shift_symbols[SHIFT_SYMBOL(sh, j)])
- break;
- if (j > shift_size)
- {
- shift_image[state_no] = shift_image[i];
- goto continu;
- }
- }
- }
- shift_domain_link[state_no] = shift_domain_table[hash_address];
- shift_domain_table[hash_address] = state_no;
-
- shift_domain_count++;
- shift_image[state_no] = shift_domain_count;
-
- real_shift_number[shift_domain_count] = shift_no;
-
- ordered_shift[shift_domain_count] = shift_domain_count;
- row_size[shift_domain_count] = shift_size;
- num_table_entries += shift_size;
- continu:;
- }
-
- /*********************************************************************/
- /* Compute the frequencies, and remap the terminal symbols */
- /* accordingly. */
- /*********************************************************************/
- for ALL_TERMINALS(symbol)
- {
- frequency_symbol[symbol] = symbol;
- frequency_count[symbol] = 0;
- }
-
- for (i = 1; i <= shift_domain_count; i++)
- {
- shift_no = real_shift_number[i];
- sh = shift[shift_no];
- for (j = 1; j <= sh.size; j++)
- {
- symbol = SHIFT_SYMBOL(sh, j);
- frequency_count[symbol]++;
- }
- }
-
- sortdes(frequency_symbol, frequency_count, 1, num_terminals,
- shift_domain_count);
-
- for ALL_TERMINALS(symbol)
- symbol_map[frequency_symbol[symbol]] = symbol;
-
- symbol_map[DEFAULT_SYMBOL] = DEFAULT_SYMBOL;
- eoft_image = symbol_map[eoft_image];
- if (error_maps_bit)
- {
- error_image = symbol_map[error_image];
- eolt_image = symbol_map[eolt_image];
- }
-
- for (i = 1; i <= num_shift_maps; i++)
- {
- sh = shift[i];
- for (j = 1; j <= sh.size; j++)
- SHIFT_SYMBOL(sh, j) = symbol_map[SHIFT_SYMBOL(sh, j)];
- }
-
- for (state_no = 1; state_no <= num_terminal_states; state_no++)
- {
- red = new_state_element[state_no].reduce;
- for (i = 1; i <= red.size; i++)
- REDUCE_SYMBOL(red, i) = symbol_map[REDUCE_SYMBOL(red, i)];
- }
-
- /*********************************************************************/
- /* If ERROR_MAPS are requested, we also have to remap the original */
- /* REDUCE maps. */
- /*********************************************************************/
- if (error_maps_bit)
- {
- for ALL_STATES(state_no)
- {
- red = reduce[state_no];
- for (i = 1; i <= red.size; i++)
- REDUCE_SYMBOL(red, i) = symbol_map[REDUCE_SYMBOL(red, i)];
- }
- }
-
- /************************************************************/
- /* Remap the SHIFT_DEFAULT map. */
- /************************************************************/
- temp_shift_default = Allocate_short_array(num_terminals + 1);
- for ALL_TERMINALS(symbol)
- temp_shift_default[symbol_map[symbol]] = shiftdf[symbol];
- ffree(shiftdf);
- shiftdf = temp_shift_default;
-
- /*********************************************************************/
- /* We now compute the starting position for each Shift check row */
- /* as we did for the terminal states. The starting positions are */
- /* stored in the vector SHIFT_CHECK_INDEX. */
- /*********************************************************************/
- sortdes(ordered_shift, row_size, 1, shift_domain_count, num_terminals);
-
- increment_size = MAX((num_table_entries / 100 * increment),
- (num_terminals + 1));
- old_table_size = table_size;
- table_size = MIN((num_table_entries + increment_size), MAX_TABLE_SIZE);
- if ((int) table_size > old_table_size)
- {
- ffree(previous);
- ffree(next);
- previous = Allocate_int_array(table_size + 1);
- next = Allocate_int_array(table_size + 1);
- }
- else
- table_size = old_table_size;
-
- first_index = 1;
- previous[first_index] = NIL;
- next[first_index] = first_index + 1;
- for (indx = 2; indx < (int) table_size; indx++)
- {
- next[indx] = indx + 1;
- previous[indx] = indx - 1;
- }
- last_index = table_size;
- previous[last_index] = last_index - 1;
- next[last_index] = NIL;
- max_indx = first_index;
-
- /*********************************************************************/
- /* Look for a suitable index where to overlay the shift check row. */
- /*********************************************************************/
- for (k = 1; k <= shift_domain_count; k++)
- {
- shift_no = ordered_shift[k];
- sh = shift[real_shift_number[shift_no]];
- indx = first_index;
-
- look_for_match_in_sh_chk_tab:
- if (indx == NIL)
- indx = table_size + 1;
- if (indx + num_terminals > (int) table_size)
- reallocate();
- for (i = 1; i <= sh.size; i++)
- {
- symbol = SHIFT_SYMBOL(sh, i);
- if (next[indx + symbol] == OMEGA)
- {
- indx = next[indx];
- goto look_for_match_in_sh_chk_tab;
- }
- }
-
- /*********************************************************************/
- /* INDX marks the starting position for the row, remove all the */
- /* positions that are claimed by that shift check row. */
- /* If a position has the value 0, then it is the starting position */
- /* of a Shift row that was previously processed, and that element */
- /* has already been removed from the list of available positions. */
- /*********************************************************************/
- for (j = 1; j <= sh.size; j++)
- {
- symbol = SHIFT_SYMBOL(sh, j);
- i = indx + symbol;
- if (next[i] != 0)
- {
- if (i == last_index)
- {
- last_index = previous[last_index];
- next[last_index] = NIL;
- }
- else
- {
- next[previous[i]] = next[i];
- previous[next[i]] = previous[i];
- }
- }
- next[i] = OMEGA;
- }
-
- /*********************************************************************/
- /* We now remove the starting position itself from the list without */
- /* marking it as taken, since it can still be used for a shift check.*/
- /* MAX_INDX is updated if required. */
- /* SHIFT_CHECK_INDEX(SHIFT_NO) is properly set to INDX as the */
- /* starting position of STATE_NO. */
- /*********************************************************************/
- if (first_index == last_index)
- first_index = NIL;
- else if (indx == first_index)
- {
- first_index = next[first_index];
- previous[first_index] = NIL;
- }
- else if (indx == last_index)
- {
- last_index = previous[last_index];
- next[last_index] = NIL;
- }
- else
- {
- next[previous[indx]] = next[indx];
- previous[next[indx]] = previous[indx];
- }
- next[indx] = 0;
-
- if (indx > max_indx)
- max_indx = indx;
- shift_check_index[shift_no] = indx;
- }
-
- /*********************************************************************/
- /* Update all counts, and report statistics. */
- /*********************************************************************/
- shift_check_size = max_indx + num_terminals;
-
- printf("\n");
- sprintf(msg_line,"Length of Shift Check Table: %d",shift_check_size);
- PRNT(msg_line);
-
- sprintf(msg_line,"Number of entries in Shift Check Table: %d",
- num_table_entries);
- PRNT(msg_line);
-
- for (k = shift_check_size; k >= max_indx; k--)
- if (next[k] == OMEGA)
- break;
- percentage = (((long) k - num_table_entries) * 1000)
- / num_table_entries;
-
- sprintf(msg_line,"Percentage of increase: %d.%d%%",
- (percentage/10),(percentage % 10));
- PRNT(msg_line);
-
- if (byte_bit)
- {
- num_bytes = shift_check_size;
- if (num_terminals > 255)
- num_bytes +=shift_check_size;
- }
- else
- num_bytes = 2 * shift_check_size;
- num_bytes += 2 * (num_terminal_states + num_terminals);
-
- k_bytes = (num_bytes / 1024) + 1;
-
- sprintf(msg_line,
- "Storage required for Shift Check Table: %ld Bytes, %dK",
- num_bytes, k_bytes);
- PRNT(msg_line);
- total_bytes += num_bytes;
-
- ffree(ordered_shift);
- ffree(terminal_list);
- ffree(shift_symbols);
- ffree(shift_domain_link);
-
- return;
- }
-
-
- /*********************************************************************/
- /* OVERLAY_SIM_T_ROWS: */
- /*********************************************************************/
- /* By now, similar states have been grouped together, and placed in */
- /* one of three linear linked lists headed by the root pointers: */
- /* MULTI_ROOT, SINGLE_ROOT, and EMPTY_ROOT. */
- /* We iterate over each of these lists and construct new states out */
- /* of these groups of similar states when they are compatible. Then, */
- /* we remap the terminal symbols. */
- /*********************************************************************/
- static void overlay_sim_t_rows(void)
- {
- int j,
- k,
- i,
- rule_no,
- state_no,
- symbol,
- default_rule,
- state_subset_root,
- state_set_root,
- state_root,
- reduce_size,
- num_shifts_saved = 0,
- num_reductions_saved = 0,
- default_saves = 0;
-
- short *rule_count,
- *reduce_action;
-
- struct shift_header_type sh;
- struct reduce_header_type red;
- struct reduce_header_type new_red;
-
- struct node *q,
- *tail;
-
- rule_count = Allocate_short_array(num_rules + 1);
- reduce_action = Allocate_short_array(num_terminals + 1);
-
- /*********************************************************************/
- /* We first iterate over the groups of similar states in the */
- /* MULTI_ROOT list. These states have been grouped together, */
- /* because they have the same Shift map, and reduce to the same */
- /* rules, but we must check that they are fully compatible by making */
- /* sure that no two states contain reduction to a different rule on */
- /* the same symbol. */
- /* The idea is to take a state out of the group, and merge with */
- /* it as many other compatible states from the group as possible. */
- /* remaining states from the group that caused clashes are thrown */
- /* back into the MULTI_ROOT list as a new group of states. */
- /*********************************************************************/
- for (i = multi_root; i != NIL; i = new_state_element[i].thread)
- {
- for (q = new_state_element_reduce_nodes[i]; q != NULL; q = q -> next)
- {
- rule_count[q -> value] = 0;
- }
-
- /*********************************************************************/
- /* REDUCE_ACTION is used to keep track of reductions that are to be */
- /* applied on terminal symbols as the states are merged. We pick */
- /* out the first state (STATE_NO) from the group of states involved, */
- /* initialize REDUCE_ACTION with its reduce map, and count the number*/
- /* of reductions associated with each rule in that state. */
- /*********************************************************************/
- state_no = new_state_element[i].image;
- if (state_no > (int) num_states)
- red = lastats[state_no].reduce;
- else
- red = reduce[state_no];
-
- for ALL_TERMINALS(j)
- reduce_action[j] = OMEGA;
- for (j = 1; j <= red.size; j++)
- {
- rule_no = REDUCE_RULE_NO(red, j);
- reduce_action[REDUCE_SYMBOL(red, j)] = rule_no;
- rule_count[rule_no]++;
- }
-
- /*********************************************************************/
- /* STATE_SET_ROOT is used to traverse the rest of the list that form */
- /* the group of states being processed. STATE_SUBSET_ROOT is used */
- /* to construct the new list that will consist of all states in the */
- /* group that are compatible starting with the initial state. */
- /* STATE_ROOT is used to construct a list of all states in the group */
- /* that are not compatible with the initial state. */
- /*********************************************************************/
- state_set_root = state_list[state_no];
- state_subset_root = state_no;
- state_list[state_subset_root] = NIL;
- state_root = NIL;
-
- for (state_no = state_set_root;
- state_no != NIL; state_no = state_set_root)
- {
- state_set_root = state_list[state_set_root];
-
- /*********************************************************************/
- /* We traverse the reduce map of the state taken out from the group */
- /* and check to see if it is compatible with the subset being */
- /* constructed so far. */
- /*********************************************************************/
- if (state_no > (int) num_states)
- red = lastats[state_no].reduce;
- else
- red = reduce[state_no];
- for (j = 1; j <= red.size; j++)
- {
- symbol = REDUCE_SYMBOL(red, j);
- if (reduce_action[symbol] != OMEGA)
- {
- if (reduce_action[symbol] != REDUCE_RULE_NO(red, j))
- break;
- }
- }
-
- /*********************************************************************/
- /* If J > Q->REDUCE_ELEMENT.N then we traversed the whole reduce map,*/
- /* and all the reductions involved are compatible with the new state */
- /* being constructed. The state involved is added to the subset, the*/
- /* rule counts are updated, and the REDUCE_ACTIONS map is updated. */
- /* Otherwise, we add the state involved to the STATE_ROOT list */
- /* which will be thrown back in the MULTI_ROOT list. */
- /*********************************************************************/
- if (j > red.size)
- {
- state_list[state_no] = state_subset_root;
- state_subset_root = state_no;
- for (j = 1; j <= red.size; j++)
- {
- symbol = REDUCE_SYMBOL(red, j);
- if (reduce_action[symbol] == OMEGA)
- {
- rule_no = REDUCE_RULE_NO(red, j);
- if (rules[rule_no].lhs == accept_image)
- rule_no = 0;
- reduce_action[symbol] = rule_no;
- rule_count[rule_no]++;
- }
- else
- num_reductions_saved++;
- }
- }
- else
- {
- state_list[state_no] = state_root;
- state_root = state_no;
- }
- }
-
- /*********************************************************************/
- /* Figure out the best default rule candidate, and update */
- /* DEFAULT_SAVES. */
- /* Recall that all accept actions were changed into reduce actions */
- /* by rule 0. */
- /*********************************************************************/
- k = 0;
- reduce_size = 0;
- default_rule = error_act;
- for (q = new_state_element_reduce_nodes[i];
- q != NULL; tail = q, q = q -> next)
- {
- rule_no = q -> value;
- reduce_size += rule_count[rule_no];
- if ((rule_count[rule_no] > k) && (rule_no != 0)
- && ! shift_on_error_symbol[state_subset_root])
- {
- k = rule_count[rule_no];
- default_rule = rule_no;
- }
- }
- default_saves += k;
- reduce_size -= k;
-
- /*********************************************************************/
- /* If STATE_ROOT is not NIL then there are states in the group that */
- /* did not meet the compatibility test. Throw those states back in */
- /* front of MULTI_ROOT as a group. */
- /*********************************************************************/
- if (state_root != NIL)
- {
- top++;
- new_state_element[top].thread = new_state_element[i].thread;
- new_state_element[i].thread = top;
- if (state_root > (int) num_states)
- new_state_element[top].shift_number =
- lastats[state_root].shift_number;
- else
- new_state_element[top].shift_number =
- statset[state_root].shift_number;
- new_state_element_reduce_nodes[top] =
- new_state_element_reduce_nodes[i];
- new_state_element[top].image = state_root;
- }
- else
- free_nodes(new_state_element_reduce_nodes[i], tail);
-
- /*********************************************************************/
- /* Create Reduce map for the newly created terminal state. */
- /* We may assume that SYMBOL field of defaults is already set to */
- /* the DEFAULT_SYMBOL value. */
- /*********************************************************************/
- new_red = Allocate_reduce_map(reduce_size);
-
- REDUCE_SYMBOL(new_red, 0) = DEFAULT_SYMBOL;
- REDUCE_RULE_NO(new_red, 0) = default_rule;
- for ALL_TERMINALS(symbol)
- {
- if (reduce_action[symbol] != OMEGA)
- {
- if (reduce_action[symbol] != default_rule)
- {
- REDUCE_SYMBOL(new_red, reduce_size) = symbol;
- if (reduce_action[symbol] == 0)
- REDUCE_RULE_NO(new_red, reduce_size) = accept_act;
- else
- REDUCE_RULE_NO(new_red, reduce_size) =
- reduce_action[symbol];
- reduce_size--;
- }
- }
- }
- new_state_element[i].reduce = new_red;
- new_state_element[i].image = state_subset_root;
- }
-
- /*********************************************************************/
- /* We now process groups of states that have reductions to a single */
- /* rule. Those states are fully compatible, and the default is the */
- /* rule in question. */
- /* Any of the REDUCE_ELEMENT maps that belongs to a state in the */
- /* group of states being processed may be reused for the new merged */
- /* state. */
- /*********************************************************************/
- for (i = single_root; i != NIL; i = new_state_element[i].thread)
- {
- state_no = new_state_element[i].image;
- q = new_state_element_reduce_nodes[i];
- rule_no = q -> value;
- free_nodes(q, q);
- if (rules[rule_no].lhs == accept_image)
- {
- red = reduce[state_no];
- reduce_size = red.size;
-
- new_red = Allocate_reduce_map(reduce_size);
-
- REDUCE_SYMBOL(new_red, 0) = DEFAULT_SYMBOL;
- REDUCE_RULE_NO(new_red, 0) = error_act;
-
- for (j = 1; j <= reduce_size; j++)
- {
- REDUCE_SYMBOL(new_red, j) = REDUCE_SYMBOL(red, j);
- REDUCE_RULE_NO(new_red, j) = accept_act;
- }
- }
- else
- {
- for ALL_TERMINALS(j)
- reduce_action[j] = OMEGA;
-
- for (; state_no != NIL; state_no = state_list[state_no])
- {
- if (state_no > (int) num_states)
- red = lastats[state_no].reduce;
- else
- red = reduce[state_no];
- for (j = 1; j <= red.size; j++)
- {
- symbol = REDUCE_SYMBOL(red, j);
- if (reduce_action[symbol] == OMEGA)
- {
- reduce_action[symbol] = rule_no;
- default_saves++;
- }
- else
- num_reductions_saved++;
- }
- }
-
- new_red = Allocate_reduce_map(0);
-
- REDUCE_SYMBOL(new_red, 0) = DEFAULT_SYMBOL;
- REDUCE_RULE_NO(new_red, 0) = rule_no;
- }
- new_state_element[i].reduce = new_red;
- }
-
- /*********************************************************************/
- /* Groups of states that have no reductions are also compatible. */
- /* Their default is ERROR_ACTION. */
- /*********************************************************************/
- for (i = empty_root; i != NIL; i = new_state_element[i].thread)
- {
- state_no = new_state_element[i].image;
- if (state_no > (int) num_states)
- red = lastats[state_no].reduce;
- else
- red = reduce[state_no];
- REDUCE_SYMBOL(red, 0) = DEFAULT_SYMBOL;
- REDUCE_RULE_NO(red, 0) = error_act;
- new_state_element[i].reduce = red;
- }
-
- num_terminal_states = top;
-
- frequency_symbol = Allocate_short_array(num_terminals + 1);
- frequency_count = Allocate_short_array(num_terminals + 1);
- row_size = Allocate_short_array(max_la_state + 1);
-
- if (shift_default_bit)
- merge_shift_domains();
-
- /*********************************************************************/
- /* We now reorder the terminal states based on the number of actions */
- /* in them, and remap the terminal symbols if they were not already */
- /* remapped in the previous block for the SHIFT_CHECK vector. */
- /*********************************************************************/
- for ALL_TERMINALS(symbol)
- {
- frequency_symbol[symbol] = symbol;
- frequency_count[symbol] = 0;
- }
-
- for (i = 1; i <= num_terminal_states; i++)
- {
- ordered_state[i] = i;
- row_size[i] = 0;
- sh = shift[new_state_element[i].shift_number];
- for (j = 1; j <= sh.size; j++)
- {
- symbol = SHIFT_SYMBOL(sh, j);
- if ((! shift_default_bit) ||
- (SHIFT_ACTION(sh, j) != shiftdf[symbol]))
- {
- row_size[i]++;
- frequency_count[symbol]++;
- }
- }
-
- for (state_no = state_list[new_state_element[i].image];
- state_no != NIL; state_no = state_list[state_no])
- {
- num_shifts_saved += row_size[i];
- }
-
- /***********************************************/
- /* Note that the Default action is skipped !!! */
- /***********************************************/
- red = new_state_element[i].reduce;
- for (j = 1; j <= red.size; j++)
- {
- symbol = REDUCE_SYMBOL(red, j);
- row_size[i]++;
- frequency_count[symbol]++;
- }
- }
- sprintf(msg_line,
- "Number of unique terminal states: %d",
- num_terminal_states);
- PRNT(msg_line);
- sprintf(msg_line, "Number of Shift actions saved by merging: %d",
- num_shifts_saved);
- PRNT(msg_line);
- sprintf(msg_line, "Number of Reduce actions saved by merging: %d",
- num_reductions_saved);
- PRNT(msg_line);
- sprintf(msg_line, "Number of Reduce saved by default: %d",
- default_saves);
- PRNT(msg_line);
-
- sortdes(ordered_state, row_size, 1, num_terminal_states,
- num_terminals);
-
- if (! shift_default_bit)
- {
- sortdes(frequency_symbol, frequency_count, 1, num_terminals,
- num_terminal_states);
- for ALL_TERMINALS(symbol)
- symbol_map[frequency_symbol[symbol]] = symbol;
- symbol_map[DEFAULT_SYMBOL] = DEFAULT_SYMBOL;
- eoft_image = symbol_map[eoft_image];
- if (error_maps_bit)
- {
- error_image = symbol_map[error_image];
- eolt_image = symbol_map[eolt_image];
- }
- for (i = 1; i <= num_shift_maps; i++)
- {
- sh = shift[i];
- for (j = 1; j <= sh.size; j++)
- SHIFT_SYMBOL(sh, j) = symbol_map[SHIFT_SYMBOL(sh, j)];
- }
-
- for (state_no = 1; state_no <= num_terminal_states; state_no++)
- {
- red = new_state_element[state_no].reduce;
- for (i = 1; i <= red.size; i++)
- REDUCE_SYMBOL(red, i) = symbol_map[REDUCE_SYMBOL(red, i)];
- }
-
- /*********************************************************************/
- /* If ERROR_MAPS are requested, we also have to remap the original */
- /* REDUCE maps. */
- /*********************************************************************/
- if (error_maps_bit)
- {
- for ALL_STATES(state_no)
- {
- red = reduce[state_no];
- for (i = 1; i <= red.size; i++)
- REDUCE_SYMBOL(red, i) = symbol_map[REDUCE_SYMBOL(red, i)];
- }
- }
- }
- num_table_entries = num_shifts + num_shift_reduces + num_reductions
- - num_shifts_saved - num_reductions_saved
- - default_saves + num_terminal_states;
-
- ffree(rule_count);
- ffree(reduce_action);
- ffree(row_size);
- ffree(frequency_count);
- ffree(frequency_symbol);
- ffree(shift_on_error_symbol);
- ffree(new_state_element_reduce_nodes);
-
- return;
- }
-
-
- /*********************************************************************/
- /* OVERLAP_T_ROWS: */
- /*********************************************************************/
- /* We now compute the starting position for each terminal state just */
- /* as we did for the non-terminal states. */
- /* The starting positions are stored in the vector TERM_STATE_INDEX. */
- /*********************************************************************/
- static void overlap_t_rows(void)
- {
- struct shift_header_type sh;
- struct reduce_header_type red;
-
- short *terminal_list;
-
- int root_symbol,
- symbol,
- i,
- k,
- k_bytes,
- percentage,
- state_no,
- old_size,
- max_indx,
- indx;
-
- long num_bytes;
-
- terminal_list = Allocate_short_array(num_terminals + 1);
- term_state_index = Allocate_int_array(max_la_state + 1);
-
- increment_size = MAX((num_table_entries * increment / 100),
- (num_terminals + 1));
- old_size = table_size;
- table_size = MIN((num_table_entries + increment_size), MAX_TABLE_SIZE);
- if ((int) table_size > old_size)
- {
- ffree(previous);
- ffree(next);
- next = Allocate_int_array(table_size + 1);
- previous = Allocate_int_array(table_size + 1);
- }
- else
- table_size = old_size;
-
- first_index = 1;
- previous[first_index] = NIL;
- next[first_index] = first_index + 1;
- for (indx = 2; indx < (int) table_size; indx++)
- {
- next[indx] = indx + 1;
- previous[indx] = indx - 1;
- }
- last_index = table_size;
- previous[last_index] = last_index - 1;
- next[last_index] = NIL;
-
- max_indx = first_index;
-
- for (k = 1; k <= num_terminal_states; k++)
- {
- state_no = ordered_state[k];
- /*********************************************************************/
- /* For the terminal table, we are dealing with two lists, the SHIFT */
- /* list, and the REDUCE list. Those lists are merged together first */
- /* in TERMINAL_LIST. Since we have to iterate over the list twice, */
- /* this merging makes things easy. */
- /*********************************************************************/
- root_symbol = NIL;
- sh = shift[new_state_element[state_no].shift_number];
- for (i = 1; i <= sh.size; i++)
- {
- symbol = SHIFT_SYMBOL(sh, i);
- if (! shift_default_bit ||
- (SHIFT_ACTION(sh, i) != shiftdf[symbol]))
- {
- terminal_list[symbol] = root_symbol;
- root_symbol = symbol;
- }
- }
-
- red = new_state_element[state_no].reduce;
- for (i = 1; i <= red.size; i++)
- {
- terminal_list[REDUCE_SYMBOL(red, i)] = root_symbol;
- root_symbol = REDUCE_SYMBOL(red, i);
- }
-
- /*********************************************************************/
- /* Look for a suitable index where to overlay the state. */
- /*********************************************************************/
- indx = first_index;
-
- look_for_match_in_term_table:
- if (indx == NIL)
- indx = table_size + 1;
- if (indx + num_terminals > (int) table_size)
- reallocate();
- for (symbol = root_symbol;
- symbol != NIL; symbol = terminal_list[symbol])
- {
- if (next[indx + symbol] == OMEGA)
- {
- indx = next[indx];
- goto look_for_match_in_term_table;
- }
- }
-
- /*********************************************************************/
- /* INDX marks the starting position for the state, remove all the */
- /* positions that are claimed by terminal actions in the state. */
- /*********************************************************************/
- for (symbol = root_symbol;
- symbol != NIL; symbol = terminal_list[symbol])
- {
- i = indx + symbol;
- if (i == last_index)
- {
- last_index = previous[last_index];
- next[last_index] = NIL;
- }
- else
- {
- next[previous[i]] = next[i];
- previous[next[i]] = previous[i];
- }
- next[i] = OMEGA;
- }
-
- /*********************************************************************/
- /* We now remove the starting position itself from the list, and */
- /* mark it as taken(CHECK(INDX) = OMEGA) */
- /* MAX_INDX is updated if required. */
- /* TERM_STATE_INDEX(STATE_NO) is properly set to INDX as the starting*/
- /* position of STATE_NO. */
- /*********************************************************************/
- if (first_index == last_index)
- first_index = NIL;
- else if (indx == first_index)
- {
- first_index = next[first_index];
- previous[first_index] = NIL;
- }
- else if (indx == last_index)
- {
- last_index = previous[last_index];
- next[last_index] = NIL;
- }
- else
- {
- next[previous[indx]] = next[indx];
- previous[next[indx]] = previous[indx];
- }
-
- next[indx] = OMEGA;
-
- if (indx > max_indx)
- max_indx = indx;
- term_state_index[state_no] = indx;
- }
-
- /*********************************************************************/
- /* Update all counts, and report statistics. */
- /*********************************************************************/
- term_check_size = max_indx + num_terminals;
- for (term_action_size = max_indx + num_terminals;
- term_action_size >= max_indx; term_action_size--)
- if (next[term_action_size] == OMEGA)
- break;
-
- printf("\n");
- sprintf(msg_line, "Length of Terminal Check Table: %d",
- term_check_size);
- PRNT(msg_line);
-
- sprintf(msg_line, "Length of Terminal Action Table: %d",
- term_action_size);
- PRNT(msg_line);
-
- sprintf(msg_line, "Number of entries in Terminal Action Table: %d",
- num_table_entries);
- PRNT(msg_line);
-
- percentage = (((long)term_action_size - num_table_entries) * 1000)
- / num_table_entries;
-
- sprintf(msg_line, "Percentage of increase: %d.%d%%",
- (percentage / 10), (percentage % 10));
- PRNT(msg_line);
-
- if (byte_bit)
- {
- num_bytes = 2 * term_action_size + term_check_size;
- if (num_terminals > 255)
- num_bytes += term_check_size;
- }
- else
- num_bytes = 2 * (term_action_size + term_check_size);
-
- if (shift_default_bit)
- num_bytes += (2 * num_terminal_states);
-
- k_bytes = (num_bytes / 1024) + 1;
-
- sprintf(msg_line,
- "Storage required for Terminal Tables: %ld Bytes, %dK",
- num_bytes, k_bytes);
- PRNT(msg_line);
-
- total_bytes += num_bytes;
-
- /*********************************************************************/
- /* Report total number of storage used. */
- /*********************************************************************/
- k_bytes = (total_bytes / 1024) + 1;
- sprintf(msg_line,
- "Total storage required for Tables: %ld Bytes, %dK",
- total_bytes, k_bytes);
- PRNT(msg_line);
-
- /*********************************************************************/
- /* We now write out the tables to the SYSTAB file. */
- /*********************************************************************/
-
- table_size = MAX(check_size, term_check_size);
- table_size = MAX(table_size, shift_check_size);
- table_size = MAX(table_size, action_size);
- table_size = MAX(table_size, term_action_size);
-
- ffree(terminal_list);
- ffree(next);
- ffree(previous);
- }
-
-
- /*********************************************************************/
- /* PRINT_TABLES: */
- /*********************************************************************/
- /* We now write out the tables to the SYSTAB file. */
- /*********************************************************************/
- static void print_tables(void)
- {
- int *check,
- *action;
-
- int la_state_offset,
- i,
- j,
- k,
- indx,
- act,
- result_act,
- default_count = 0,
- goto_count = 0,
- goto_reduce_count = 0,
- reduce_count = 0,
- la_shift_count = 0,
- shift_count = 0,
- shift_reduce_count = 0,
- rule_no,
- symbol,
- state_no;
-
- char *tok;
-
- long offset;
-
- check = Allocate_int_array(table_size + 1);
- action = Allocate_int_array(table_size + 1);
-
- /******************************************************************/
- /* Prepare header card with proper information, and write it out. */
- /******************************************************************/
- offset = error_act;
- if (read_reduce_bit)
- offset += num_rules;
- la_state_offset = offset;
-
- if (offset > (MAX_TABLE_SIZE + 1))
- {
- sprintf(msg_line, "Table contains entries that are > "
- "%d; Processing stopped.", MAX_TABLE_SIZE + 1);
- PRNTERR(msg_line);
- exit(12);
- }
-
- output_buffer[0] = 'S';
- output_buffer[1] = (goto_default_bit ? '1' : '0');
- output_buffer[2] = (nt_check_bit ? '1' : '0');
- output_buffer[3] = (read_reduce_bit ? '1' : '0');
- output_buffer[4] = (single_productions_bit ? '1' : '0');
- output_buffer[5] = (shift_default_bit ? '1' : '0');
- output_buffer[6] = (rules[1].lhs == accept_image ? '1' : '0');
- /* are there more than 1 start symbols? */
- output_buffer[7] = (error_maps_bit ? '1' : '0');
- output_buffer[8] = (byte_bit && last_symbol <= 255 ? '1' : '0');
- output_buffer[9] = escape;
-
- output_ptr = output_buffer + 10;
- field(num_terminals, 5);
- field(num_non_terminals, 5);
- field(num_rules, 5);
- field(num_states, 5);
- field(check_size, 5);
- field(action_size, 5);
- field(term_check_size, 5);
- field(term_action_size, 5);
- field(state_index[1] + num_rules, 5);
- field(eoft_image, 5);
- field(accept_act, 5);
- field(error_act, 5);
- field(la_state_offset, 5);
- field(lalr_level, 5);
- *output_ptr++ = '\n';
-
- /*********************************************************/
- /* We write the terminal symbols map. */
- /*********************************************************/
- for ALL_TERMINALS(symbol)
- {
- int len;
-
- tok = RETRIEVE_STRING(symbol);
- if (tok[0] == '\n') /* we're dealing with special symbol? */
- tok[0] = escape; /* replace initial marker with escape. */
- len = strlen(tok);
- field(symbol_map[symbol], 4);
- field(len, 4);
- if (len <= 64)
- strcpy(output_ptr, tok);
- else
- {
- memcpy(output_ptr, tok, 64);
- output_ptr += 64;
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- tok += 64;
-
- for (len = strlen(tok); len > 72; len = strlen(tok))
- {
- memcpy(output_ptr, tok, 72);
- output_ptr += 72;
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- tok += 72;
- }
- memcpy(output_ptr, tok, len);
- }
- output_ptr += len;
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- /*********************************************************/
- /* We write the non-terminal symbols map. */
- /*********************************************************/
- for ALL_NON_TERMINALS(symbol)
- {
- int len;
-
- tok = RETRIEVE_STRING(symbol);
- if (tok[0] == '\n') /* we're dealing with special symbol? */
- tok[0] = escape; /* replace initial marker with escape. */
- len = strlen(tok);
- field(symbol_map[symbol]-num_terminals, 4);
- field(len, 4);
- if (len <= 64)
- strcpy(output_ptr, tok);
- else
- {
- memcpy(output_ptr, tok, 64);
- output_ptr += 64;
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- tok += 64;
-
- for (len = strlen(tok); len > 72; len = strlen(tok))
- {
- memcpy(output_ptr, tok, 72);
- output_ptr += 72;
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- tok += 72;
- }
- memcpy(output_ptr, tok, len);
- }
- output_ptr += len;
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- /*********************************************************/
- /* Initialize TABLES with default actions. */
- /*********************************************************/
- for (i = 1; i <= check_size; i++)
- check[i] = DEFAULT_SYMBOL;
-
- for (i = 1; i <= (int) action_size; i++)
- action[i] = error_act;
-
- /********************************************************************/
- /* Update the default non-terminal action of each state with the */
- /* appropriate corresponding terminal state starting index. */
- /********************************************************************/
- for (i = 1; i <= num_terminal_states; i++)
- {
- indx = term_state_index[i];
- state_no = new_state_element[i].image;
-
- /*********************************************************************/
- /* Update the action link between the non-terminal and terminal */
- /* tables. If error-maps are requested, an indirect linking is made */
- /* as follows: */
- /* Each non-terminal row identifies its original state number, and */
- /* a new vector START_TERMINAL_STATE indexable by state numbers */
- /* identifies the starting point of each state in the terminal table.*/
- /*********************************************************************/
- if (state_no <= (int) num_states)
- {
- for (; state_no != NIL; state_no = state_list[state_no])
- {
- action[state_index[state_no]] = indx;
- }
- }
- else
- {
- for (; state_no != NIL; state_no = state_list[state_no])
- {
- act = la_state_offset + indx;
- state_index[state_no] = act;
- }
- }
- }
-
- /*********************************************************************/
- /* Now update the non-terminal tables with the non-terminal actions.*/
- /*********************************************************************/
- for ALL_STATES(state_no)
- {
- struct goto_header_type go_to;
-
- indx = state_index[state_no];
- go_to = statset[state_no].go_to;
- for (j = 1; j <= go_to.size; j++)
- {
- symbol = GOTO_SYMBOL(go_to, j);
- i = indx + symbol;
- if (goto_default_bit || nt_check_bit)
- check[i] = symbol;
- act = GOTO_ACTION(go_to, j);
- if (act > 0)
- {
- action[i] = state_index[act] + num_rules;
- goto_count++;
- }
- else
- {
- action[i] = -act;
- goto_reduce_count++;
- }
- }
- }
-
- /*********************************************************************/
- /* Write size of right hand side of rules followed by CHECK table. */
- /*********************************************************************/
- k = 0;
- for (i = 1; i <= num_rules; i++)
- {
- field(RHS_SIZE(i), 4);
- k++;
- if (k == 18)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
-
- for (i = 1; i <= check_size; i++)
- {
- field(check[i], 4);
- k++;
- if (k == 18)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
-
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- /*********************************************************************/
- /* Write left hand side symbol of rules followed by ACTION table. */
- /*********************************************************************/
- k = 0;
- for (i = 1; i <= num_rules; i++)
- {
- field(symbol_map[rules[i].lhs] - num_terminals, 6);
- k++;
- if (k == 12)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
-
- for (i = 1; i <= (int) action_size; i++)
- {
- field(action[i], 6);
- k++;
- if (k == 12)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
-
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- /********************************************************************/
- /* Initialize the terminal tables,and update with terminal actions. */
- /********************************************************************/
- for (i = 1; i <= term_check_size; i++)
- check[i] = DEFAULT_SYMBOL;
-
- for (i = 1; i <= term_action_size; i++)
- action[i] = error_act;
-
- for (state_no = 1; state_no <= num_terminal_states; state_no++)
- {
- struct shift_header_type sh;
- struct reduce_header_type red;
-
- indx = term_state_index[state_no];
- sh = shift[new_state_element[state_no].shift_number];
- for (j = 1; j <= sh.size; j++)
- {
- symbol = SHIFT_SYMBOL(sh, j);
- act = SHIFT_ACTION(sh, j);
- if ((! shift_default_bit) || (act != shiftdf[symbol]))
- {
- i = indx + symbol;
- check[i] = symbol;
-
- if (act > (int) num_states)
- {
- result_act = state_index[act];
- la_shift_count++;
- }
- else if (act > 0)
- {
- result_act = state_index[act] + num_rules;
- shift_count++;
- }
- else
- {
- result_act = -act + error_act;
- shift_reduce_count++;
- }
-
- if (result_act > (MAX_TABLE_SIZE + 1))
- {
- sprintf(msg_line,
- "Table contains look-ahead shift entry that is >"
- " %d; Processing stopped.", MAX_TABLE_SIZE + 1);
- PRNTERR(msg_line);
- return;
- }
-
- action[i] = result_act;
- }
- }
-
- red = new_state_element[state_no].reduce;
- for (j = 1; j <= red.size; j++)
- {
- symbol = REDUCE_SYMBOL(red, j);
- rule_no = REDUCE_RULE_NO(red, j);
- i = indx + symbol;
- check[i] = symbol;
- action[i] = rule_no;
- reduce_count++;
- }
-
- rule_no = REDUCE_RULE_NO(red, 0);
- if (rule_no != error_act)
- default_count++;
-
- check[indx] = DEFAULT_SYMBOL;
- if (shift_default_bit)
- action[indx] = state_no;
- else
- action[indx] = rule_no;
- }
-
- PRNT("\n\nActions in Compressed Tables:");
- sprintf(msg_line," Number of Shifts: %d",shift_count);
- PRNT(msg_line);
-
- sprintf(msg_line," Number of Shift/Reduces: %d",shift_reduce_count);
- PRNT(msg_line);
-
- if (max_la_state > num_states)
- {
- sprintf(msg_line,
- " Number of Look-Ahead Shifts: %d",
- la_shift_count);
- PRNT(msg_line);
- }
-
- sprintf(msg_line," Number of Gotos: %d",goto_count);
- PRNT(msg_line);
-
- sprintf(msg_line," Number of Goto/Reduces: %d",goto_reduce_count);
- PRNT(msg_line);
-
- sprintf(msg_line," Number of Reduces: %d",reduce_count);
- PRNT(msg_line);
-
- sprintf(msg_line," Number of Defaults: %d",default_count);
- PRNT(msg_line);
-
- /********************************************************************/
- /* Write Terminal Check Table. */
- /********************************************************************/
- k = 0;
- for (i = 1; i <= term_check_size; i++)
- {
- field(check[i], 4);
- k++;
- if (k == 18)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
-
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- /********************************************************************/
- /* Write Terminal Action Table. */
- /********************************************************************/
- k = 0;
- for (i = 1; i <= term_action_size; i++)
- {
- field(action[i], 6);
- k++;
- if (k == 12)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
-
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- /********************************************************************/
- /* If GOTO_DEFAULT is requested, we print out the GOTODEF vector. */
- /********************************************************************/
- if (goto_default_bit)
- {
- k = 0;
- for ALL_NON_TERMINALS(symbol)
- {
- act = gotodef[symbol];
- if (act < 0)
- result_act = -act;
- else if (act == 0)
- result_act = error_act;
- else
- result_act = state_index[act] + num_rules;
-
- field(result_act, 6);
- k++;
- if (k == 12)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
-
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
- }
-
- /*********************************************************************/
- /* If SHIFT_DEFAULT is requested, we print out the Default Reduce */
- /* map, the Shift State map, the Shift Check vector, and the SHIFTDF */
- /* vector. */
- /*********************************************************************/
- if (shift_default_bit)
- {
- /* Print out header */
- field(num_terminal_states, 5);
- field(shift_check_size, 5);
- *output_ptr++ = '\n';
-
- k = 0;
- for (state_no = 1; state_no <= num_terminal_states; state_no++)
- {
- struct reduce_header_type red;
-
- red = new_state_element[state_no].reduce;
- field(REDUCE_RULE_NO(red, 0), 4);
- k++;
- if (k == 18)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- /*************************************************************/
- /* First, check whether or not maximum value in SHIFT_STATE */
- /* table exceeds 9999. If so, stop. Otherwise, write out */
- /* SHIFT_STATE table. */
- /*************************************************************/
- if ((shift_check_size - num_terminals) > 9999)
- {
- PRNTERR("SHIFT_STATE map contains > 9999 elements");
- return;
- }
-
- k = 0;
- for (state_no = 1; state_no <= num_terminal_states; state_no++)
- {
- field(shift_check_index[shift_image[state_no]], 4);
- k++;
- if (k == 18)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- /*********************************************************************/
- /* Set the Check vector with the symbols in the domain of the shift */
- /* maps. */
- /*********************************************************************/
- for (i = 1; i <= shift_check_size; i++)
- check[i] = DEFAULT_SYMBOL;
-
- for (i = 1; i <= shift_domain_count; i++)
- {
- struct shift_header_type sh;
-
- indx = shift_check_index[i];
- sh = shift[real_shift_number[i]];
- for (j = 1; j <= sh.size; j++)
- {
- symbol = SHIFT_SYMBOL(sh, j);
- check[indx + symbol] = symbol;
- }
- }
-
- k = 0;
- for (i = 1; i <= shift_check_size; i++)
- {
- field(check[i], 4);
- k++;
- if (k == 18)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
-
- k = 0;
- for ALL_TERMINALS(symbol)
- {
- act = shiftdf[symbol];
- if (act < 0)
- result_act = -act + error_act;
- else if (act == 0)
- result_act = error_act;
- else if (act > (int) num_states)
- result_act = state_index[act];
- else
- result_act = state_index[act] + num_rules;
-
- if (result_act > (MAX_TABLE_SIZE + 1))
- {
- sprintf(msg_line,
- "Table contains look-ahead shift entry that is >"
- " %d; Processing stopped.", MAX_TABLE_SIZE + 1);
- PRNTERR(msg_line);
- return;
- }
-
- field(result_act, 6);
- k++;
- if (k == 12)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- k = 0;
- }
- }
- if (k != 0)
- {
- *output_ptr++ = '\n';
- BUFFER_CHECK(systab);
- }
- }
-
- /*********************************************************************/
- /* We first sort the new state numbers. A bucket sort technique */
- /* is used using the ACTION vector as a base to simulate the */
- /* buckets. NOTE: the iteration over the buckets is done backward */
- /* because we also construct a list of the original state numbers */
- /* that reflects the permutation of the new state numbers. */
- /* During the backward iteration, we construct the list as a stack. */
- /*********************************************************************/
- if (error_maps_bit || states_bit)
- {
- int max_indx;
-
- max_indx = accept_act - num_rules - 1;
- for (i = 1; i <= max_indx; i++)
- action[i] = OMEGA;
- for ALL_STATES(state_no)
- action[state_index[state_no]] = state_no;
-
- j = num_states + 1;
- for (i = max_indx; i >= 1; i--)
- {
- state_no = action[i];
- if (state_no != OMEGA)
- {
- j--;
- ordered_state[j] = i + num_rules;
- state_list[j] = state_no;
- }
- }
- }
-
- ffree(check);
- ffree(action);
-
- if (error_maps_bit)
- process_error_maps();
-
- fwrite(output_buffer, sizeof(char),
- output_ptr - &output_buffer[0], systab);
-
- return;
- }
-
-
- /*********************************************************************/
- /* CMPRSPA: */
- /*********************************************************************/
- void cmprspa(void)
- {
- state_index = Allocate_int_array(max_la_state + 1);
-
- ordered_state = Allocate_short_array(max_la_state + 1);
- symbol_map = Allocate_short_array(num_symbols + 1);
- state_list = Allocate_short_array(max_la_state + 1);
- shift_on_error_symbol = Allocate_boolean_array(max_la_state + 1);
- new_state_element = (struct new_state_type *)
- calloc(max_la_state + 1,
- sizeof(struct new_state_type));
- if (new_state_element == NULL)
- nospace(__FILE__, __LINE__);
-
- new_state_element_reduce_nodes = (struct node **)
- calloc(max_la_state + 1,
- sizeof(struct node *));
- if (new_state_element_reduce_nodes == NULL)
- nospace(__FILE__, __LINE__);
-
- remap_non_terminals();
- overlap_nt_rows();
- merge_similar_t_rows();
- overlay_sim_t_rows();
- overlap_t_rows();
- if (c_bit || cpp_bit || java_bit)
- print_space_parser();
- else
- print_tables();
-
- return;
- }
-