Package net.sourceforge.chaperon.parser.generator

Source Code of net.sourceforge.chaperon.parser.generator.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.parser.generator;

import java.util.Vector;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import net.sourceforge.chaperon.grammar.Grammar;
import net.sourceforge.chaperon.grammar.symbol.EmptySymbol;
import net.sourceforge.chaperon.grammar.symbol.Symbol;
import net.sourceforge.chaperon.grammar.symbol.SymbolList;
import net.sourceforge.chaperon.helpers.IntegerList;

/**
* This class represents a set of items
*
* @author Stephan Michels
* @version CVS $Id: ItemSet.java,v 1.7 2002/05/06 16:22:57 benedikta Exp $
*/
public class ItemSet
{

  private int         _capacityIncrement = 100;

  private int         _elementCount = 0;
  private int[]       _productions = new int[10];
  private int[]       _positions = new int[10];
  private Symbol[]    _lookaheads = new Symbol[10];

  // The symbols, which translate the states into other states
  private SymbolList  _transitionsymbols = new SymbolList(true);
  private IntegerList _transitionstates = new IntegerList();

  private Grammar     _grammar;
  private FirstSets   _firstsets;

  /**
   * Create an empty set of items
   *
   * @param grammar Grammar
   * @param firstsets The first sets
   */
  public ItemSet(Grammar grammar, FirstSets firstsets)
  {
    _grammar = grammar;
    _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, FirstSets firstsets, ItemSet I)
  {
    _grammar = grammar;
    _firstsets = firstsets;
    add(I);
  }

  /**
   * Add a item to this set
   *
   * @param production Production
   * @param position Position in this production
   * @param lookahead Lookahead symbol
   */
  public void addItem(int production, int position, Symbol lookahead)
  {
    if (!containsItem(production, position, lookahead))
    {
      ensureCapacity(_elementCount + 1);
      _productions[_elementCount] = production;
      _positions[_elementCount] = position;
      _lookaheads[_elementCount++] = lookahead;
    }
  }

  /**
   * Add the items from a itemset to this set.
   * If this set changed the method return true.
   *
   * @param I ItemSet
   *
   * @return True, if this set changed
   */
  public boolean add(ItemSet I)
  {
    boolean changed = false;

    for (int i = 0; i < I._elementCount; i++)
      if (!containsItem(I._productions[i], I._positions[i], I._lookaheads[i]))
      {
        addItem(I._productions[i], I._positions[i], I._lookaheads[i]);
        changed = true;
      }
    return changed;
  }

  /**
   * Get the production from an item from this set
   *
   * @param index Index of item
   *
   * @return Index of the production
   */
  /*private int getItemProduction(int index)
  {
    return productions[index];
  }*/

  /**
   * Get the position from an item from this set
   *
   * @param index Index of item
   *
   * @return Position in the porduction
   */
  /*private int getItemPosition(int index)
  {
    return positions[index];
  }*/

  /**
   * Get the symbol from an item from this set
   *
   * @param index Index of item
   *
   * @return Symbol
   */
  /*private Symbol getItemLookAhead(int index)
  {
    return lookaheads[index];
  }*/

  /**
   * 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)
  {
    for (int i = 0; i < _elementCount; i++)
      if ((_productions[i] == production) &&
          (_positions[i] == position) &&
          (_lookaheads[i].equals(lookahead)))
        return true;
    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 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 state
   *
   * @return True, if the state contains all items
   */
  private boolean contains(ItemSet itemset)
  {
    int i, j;
    int production, position;
    Symbol lookahead;
    boolean found;

    for (i = 0; i < itemset._elementCount; i++)
    {
      production = itemset._productions[i];
      position = itemset._positions[i];
      lookahead = itemset._lookaheads[i];

      found = false;
      for (j = 0; (j < _elementCount) && !found; j++)
        if ((_productions[j] == production) &&
            (_positions[j] == position) &&
            (_lookaheads[j]==lookahead))
          found = true;
      if (!found)
        return false;
    }
    return true;
  }

  /**
   * Test, if all cores of the items from a other
   * state exists in this state
   *
   * @param itemset Other state
   *
   * @return True, if the state contains all cores the
   *         items
   */
  private boolean containsCore(ItemSet itemset)
  {
    int i, j;
    int production, position;
    boolean found;

    for (i = 0; i < itemset._elementCount; i++)
    {
      production = itemset._productions[i];
      position = itemset._positions[i];

      found = false;
      for (j = 0; (j < _elementCount) && !found; j++)
        if ((_productions[j] == production) &&
            (_positions[j] == position))
          found = true;
      if (!found)
        return false;
    }
    return true;
  }

