package javakurs.musterloesung.uebung10;

import java.io.IOException;
import java.util.Comparator;

/**
 * {@link CharFsa} extends {@link FiniteAutomaton} to be used to create an
 * automaton for a regular expression.
 *
 * @author Bernd Kiefer, DFKI
 * @author Joerg Steffen, DFKI
 * @version $Id: CharFsa.java,v 1.1 2011/01/19 09:35:10 steffen Exp $
 */
public class CharFsa extends FiniteAutomaton<Character> {

  /**
   * This contains the comparator used to compare the character edges of the
   * automaton.
   */
  private static Comparator<Character> charComp =
    new Comparator<Character>() {

    /**
     * {@inheritDoc}
     */
    @Override
    public int compare(Character arg1, Character arg2) {

      // EPSILON is smaller than anything
      if (arg1 == null) {
        return (arg2 == null) ? 0 : -1;
      }
      if (arg2 == null) {
        return 1;
      }
      return arg1.charValue() - arg2.charValue();
    }
  };


  /**
   * This creates a new instance of {@link CharFsa}.
   */
  public CharFsa() {

    super();
    super.setComparator(charComp);
  }


  /**
   * This sets the initial and final state of this automaton to the initial and
   * final state of the given subautomaton. Required by {@link RegexParser}.
   *
   * @param sub
   *          a subautomaton
   */
  public void setStates(SubAutomaton sub) {

    super.setInitialState(sub.getInitialState());
    super.setFinalState(sub.getFinalState());
  }


  /**
   * This creates an automaton with the language of the given regular
   * expression.
   *
   * @param regex
   *          a regular expression
   * @return a finite state automaton or {@code null} if no automaton could be
   *         created
   */
  public static CharFsa compileRegex(String regex) {

    boolean result = false;
    RegexParser p = new RegexParser(regex);
    try {
      // can be used to trace the parser
      p.setDebugLevel(0);
      result = p.parse();
    } catch (IOException ioex) {
      return null;
    }
    if (result) {
      return p.getAutomaton();
    }
    return null;
  }


  /**
   * This returns a determinized version of this automaton.
   *
   * @return a deterministic finite state automaton
   */
  public CharFsa determinize() {

    CharFsa dfa = new CharFsa();
    super.determinize(dfa);
    return dfa;
  }
}
