示例#1
0
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;
}
char * print_hash_key_set( struct hash * current ) {
    struct list * var_list = new_list();
    list_keys_in_hash( current, var_list, "" );
    int var_list_len = 0;
    int i = var_list->next_index;
    while ( i-- ) {
        var_list_len += strlen(listlookup( var_list, i ));
    }
    int brace_len = BRACE_LEN;
    int comma_len = COMMA_LEN;
    char * key_set_str = malloc(
                             ( var_list->next_index  * comma_len
                               + var_list_len
                               + 2 * brace_len
                               + 1
                             ) * sizeof(char)
                         );

    *key_set_str = '\0';
    sprintf( key_set_str, "{" );
    i = var_list->next_index;
    while ( i-- ) {
        strcat( key_set_str, listlookup( var_list, i ));
        if ( i ) {
            strcat( key_set_str, "," );
        }
    }
    strcat( key_set_str, "}" );
    destroy_key_list(var_list);
    return key_set_str;
}
void list_keys_in_hash( struct hash * current, struct list * result, char * prefix ) {
    int siglen = strlen(current->sigstr);
    int prefixlen = strlen(prefix);
    char * path = malloc( ( prefixlen + siglen + 2 ) * sizeof(char) ); // Extra child char.
    strcpy( path, prefix );
    strcat( path, current->sigstr );
    path[ prefixlen + siglen + 1 ] = path[ prefixlen + siglen ] = '\0';
    char * chars_in_child = chars_in( current->child, 0, 0 );
    char child_char = '\0';
    struct hash * child_hash = NULL;
    int i = current->num_children;
    while ( i-- ) { // Recurse through all children.
        child_char = chars_in_child[i];
        if ( child_char == '\0' ) { // No keys to recurse through.
            continue;
        }
        path[ prefixlen + siglen ] = child_char; // Get the path prefix for this child.
        child_hash = charhashlookup( current->child, child_char )->data;
        list_keys_in_hash( child_hash, result, path );
    }

    // Decide if the path to this node needs to be included in the list of keys.
    if ( current->data ) {
        path[ prefixlen + siglen ] = '\0';
        append_to_list( result, (void *) path );
    }
    else {
        free(path);
    }
    free(chars_in_child);
    return;
}
示例#4
0
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 );
        }
    }
}
示例#5
0
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;
                }
            }
        }
    }
}
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;
}
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 );

}
示例#8
0
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;
}
示例#9
0
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;
}
示例#10
0
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 );
    }
}
示例#11
0
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;
}
示例#12
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;
}