  /**
   * Returns the count of items in this set
   *
   * @return Count of items
   */
  public int getSize()
  {
    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 itemsets are equal
   */
  public boolean equals(Object o)
  {
    if (o instanceof ItemSet)
    {
      ItemSet itemset = (ItemSet) o;

      if (itemset.getSize() != getSize())
        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
   */
  private Symbol getItemNext(int index)
  {
    SymbolList productiondefinition;

    if (_positions[index] < ((productiondefinition =
        _grammar.getProductionList().getProduction(_productions[index]).getDefinition()).getSymbolCount()))
      return productiondefinition.getSymbol(_positions[index]);
    return EmptySymbol.EMPTY;
  }

  /**
   * Complete the itemset
   *
   * @return The new Itemset
   */
  public ItemSet closure()
  {
    ItemSet J = new ItemSet(_grammar, _firstsets, this); // J=I

    int i, j, k;                                       // Index variables
    SymbolList productiondefinition;
    SymbolList b = new SymbolList();
    SymbolList b2 = new SymbolList(true);
    IntegerList productionlist;
    Symbol symbol;

    // for every item in itemset I
    for (i = 0; i < J._elementCount; i++)
    {
      productiondefinition = _grammar.getProductionList().getProduction(J._productions[i]).getDefinition();

      // and not A=XYZ^
      if (J._positions[i] < productiondefinition.getSymbolCount())
      {
        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.isTerminal())
        {
          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 alle terminal symbols from FIRST(va)
            do
            {
              if (productiondefinition.getSymbol(pos).isTerminal())
              {
                b2.clear();
                b2.addSymbol(productiondefinition.getSymbol(pos));
              }
              else
                b2 = _firstsets.getFirstSet(productiondefinition.getSymbol(pos));
              b.addSymbolList(b2);
              pos++;
            }
            while ((b2.contains(EmptySymbol.EMPTY)) && (pos < productiondefinition.getSymbolCount()));

            if (b.contains(EmptySymbol.EMPTY))
              b.addSymbol(J._lookaheads[i]);

            b.removeSymbol(EmptySymbol.EMPTY);
          }
          else if (pos >= productiondefinition.getSymbolCount())
            // otherwise is b FIRST(a)
            b.addSymbol(J._lookaheads[i]);

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

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

  /**
   * Calculates the next State by a transition through the symbol X.
   *
   * @param X A Symbol, which can be a terminal or a non terminal symbol
   *
   * @return The next state
   */
  public ItemSet gotoX(Symbol X)
  {
    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(X))
        // add [A=uX^v,a] to J
        J.addItem(_productions[i], _positions[i] + 1, _lookaheads[i]);
    }
    // goto(I,X) = closure(J)
    return J.closure();
  }

  /**
   * Add a transition
   *
   * @param symbol Symbol, which transform the states into the
   *               other 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 transform the state
   *
   * @return List of symbols.
   */
  public SymbolList getShiftSymbols()
  {
    return _transitionsymbols;
  }

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

    for (int i = 0; i < _elementCount; i++)
    {
      if (getItemNext(i).isEmpty()) // 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 List of indicies from the productions
   */
  public IntegerList getReduceProductions(Symbol lookahead)
  {
    IntegerList reduceproductions = new IntegerList(true);

    for (int i = 0; i < _elementCount; i++)
    {
      // for all A=u^ and all symbols in FOLLOW(A)
      if ((getItemNext(i).isEmpty()) && (_lookaheads[i].equals(lookahead)))
        reduceproductions.add(_productions[i]);
    }
    return reduceproductions;
  }

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

    for (int i = 0; i < _elementCount; i++)
    {
      if (getItemNext(i).isEmpty()) // for all A=u^ and all symbols in FOLLOW(A)
        reducesymbols.addSymbol(_lookaheads[i]);
    }
    return reducesymbols;
  }

  /**
   * Ensure the capacity for adding values
   *
   * @param minCapacity
   */
  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)];
    Symbol[] newLookaheads = new Symbol[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;
  }

  /**
   * Converts the itemset to a string
   *
   * @return Content of the itemset
   */
  public String toString()
  {
    StringBuffer buffer = new StringBuffer();
    SymbolList list;

    for (int i = 0; i < _elementCount; i++)
    {
      buffer.append(_grammar.getProductionList().getProduction(_productions[i]).getSymbol());
      buffer.append("->");
      list = (SymbolList) _grammar.getProductionList().getProduction(_productions[i]).getDefinition();

      for (int j = 0; j < list.getSymbolCount(); j++)
      {
        if (j == _positions[i])
          buffer.append(".");

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

      if (_positions[i] == list.getSymbolCount())
        buffer.append(".");

      if (_lookaheads[i] != null)
        buffer.append("," + _lookaheads[i]);

      buffer.append(" [" + _productions[i] + "," + _positions[i] + "]");

      buffer.append("\n");
    }
    return buffer.toString();
  }
}
TOP

Related Classes of net.sourceforge.chaperon.parser.generator.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.