Пример #1
0
        /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

        /** Calculate lookahead representing symbols that could appear after the
         *   symbol that the dot is currently in front of.  Note: this routine must
         *   not be invoked before first sets and nullability has been calculated
         *   for all non terminals.
         */
        public terminal_set calc_lookahead(terminal_set lookahead_after)

        {
            terminal_set    result;
            int             pos;
            production_part part;
            symbol          sym;

            /* sanity check */
            if (dot_at_end())
            {
                throw new internal_error(
                          "Attempt to calculate a lookahead Set with a completed item");
            }

            /* start with an empty result */
            result = new terminal_set();

            /* consider all nullable symbols after the one to the right of the dot */
            for (pos = dot_pos() + 1; pos < the_production().rhs_length(); pos++)
            {
                part = the_production().rhs(pos);

                /* consider what kind of production part it is -- skip actions */
                if (!part.is_action())
                {
                    sym = ((symbol_part)part).the_symbol();

                    /* if its a terminal add it in and we are done */
                    if (!sym.is_non_term())
                    {
                        result.add((terminal)sym);
                        return(result);
                    }
                    else
                    {
                        /* otherwise add in first Set of the non terminal */
                        result.add(((non_terminal)sym).first_set());

                        /* if its nullable we continue adding, if not, we are done */
                        if (!((non_terminal)sym).nullable())
                        {
                            return(result);
                        }
                    }
                }
            }

            /* if we get here everything past the dot was nullable
             *       we add in the lookahead for after the production and we are done */
            result.add(lookahead_after);
            return(result);
        }
Пример #2
0
        /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

        /** Update (and return) the first Set based on current NT firsts.
         *  This assumes that nullability has already been computed for all non
         *  terminals and productions.
         */
        public terminal_set check_first_set()
        {
            int    part;
            symbol sym;

            /* walk down the right hand side till we get past all nullables */
            for (part = 0; part < rhs_length(); part++)
            {
                /* only look at non-actions */
                if (!rhs(part).is_action())
                {
                    sym = ((symbol_part)rhs(part)).the_symbol();

                    /* is it a non-terminal?*/
                    if (sym.is_non_term())
                    {
                        /* add in current firsts from that NT */
                        _first_set.add(((non_terminal)sym).first_set());

                        /* if its not nullable, we are done */
                        if (!((non_terminal)sym).nullable())
                        {
                            break;
                        }
                    }
                    else
                    {
                        /* its a terminal -- add that to the Set */
                        _first_set.add((terminal)sym);

                        /* we are done */
                        break;
                    }
                }
            }

            /* return our updated first Set */
            return(first_set());
        }
Пример #3
0
        /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
        /** Calculate lookahead representing symbols that could appear after the
         *   symbol that the dot is currently in front of.  Note: this routine must
         *   not be invoked before first sets and nullability has been calculated
         *   for all non terminals.
         */
        public terminal_set calc_lookahead(terminal_set lookahead_after)
        {
            terminal_set    result;
            int             pos;
            production_part part;
            symbol          sym;

            /* sanity check */
            if (dot_at_end())
            throw new internal_error(
            "Attempt to calculate a lookahead Set with a completed item");

            /* start with an empty result */
            result = new terminal_set();

            /* consider all nullable symbols after the one to the right of the dot */
            for (pos = dot_pos()+1; pos < the_production().rhs_length(); pos++)
            {
            part = the_production().rhs(pos);

            /* consider what kind of production part it is -- skip actions */
            if (!part.is_action())
            {
            sym = ((symbol_part)part).the_symbol();

            /* if its a terminal add it in and we are done */
            if (!sym.is_non_term())
            {
            result.add((terminal)sym);
            return result;
            }
            else
            {
            /* otherwise add in first Set of the non terminal */
            result.add(((non_terminal)sym).first_set());

            /* if its nullable we continue adding, if not, we are done */
            if (!((non_terminal)sym).nullable())
            return result;
            }
            }
            }

            /* if we get here everything past the dot was nullable
             we add in the lookahead for after the production and we are done */
            result.add(lookahead_after);
            return result;
        }
