示例#1
0
        /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

        /** Add a single terminal to the Set.
         * @param sym the terminal being added.
         * @return true if this changes the Set.
         */
        public bool add(terminal sym)
        {
            bool result;

            not_null(sym);

            /* see if we already have this */
            result = _elements.Get(sym.index());

            /* if not we add it */
            if (!result)
            {
                _elements.Set(sym.index(), true);
            }

            return(result);
        }
示例#2
0
        /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

        /** Determine if the Set contains a particular terminal.
         * @param sym the terminal symbol we are looking for.
         */
        public bool contains(terminal sym)
        {
            not_null(sym);
            return(_elements.Get(sym.index()));
        }
示例#3
0
        /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

        /** Remove a terminal if it is in the Set.
         * @param sym the terminal being removed.
         */
        public void remove(terminal sym)
        {
            not_null(sym);
            _elements.Set(sym.index(), false);
        }
示例#4
0
        /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/


        /** Procedure that attempts to fix a shift/reduce error by using
         * precedences.  --frankf 6/26/96
         *
         *  if a production (also called rule) or the lookahead terminal
         *  has a precedence, then the table can be fixed.  if the rule
         *  has greater precedence than the terminal, a reduce by that rule
         *  in inserted in the table.  If the terminal has a higher precedence,
         *  it is shifted.  if they have equal precedence, then the associativity
         *  of the precedence is used to determine what to put in the table:
         *  if the precedence is left associative, the action is to reduce.
         *  if the precedence is right associative, the action is to shift.
         *  if the precedence is non associative, then it is a syntax error.
         *
         *  @param p           the production
         *  @param term_index  the index of the lokahead terminal
         *  @param parse_action_row  a row of the action table
         *  @param act         the rule in conflict with the table entry
         */

        protected bool fix_with_precedence(
            production p,
            int term_index,
            parse_action_row table_row,
            parse_action act)

        {
            terminal term = terminal.find(term_index);

            /* if the production has a precedence number, it can be fixed */
            if (p.precedence_num() > assoc.no_prec)
            {
                /* if production precedes terminal, put reduce in table */
                if (p.precedence_num() > term.precedence_num())
                {
                    table_row.under_term[term_index] =
                        insert_reduce(table_row.under_term[term_index], act);
                    return(true);
                }

                /* if terminal precedes rule, put shift in table */
                else if (p.precedence_num() < term.precedence_num())
                {
                    table_row.under_term[term_index] =
                        insert_shift(table_row.under_term[term_index], act);
                    return(true);
                }
                else /* they are == precedence */

                /* equal precedences have equal sides, so only need to
                 * look at one: if it is right, put shift in table */
                {
                    if (term.precedence_side() == assoc.right)
                    {
                        table_row.under_term[term_index] =
                            insert_shift(table_row.under_term[term_index], act);
                        return(true);
                    }

                    /* if it is left, put reduce in table */
                    else if (term.precedence_side() == assoc.left)
                    {
                        table_row.under_term[term_index] =
                            insert_reduce(table_row.under_term[term_index], act);
                        return(true);
                    }

                    /* if it is nonassoc, we're not allowed to have two nonassocs
                     * of equal precedence in a row, so put in NONASSOC */
                    else if (term.precedence_side() == assoc.nonassoc)
                    {
                        table_row.under_term[term_index] = new nonassoc_action();
                        return(true);
                    }
                    else
                    {
                        /* something really went wrong */
                        throw new internal_error("Unable to resolve conflict correctly");
                    }
                }
            }

            /* check if terminal has precedence, if so, shift, since
             * rule does not have precedence */
            else if (term.precedence_num() > assoc.no_prec)
            {
                table_row.under_term[term_index] =
                    insert_shift(table_row.under_term[term_index], act);
                return(true);
            }

            /* otherwise, neither the rule nor the terminal has a precedence,
             * so it can't be fixed. */
            return(false);
        }
示例#5
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);
            }
        }
示例#6
0
	/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

	/** Determine if the Set contains a particular terminal. 
	 * @param sym the terminal symbol we are looking for.
	 */
	public bool contains(terminal sym) 
{
	not_null(sym); 
	return _elements.Get(sym.index());
}
示例#7
0
	/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

	/** Remove a terminal if it is in the Set.
	 * @param sym the terminal being removed.
	 */
	public void remove(terminal sym) 
{
	not_null(sym); 
	_elements.Set(sym.index(),false);
}
示例#8
0
	/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

	/** Add a single terminal to the Set.  
	 * @param sym the terminal being added.
	 * @return true if this changes the Set.
	 */
	public bool add(terminal sym) 
{
	bool result;

	not_null(sym); 

	/* see if we already have this */ 
	result = _elements.Get(sym.index());

	/* if not we add it */
	if (!result)
	_elements.Set(sym.index(),true);

	return result;
}