FollowSetCollection.java :  » Parser » chaperon-3.0 » net » sourceforge » chaperon » build » Java Open Source

Java Open Source » Parser » chaperon 3.0 
chaperon 3.0 » net » sourceforge » chaperon » build » FollowSetCollection.java
/*
 *  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.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 org.apache.commons.logging.Log;

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

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

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

    SymbolSet usedsymbols = grammar.getSymbols();

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

      symbols[i] = usedsymbols.getSymbol(i);
      followsets[i] = follow(symbols[i]);
    }
  }

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

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

  /**
   * Calculates the FOLLOW set. The FOLLOW set is the set of terminal symbols, which come as next
   * symbol
   *
   * @param symbol Symbol.
   *
   * @return Set of symbol.
   */
  private SymbolSet follow(Symbol symbol)
  {
    System.out.println();
    System.out.println("Calculate FOLLOW set for "+symbol);

    SymbolSet followset = new SymbolSet();

    // if symbol is start symbol, then add symbol for end of file
    if (symbol.equals(grammar.getStartSymbol()))
      followset.addSymbol(new EndOfFile());

    // if production A -> a B b exists, then add every symbol of
    // FIRST(b) except the symbol for an empty list to FOLLOW(B)
    SymbolList definition;
    for (int production = 0; production<grammar.getProductionCount(); production++)
    {
      definition = grammar.getProduction(production).getDefinition();
      for (int position = 0; position<definition.getSymbolCount(); position++)
        if (definition.getSymbol(position).equals(symbol))
        {
          System.out.println("Found "+symbol+" at position "+position+" in production "+production);

          SymbolSet firstset = null;
          if ((position+1)<definition.getSymbolCount())
          {
            SymbolList rest = new SymbolList();
            for (int restposition = position+1; restposition<definition.getSymbolCount();
                 restposition++)
              rest.addSymbol(definition.getSymbol(restposition));

            firstset = firstsets.getFirstSet(rest);

            System.out.println("first("+rest+")="+firstset);

            followset.addSymbol(firstset);
            followset.removeSymbol(EMPTYLIST);
          }

          if ((position+1)==definition.getSymbolCount())
            System.out.println(symbol+" is last symbol of production "+production);

          // if a production A -> a B or A -> a B b exist and FIRST(b)
          // contains the symbol for an empty list, then every symbol
          // of FOLLOW(A) belongs to FOLLOW(B)
          if ((((position+1)==definition.getSymbolCount()) || (firstset.contains(EMPTYLIST))) &&
              (!grammar.getProduction(production).getSymbol().equals(symbol)))
            followset.addSymbol(follow(grammar.getProduction(production).getSymbol()));
        }
    }

    return followset;
  }

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

    SymbolSet symbols = grammar.getSymbols();

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

    return buffer.toString();
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.