예제 #1
0
        /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

        /** Equality comparison. */

        /* equality comparison, but with different name as Equal because
         * it's only logical equation. That means that Sets of different length but
         * padded only with 0's are equal
         */
        public bool equals(BitArray set1, terminal_set set2)
        {
            if (set2 == null || set1 == null)
            {
                return(false);
            }
            else
            {
                int    max = System.Math.Max(set1.Length, set2._elements.Length);
                bool[] ar1 = new bool[max];
                bool[] ar2 = new bool[max];
                set1.CopyTo(ar1, 0);
                set2._elements.CopyTo(ar2, 0);
                bool eq = true;
                for (int i = 0; i < max; i++)
                {
                    if (ar1[i] != ar2[i])
                    {
                        eq = false;
                    }
                }

                return(eq);
            }
        }
예제 #2
0
        /*-----------------------------------------------------------*/
        /*--- General Methods ---------------------------------------*/
        /*-----------------------------------------------------------*/

        /** Propagate incoming lookaheads through this item to others need to
         *  be changed.
         * @params incoming symbols to potentially be added to lookahead of this item.
         */
        public void propagate_lookaheads(terminal_set incoming)
        {
            bool change = false;

            /* if we don't need to propagate, then bail out now */
            if (!needs_propagation && (incoming == null || incoming.empty()))
            {
                return;
            }

            /* if we have null incoming, treat as an empty Set */
            if (incoming != null)
            {
                /* add the incoming to the lookahead of this item */
                change = lookahead().add(incoming);
            }

            /* if we changed or need it anyway, propagate across our links */
            if (change || needs_propagation)
            {
                /* don't need to propagate again */
                needs_propagation = false;

                /* propagate our lookahead into each item we are linked to */
                IEnumerator myEnum = propagate_items().GetEnumerator();
                while (myEnum.MoveNext())
                {
                    ((lalr_item)myEnum.Current).propagate_lookaheads(lookahead());
                }
            }
        }
예제 #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
        /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

        /** Determine if this Set intersects another.
         * @param other the other Set in question.
         */
        public bool intersects(terminal_set other)
        {
            not_null(other);

            /* make a copy of the other Set */
            BitArray copy = (BitArray)other._elements.Clone();

            /* xor out our values */
            copy.Xor(this._elements);

            /* see if its different */
            return(!equals(copy, other));
        }
예제 #5
0
        /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

        /** Add (union) in a complete Set.
         * @param other the Set being added.
         * @return true if this changes the Set.
         */
        public bool add(terminal_set other)
        {
            not_null(other);

            /* make a copy */
            BitArray copy = (BitArray)_elements.Clone();

            /* or in the other Set */
            equalize(ref _elements, ref other._elements);
            _elements.Or(other._elements);

            /* changed if we are not the same as the copy */
            return(!equals(_elements, copy));
        }
예제 #6
0
        public bool is_subset_of(terminal_set other)
        {
            not_null(other);

            /* make a copy of the other Set */

            BitArray copy_other = (BitArray)other._elements.Clone();

            equalize(ref copy_other, ref _elements);
            /* and or in */

            copy_other.Or(_elements);



            /* if it hasn't changed, we were a subset */
            return(equals(copy_other, other));
        }