Пример #4
0
        /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

        /** Fill in the parse table entries for this state.  There are two
         *  parse tables that encode the viable prefix recognition machine, an
         *  action table and a reduce-goto table.  The rows in each table
         *  correspond to states of the machine.  The columns of the action table
         *  are indexed by terminal symbols and correspond to either transitions
         *  out of the state (shift entries) or reductions from the state to some
         *  previous state saved on the stack (reduce entries).  All entries in the
         *  action table that are not shifts or reduces, represent errors.    The
         *  reduce-goto table is indexed by non terminals and represents transitions
         *  out of a state on that non-terminal.<p>
         *  Conflicts occur if more than one action needs to go in one entry of the
         *  action table (this cannot happen with the reduce-goto table).  Conflicts
         *  are resolved by always shifting for shift/reduce conflicts and choosing
         *  the lowest numbered production (hence the one that appeared first in
         *  the specification) in reduce/reduce conflicts.  All conflicts are
         *  reported and if more conflicts are detected than were declared by the
         *  user, code generation is aborted.
         *
         * @param act_table    the action table to put entries in.
         * @param reduce_table the reduce-goto table to put entries in.
         */
        public void build_table_entries(
            parse_action_table act_table,
            parse_reduce_table reduce_table)

        {
            parse_action_row our_act_row;
            parse_reduce_row our_red_row;
            lalr_item        itm;
            parse_action     act, other_act;
            symbol           sym;
            terminal_set     conflict_set = new terminal_set();

            /* pull out our rows from the tables */
            our_act_row = act_table.under_state[index()];
            our_red_row = reduce_table.under_state[index()];

            /* consider each item in our state */
            IEnumerator i = items().all();

            while (i.MoveNext())
            {
                itm = (lalr_item)i.Current;


                /* if its completed (dot at end) then reduce under the lookahead */
                if (itm.dot_at_end())
                {
                    act = new reduce_action(itm.the_production());

                    /* consider each lookahead symbol */
                    for (int t = 0; t < terminal.number(); t++)
                    {
                        /* skip over the ones not in the lookahead */
                        if (!itm.lookahead().contains(t))
                        {
                            continue;
                        }

                        /* if we don't already have an action put this one in */
                        if (our_act_row.under_term[t].kind() ==
                            parse_action.ERROR)
                        {
                            our_act_row.under_term[t] = act;
                        }
                        else
                        {
                            /* we now have at least one conflict */
                            terminal term = terminal.find(t);
                            other_act = our_act_row.under_term[t];

                            /* if the other act was not a shift */
                            if ((other_act.kind() != parse_action.SHIFT) &&
                                (other_act.kind() != parse_action.NONASSOC))
                            {
                                /* if we have lower index hence priority, replace it*/
                                if (itm.the_production().index() <
                                    ((reduce_action)other_act).reduce_with().index())
                                {
                                    /* replace the action */
                                    our_act_row.under_term[t] = act;
                                }
                            }
                            else
                            {
                                /*  Check precedences,see if problem is correctable */
                                if (fix_with_precedence(itm.the_production(),
                                                        t, our_act_row, act))
                                {
                                    term = null;
                                }
                            }
                            if (term != null)
                            {
                                conflict_set.add(term);
                            }
                        }
                    }
                }
            }

            /* consider each outgoing transition */
            for (lalr_transition trans = transitions(); trans != null; trans = trans.next())
            {
                /* if its on an terminal add a shift entry */
                sym = trans.on_symbol();
                if (!sym.is_non_term())
                {
                    act = new shift_action(trans.to_state());

                    /* if we don't already have an action put this one in */
                    if (our_act_row.under_term[sym.index()].kind() ==
                        parse_action.ERROR)
                    {
                        our_act_row.under_term[sym.index()] = act;
                    }
                    else
                    {
                        /* we now have at least one conflict */
                        production p = ((reduce_action)our_act_row.under_term[sym.index()]).reduce_with();

                        /* shift always wins */
                        if (!fix_with_precedence(p, sym.index(), our_act_row, act))
                        {
                            our_act_row.under_term[sym.index()] = act;
                            conflict_set.add(terminal.find(sym.index()));
                        }
                    }
                }
                else
                {
                    /* for non terminals add an entry to the reduce-goto table */
                    our_red_row.under_non_term[sym.index()] = trans.to_state();
                }
            }

            /* if we end up with conflict(s), report them */
            if (!conflict_set.empty())
            {
                report_conflicts(conflict_set);
            }
        }
        /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
        /** Fill in the parse table entries for this state.  There are two
           *  parse tables that encode the viable prefix recognition machine, an
           *  action table and a reduce-goto table.  The rows in each table
           *  correspond to states of the machine.  The columns of the action table
           *  are indexed by terminal symbols and correspond to either transitions
           *  out of the state (shift entries) or reductions from the state to some
           *  previous state saved on the stack (reduce entries).  All entries in the
           *  action table that are not shifts or reduces, represent errors.    The
           *  reduce-goto table is indexed by non terminals and represents transitions
           *  out of a state on that non-terminal.<p>
           *  Conflicts occur if more than one action needs to go in one entry of the
           *  action table (this cannot happen with the reduce-goto table).  Conflicts
           *  are resolved by always shifting for shift/reduce conflicts and choosing
           *  the lowest numbered production (hence the one that appeared first in
           *  the specification) in reduce/reduce conflicts.  All conflicts are
           *  reported and if more conflicts are detected than were declared by the
           *  user, code generation is aborted.
           *
           * @param act_table    the action table to put entries in.
           * @param reduce_table the reduce-goto table to put entries in.
           */
        public void build_table_entries(
    parse_action_table act_table, 
    parse_reduce_table reduce_table)
        {
            parse_action_row our_act_row;
              parse_reduce_row our_red_row;
              lalr_item        itm;
              parse_action     act, other_act;
              symbol           sym;
              terminal_set     conflict_set = new terminal_set();

              /* pull out our rows from the tables */
              our_act_row = act_table.under_state[index()];
              our_red_row = reduce_table.under_state[index()];

              /* consider each item in our state */
              IEnumerator i = items().all();
              while ( i.MoveNext() )
            {
              itm = (lalr_item)i.Current;

              /* if its completed (dot at end) then reduce under the lookahead */
              if (itm.dot_at_end())
            {
              act = new reduce_action(itm.the_production());

              /* consider each lookahead symbol */
              for (int t = 0; t < terminal.number(); t++)
            {
              /* skip over the ones not in the lookahead */
              if (!itm.lookahead().contains(t)) continue;

              /* if we don't already have an action put this one in */
              if (our_act_row.under_term[t].kind() ==
              parse_action.ERROR)
            {
                  our_act_row.under_term[t] = act;
            }
              else
            {
              /* we now have at least one conflict */
              terminal term = terminal.find(t);
              other_act = our_act_row.under_term[t];

              /* if the other act was not a shift */
              if ((other_act.kind() != parse_action.SHIFT) &&
              (other_act.kind() != parse_action.NONASSOC))
                {
                /* if we have lower index hence priority, replace it*/
                  if (itm.the_production().index() <
                  ((reduce_action)other_act).reduce_with().index())
                {
                  /* replace the action */
                  our_act_row.under_term[t] = act;
                }
                } else {
              /*  Check precedences,see if problem is correctable */
              if(fix_with_precedence(itm.the_production(),
                         t, our_act_row, act)) {
                term = null;
              }
            }
              if(term!=null) {

            conflict_set.add(term);
              }
            }
            }
            }
            }

              /* consider each outgoing transition */
              for (lalr_transition trans=transitions(); trans!=null; trans=trans.next())
            {
              /* if its on an terminal add a shift entry */
              sym = trans.on_symbol();
              if (!sym.is_non_term())
            {
              act = new shift_action(trans.to_state());

              /* if we don't already have an action put this one in */
              if ( our_act_row.under_term[sym.index()].kind() ==
               parse_action.ERROR)
            {
              our_act_row.under_term[sym.index()] = act;
            }
              else
            {
              /* we now have at least one conflict */
              production p = ((reduce_action)our_act_row.under_term[sym.index()]).reduce_with();

              /* shift always wins */
              if (!fix_with_precedence(p, sym.index(), our_act_row, act)) {
            our_act_row.under_term[sym.index()] = act;
            conflict_set.add(terminal.find(sym.index()));
              }
            }
            }
              else
            {
              /* for non terminals add an entry to the reduce-goto table */
              our_red_row.under_non_term[sym.index()] = trans.to_state();
            }
            }

              /* if we end up with conflict(s), report them */
              if (!conflict_set.empty())
            report_conflicts(conflict_set);
        }