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

📄 mkred.c

📁 一个非常好的检索工具
💻 C
📖 第 1 页 / 共 4 页
字号:
/* $Id: mkred.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 "common.h"#include "reduce.h"#include "header.h"/***********************************************************************//* STACK_ROOT is used in la_traverse to construct a stack of symbols.  *//* The boolean vector SINGLE_COMPLETE_ITEM identifies states whose     *//* kernel consists of a single final item and other conditions allows  *//* us to compute default reductions for such states.                   *//* The vector LA_BASE is used in COMPUTE_READ and TRACE_LALR_PATH to   *//* identify states whose read sets can be completely computed from     *//* their kernel items.                                                 *//***********************************************************************/static struct node *stack_root = NULL;static BOOLEAN *single_complete_item;static int *la_base;/*****************************************************************************//*                                 LPGACCESS:                                *//*****************************************************************************//* Given a STATE_NO and an ITEM_NO, ACCESS computes the set of states where  *//* the rule from which ITEM_NO is derived was introduced through closure.    *//*****************************************************************************/struct node *lpgaccess(int state_no, int item_no){    int i;    BOOLEAN end_node;    struct node *access_root,                *head,                *tail,                *q,                *p,                *s;/****************************************************************//* Build a list pointed to by ACCESS_ROOT originally consisting *//* only of STATE_NO.                                            *//****************************************************************/    access_root = Allocate_node();    access_root -> value = state_no;    access_root -> next = NULL;    for (i = item_table[item_no].dot; i > 0; i--)/*distance to travel is DOT */    {        head = access_root;  /* Save old ACCESS_ROOT */        access_root = NULL;  /* Initialize ACCESS_ROOT for new list */        for (p = head; p != NULL; tail = p, p = p -> next)        {            /***********************************************************/            /* Compute set of states with transition into p->value.    */            /***********************************************************/            for (end_node = ((s = in_stat[p -> value]) == NULL);                 ! end_node;                 end_node = (s == in_stat[p -> value]))            {                s = s -> next;                q = Allocate_node();                q -> value = s -> value;                q -> next = access_root;                access_root = q;            }        }        free_nodes(head, tail);    /* free previous list */     }     return(access_root);}/*****************************************************************************//*                              TRACE_LALR_PATH:                             *//*****************************************************************************//* Given an item of the form: [x .A y], where x and y are arbitrary strings, *//* and A is a non-terminal, we pretrace the path(s) in the automaton  that   *//* will be followed in computing the look-ahead set for that item in         *//* STATE_NO.  A number is assigned to all pairs (S, B), where S is a state,  *//* and B is a non-terminal, involved in the paths. GOTO_INDX points to the   *//* GOTO_ELEMENT of (STATE_NO, A).                                            *//*****************************************************************************/static void trace_lalr_path(int state_no, int goto_indx){    int i,        symbol,        item,        state;    struct goto_header_type go_to;    BOOLEAN contains_empty;    struct node *p,                *r,                *t,                *w;/*********************************************************************//*  If STATE is a state number we first check to see if its base     *//* look-ahead set is a special one that does not contain EMPTY and   *//* has already been assigned a slot that can be reused.              *//* ((LA_BASE[STATE] != OMEGA) signals this condition.)               *//* NOTE that look-ahead follow sets are shared only when the maximum *//* look-ahead level allowed is 1 and single productions will not be  *//* removed. If either (or both) of these conditions is true, we need *//* to have a unique slot assigned to each pair [S, A] (where S is a  *//* state, and A is a non-terminal) in the automaton.                 *//*********************************************************************/    go_to = statset[state_no].go_to;    state = GOTO_ACTION(go_to, goto_indx);    if (state > 0)    {        if (la_base[state] != OMEGA &&            lalr_level == 1 && (! single_productions_bit))        {            GOTO_LAPTR(go_to, goto_indx) = la_base[state];            return;        }        r = statset[state].kernel_items;    }    else        r = adequate_item[-state];/***********************************************************************//* At this point, R points to a list of items which are the successors *//* of the items needed to initialize the Look-ahead follow sets.  If   *//* anyone of these items contains EMPTY, we trace the Digraph for other*//* look-ahead follow sets that may be needed, and signal this fact     *//* using the variable CONTAINS_EMPTY.                                  *//***********************************************************************/    la_top++;   /* allocate new slot */    INT_CHECK(la_top);    GOTO_LAPTR(go_to, goto_indx) = la_top;    contains_empty = FALSE;    for (; r != NULL;  r = r -> next)    {        item = r -> value - 1;        if (IS_IN_SET(first, item_table[item].suffix_index, empty))        {            contains_empty = TRUE;            symbol = rules[item_table[item].rule_number].lhs;            w = lpgaccess(state_no, item);            for (t = w; t != NULL; p = t, t = t -> next)            {                struct goto_header_type go_to;                go_to = statset[t -> value].go_to;                for (i = 1; GOTO_SYMBOL(go_to, i) != symbol; i++)                    ;                if (GOTO_LAPTR(go_to, i) == OMEGA)                    trace_lalr_path(t -> value, i);            }            free_nodes(w, p);        }    }/********************************************************************//* If the look-ahead follow set involved does not contain EMPTY, we *//* mark the state involved (STATE) so that other look-ahead follow  *//* sets which may need this set may reuse the same one.             *//* NOTE that if CONTAINS_EMPTY is false, then STATE has to denote a *//* state number (positive value) and not a rule number (negative).  *//********************************************************************/    if (! contains_empty)        la_base[state] = GOTO_LAPTR(go_to, goto_indx);    return;}/*****************************************************************************//*                               COMPUTE_READ:                               *//*****************************************************************************//* COMPUTE_READ computes the number of intermediate look-ahead sets that     *//* will be needed (in LA_TOP), allocates space for the sets(LA_SET), and    *//* initializes them.                                                         *//*  By intermediate look-ahead set, we mean the set of terminals that may    *//* follow a non-terminal in a given state.                                   *//*  These sets are initialized to the set of terminals that can immediately  *//* follow the non-terminal in the state to which it can shift (READ set).    *//*****************************************************************************/static void compute_read(void){    int state_no,        item_no,        rule_no,        lhs_symbol,        state,        i,        j,        la_ptr;    struct node *p,                *q,                *s,                *v;    if (lalr_level > 1 || single_productions_bit)    {        read_set = (SET_PTR)                   calloc(num_states + 1,                          sizeof(BOOLEAN_CELL) * term_set_size);        if (read_set == NULL)            nospace(__FILE__, __LINE__);    }/************************************************************************//*  We traverse all the states and for all complete items that requires *//* a look-ahead set, we retrace the state digraph (with the help of the *//* routine TRACE_LALR_PATH) and assign a unique number to all look-ahead*//* follow sets that it needs. A look-ahead follow set is a set of       *//* terminal symbols associated with a pair [S, A], where S is a state,  *//* and A is a non-terminal:                                             *//*                                                                      *//* [S, A] --> Follow-set                                                *//* Follow-set = {t | t is a terminal that can be shifted on after       *//*                      execution of a goto action on A in state S}.    *//*                                                                      *//* Each follow set is initialized with the set of terminals that can be *//* shifted on in state S2, where GOTO(S, A) = S2. After initialization  *//* a follow set F that does not contain the special terminal symbol     *//* EMPTY is marked with the help of the array LA_BASE, and if the       *//* highest level of look-ahead allowed is 1, then only one such set is  *//* allocated, and shared for all pairs (S, B) whose follow set is F.    *//************************************************************************/    la_top = 0;    la_base = (int *) calloc(num_states + 1, sizeof(int));    if (la_base == NULL)        nospace(__FILE__, __LINE__);    for ALL_STATES(i)        la_base[i] = OMEGA;    for ALL_STATES(state_no)    {        for (p = ((lalr_level <= 1 && single_complete_item[state_no])                  ? NULL                  : statset[state_no].complete_items);             p != NULL; p = p -> next)        {            item_no = p -> value;            rule_no = item_table[item_no].rule_number;            lhs_symbol = rules[rule_no].lhs;            if (lhs_symbol != accept_image)            {                v = lpgaccess(state_no, item_no);                for (s = v; s != NULL; q = s, s = s -> next)                {                    struct goto_header_type go_to;                    go_to = statset[s -> value].go_to;                    for (i = 1; GOTO_SYMBOL(go_to, i) != lhs_symbol; i++)                        ;                    if (GOTO_LAPTR(go_to, i) == OMEGA)                        trace_lalr_path(s -> value, i);                }                free_nodes(v, q);            }        }    /***********************************************************************/    /*  If the look-ahead level is greater than 1 or single productions    */    /* actions are to be removed when possible, then we have to compute    */    /* a Follow-set for all pairs [S, A] in the state automaton. Therefore,*/    /* we also have to consider Shift-reduce actions as reductions, and    */    /* trace back to their roots as well.                                  */    /* Note that this is not necessary for Goto-reduce actions. Since      */    /* they terminate with a non-terminal, and that non-terminal is        */    /* followed by the empty string, and we know that it must produce a    */    /* rule that either ends up in a reduction, a shift-reduce, or another */    /* goto-reduce. It will therefore be taken care of automatically by    */    /* transitive closure.                                                 */    /***********************************************************************/        if (lalr_level > 1 || single_productions_bit)        {            struct shift_header_type sh;            struct goto_header_type  go_to;            sh = shift[statset[state_no].shift_number];            for (j = 1; j <= sh.size; j++)            {                if (SHIFT_ACTION(sh, j) < 0)                {                    rule_no = - SHIFT_ACTION(sh, j);                    lhs_symbol = rules[rule_no].lhs;

⌨️ 快捷键说明

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