⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mkfirst.c

📁 一个非常好的检索工具
💻 C
📖 第 1 页 / 共 5 页
字号:
    {        if (! produces_terminals[nt])        {            if (nt_root == NIL)                nt_root = nt;            else                nt_list[nt_last] = nt;            nt_last = nt;        }    }    /*************************************************************/    /* If there are non-terminal symbols that do not generate    */    /* terminal strings, print them out and stop the program.    */    /*************************************************************/    if (nt_root != NIL)    {        nt_list[nt_last] = NIL;  /* mark end of list */        PR_HEADING;        strcpy(line, "*** ERROR: The following Non-terminal");        if (nt_list[nt_root] == NIL)            strcat(line, " does not generate any terminal strings: ");        else        {            strcat(line, "s do not generate any terminal strings: ");            PRNT(line);            strcpy(line, "        "); /* 8 spaces */        }        for (symbol = nt_root; symbol != NIL; symbol = nt_list[symbol])        {            restore_symbol(tok, RETRIEVE_STRING(symbol));            if (strlen(line) + strlen(tok) > PRINT_LINE_SIZE-1)            {                PRNT(line);                print_large_token(line, tok, "    ", LEN);            }            else                strcat(line, tok);            strcat(line, BLANK);        }        PRNT(line);        exit(12);    }    produces_terminals += (num_terminals + 1);    ffree(produces_terminals);    ffree(rhs_start);}/*****************************************************************************//*                          IS_TERMINAL_RHS:                                 *//*****************************************************************************//*   This procedure tries to advance the RHS_START pointer.  If the current  *//* symbol identified by the RHS_START element is a bad non-terminal it       *//* returns FALSE.  Otherwise, the whole right-hand side is traversed, and it *//* returns the value TRUE.                                                   *//*****************************************************************************/static BOOLEAN is_terminal_rhs(short *rhs_start,                               BOOLEAN *produces_terminals, int rule_no){    int symbol;    for(rhs_start[rule_no] = rhs_start[rule_no];        rhs_start[rule_no] <= rules[rule_no + 1].rhs - 1;        rhs_start[rule_no]++)    {        symbol = rhs_sym[rhs_start[rule_no]];        if (symbol IS_A_NON_TERMINAL)        {            if (! produces_terminals[symbol])                return(FALSE);        }    }    return(TRUE);}/*****************************************************************************//*                             FIRST_MAP:                                    *//*****************************************************************************//*  FIRST_MAP takes as arguments two pointers, ROOT and TAIL, to a sequence  *//* of symbols in RHS which it inserts in FIRST_TABLE.  The vector FIRST_TABLE*//* is used as the base for a hashed table where collisions are resolved by   *//* links.  Elements added to this hash table are allocated from the vector   *//* FIRST_ELEMENT, with the variable TOP always indicating the position of the*//* last element in FIRST_ELEMENT that was allocated.                         *//* NOTE: The suffix indentified by ROOT and TAIL is presumed not to be empty.*//*       That is, ROOT <= TAIL !!!                                           *//*****************************************************************************/static short first_map(int root, int tail){    int i,        j,        k;    for (i = first_table[rhs_sym[root]]; i != NIL; i = first_element[i].link)    {        for (j = root + 1,             k = first_element[i].suffix_root + 1;             (j <= tail && k <= first_element[i].suffix_tail);             j++, k++)        {            if (rhs_sym[j] != rhs_sym[k])                break;        }        if (j > tail && k > first_element[i].suffix_tail)            return((short) i);    }    top++;    first_element[top].suffix_root = root;    first_element[top].suffix_tail = tail;    first_element[top].link = first_table[rhs_sym[root]];    first_table[rhs_sym[root]] = top;    return(top);}/*****************************************************************************//*                              S_FIRST:                                     *//*****************************************************************************//* S_FIRST takes as argument, two pointers: ROOT and TAIL to a sequence of   *//* symbols in the vector RHS, and INDEX which is the index of a first set.   *//* It computes the set of all terminals that can appear as the first symbol  *//* in the sequence and places the result in the FIRST set indexable by INDEX.*//*****************************************************************************/static void s_first(int root, int tail, int index){    int i,        symbol;    symbol = (root > tail ? empty : rhs_sym[root]);    if (symbol IS_A_TERMINAL)    {        INIT_FIRST(index);        SET_BIT_IN(first, index, symbol); /* add it to set */    }    else    {        ASSIGN_SET(first, index, nt_first, symbol);    }    for (i = root + 1; i <= tail && IS_IN_SET(first, index, empty); i++)    {        symbol = rhs_sym[i];        RESET_BIT_IN(first, index, empty);    /* remove EMPTY */        if (symbol IS_A_TERMINAL)        {            SET_BIT_IN(first, index, symbol);  /* add it to set */        }        else        {            SET_UNION(first, index, nt_first, symbol);        }    }    return;}/******************************************************************//*                     COMPUTE_PRODUCES:                          *//******************************************************************//* For a given symbol, complete the computation of                *//* PRODUCES[symbol].                                              *//******************************************************************/static void compute_produces(int symbol){    int indx;    int new_symbol;    struct node *p,                *q;    stack[++top] = symbol;    indx = top;    index_of[symbol] = indx;    for (p = direct_produces[symbol]; p != NULL; q = p, p = p -> next)    {        new_symbol = p -> value;        if (index_of[new_symbol] == OMEGA)  /* first time seen? */            compute_produces(new_symbol);        index_of[symbol] = MIN(index_of[symbol], index_of[new_symbol]);        NTSET_UNION(produces, symbol, produces, new_symbol);    }    if (direct_produces[symbol] != NULL)        free_nodes(direct_produces[symbol], q);    if (index_of[symbol] == indx)  /*symbol is SCC root */    {        for (new_symbol = stack[top];             new_symbol != symbol; new_symbol = stack[--top])        {            ASSIGN_NTSET(produces, new_symbol, produces, symbol);            index_of[new_symbol] = INFINITY;        }        index_of[symbol] = INFINITY;        top--;    }    return;}/*****************************************************************************//*                          COMPUTE_FOLLOW:                                  *//*****************************************************************************//* COMPUTE_FOLLOW computes FOLLOW[nt] for some non-terminal NT using the     *//* digraph algorithm.  FOLLOW[NT] is the set of all terminals Ti that        *//* may immediately follow a string X generated by NT. I.e., if NT *::= X     *//* then X Ti is a valid substring of a class of strings that may be          *//* recognized by the language.                                               *//*****************************************************************************/static void compute_follow(int nt){    int indx;    int rule_no,        lhs_symbol,        item_no;    SET_PTR temp_set;    temp_set = (SET_PTR)               calloc(1, term_set_size * sizeof(BOOLEAN_CELL));    if (temp_set == NULL)        nospace(__FILE__, __LINE__);    /**************************************************************/    /* FOLLOW[NT] was initialized to 0 for all non-terminals.     */    /**************************************************************/    stack[++top] = nt;    indx = top;    index_of[nt] = indx;    for (item_no = nt_items[nt]; item_no != NIL; item_no = next_item[item_no])    { /* iterate over all items of NT */        ASSIGN_SET(temp_set, 0, first, item_table[item_no].suffix_index);        if (IS_ELEMENT(temp_set, empty))        {            RESET_BIT(temp_set, empty);            rule_no = item_table[item_no].rule_number;            lhs_symbol = rules[rule_no].lhs;            if (index_of[lhs_symbol] == OMEGA)                compute_follow(lhs_symbol);            SET_UNION( follow, nt, follow, lhs_symbol);            index_of[nt] = MIN( index_of[nt], index_of[lhs_symbol]);        }        SET_UNION(follow, nt, temp_set, 0);    }    if (index_of[nt] == indx)    {        for (lhs_symbol = stack[top];             lhs_symbol != nt; lhs_symbol = stack[--top])        {            ASSIGN_SET(follow, lhs_symbol, follow, nt);            index_of[lhs_symbol] = INFINITY;        }        index_of[nt] = INFINITY;        top--;    }    ffree(temp_set);    return;}/*****************************************************************************//*                           PRINT_UNREACHABLES:                             *//*****************************************************************************/static void print_unreachables(void){    short *symbol_list;    int nt,        t_root,        nt_root,        rule_no,        symbol,        i;    BOOLEAN end_node;    char line[PRINT_LINE_SIZE + 1],         tok[SYMBOL_SIZE + 1];    /***************************************************************/    /* SYMBOL_LIST is used for two purposes:                       */    /*  1) to mark symbols that are reachable from the Accepting   */    /*        non-terminal.                                        */    /*  2) to construct lists of symbols that are not reachable.   */    /***************************************************************/    symbol_list = Allocate_short_array(num_symbols + 1);    for ALL_SYMBOLS(i)        symbol_list[i] = OMEGA;    symbol_list[eoft_image] = NIL;    symbol_list[empty] = NIL;    if (error_maps_bit)        symbol_list[error_image] = NIL;    /*********************************************************************/    /* Initialize a list consisting only of the Accept non-terminal.     */    /* This list is a work pile of non-terminals to process as follows:  */    /* Each non-terminal in the front of the list is removed in turn and */    /* 1) All terminal symbols in one of its right-hand sides are        */    /*     marked reachable.                                             */    /* 2) All non-terminals in one of its right-hand sides are placed    */    /*     in the the work pile of it had not been processed previously  */    /*********************************************************************/    nt_root = accept_image;    symbol_list[nt_root] = NIL;    for (nt = nt_root; nt != NIL; nt = nt_root)    {        nt_root = symbol_list[nt];        for (end_node = ((rule_no = lhs_rule[nt]) == NIL);             ! end_node;             end_node = (rule_no == lhs_rule[nt]))        {            rule_no = next_rule[rule_no];            for ENTIRE_RHS(i, rule_no)            {                symbol = rhs_sym[i];                if (symbol IS_A_TERMINAL)                    symbol_list[symbol] = NIL;                else if (symbol_list[symbol] == OMEGA)                {                    symbol_list[symbol] = nt_root;                    nt_root = symbol;                }            }        }    }    /***************************************************************/    /* We now iterate (backwards to keep things in order) over the */    /* terminal symbols, and place each unreachable terminal in a  */    /* list. If the list is not empty, we signal that these symbols*/    /* are unused.                                                 */    /***************************************************************/    t_root = NIL;    for ALL_TERMINALS_BACKWARDS(symbol)    {        if (symbol_list[symbol] == OMEGA)        {            symbol_list[symbol] = t_root;            t_root = symbol;        }    }    if (t_root != NIL)    {        PR_HEADING;        if (symbol_list[t_root] != NIL)        {            PRNT("*** The following Terminals are useless: ");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -