Package net.sourceforge.chaperon.build

Source Code of net.sourceforge.chaperon.build.ItemSet

/*
*  Copyright (C) Chaperon. All rights reserved.
*  -------------------------------------------------------------------------
*  This software is published under the terms of the Apache Software License
*  version 1.1, a copy of which has been included  with this distribution in
*  the LICENSE file.
*/

package net.sourceforge.chaperon.build;

import net.sourceforge.chaperon.common.IntegerList;
import net.sourceforge.chaperon.common.IntegerSet;
import net.sourceforge.chaperon.model.grammar.Error;
import net.sourceforge.chaperon.model.grammar.Grammar;
import net.sourceforge.chaperon.model.symbol.Nonterminal;
import net.sourceforge.chaperon.model.symbol.Symbol;
import net.sourceforge.chaperon.model.symbol.SymbolList;
import net.sourceforge.chaperon.model.symbol.SymbolSet;
import net.sourceforge.chaperon.model.symbol.Terminal;

/**
* This class represents a set of items, which means positions of production, in production and
* lookahead symbols. These  item sets were used to decribes states.
*
* @author <a href="mailto:stephan@apache.org">Stephan Michels</a>
* @version CVS $Id: ItemSet.java,v 1.17 2003/12/09 19:55:52 benedikta Exp $
*/
public class ItemSet
{
  private int capacityIncrement = 25;
  private int elementCount = 0;
  private int[] productions = new int[25];
  private int[] positions = new int[25];
  private SymbolSet[] lookaheads = new SymbolSet[25];

  // The symbols, which translate the states into other states
  private SymbolSet transitionsymbols = new SymbolSet();
  private IntegerList transitionstates = new IntegerList();
  private Grammar grammar;
  private FirstSetCollection firstsets;
  private static final EmptyList EMPTYLIST = new EmptyList();

  /**
   * Create an empty set of items.
   *
   * @param grammar Grammar.
   * @param firstsets The first sets.
   */
  public ItemSet(Grammar grammar, FirstSetCollection firstsets)
  {
    this.grammar = grammar;
    this.firstsets = firstsets;
  }

  /**
   * Create a state, which contains this itemset.
   *
   * @param grammar Grammar.
   * @param firstsets The first sets.
   * @param I Itemset, which the state should contain.
   */
  private ItemSet(Grammar grammar, FirstSetCollection firstsets, ItemSet I)
  {
    this.grammar = grammar;
    this.firstsets = firstsets;
    addItemSet(I);
  }

  /**
   * Add a item to this set.
   *
   * @param production Production.
   * @param position Position in this production.
   * @param lookahead Lookahead symbol.
   *
   * @return True, if this item was added
   */
  public boolean addItem(int production, int position, Symbol lookahead)
  {
    if (lookahead==null)
      throw new NullPointerException("Lookahead symbol is null");

    for (int i = 0; i<elementCount; i++)
      if ((productions[i]==production) && (positions[i]==position))
      {
        if (lookaheads[i]==null)
          lookaheads[i] = new SymbolSet();

        return lookaheads[i].addSymbol(lookahead);
      }

    ensureCapacity(elementCount+1);
    productions[elementCount] = production;
    positions[elementCount] = position;
    lookaheads[elementCount] = new SymbolSet();
    lookaheads[elementCount++].addSymbol(lookahead);

    return true;
  }

  public boolean addItem(int production, int position, SymbolSet lookaheads)
  {
    if (lookaheads==null)
      throw new NullPointerException("Lookahead symbol set is null");

    for (int i = 0; i<elementCount; i++)
      if ((productions[i]==production) && (positions[i]==position))
      {
        if (this.lookaheads[i]==null)
          this.lookaheads[i] = new SymbolSet();

        return this.lookaheads[i].addSymbol(lookaheads);
      }

    ensureCapacity(elementCount+1);
    productions[elementCount] = production;
    positions[elementCount] = position;
    this.lookaheads[elementCount] = new SymbolSet();
    this.lookaheads[elementCount++].addSymbol(lookaheads);

    return true;
  }

  /**
   * Add the items from another itemset to this set. If this set changed the method will return
   * true.
   *
   * @param I ItemSet, which should be addded.
   *
   * @return True, if this set was changed
   */
  public boolean addItemSet(ItemSet I)
  {
    boolean changed = false;

    for (int i = 0; i<I.elementCount; i++)
      changed |= addItem(I.productions[i], I.positions[i], I.lookaheads[i]);

    return changed;
  }

  /**
   * If this set contains an item, which compare by the production, position and lookahead symbol.
   *
   * @param production Index of production in the grammar.
   * @param position Position in the production.
   * @param lookahead Lookahead symbol.
   *
   * @return True, if this set contains the item.
   */

  /*private boolean containsItem(int production, int position, Symbol lookahead)
  {
    if (lookahead==null)
      throw new NullPointerException("Lookahead symbol is null");

    for (int i = 0; i<elementCount; i++)
      if ((productions[i]==production) && (positions[i]==position))
        return lookaheads[i].contains(lookahead);
    return false;
  }*/

  /**
   * If this set contains an item, which compare by the production and position.
   *
   * @param production Index of production in the grammar.
   * @param position Position in the production.
   *
   * @return True, if this set contains the core of the item.
   */

  /*private boolean containsItemCore(int production, int position)
  {
    for (int i = 0; i<elementCount; i++)
      if ((productions[i]==production) && (positions[i]==position))
        return true;
    return false;
  }*/

  /**
   * Test, if all items from a other state exists in this state
   *
   * @param itemset Other item set.
   *
   * @return True, if the state contains all items.
   */
  public boolean contains(ItemSet itemset)
  {
    for (int i = 0; i<itemset.elementCount; i++)
    {
      int production = itemset.productions[i];
      int position = itemset.positions[i];

      boolean found = false;
      for (int j = 0; j<elementCount; j++)
        if ((productions[j]==production) && (positions[j]==position))
        {
          found = lookaheads[j].contains(itemset.lookaheads[i]);
          break;
        }

      if (!found)
        return false;
    }

    return true;
  }

  /**
   * Test, if all cores of the items from another item set exists in this item set.
   *
   * @param itemset Other item set.
   *
   * @return True, if the state contains all cores the items.
   */
  private boolean containsCore(ItemSet itemset)
  {
    for (int i = 0; i<itemset.elementCount; i++)
    {
      int production = itemset.productions[i];
      int position = itemset.positions[i];

      boolean found = false;
      for (int j = 0; (j<elementCount) && !found; j++)
        found = ((productions[j]==production) && (positions[j]==position));

      if (!found)
        return false;
    }

    return true;
  }

  /**
   * Returns the count of items in this set.
   *
   * @return Count of items of the core.
   */
  public int getItemCount()
  {
    return elementCount;
  }

  /**
   * Returns true, if this set is empty.
   *
   * @return True, if this set is empty.
   */
  public boolean isEmpty()
  {
    return (elementCount==0);
  }

  /**
   * Compares two item sets.
   *
   * @param o Other itemset.
   *
   * @return True, if the item sets are equal.
   */
  public boolean equals(Object o)
  {
    if (o instanceof ItemSet)
    {
      ItemSet itemset = (ItemSet)o;

      if (itemset.getItemCount()!=getItemCount())
        return false;

      // The itemset must contain all item from this set.
      if (!contains(itemset))
        return false;

      // And this set must contain all item from the item set
      if (!itemset.contains(this))
        return false;

      return true;
    }

    return false;
  }

  /**
   * Compares the core of two item sets.
   *
   * @param o Other itemset.
   *
   * @return True, if the core of the itemsets are equal.
   */
  public boolean equalsCore(Object o)
  {
    if (o instanceof ItemSet)
    {
      ItemSet itemset = (ItemSet)o;

      // The itemset must contain all item from this set.
      if (!containsCore(itemset))
        return false;

      // And this set must contain all item from the item set
      if (!itemset.containsCore(this))
        return false;

      return true;
    }

    return false;
  }

  /**
   * Return the next Symbol, which follow the item.
   *
   * @param index Index the item.
   *
   * @return Symbol of the next position, otherwise the symbol for an empty list.
   */
  private Symbol getItemNext(int index)
  {
    SymbolList productiondefinition;

    if (positions[index]<((productiondefinition =
                          grammar.getProduction(productions[index]).getDefinition()).getSymbolCount()))
      return productiondefinition.getSymbol(positions[index]);

    return EMPTYLIST;
  }

  public SymbolSet getNextTerminals()
  {
    SymbolSet set = new SymbolSet();

    SymbolList productiondefinition;
    for (int item = 0; item<elementCount; item++)
      if ((positions[item]<((productiondefinition =
                            grammar.getProduction(productions[item]).getDefinition()).getSymbolCount())) &&
          (productiondefinition.getSymbol(positions[item]) instanceof Terminal))
        set.addSymbol(productiondefinition.getSymbol(positions[item]));

    return set;
  }

  public SymbolSet getNextNonterminals()
  {
    SymbolSet set = new SymbolSet();

    SymbolList productiondefinition;
    for (int item = 0; item<elementCount; item++)
      if ((positions[item]<((productiondefinition =
                            grammar.getProduction(productions[item]).getDefinition()).getSymbolCount())) &&
          (productiondefinition.getSymbol(positions[item]) instanceof Nonterminal))
        set.addSymbol(productiondefinition.getSymbol(positions[item]));

    return set;
  }

  public Error getNextError()
  {
    SymbolList productiondefinition;
    for (int item = 0; item<elementCount; item++)
      if ((positions[item]<((productiondefinition =
                            grammar.getProduction(productions[item]).getDefinition()).getSymbolCount())) &&
          (productiondefinition.getSymbol(positions[item]) instanceof Error))
        return (Error)productiondefinition.getSymbol(positions[item]);

    return null;
  }

  /**
   * Calculate the closure for this item set.
   *
   * @return Closure of the item set
   */
  public ItemSet closure()
  {
    ItemSet J = new ItemSet(grammar, firstsets, this)// J=I

    SymbolSet b = new SymbolSet();
    SymbolSet b2 = new SymbolSet();

    boolean changed = false;
    do
    {
      changed = false;

      // for every item in itemset I
      for (int i = 0; i<J.elementCount; i++)
      {
        SymbolList productiondefinition = grammar.getProduction(J.productions[i]).getDefinition();

        // and not A=XYZ^
        if (J.positions[i]<productiondefinition.getSymbolCount())
        {
          Symbol symbol = productiondefinition.getSymbol(J.positions[i])// A=X ^symbol Z

          // for every item [A=u^Bv,a] in J and production B=w in G
          if (symbol instanceof Nonterminal)
          {
            int pos = J.positions[i]+1// for the FIRST set from (va)

            b.clear();

            // if [A=u^Bv,a]
            if (pos<productiondefinition.getSymbolCount())
            {
              // then is b the list of all terminal symbols from FIRST(va)
              do
              {
                if (productiondefinition.getSymbol(pos) instanceof Terminal)
                {
                  b2.clear();
                  b2.addSymbol(productiondefinition.getSymbol(pos));
                }
                else
                {
                  b2.clear();
                  b2.addSymbol(firstsets.getFirstSet(productiondefinition.getSymbol(pos)));
                }

                b.addSymbol(b2);
                pos++;
              }
              while ((b2.contains(EMPTYLIST)) && (pos<productiondefinition.getSymbolCount()));

              if (b.contains(EMPTYLIST))
                b.addSymbol(J.lookaheads[i]);

              b.removeSymbol(EMPTYLIST);
            }
            else if (pos>=productiondefinition.getSymbolCount())

              // otherwise is b FIRST(a)
              b.addSymbol(J.lookaheads[i]);

            // list of all productions B
            IntegerList productionlist = grammar.getProductionList(symbol);

            // for alle productions B
            for (int j = 0; j<productionlist.getCount(); j++)
            {
              // if J doesn't contain [B=^w,b] , should it added
              for (int k = 0; k<b.getSymbolCount(); k++)
                changed |= J.addItem(productionlist.get(j), 0, b.getSymbol(k));
            }
          }
        }
      }
    }
    while (changed);

    return J;
  }

  /**
   * Calculates the next state by a transition through the symbol X.
   *
   * @param symbol A Symbol, which can be a terminal or a nonterminal symbol.
   *
   * @return The next state, represented by an item set.
   */
  public ItemSet jump(Symbol symbol)
  {
    ItemSet J = new ItemSet(grammar, firstsets);

    // For every item [A=u^Xv,a] in I
    for (int i = 0; i<elementCount; i++)
    {
      if (getItemNext(i).equals(symbol))

        // add [A=uX^v,a] to J
        J.addItem(productions[i], positions[i]+1, lookaheads[i]);
    }

    // jump(I,X) = closure(J)
    return J.closure();
  }

  /**
   * Add a transition to this state.
   *
   * @param symbol Symbol, which forces a transition into another state.
   * @param state Destination state.
   */
  public void setTransition(Symbol symbol, int state)
  {
    if (transitionsymbols.contains(symbol))
      transitionstates.set(transitionsymbols.indexOf(symbol), state);
    else
    {
      transitionsymbols.addSymbol(symbol);
      transitionstates.add(state);
    }
  }

  /**
   * Returns the destination state of a transition.
   *
   * @param symbol Symbol, which force the transition.
   *
   * @return Destination state.
   */
  public int getTransition(Symbol symbol)
  {
    if (transitionsymbols.contains(symbol))
      return transitionstates.get(transitionsymbols.indexOf(symbol));

    return -1;
  }

  /**
   * Returns all symbols, which forces a transition.
   *
   * @return List of symbols.
   */
  public SymbolSet getShiftSymbols()
  {
    return transitionsymbols;
  }

  /**
   * Returns the list of productions, which could be reduced.
   *
   * @return List of indicies for the productions.
   */
  public IntegerSet getReduceProductions()
  {
    IntegerSet reduceproductions = new IntegerSet();

    for (int i = 0; i<elementCount; i++)
    {
      if (getItemNext(i).equals(EMPTYLIST))  // for all A=u^ and all symbols in FOLLOW(A)

        reduceproductions.add(productions[i]);
    }

    return reduceproductions;
  }

  /**
   * Returns the list of productions, which a special symbol reduce.
   *
   * @param lookahead Symbol, which the productions reduce.
   *
   * @return Set of indicies from the productions.
   */
  public IntegerSet getReduceProductions(Symbol lookahead)
  {
    IntegerSet reduceproductions = new IntegerSet();

    for (int i = 0; i<elementCount; i++)
    {
      // for all A=u^ and all symbols in FOLLOW(A)
      if ((getItemNext(i).equals(EMPTYLIST)) &&
          (lookaheads[i].contains(lookahead) || lookaheads[i].contains(Error.instance)))
        reduceproductions.add(productions[i]);
    }

    return reduceproductions;
  }

  /**
   * Return all symbols, which reduce productions in this state.
   *
   * @return Set of symbols.
   */
  public SymbolSet getReduceSymbols()
  {
    SymbolSet reducesymbols = new SymbolSet();

    for (int i = 0; i<elementCount; i++)
    {
      if (getItemNext(i).equals(EMPTYLIST))  // for all A=u^ and all symbols in FOLLOW(A)

        reducesymbols.addSymbol(lookaheads[i]);
    }

    return reducesymbols;
  }

  /**
   * Ensure the capacity for adding items.
   *
   * @param minCapacity Minimum capacity.
   */
  private void ensureCapacity(int minCapacity)
  {
    if (productions.length>=minCapacity)
      return;

    int newCapacity = productions.length+capacityIncrement;

    if (capacityIncrement<=0)
      newCapacity = productions.length*2;

    int[] newProductions = new int[Math.max(newCapacity, minCapacity)];
    int[] newPositions = new int[Math.max(newCapacity, minCapacity)];
    SymbolSet[] newLookaheads = new SymbolSet[Math.max(newCapacity, minCapacity)];

    System.arraycopy(productions, 0, newProductions, 0, productions.length);
    System.arraycopy(positions, 0, newPositions, 0, productions.length);
    System.arraycopy(lookaheads, 0, newLookaheads, 0, productions.length);

    productions = newProductions;
    positions = newPositions;
    lookaheads = newLookaheads;
  }

  /**
   * Return a string representation of this item set.
   *
   * @return String representation of this item set.
   */
  public String toString()
  {
    StringBuffer buffer = new StringBuffer();

    SymbolList list;

    for (int production = 0; production<grammar.getProductionCount(); production++)
    {
      list = grammar.getProduction(production).getDefinition();

      for (int position = 0; position<=list.getSymbolCount(); position++)
      {
        for (int item = 0; item<elementCount; item++)
          if ((productions[item]==production) && (positions[item]==position))
          {
            buffer.append(grammar.getProduction(production).getSymbol());
            buffer.append(" -> ");

            for (int i = 0; i<list.getSymbolCount(); i++)
            {
              if (i==position)
                buffer.append(".");

              buffer.append(list.getSymbol(i)+" ");
            }

            if (position==list.getSymbolCount())
              buffer.append(".");

            buffer.append(" , ");
            for (int lookahead = 0; lookahead<lookaheads[item].getSymbolCount(); lookahead++)
            {
              if (lookahead>0)
                buffer.append(" / ");

              buffer.append(lookaheads[item].getSymbol(lookahead).toString());
            }

            buffer.append("\n");
            break;
          }
      }
    }

    SymbolSet set = getShiftSymbols();

    for (int index = 0; index<set.getSymbolCount(); index++)
    {
      buffer.append("Transition for ");
      buffer.append(set.getSymbol(index));
      buffer.append(" -> State ");
      buffer.append(String.valueOf(getTransition(set.getSymbol(index))));
      buffer.append("\n");
    }

    return buffer.toString();
  }
}
TOP

Related Classes of net.sourceforge.chaperon.build.ItemSet

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.