// FiniteAutomaton.java import java.io.*; import java.util.*; /** A non-deterministic finite automaton. */ public class FiniteAutomaton extends FiniteStateMachine { // STATE VARIABLES /** boolean array marking whether each state is a current state */ private boolean[] b; // CONSTRUCTORS /** constructs a finite automaton with the given set of states and start state */ public FiniteAutomaton(State[] states, State start) { this(states, start, new TransitionFunction(false)); } /** constructs a finite automaton with the given set of states, start state, and transition function */ public FiniteAutomaton(State[] states, State start, TransitionFunction function) { super(states, start, function); for (int i=0; i 0) { char l = list.charAt(listLen - 1); if (l == EPSILON_CHAR) { // transition is actually an epsilon transition l = EPSILON; } function.removeTransition(new TransitionTuple(source, l), new TransitionTuple(dest)); list = list.substring(0, listLen - 1); meta.put(dest, list); } } else { // add the typed character to the transition list if (key >= 32 && key < 256 && key != 127) { if (key == 32) { if (list.indexOf(EPSILON_CHAR) >= 0) return; function.addTransition(new TransitionTuple(source, EPSILON), new TransitionTuple(dest)); list = list + EPSILON_CHAR; } else { if (list.indexOf(key) >= 0) return; function.addTransition(new TransitionTuple(source, key), new TransitionTuple(dest)); list = list + key; } meta.put(dest, list); } } } // REQUIRED ACCESSORS /** returns a set of strings representing the transitions from the given source state to the given destination state */ protected String[] getTransitionStrings(State source, State dest) { Hashtable meta = (Hashtable) source.getMetadata(); String s = (String) meta.get(dest); if (s == null || s.equals("")) return null; else return new String[] {s}; } // HELPER METHODS /** adjusts the size of the current state array if the number of states has changed */ private void fixB() { synchronized (states) { boolean[] newB = new boolean[numStates]; for (int i=0; i