Package net.sourceforge.chaperon.parser.generator

Source Code of net.sourceforge.chaperon.parser.generator.FirstSets

/*
*  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 org.apache.avalon.framework.logger.LogEnabled;
import org.apache.avalon.framework.logger.Logger;

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 creates the set of first-sets
*
* @author Stephan Michels
* @version CVS $Id: FirstSets.java,v 1.6 2002/05/06 16:22:57 benedikta Exp $
*/
public class FirstSets implements LogEnabled
{

  private Grammar      _grammar;

  private Symbol[]     _symbols;
  private SymbolList[] _firstsets;

  private Logger       _logger;

  /**
   * Create a firstset of the first sets
   *
   * @param grammar Grammar
   * @param logger the logger
   */
  public FirstSets(Grammar grammar, Logger logger)
  {
    _grammar = grammar;
    enableLogging(logger);

    SymbolList usedsymbols = grammar.getSymbols();

    _symbols = new Symbol[usedsymbols.getSymbolCount()];
    _firstsets = new SymbolList[usedsymbols.getSymbolCount()];
    for (int i = 0; i < usedsymbols.getSymbolCount(); i++)
    {
      if (_logger!=null)
        _logger.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 List of symbols
   */
  public SymbolList getFirstSet(Symbol symbol)
  {
    for (int i = 0; i < _symbols.length; i++)
      if (_symbols[i].equals(symbol))
        return _firstsets[i];
    return new SymbolList();
  }

  /**
   * Provide component with a logger.
   *
   * @param logger the logger
   */
  public void enableLogging(Logger logger)
  {
    _logger = logger;
  }

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

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

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

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

    //System.out.println("Symbol="+symbol.toString());

    // if is a non terminal symbol
    IntegerList productions = _grammar.getProductionList().getProductionList(symbol);
    SymbolList examined = new SymbolList(true); // List of all examined symbols
    SymbolList productiondefinition, newfirstset;
    boolean foundEMPTY;
    int i, j, k; // index variables
    Symbol newsymbol;

    for (i = 0; i < productions.getSize(); i++)
    {
      productiondefinition = _grammar.getProductionList().getProduction(
        productions.get(i)).getDefinition();
      if (productiondefinition.getSymbolCount() == 0)
      {
        // Symbol for a empty firstset added
        firstset.addSymbol(EmptySymbol.EMPTY);
      }
      else
      {
        // for every symbol in the production
        j = 0;
        do
        {
          foundEMPTY = true;
          newsymbol = productiondefinition.getSymbol(j);
          if (newsymbol.isTerminal())
          {
            // if a terminal symbol
            firstset.addSymbol(newsymbol);
          }
          else if (!newsymbol.equals(symbol))
          {
            // and if a non terminal symbol
            if (!examined.contains(newsymbol))
            {
              newfirstset = first(newsymbol, visited);
              foundEMPTY = newfirstset.contains(EmptySymbol.EMPTY);
              for (k = 0; k < newfirstset.getSymbolCount(); k++)
                if (!newfirstset.getSymbol(k).isEmpty())
                  firstset.addSymbol(newfirstset.getSymbol(k));
              examined.addSymbol(newsymbol);
            }
          }

          j++;
        }
        while ((!newsymbol.isTerminal()) && (foundEMPTY) &&
               (j < productiondefinition.getSymbolCount()) &&
               (!productiondefinition.getSymbol(j - 1).equals(symbol)));
      }
    }
    //System.out.println("Symbol="+symbol.toString()+" beendet");
    return firstset;
  }
}
TOP

Related Classes of net.sourceforge.chaperon.parser.generator.FirstSets

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.