예제 #7
0
        /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

        /** Determine if this Set is an (improper) superset of another.
         * @param other the Set we are testing against.
         */
        public bool is_superset_of(terminal_set other)
        {
            not_null(other);
            return(other.is_subset_of(this));
        }
        /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
        /** Produce warning messages for all conflicts found in this state.  */
        protected void report_conflicts(terminal_set conflict_set)
        {
            lalr_item    itm, compare;

              bool      after_itm;

              /* consider each element */
              IEnumerator itms = items().all();
              while ( itms.MoveNext() )
            {
              itm = (lalr_item)itms.Current;

              /* clear the S/R conflict Set for this item */

              /* if it results in a reduce, it could be a conflict */
              if (itm.dot_at_end())
            {
              /* not yet after itm */
              after_itm = false;

              /* compare this item against all others looking for conflicts */
              IEnumerator comps = items().all();
              while (comps.MoveNext() )
            {
              compare = (lalr_item)comps.Current;

              /* if this is the item, next one is after it */
              if (itm == compare) after_itm = true;

              /* only look at it if its not the same item */
              if (itm != compare)
            {
              /* is it a reduce */
              if (compare.dot_at_end())
            {
              /* only look at reduces after itm */
              if (after_itm)
                            /* does the comparison item conflict? */
                            if (compare.lookahead().intersects(itm.lookahead()))
                              /* report a reduce/reduce conflict */
                              report_reduce_reduce(itm, compare);
            }
            }
            }
              /* report S/R conflicts under all the symbols we conflict under */
              for (int t = 0; t < terminal.number(); t++)
            if (conflict_set.contains(t))
              report_shift_reduce(itm,t);
            }
            }
        }
예제 #9
0
        /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

        /** Constructor with default position (dot at start).
         * @param prod the production for the item.
         * @param look the Set of lookahead symbols.
         */
        public lalr_item(production prod, terminal_set look) : this(prod, 0, look)
        {
//	this(prod,0,look);
        }
예제 #10
0
 /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/
 /** Constructor with default position (dot at start).
  * @param prod the production for the item.
  * @param look the Set of lookahead symbols.
  */
 public lalr_item(production prod, terminal_set look)
     : this(prod,0,look)
 {
     //	this(prod,0,look);
 }
예제 #11
0
	/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

	/** Add (union) in a complete Set.  
	 * @param other the Set being added.
	 * @return true if this changes the Set.
	 */
	public bool add(terminal_set other)
{
	not_null(other);
  
	/* make a copy */
	BitArray copy = (BitArray)_elements.Clone();

	/* or in the other Set */
    equalize(ref _elements,ref other._elements);
    _elements.Or(other._elements);

	/* changed if we are not the same as the copy */
	return !equals(_elements,copy);
}
예제 #12
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);
            }
        }
예제 #13
0
        /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

        /** Produce warning messages for all conflicts found in this state.  */
        protected void report_conflicts(terminal_set conflict_set)

        {
            lalr_item itm, compare;

            bool after_itm;

            /* consider each element */
            IEnumerator itms = items().all();

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

                /* clear the S/R conflict Set for this item */

                /* if it results in a reduce, it could be a conflict */
                if (itm.dot_at_end())
                {
                    /* not yet after itm */
                    after_itm = false;

                    /* compare this item against all others looking for conflicts */
                    IEnumerator comps = items().all();
                    while (comps.MoveNext())
                    {
                        compare = (lalr_item)comps.Current;

                        /* if this is the item, next one is after it */
                        if (itm == compare)
                        {
                            after_itm = true;
                        }

                        /* only look at it if its not the same item */
                        if (itm != compare)
                        {
                            /* is it a reduce */
                            if (compare.dot_at_end())
                            {
                                /* only look at reduces after itm */
                                if (after_itm)
                                {
                                    /* does the comparison item conflict? */
                                    if (compare.lookahead().intersects(itm.lookahead()))
                                    {
                                        /* report a reduce/reduce conflict */
                                        report_reduce_reduce(itm, compare);
                                    }
                                }
                            }
                        }
                    }
                    /* report S/R conflicts under all the symbols we conflict under */
                    for (int t = 0; t < terminal.number(); t++)
                    {
                        if (conflict_set.contains(t))
                        {
                            report_shift_reduce(itm, t);
                        }
                    }
                }
            }
        }
예제 #14
0
		/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

		/** Constructor for cloning from another Set. 
		 * @param other the Set we are cloning from.
		 */
		public terminal_set(terminal_set other) 
			{
				not_null(other);
		_elements = (BitArray)other._elements.Clone();
	}
