void destroy_itemset( struct itemset * this_itemset ) { int i; char * key; struct list * key_list = new_list(); list_keys_in_hash( this_itemset->items, key_list, "" ); for ( i = 0; i < key_list->next_index; i++ ) { key = listlookup( key_list, i ); struct item * data = hashlookup( this_itemset->items, key )->data; free( data ); } destroy_key_list( key_list ); destroy_hash( this_itemset->items ); key_list = new_list(); list_keys_in_hash( this_itemset->ready_for, key_list, "" ); for ( i = 0; i < key_list->next_index; i++ ) { key = listlookup( key_list, i ); struct list * ready_items = hashlookup( this_itemset->ready_for, key )->data; destroy_list( ready_items ); } destroy_key_list( key_list ); destroy_hash( this_itemset->ready_for ); destroy_list( this_itemset->complete ); free( this_itemset ); return; }
void fill_FOLLOW() { FOLLOW = new_hash(); char * symbol; char * next_symbol; char * lhs; int i; int j; struct list * production; int change; struct hash * symbol_followers; struct list * key_list = new_list(); list_keys_in_hash( IS_TERMINAL, key_list, "" ); for ( i = 0; i < key_list->next_index; i++ ) { symbol = listlookup( key_list, i ); if ( ( (int *) hashlookup( IS_TERMINAL, symbol )->data ) == &FALSE ) { symbol_followers = new_hash(); add_to_hash( FOLLOW, symbol, (void *) symbol_followers ); } } destroy_key_list( key_list ); change = 1; while ( change ) { change = 0; for ( i = 0; i < NUM_PRODUCTIONS; i++ ) { production = GRAMMAR[i].production; lhs = listlookup( production, 0 ); for ( j = 1; j < production->next_index; j++ ) { // Loop RHS symbols. symbol = listlookup( production, j ); if ( ( (int *) hashlookup( IS_TERMINAL, symbol )->data ) == &TRUE ) { // No FOLLOW for terminals. continue; } symbol_followers = hashlookup( FOLLOW, symbol )->data; if ( j + 1 < production->next_index ) { // There is an adjacent symbol. next_symbol = listlookup( production, j + 1 ); struct hash * next_symbol_firsts = hashlookup( FIRST, next_symbol )->data; // Everything in FIRST{next_symbol} should be in FOLLOW{symbol}. change = expand_hash( symbol_followers, next_symbol_firsts ) || change; continue; } else { // Last symbol in production is nonterminal. struct hash * lhs_followers = hashlookup( FOLLOW, lhs )->data; // Everything in FOLLOW{lhs} should be in FOLLOW{symbol}. change = expand_hash( symbol_followers, lhs_followers ) || change; continue; } } } } }
int main() { struct hash * frequency_hash = new_hash(); char char_string[2] = { ' ', '\0' }; int number_of_characters = 0; int i; char c; while ( ( c = getchar() ) != EOF ) { if ( c == '\n' ) { continue; } char_string[0] = c; struct hash * looked_up = hashlookup( frequency_hash, char_string ); struct index_frequency * data; if ( !looked_up ) { data = malloc( sizeof( struct index_frequency ) ); data->index = number_of_characters; data->frequency = 0; looked_up = add_to_hash( frequency_hash, char_string, (void *) data ); } data = looked_up->data; int frequency = data->frequency; data->frequency = frequency + 1; number_of_characters++; } struct list * key_list = new_list(); list_keys_in_hash( frequency_hash, key_list, "" ); int min_index = number_of_characters + 1; char * min_key = ""; int min_frequency = number_of_characters + 1; for ( i = 0; i < key_list->next_index; i++ ) { char * key = listlookup( key_list, i ); struct index_frequency * data; data = hashlookup( frequency_hash, key )->data; if ( data->frequency < min_frequency ) { min_index = data->index; min_frequency = data->frequency; min_key = key; } else if ( data->frequency == min_frequency ) { if ( data->index < min_index ) { min_index = data->index; min_key = key; } } } printf( "The first non-repeated character is: \n%s\n", min_key ); }
int expand_hash( struct hash * target, struct hash * source ) { int i; char * symbol; void * value; int change = 0; struct list * key_list = new_list(); list_keys_in_hash( source, key_list, "" ); for ( i = 0; i < key_list->next_index; i++ ) { symbol = listlookup( key_list, i ); struct hash * looked_up = hashlookup( target, symbol ); if ( ! looked_up ) { value = hashlookup( source, symbol )->data; add_to_hash( target, symbol, value ); // Use the same value or pointer. change = 1; } } return change; }
void analyze_productions() { GSIZE = NUM_PRODUCTIONS; int i; int j; struct list * production; struct list * productions_for_symbol; char * symbol; if ( ! IS_TERMINAL ) { IS_TERMINAL = new_hash(); } if ( ! PRODUCTIONS_FOR ) { PRODUCTIONS_FOR = new_hash(); } for ( i = 0; i < NUM_PRODUCTIONS; i++ ) { production = GRAMMAR[i].production; if ( production->next_index > GSIZE ) { GSIZE = production->next_index; } for ( j = 0; j < production->next_index; j++ ) { symbol = listlookup( production, j ); struct hash * looked_up = hashlookup( IS_TERMINAL, symbol ); if ( ! looked_up ) { // Assume each new symbol is a terminal. add_to_hash( IS_TERMINAL, symbol, (void *) &TRUE ); } if ( j == 0 ) { // Symbols on the left side of a productions are nonterminal. add_to_hash( IS_TERMINAL, symbol, (void *) &FALSE ); looked_up = hashlookup( PRODUCTIONS_FOR, symbol ); if ( ! looked_up ) { productions_for_symbol = new_list(); add_to_hash( PRODUCTIONS_FOR, symbol, (void *) productions_for_symbol ); } else { productions_for_symbol = looked_up->data; } append_to_list( productions_for_symbol, (void *) (long int) i ); } } } }
void fill_FIRST() { FIRST = new_hash(); int i; int j; char * symbol; char * lhs; char * left_corner; struct list * key_list = new_list(); list_keys_in_hash( IS_TERMINAL, key_list, "" ); for ( i = 0; i < key_list->next_index; i++ ) { symbol = listlookup( key_list, i ); struct hash * symbol_firsts = new_hash(); if ( ( (int *) hashlookup( IS_TERMINAL, symbol )->data ) == &TRUE ) { // Terminals self-derive. add_to_hash( symbol_firsts, symbol, (void *) (long int) 1 ); } add_to_hash( FIRST, symbol, (void *) symbol_firsts ); } destroy_key_list( key_list ); int change = 1; while ( change ) { change = 0; for ( i = 0; i < NUM_PRODUCTIONS; i++ ) { struct list * production = GRAMMAR[i].production; lhs = listlookup( production, 0 ); left_corner = listlookup( production, 1 ); key_list = new_list(); list_keys_in_hash( hashlookup( FIRST, left_corner )->data, key_list, "" ); for ( j = 0; j < key_list->next_index; j++ ) { // Go through all the firsts of left_corner. symbol = listlookup( key_list, j ); struct hash * lhs_firsts = hashlookup( FIRST, lhs )->data; struct hash * looked_up = hashlookup( lhs_firsts, symbol ); if ( ! looked_up ) { add_to_hash( lhs_firsts, symbol, (void *) &TRUE ); // Add them to firsts of lhs. change = 1; } } destroy_key_list( key_list ); } } }
struct hash * copy_shallow_hash( struct hash * original ) { struct hash * copy = new_hash(); struct list * key_list = new_list(); list_keys_in_hash( original, key_list, "" ); char * key = NULL; int i = key_list->next_index; while ( i-- ) { key = listlookup( key_list, i ); add_to_hash( copy, key, hashlookup( original, key ) ); } destroy_key_list( key_list ); return copy; }
void install_complete_transitions( int i, struct itemset * current_itemset, struct parser_generator * self ) { struct list * table = self->TABLE; struct list * complete_items = current_itemset->complete; char * lhs; struct item * complete_item; struct list * complete_production; int j; int k; struct hash * table_row = listlookup( self->TABLE, i ); for ( j = 0; j < complete_items->next_index; j++ ) { complete_item = listlookup( complete_items, j ); int prod_num = complete_item->prod_num; complete_production = GRAMMAR[prod_num].production; lhs = listlookup( complete_production, 0 ); // Loop all terminals which can follow this lhs. struct list * key_list = new_list(); list_keys_in_hash( hashlookup( FOLLOW, lhs )->data, key_list, "" ); for ( k = 0; k < key_list->next_index; k++ ) { struct list * trans_list; char * follower = listlookup( key_list, k ); // Add a reduce transition on each follower token. struct hash * looked_up = hashlookup( table_row, follower ); if ( ! looked_up ) { trans_list = new_list(); add_to_hash( table_row, follower, (void *) trans_list ); } else { trans_list = looked_up->data; } struct transition * reduce_transition = new_transition(); reduce_transition->action = "reduce"; reduce_transition->arg = prod_num; append_to_list( trans_list, reduce_transition ); } destroy_key_list( key_list ); } }
void install_incomplete_transitions( int i, struct itemset * current_itemset, struct parser_generator * self ) { struct list * itemsets = self->itemsets; struct hash * itemsets_by_key = self->itemsets_by_key; struct hash * ready_for = current_itemset->ready_for; // Prepare to loop through the keys of current_itemset->ready_for. struct list * key_list = new_list(); list_keys_in_hash( ready_for, key_list, "" ); int j; int k; for ( j = 0; j < key_list->next_index; j++ ) { // Loop ready-for symbols. char * symbol = listlookup( key_list, j ); struct list * ready_for_symbol = hashlookup( ready_for, symbol )->data; struct itemset * proposed_itemset = new_itemset(); for ( k = 0; k < ready_for_symbol->next_index; k++ ) { // Loop symbol items. struct item * ready_item = listlookup( ready_for_symbol, k ); struct item * proposed_item = new_item(); proposed_item->prod_num = ready_item->prod_num; proposed_item->dot = ready_item->dot + 1; char * proposed_item_key = create_item_key( proposed_item ); add_to_hash( proposed_itemset->items, proposed_item_key, (void *) proposed_item ); free( proposed_item_key ); // It's now in the hash. } // End symbol items loop. char * proposed_itemset_key = create_closure_key( proposed_itemset ); struct hash * looked_up = hashlookup( itemsets_by_key, proposed_itemset_key ); if ( ! looked_up ) { append_to_list( itemsets, (void *) proposed_itemset ); int state_num = itemsets->next_index - 1; looked_up = add_to_hash( itemsets_by_key, proposed_itemset_key, (void *) (long int) state_num ); } else { destroy_itemset( proposed_itemset ); } int destination = (long int) looked_up->data; install_incomplete_transition( i, symbol, destination, self ); } // End ready-for symbols loop. return; }
static boolean tablemoveverb (hdltreenode hparam1, tyvaluerecord *v) { /* table.move (address, tableaddress): boolean; move the indicated table entry to the given table 9/30/91 dmb: use hashassign, not hashinsert, so existing item is overwritten 10/3/91 dmb: use new fllanghashassignprotect flag to override protection 5.0a15 dmb: on success, return address of moved value 5.1.4 dmb: generate errors if item doesn't exist */ hdlhashtable ht1, ht2; bigstring bs; tyvaluerecord val; boolean fl; hdlhashnode hnode; if (!getvarparam (hparam1, 1, &ht1, bs)) return (false); flnextparamislast = true; if (!gettablevalue (hparam1, 2, &ht2)) return (false); pushhashtable (ht1); fl = hashlookup (bs, &val, &hnode); if (fl) hashdelete (bs, false, false); /*don't toss the value*/ pophashtable (); if (!fl) { langparamerror (unknownidentifiererror, bs); return (false); } if (!hashtableassign (ht2, bs, val)) return (false); return (setaddressvalue (ht2, bs, v)); } /*tablemoveverb*/
boolean claymovefile (const tybrowserspec *fs, const tybrowserspec *fsto) { tyvaluerecord val; hdlhashtable hdest; boolean fl; hdlhashnode hnode; if (!claygetdirid (fsto, &hdest)) { langerrormessage (BIGSTRING ("\x1b" "destination must be a table")); return (false); } opstartinternalchange (); pushhashtable ((*fs).parID); fl = hashlookup ((*fs).name, &val, &hnode); if (fl) { // if ((*fs).parID == agentstable) hashdelete ((*fs).name, false, false); /*don't toss the value*/ } pophashtable (); if (fl) { fl = hashtableassign (hdest, (*fs).name, val); /* if (fl && (hdest == agentstable) { hashtablelookupnode (hdest, (*fs).name, &hnode); scriptinstallagent (hnode); } */ } opendinternalchange (); return (true); } /*claymovefile*/
void fill_TRIE( struct hash * token_types ) { int i; char * path; char * accepting_type; TRIE = new_trie_node(); struct list * key_list = new_list(); list_keys_in_hash( token_types, key_list, "" ); for ( i = 0; i < key_list->next_index; i++ ) { path = listlookup( key_list, i ); accepting_type = hashlookup( token_types, path )->data; add_to_trie( TRIE, path, accepting_type ); } destroy_key_list( key_list ); return; }
void install_incomplete_transition( int i, char * symbol, int destination, struct parser_generator * self ) { struct hash * table_row = listlookup( self->TABLE, i ); struct hash * goto_row = listlookup( self->GOTO, i ); struct list * trans_list; struct hash * looked_up; if ( ( (int *) hashlookup( IS_TERMINAL, symbol )->data ) == &TRUE ) { // Transitions on terminals go in TABLE. looked_up = hashlookup( table_row, symbol ); if ( ! looked_up ) { trans_list = new_list(); add_to_hash( table_row, symbol, (void *) trans_list ); } else { trans_list = looked_up->data; } struct transition * terminal_transition = new_transition(); terminal_transition->action = "shift"; terminal_transition->arg = destination; if ( ! strcmp( symbol, "end" ) ) { terminal_transition->action = "accept"; } append_to_list( trans_list, (void *) terminal_transition ); } else { // Transitions on nonterminals go in GOTO. looked_up = hashlookup( goto_row, symbol ); if ( ! looked_up ) { trans_list = new_list(); add_to_hash( goto_row, symbol, (void *) trans_list ); } else { trans_list = looked_up->data; } append_to_list( trans_list, (void *) (long int) destination ); } }
static boolean tablemoveandrenameverb (hdltreenode hparam1, tyvaluerecord *v) { /* 5.0a15 dmb: on success, return address of moved value 5.1.4 dmb: generate errors if item doesn't exist */ hdlhashtable ht1, ht2; bigstring bs1, bs2; tyvaluerecord val; boolean fl; hdlhashnode hnode; if (!getvarparam (hparam1, 1, &ht1, bs1)) return (false); flnextparamislast = true; if (!getvarparam (hparam1, 2, &ht2, bs2)) return (false); pushhashtable (ht1); fl = hashlookup (bs1, &val, &hnode); if (fl) hashdelete (bs1, false, false); /*don't toss the value*/ pophashtable (); if (!fl) { langparamerror (unknownidentifiererror, bs1); return (false); } if (!hashtableassign (ht2, bs2, val)) return (false); return (setaddressvalue (ht2, bs2, v)); } /*tablemoveandrenameverb*/
//================================================================= // Negamax Function. //================================================================= static s32bit negamax(s32bit depth_remaining, s32bit whos_turn_t, s32bit alpha, s32bit beta) { Move movelist[MAXMOVES], best; s32bit whos_turn = whos_turn_t & PLAYER_MASK; s32bit opponent = whos_turn_t ^ PLAYER_MASK; s32bit value; s32bit init_alpha = alpha, init_beta = beta; u32bit start_nodes = g_num_nodes; Move forcefirst; s32bit who_wins_value; s32bit stage = 0, state = 0, true_count, i = 0, num_moves = 1; #ifdef DYNAMIC_POSITION_VALUES s32bit dyn_set; #endif // increment a couple of stats g_num_nodes++; #ifdef COLLECT_STATS stat_nodes[starting_depth - depth_remaining]++; #endif // if no depth remaining stop search. if( depth_remaining <= 0 ){ s32bit a = 0, b = 0; if( (a = does_next_player_win(whos_turn, 0)) > 0 ) { // current player wins. return 5000; } if( (b = does_who_just_moved_win(opponent, 0)) >= 0 ) { // opponent wins. return -5000; } return a - b; } //------------------------------------------ // Can we determine a winner yet (simple check). //------------------------------------------ // does current player win if(g_info_totals[whos_turn].safe > g_info_totals[opponent].real){ #ifdef COLLECT_STATS cut1++; #endif return 5000; } // does opponent win if(g_info_totals[opponent].safe >= g_info_totals[whos_turn].real){ #ifdef COLLECT_STATS cut2++; #endif return -5000; } //------------------------------------------ // check transposition table //------------------------------------------ forcefirst.array_index = -1; if(hashlookup(&value, &alpha, &beta, depth_remaining, &forcefirst, whos_turn)) return value; // since we aren't using iter deep not interested in forcefirst. forcefirst.array_index = -1; //------------------------------------------ // Can we determine a winner yet (look harder). //------------------------------------------ // does current player win if( (who_wins_value = does_next_player_win(whos_turn, 0)) > 0 ) { #ifdef DEBUG_NEGAMAX if(random() % 1000000 == -1){ does_next_player_win(whos_turn, 1); print_board(whos_turn); } #endif #ifdef COLLECT_STATS cut3++; #endif return 5000; } // does opponent win if( (who_wins_value = does_who_just_moved_win(opponent, 0)) >= 0 ) { #ifdef DEBUG_NEGAMAX if(who_wins_value < 3){ // && random() % 500 == -1){ does_who_just_moved_win(opponent, 1); // print_board(opponent); } #endif #ifdef COLLECT_STATS cut4++; #endif return -5000; } #if 0 { s32bit num; num = move_generator_stage1(movelist, whos_turn); num = move_generator_stage2(movelist, num, whos_turn); if(move_generator(movelist, whos_turn) != num) fatal_error(1, "NOPE\n"); } #endif //------------------------------------------ // Generate child nodes and examine them. //------------------------------------------ // initialize a few variables. (some of them don't really need to be.) stage = state = true_count = i = 0; num_moves = 1; #ifdef TWO_STAGE_GENERATION true_count = move_generator_stage1(movelist, whos_turn); if(true_count == 0){ true_count = move_generator_stage2(movelist, 0, whos_turn); stage = 1; if(true_count == 0) fatal_error(1, "Should always have a move.\n"); } #else true_count = move_generator(movelist, whos_turn); stage = 1; if(true_count == 0) fatal_error(1, "Should always have a move.\n"); #endif // score all the moves and move the best to the front. score_and_get_first(movelist, true_count, whos_turn, forcefirst); best = movelist[0]; // need to sort moves and generate more moves in certain situations. while(state < 3){ if(state == 0) { state = 1; } else if(state == 1){ sort_moves(movelist, 1, true_count); num_moves = true_count; if(stage == 0) state = 2; else state = 3; } else { num_moves = move_generator_stage2(movelist, num_moves, whos_turn); state = 3; } // Iterate through all the moves. for(; i < num_moves; i++){ // A few statistics g_move_number[starting_depth - depth_remaining] = i; #ifdef RECORD_MOVES g_move_player[starting_depth - depth_remaining] = whos_turn; g_move_position[starting_depth - depth_remaining] = movelist[i]; #endif // make move. g_empty_squares -= 2; toggle_move(movelist[i], whos_turn); toggle_hash_code (g_keyinfo[whos_turn][movelist[i].array_index][movelist[i].mask_index]); #ifdef DYNAMIC_POSITION_VALUES dyn_set = set_move_value(movelist[i], whos_turn); #endif // recurse. value = -negamax(depth_remaining-1,whos_turn^PLAYER_MASK, -beta, -alpha); // undo move. g_empty_squares += 2; toggle_move(movelist[i], whos_turn); toggle_hash_code (g_keyinfo[whos_turn][movelist[i].array_index][movelist[i].mask_index]); #ifdef DYNAMIC_POSITION_VALUES if(dyn_set != 0) unset_move_value(movelist[i], whos_turn); #endif #if 0 if(starting_depth - depth_remaining == 8) { s32bit g; printf("goof:"); for(g = 0; g < 8; g++){ printf(" :%c:%d(%d,%d)", (g_move_player[g] == VERTICAL) ? 'V' : 'H', g_move_number[g], g_move_position[g].array_index - 1, g_move_position[g].mask_index - 1); } printf("\n"); } #endif // If this is a cutoff, break. if(value >= beta){ alpha = value; best = movelist[i]; #ifdef COLLECT_STATS stat_cutoffs[starting_depth - depth_remaining]++; if(i < 5) stat_nth_try[starting_depth - depth_remaining][i]++; else stat_nth_try[starting_depth - depth_remaining][5]++; #endif break; } // If the current value is greater than alpha, increase alpha. if(value > alpha) { alpha = value; best = movelist[i]; } } // If we have broken out of previous FOR loop make sure we break out // of this loop as well. if(value >= beta) break; } // save the position in the hashtable hashstore(alpha, init_alpha, init_beta, (g_num_nodes - start_nodes) >> 5, depth_remaining, best, whos_turn); return alpha; }
int main(int argc, char *argv[]) { numb i,j,c; obj o; int repeatObj,sumRO,sumCollisions; repeatObj=sumRO=sumCollisions=0; if (argc != 4) { puts("Usage: hashexample N m k"); puts(" where N is the number of objects to hash"); puts(" and m is the length of the objects in bytes"); puts(" and k is the number of times objects are expected"); return 0; } N = atol(argv[1]); m = (size_t) atol(argv[2]); m = (m + sizeof(numb) - 1) / sizeof(numb); m *= sizeof(numb); k = atol(argv[3]); inithash(N); if(rank==0){ /* printf("%s:initialise hash N=%d N/MPI_TASKS=%d\n",argv[0],N,N/size); */ printf("%s:initialise hash N=%d N/MPI_TASKS=%d\n",argv[0],(int)N,(int)(N/size)); } /* for(i=0;i<nobj;i++){ hashtab[i]=rank*nobj+i; } MPI_Win_fence(0,win); c=rank*100; status=-1; printf("rank[%d] testVar %d\n",rank,c); status=MPI_Get(&c,1,MPI_INT,1,3,1,MPI_INT,win); MPI_Win_fence(0,win); printf("Get? rank[%d] testVar %d status %d\n",rank,c,status); */ for (i = 1; i <= k; i++) { resetvalue(); for (j = 0; j < N/size; j++) { o = newobj(); c = hashlookup(o); if (c > 1) free(o); if (c != i) { repeatObj++; } } } /* write out stuff */ /* for(j=0;j<nobj;j++){ if(hashtab[j]){ printf("rank[%d] j %d #j %d *j %d collisions %d\n",rank, ((rank*nobj)+j),hashtab[j], hashtab[j],collisions); } }*/ /* need to aggregate collisions and repititions */ MPI_Reduce(&collisions,&sumCollisions,1,MPI_INT,MPI_SUM,0,comm); MPI_Reduce(&repeatObj,&sumRO,1,MPI_INT,MPI_SUM,0,comm); if(rank==0){ printf("finn: collisions %d repetitions %d\n",sumCollisions,sumRO); } status = MPI_Win_free(&win); status = MPI_Win_free(&win2); MPI_Finalize(); return 0; }
char * create_closure_key( struct itemset * current_itemset ) { struct item * current_item; struct hash * looked_up; struct list * production; int p; int d; int i; // Push all the items in the itemset onto the unchecked stack. struct list * unchecked = new_list(); struct hash * current_items = current_itemset->items; struct list * key_list = new_list(); list_keys_in_hash( current_items, key_list, "" ); for ( i = 0; i < key_list->next_index; i++ ) { char * key = listlookup( key_list, i ); append_to_list( unchecked, (void *) hashlookup( current_items, key )->data ); } destroy_key_list( key_list ); // Now process unchecked items, possibly adding more along the way. while ( unchecked->next_index ) { current_item = pop_from_list( unchecked ); p = current_item->prod_num; d = current_item->dot; production = GRAMMAR[p].production; if ( d == production->next_index - 1 ) { // This item is complete. append_to_list( current_itemset->complete, (void *) current_item ); continue; // Nothing more to do here. } // Otherwise, this item is incomplete, // so record it in the appropriate ready_for slot for this itemset. char * predicted = listlookup( production, d + 1 ); struct list * items_ready_for = NULL; struct hash * looked_up = hashlookup( current_itemset->ready_for, predicted ); if ( ! looked_up ) { items_ready_for = new_list(); add_to_hash( current_itemset->ready_for, predicted, (void *) items_ready_for ); } else { items_ready_for = looked_up->data; } append_to_list( items_ready_for, (void *) current_item ); // If the predicted symbol is terminal, this item is done processing. if ( ( (int *) hashlookup( IS_TERMINAL, predicted )->data ) == &TRUE ) { continue; // Can't expand terminals. } // Otherwise, the predicted symbol is nonterminal, // so expand the itemset using all applicable productions. struct list * predicted_productions = hashlookup( PRODUCTIONS_FOR, predicted )->data; for ( i = 0; i < predicted_productions->next_index; i++ ) { int predicted_p = (long int) listlookup( predicted_productions, i ); struct item * predicted_item = new_item(); predicted_item->prod_num = predicted_p; char * predicted_key = create_item_key( predicted_item ); if ( looked_up = hashlookup( current_items, predicted_key ) ) { // Item unneeded. free( predicted_item ); free( predicted_key ); continue; } // Otherwise, add the new item to the itemset, and to the unchecked stack. add_to_hash( current_items, predicted_key, (void *) predicted_item ); free( predicted_key ); append_to_list( unchecked, (void *) predicted_item ); } } // Now that the itemset has been filled out, create and return its identifying string. key_list = new_list(); list_keys_in_hash( current_items, key_list, "" ); char * closure_key = join_key_list( key_list, "_" ); destroy_key_list( key_list ); return closure_key; }
struct lambda_expr * parse( char * string, char ** error ) { INPUT = string; struct lambda_expr * result; struct token * t = NULL; struct lambda_expr * (*action_function)( int, struct list * ); int current_state = 0; struct list * stack = new_list(); append_to_list( stack, (void *) (long int) 0 ); // Start stack with initial state. int i = 0; struct hash * row; struct hash * looked_up; struct list * trans_list; struct transition * trans; char * action; int arg; // Loop tokens of input. while ( 1 ) { if ( ! t ) { t = get_next_token( string, i ); if ( strcmp( t->type, "end" ) ) { i += ( t->last - t->first + 1 ); } } row = listlookup( TABLE, current_state ); looked_up = hashlookup( row, t->type ); if ( ! looked_up ) { *error = "No transition"; return NULL; } trans_list = looked_up->data; if ( trans_list->next_index == 0 ) { *error = "No transition"; return NULL; } if ( trans_list->next_index > 1 ) { *error = "Ambiguous transition."; return NULL; } trans = listlookup( trans_list, 0 ); action = trans->action; if ( !strcmp( action, "accept" ) ) { pop_from_list( stack ); // Throw away old state result = pop_from_list( stack ); pop_from_list( stack ); // Throw away initial state number destroy_empty_list( stack ); free( t ); return result; } arg = trans->arg; if ( !strcmp( action, "shift" ) ) { append_to_list( stack, (void *) t ); append_to_list( stack, (void *) (long int) arg ); current_state = arg; // Iterate state. t = NULL; // Force reading of another token,. continue; } // The action is "reduce" action_function = GRAMMAR[arg].reduction; result = (*action_function)( arg, stack ); // Perform action, change stack. current_state = (int) (long int) listlookup( stack, stack->next_index - 1 ); append_to_list( stack, (void *) result ); struct list * production = GRAMMAR[arg].production; char * lhs = listlookup( production, 0 ); row = listlookup( GOTO, current_state ); struct list * trans_list = hashlookup( row, lhs )->data; if ( !trans_list || trans_list->next_index == 0 ) { *error = "No transition."; return NULL; } else if ( trans_list->next_index >= 2 ) { *error = "Ambiguous transition."; return NULL; } current_state = (int) (long int) listlookup( trans_list, 0 ); append_to_list( stack, (void *) (long int) current_state ); } // End tokens of input loop. // Should never get here! }