Package net.sourceforge.chaperon.build

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

/*
*  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.model.grammar.Grammar;
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;

import org.apache.commons.logging.Log;

/**
* This class creates a collection of FIRST sets.
*
* @author <a href="mailto:stephan@apache.org">Stephan Michels</a>
* @version CVS $Id: FirstSetCollection.java,v 1.10 2003/12/10 16:34:38 benedikta Exp $
*/
public class FirstSetCollection
{
  private Grammar grammar;
  private Symbol[] symbols;
  private SymbolSet[] firstsets;
  private Log log;
  private static final EmptyList EMPTYLIST = new EmptyList();

  /**
   * Create a collection of FIRST sets.
   *
   * @param grammar Grammar.
   */
  public FirstSetCollection(Grammar grammar)
  {
    this(grammar, null);
  }

  /**
   * Create a collection of FIRST sets
   *
   * @param grammar Grammar
   * @param log Log, whch should be used.
   */
  public FirstSetCollection(Grammar grammar, Log log)
  {
    this.grammar = grammar;
    this.log = log;

    SymbolSet usedsymbols = grammar.getSymbols();

    symbols = new Symbol[usedsymbols.getSymbolCount()];
    firstsets = new SymbolSet[usedsymbols.getSymbolCount()];
    for (int i = 0; i<usedsymbols.getSymbolCount(); i++)
    {
      if (log!=null)
        log.debug("Generating first set for "+usedsymbols.getSymbol(i).getName());

      symbols[i] = usedsymbols.getSymbol(i);
      firstsets[i] = first(symbols[i]);
    }
  }

  /**
   * Returns the FIRST set for a symbol.
   *
   * @param symbol Symbol.
   *
   * @return Set of symbols.
   */
  public SymbolSet getFirstSet(Symbol symbol)
  {
    for (int i = 0; i<symbols.length; i++)
      if (symbols[i].equals(symbol))
        return firstsets[i];

    throw new IllegalArgumentException("No first set found for symbol");
  }

  /**
   * Returns the FIRST set for a sequence of symbols.
   *
   * @param symbol Sequence of symbols.
   *
   * @return Set of symbols.
   */
  public SymbolSet getFirstSet(SymbolList symbols)
  {
    SymbolSet firstset = new SymbolSet();

    if (symbols.getSymbolCount()==0)
    {
      firstset.addSymbol(EMPTYLIST);
      return firstset;
    }

    int position = 0;
    do
    {
      firstset.removeSymbol(EMPTYLIST);

      if (symbols.getSymbol(position) instanceof Terminal)
        firstset.addSymbol(symbols.getSymbol(position));
      else
        firstset.addSymbol(getFirstSet(symbols.getSymbol(position)));

      position++;
    }
    while ((firstset.contains(EMPTYLIST)) && (position<symbols.getSymbolCount()));

    return firstset;
  }

  /**
   * Calculates the FIRST set. The FIRST set is the set of terminal symbols, which come as next
   * symbol
   *
   * @param symbol Symbol.
   *
   * @return Set of symbol.
   */
  private SymbolSet first(Symbol symbol)
  {
    return first(symbol, new SymbolSet());
  }

  /**
   * Calculates the FIRST set. The FIRST set is the set of terminal symbols, which come as next
   * symbol.
   *
   * @param symbol Symbol.
   * @param visited Set of symbol, which were already calculated.
   *
   * @return Set of symbols.
   */
  private SymbolSet first(Symbol symbol, SymbolSet visited)
  {
    SymbolSet firstset = new SymbolSet();

    // if the symbol is a terminal symbol
    if (symbol instanceof Terminal)
    {
      firstset.addSymbol(symbol);
      return firstset;
    }

    if (visited.contains(symbol))
      return firstset;
    else
      visited.addSymbol(symbol);

    // if is a non terminal symbol
    IntegerList productions = grammar.getProductionList(symbol);
    SymbolSet examined = new SymbolSet()// List of all examined symbols

    for (int i = 0; i<productions.getCount(); i++)
    {
      SymbolList productiondefinition = grammar.getProduction(productions.get(i)).getDefinition();
      if (productiondefinition.getSymbolCount()==0)

        // Symbol for a empty firstset added
        firstset.addSymbol(EMPTYLIST);
      else
      {
        // for every symbol in the production
        int j = 0;
        Symbol newsymbol;
        boolean foundEmptyList;
        do
        {
          foundEmptyList = true;
          newsymbol = productiondefinition.getSymbol(j);
          if (newsymbol instanceof Terminal)

            // if a terminal symbol
            firstset.addSymbol(newsymbol);
          else if (!newsymbol.equals(symbol))
          {
            // and if a non terminal symbol
            if (!examined.contains(newsymbol))
            {
              SymbolSet newfirstset = first(newsymbol, visited);
              foundEmptyList = newfirstset.contains(EMPTYLIST);
              for (int k = 0; k<newfirstset.getSymbolCount(); k++)
                if (!newfirstset.getSymbol(k).equals(EMPTYLIST))
                  firstset.addSymbol(newfirstset.getSymbol(k));

              examined.addSymbol(newsymbol);
            }
          }

          j++;
        }
        while ((!(newsymbol instanceof Terminal)) && (foundEmptyList) &&
               (j<productiondefinition.getSymbolCount()) &&
               (!productiondefinition.getSymbol(j-1).equals(symbol)));
      }
    }

    return firstset;
  }

  /**
   * Return a string representation of the FIRST sets.
   *
   * @return String representation of the FIRST sets.
   */
  public String toString()
  {
    StringBuffer buffer = new StringBuffer();

    SymbolSet symbols = grammar.getSymbols();

    for (int symbol = 0; symbol<symbols.getSymbolCount(); symbol++)
    {
      buffer.append("first(");
      buffer.append(symbols.getSymbol(symbol).toString());
      buffer.append(")=");
      buffer.append(getFirstSet(symbols.getSymbol(symbol)).toString());
      buffer.append("\n");
    }

    return buffer.toString();
  }
}
TOP

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

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.