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

📄 mkfirst.c

📁 一个非常好的检索工具
💻 C
📖 第 1 页 / 共 5 页
字号:
/* $Id: mkfirst.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 "header.h"#define LEN (PRINT_LINE_SIZE - 4)#define NEXT_RULE_SIZE (num_rules + 1)#define LAST_RHS_INDEX(rule_no) rules[rule_no + 1].rhs - 1#define INIT_FIRST(nt) \        { \            register int k; \            for (k = 0; k < term_set_size; k++)\                 first[nt * term_set_size + k] = 0;\        }static BOOLEAN is_terminal_rhs(short *rhs_start,                               BOOLEAN *produces_terminals, int rule_no);static BOOLEAN is_nullable_rhs(short *rhs_start, int rule_no);static void compute_first(int nt);static void print_unreachables(void);static void print_xref(void);static void print_nt_first(void);static void print_follow_map(void);static short first_map(int root, int tail);static void s_first(int root, int tail, int set);static void compute_follow(int nt);static void quick_sym(short array[], int l, int h);static void check_non_terminals(void);static void no_rules_produced(void);static void nullables_computation(void);static void compute_closure(int lhs_symbol);static void compute_produces(int symbol);static struct f_element_type{    short suffix_root,          suffix_tail,          link;} *first_element;static struct node **direct_produces;static SET_PTR produces;/****************************************************************************//* TOP, STACK, and INDEX_OF are used for the linear graph algorithm in      *//* constructing the FIRST, FOLLOW and CLOSURE maps.                         *//*                                                                          *//* LHS_RULE and NEXT_RULE are used in constructing a map from non-terminals *//* to the set of rules produced by the non-terminals.                       *//*                                                                          *//* FIRSTis an array used as a hash table to construct                       *//* the mapping from sequence of symbols to their FIRST terminal             *//* set.  A sequence is hashed into a location depending on the              *//* first symbol in that sequence.                                           *//*                                                                          *//* FIRST_ITEM_OF is a map from each rule into the first item                *//* that it generates.                                                       *//*                                                                          *//* The following pointers are used to construct a mapping from each symbol  *//* in the grammar into the set of items denoted by that symbol. I.e.,       *//*                                                                          *//*     f(t) := { [A -> x .t y] | A -> x t y is a rule in the grammar }      *//*                                                                          *//* Since these sets are simply partitions of the set of items, they are kept*//* all in a sequential list in the array NEXT_ITEM.  The roots of the lists *//* are placed in the arrats T_ITEMS and NT_ITEMS.                           *//****************************************************************************/static short *stack,             *index_of,             *lhs_rule,             *next_rule,             *first_table,             *first_item_of,             *next_item,             *nt_items,             *nt_list;static int top;/*****************************************************************************//*                               MKFIRST:                                    *//*****************************************************************************//*    MKFIRST constructs the FIRST and FOLLOW maps, the CLOSURE map,         *//* ADEQUATE_ITEM and ITEM_TABLE maps and all other basic maps.               *//*****************************************************************************/void mkfirst(void){    int symbol,        nt,        item_no,        first_of_empty,        rule_no,        i;    BOOLEAN end_node;    term_set_size = num_terminals / SIZEOF_BC                  + (num_terminals % SIZEOF_BC ? 1 : 0);    non_term_set_size = num_non_terminals / SIZEOF_BC                      + (num_non_terminals % SIZEOF_BC ? 1 : 0);    /* allocate various arrays */    lhs_rule = Allocate_short_array(num_non_terminals);    lhs_rule -= (num_terminals + 1);    next_rule = Allocate_short_array(NEXT_RULE_SIZE);    first_item_of = Allocate_short_array(NEXT_RULE_SIZE);    stack = Allocate_short_array(num_non_terminals + 1);    index_of = Allocate_short_array(num_non_terminals);    index_of -= (num_terminals + 1);    /*********************************************************************/    /* NT_FIRST is used to construct a mapping from non-terminals to the */    /* set of terminals taht may appear first in a string derived from   */    /* the non-terminal.                                                 */    /*********************************************************************/    nt_first = (SET_PTR)               calloc(num_non_terminals,                      term_set_size * sizeof(BOOLEAN_CELL));    if (nt_first == NULL)        nospace(__FILE__, __LINE__);    nt_first -= ((num_terminals + 1) * term_set_size);    next_item = Allocate_short_array(num_items + 1);    nt_items = Allocate_short_array(num_non_terminals);    nt_items -= (num_terminals + 1);    nt_list = Allocate_short_array(num_non_terminals);    nt_list -= (num_terminals + 1);    first_element = (struct f_element_type *)                    calloc(num_items + 1, sizeof(struct f_element_type));    if (first_element == NULL)        nospace(__FILE__, __LINE__);    item_table = (struct itemtab *)                 calloc(num_items + 1, sizeof(struct itemtab));    if (item_table == NULL)        nospace(__FILE__, __LINE__);    for ALL_NON_TERMINALS(i) /* Initialize LHS_RULE to NIL */        lhs_rule[i] = NIL;    /**************************************************************/    /* In this loop, we construct the LHS_RULE map which maps     */    /* each non-terminal symbol into the set of rules it produces */    /**************************************************************/    for ALL_RULES(rule_no)    {        symbol = rules[rule_no].lhs;        if (lhs_rule[symbol] == NIL)            next_rule[rule_no] = rule_no;        else        {            next_rule[rule_no] = next_rule[lhs_rule[symbol]];            next_rule[lhs_rule[symbol]]  = rule_no;        }        lhs_rule[symbol] = rule_no;    }    /*************************************************************/    /* Check if there are any non-terminals that do not produce  */    /* any rules.                                                */    /*************************************************************/    no_rules_produced();    /*************************************************************/    /* Construct the CLOSURE map of non-terminals.               */    /*************************************************************/    closure = (struct node **)              calloc(num_non_terminals, sizeof(struct node *));    if (closure == NULL)        nospace(__FILE__, __LINE__);    closure -= (num_terminals + 1);    for ALL_NON_TERMINALS(i)        index_of[i] = OMEGA;    top = 0;    for ALL_NON_TERMINALS(nt)    {        if (index_of[nt] == OMEGA)            compute_closure(nt);    }    /*************************************************************/    /* Construct the NULL_NT map for non-terminals.              */    /* A non-terminal B is said to be nullable if either:        */    /*    B -> %empty  or  B -> B1 B2 B3 ... Bk  where Bi is     */    /*                         nullable for 1 <= i <= k          */    /*************************************************************/    null_nt = Allocate_boolean_array(num_non_terminals);    null_nt -= (num_terminals + 1);    nullables_computation();    /*************************************************************/    /* Construct the FIRST map for non-terminals and also a list */    /* of non-terminals whose first set is empty.                */    /*************************************************************/    for ALL_NON_TERMINALS(i) /* Initialize INDEX_OF to OMEGA */        index_of[i] = OMEGA;    top = 0;    for ALL_NON_TERMINALS(nt)    {        if (index_of[nt] == OMEGA)            compute_first(nt);    }    /*************************************************************/    /*  Since every input source will be followed by the EOFT    */    /*  symbol, FIRST[accept_image] cannot contain empty but     */    /*  instead must contain the EOFT symbol.                    */    /*************************************************************/    if (null_nt[accept_image])    {        null_nt[accept_image] = FALSE;        RESET_BIT_IN(nt_first, accept_image, empty);        SET_BIT_IN(nt_first, accept_image, eoft_image);    }    /***************************************************************/    /* Check whether there are any non-terminals that do not       */    /* generate any terminal strings. If so, signal error and stop.*/    /***************************************************************/    check_non_terminals();    /***************************************************************/    /* Construct the ITEM_TABLE, FIRST_ITEM_OF, and NT_ITEMS maps. */    /***************************************************************/    first_table = Allocate_short_array(num_symbols + 1);    for ALL_SYMBOLS(i) /* Initialize FIRST_TABLE to NIL */        first_table[i] = NIL;    top = 1;    first_of_empty = top;    first_element[first_of_empty].suffix_root = 1;    first_element[first_of_empty].suffix_tail = 0;    for ALL_NON_TERMINALS(i) /* Initialize NT_ITEMS to NIL */        nt_items[i] = NIL;    item_no = 0;    item_table[item_no].rule_number = 0;    item_table[item_no].symbol = empty;    item_table[item_no].dot = 0;    item_table[item_no].suffix_index = NIL;    for ALL_RULES(rule_no)    {        int j,            k;        first_item_of[rule_no] = item_no + 1;        j = 0;        k = LAST_RHS_INDEX(rule_no);        for ENTIRE_RHS(i, rule_no)        {            item_no++;            symbol = rhs_sym[i];            item_table[item_no].rule_number = rule_no;            item_table[item_no].symbol = symbol;            item_table[item_no].dot = j;            if (lalr_level > 1 ||                symbol IS_A_NON_TERMINAL ||                symbol == error_image)            {                if (i == k)                    item_table[item_no].suffix_index = first_of_empty;                else                    item_table[item_no].suffix_index = first_map(i + 1, k);            }            else                item_table[item_no].suffix_index = NIL;            if (symbol IS_A_NON_TERMINAL)            {                next_item[item_no] = nt_items[symbol];                nt_items[symbol] = item_no;            }            j++;        }        item_table[++item_no].rule_number = rule_no;        item_table[item_no].symbol = empty;        item_table[item_no].dot = j;        item_table[item_no].suffix_index = NIL;    }    /***************************************************************/    /* We now compute the first set for all suffixes that were     */    /* inserted in the FIRST_TABLE map. There are TOP such suffixes*/    /* Extra space is also allocated to compute the first set for  */    /* suffixes whose left-hand side is the ACCEPT non-terminal.   */    /* The first set for these suffixes are the sets needed to     */    /* construct the FOLLOW map and compute look-ahead sets.  They */    /* are placed in the FIRST table in the range 1..NUM_FIRST_SETS*/    /* The first element in the FIRST table contains the first sets*/    /* for the empty sequence.                                     */    /***************************************************************/    num_first_sets = top;    for (end_node = ((rule_no = lhs_rule[accept_image]) == NIL);         ! end_node;         end_node = (rule_no == lhs_rule[accept_image]))    {        rule_no = next_rule[rule_no];        num_first_sets++;    }    first = (SET_PTR)            calloc(num_first_sets + 1, term_set_size * sizeof(BOOLEAN_CELL));    if (first == NULL)        nospace(__FILE__, __LINE__);    for (i = 1; i <= top; i++)    {        s_first(first_element[i].suffix_root,                first_element[i].suffix_tail, i);    }    rule_no = lhs_rule[accept_image];    for (i = top + 1; i <= num_first_sets; i++)    {        rule_no = next_rule[rule_no];        item_no = first_item_of[rule_no];        item_table[item_no].suffix_index = i;        INIT_FIRST(i);        SET_BIT_IN(first, i, eoft_image);    }    /***************************************************************/    /* If the READ/REDUCE option is on, we precalculate the kernel */    /* of the final states which simply consists of the last item  */    /* in  the corresponding rule.  Rules with the ACCEPT          */    /* non-terminal as their left-hand side are not considered so  */    /* as to let the Accpet action remain as a Reduce action       */    /* instead of a Goto/Reduce action.                            */    /***************************************************************/    adequate_item = (struct node **)                    calloc(num_rules + 1, sizeof(struct node *));    if (adequate_item == NULL)

⌨️ 快捷键说明

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