package javakurs.musterloesung.uebung11;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * {@link TopDownParser} implements the abstract methods of
 * {@link TopDownParserBase}.
 *
 * @author Joerg Steffen, DFKI
 * @version $Id: TopDownParser.java,v 1.1 2011/01/26 15:50:17 steffen Exp $
 */
public class TopDownParser extends TopDownParserBase {

  /**
   * Caches the results of the expand method (for non-terminal toRecognize). It
   * maps non-terminals and positions in the input to a set of reachable end
   * positions in the input. The non-terminals and positions in the input are
   * merged into a single key.
   */
  private Map<String, Set<Integer>> expandCache;


  /**
   * Creates a new instance of {@link TopDownParser}.
   *
   * @param grammarFile
   *          the file name of the grammar
   */
  public TopDownParser(String grammarFile) {

    super(grammarFile);
    this.expandCache = new HashMap<String, Set<Integer>>();
  }


  /**
   * {@inheritDoc}
   */
  @Override
  protected Set<Integer> expandNonTerminalWithCache(
      String toRecognize, int currentPos, List<String> inputTerminals) {

    // create unique key for input parameters
    String key = new StringBuilder()
        .append(toRecognize).append(" ").append(currentPos).toString();

    // cache lookup
    Set<Integer> cachedEndPositions = this.expandCache.get(key);
    if (null != cachedEndPositions) {
      return cachedEndPositions;
    }

    // no result found in cache, so calculate it
    Set<Integer> endPositions =
      this.expandNonTerminal(toRecognize, currentPos, inputTerminals);

    // cache result
    this.expandCache.put(key, endPositions);

    return endPositions;
  }


  /**
   * {@inheritDoc}
   */
  @Override
  protected void resetCache() {

    this.expandCache.clear();
  }
}