예제 #15
0
	/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

	/** Equality comparison. */
        /* equality comparison, but with different name as Equal because 
         * it's only logical equation. That means that Sets of different length but 
         * padded only with 0's are equal
         */
        public  bool equals(BitArray set1,terminal_set set2)
        {
            if (set2 == null||set1==null) 
                return false;
            else
            {
                int max=System.Math.Max(set1.Length,set2._elements.Length);
                bool[] ar1=new bool[max];
                bool[] ar2=new bool[max];
                set1.CopyTo(ar1,0);
                set2._elements.CopyTo(ar2,0);
                bool eq=true;
                for (int i=0;i<max;i++)
                    if (ar1[i]!=ar2[i]) eq=false;

                return eq;
            }
        }
예제 #16
0
	/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

	/** Determine if this Set intersects another.
	 * @param other the other Set in question.
	 */
	public bool intersects(terminal_set other)
{
	not_null(other);

	/* make a copy of the other Set */
	BitArray copy = (BitArray)other._elements.Clone();

	/* xor out our values */
	copy.Xor(this._elements);

	/* see if its different */
	return !equals(copy,other);
}
예제 #17
0
	public bool is_subset_of(terminal_set other)
{
	not_null(other);

	/* make a copy of the other Set */ 
    
	BitArray copy_other = (BitArray)other._elements.Clone();
    equalize(ref copy_other,ref  _elements);
	/* and or in */
       
    copy_other.Or(_elements);

          
    
	/* if it hasn't changed, we were a subset */
	return equals(copy_other,other);
}
예제 #18
0
        /*-----------------------------------------------------------*/
        /*--- General Methods ---------------------------------------*/
        /*-----------------------------------------------------------*/
        /** Propagate incoming lookaheads through this item to others need to
         *  be changed.
         * @params incoming symbols to potentially be added to lookahead of this item.
         */
        public void propagate_lookaheads(terminal_set incoming)
        {
            bool change = false;

            /* if we don't need to propagate, then bail out now */
            if (!needs_propagation && (incoming == null || incoming.empty()))
            return;

            /* if we have null incoming, treat as an empty Set */
            if (incoming != null)
            {
            /* add the incoming to the lookahead of this item */
            change = lookahead().add(incoming);
            }

            /* if we changed or need it anyway, propagate across our links */
            if (change || needs_propagation)
            {
            /* don't need to propagate again */
            needs_propagation = false;

            /* propagate our lookahead into each item we are linked to */
            IEnumerator myEnum= propagate_items().GetEnumerator();
            while (myEnum.MoveNext())
            ((lalr_item)myEnum.Current).propagate_lookaheads(lookahead());
            }
        }
예제 #19
0
        /*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

        /** Constructor for cloning from another Set.
         * @param other the Set we are cloning from.
         */
        public terminal_set(terminal_set other)
        {
            not_null(other);
            _elements = (BitArray)other._elements.Clone();
        }
예제 #20
0
	/*. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .*/

	/** Determine if this Set is an (improper) superset of another.
	 * @param other the Set we are testing against.
	 */
	public bool is_superset_of(terminal_set other)
{
	not_null(other);
	return other.is_subset_of(this);
}
예제 #21
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;
        }
예제 #22
0
        /*-----------------------------------------------------------*/
        /*--- Constructor(s) ----------------------------------------*/
        /*-----------------------------------------------------------*/

        /** Full constructor.
         * @param prod the production for the item.
         * @param pos  the position of the "dot" within the production.
         * @param look the Set of lookahead symbols.
         */
        public lalr_item(production prod, int pos, terminal_set look) : base(prod, pos)
        {
            _lookahead        = look;
            _propagate_items  = new Stack();
            needs_propagation = true;
        }
예제 #23
0
 /*-----------------------------------------------------------*/
 /*--- Constructor(s) ----------------------------------------*/
 /*-----------------------------------------------------------*/
 /** Full constructor.
                         * @param prod the production for the item.
                         * @param pos  the position of the "dot" within the production.
                         * @param look the Set of lookahead symbols.
                         */
 public lalr_item(production prod, int pos, terminal_set look)
     : base(prod,pos)
 {
     _lookahead = look;
     _propagate_items = new Stack();
     needs_propagation = true;
 }
예제 #24
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);
        }