package project.phase2.ll1parsergenerator.dfastuff; /** * A specific, Nondeterministic, type of Finite Automaton. This specific example * assumes Characters as the transition values. */ public class NFA extends TableDrivenFiniteAutomaton<String> { /** * Empty construct of NFA */ public NFA() { } /** * Constructor of NFA * * @param a the string to generate the new NFA from (only the first character is used). */ public NFA(String a) { this.createState(); this.createState(); this.addTransition(new Transition<String, Integer>(a.substring(0, 1), 0, new Integer[] { 1 })); this.setStartState(0); this.setGoalState(1); } /** * Create a NFA with start state and goal state * * @return new NFA */ public static NFA nullNFA() { NFA ret = new NFA(); int state = ret.createState(); ret.setStartState(state); ret.setGoalState(state); return ret; } /** * Union * * @param sec * The NFA to be unioned with * @return a new NFA a|b */ public TableDrivenFiniteAutomaton<String> union( TableDrivenFiniteAutomaton<String> sec) { // null check if (sec == null) { return this; } NFA ret = new NFA(); // Copyt states of first into ret int firstnumStates = this.getStates().size(); for (int i = 0; i < firstnumStates; i++) { ret.createState(); } // Copy transition from first NFA to ret for (int i : this.getStates()) { for (Transition<String, Integer> t : this.getTransitions(i)) { ret.addTransition(new Transition<String, Integer>(t.getValue(), t.getStart(), t.getDestinations())); } } // Copy states from sec to ret int secnumStates = sec.getStates().size(); for (int i = 0; i < secnumStates; i++) { ret.createState(); } for (int i : sec.getStates()) { for (Transition<String, Integer> t : sec.getTransitions(i)) { Integer[] dest = new Integer[t.getDestinations().length]; for (int j = 0; j < dest.length; j++) { dest[j] = t.getDestinations()[j] + firstnumStates; } ret.addTransition(new Transition<String, Integer>(t.getValue(), t.getStart() + firstnumStates, dest)); } } int start = ret.createState(); ret.addTransition(new Transition<String, Integer>(null, start, new Integer[] { this.getStartState(), sec.getStartState() + firstnumStates })); ret.setStartState(start); // Copy first final states for (int i : this.getGoalStates()) { ret.setGoalState(i, this.getGoalLabel(i)); } // Set sec final states for (int i : sec.getGoalStates()) { ret.setGoalState(i + firstnumStates, sec.getGoalLabel(i)); } return ret; } /** * Concatenation * * @param sec * The NFA to be concatenated with * @return A new NFA ab */ public TableDrivenFiniteAutomaton<String> concat( TableDrivenFiniteAutomaton<String> sec) { // null check if (sec == null) { return this; } NFA ret = new NFA(); // Copyt states of first into ret int firstnumStates = this.getStates().size(); for (int i = 0; i < firstnumStates; i++) { ret.createState(); } // Copy transitions ret.setStartState(this.getStartState()); for (int i : this.getStates()) { for (Transition<String, Integer> t : this.getTransitions(i)) { ret.addTransition(new Transition<String, Integer>(t.getValue(), t.getStart(), t.getDestinations())); } } // Copy states of sec into ret int secnumStates = sec.getStates().size(); for (int i = 0; i < secnumStates; i++) { ret.createState(); } // Copy transitions for (int i : sec.getStates()) { for (Transition<String, Integer> t : sec.getTransitions(i)) { Integer[] dest = new Integer[t.getDestinations().length]; for (int j = 0; j < dest.length; j++) { dest[j] = t.getDestinations()[j] + firstnumStates; } ret.addTransition(new Transition<String, Integer>(t.getValue(), t.getStart() + firstnumStates, dest)); } } // Concat for (int i : this.getGoalStates()) { ret.addTransition(new Transition<String, Integer>(null, i, new Integer[] { sec.getStartState() + firstnumStates })); } // Set final states for (int i : sec.getGoalStates()) { ret.setGoalState(i + firstnumStates, sec.getGoalLabel(i)); } return ret; } /** * Repetition * * @return A new NFA a* */ public TableDrivenFiniteAutomaton<String> star() { NFA ret = new NFA(); // Copyt states of into ret int states = this.getStates().size(); for (int i = 0; i < states; i++) { ret.createState(); } // Copy transition from NFA to ret for (int i : this.getStates()) { for (Transition<String, Integer> t : this.getTransitions(i)) { ret.addTransition(new Transition<String, Integer>(t.getValue(), t.getStart(), t.getDestinations())); } } int start = ret.createState(); ret.addTransition(new Transition<String, Integer>(null, start, new Integer[] { this.getStartState() })); ret.setStartState(start); // Copy final states // Add Transition from this goal state to start state for (int i : this.getGoalStates()) { ret.setGoalState(i, this.getGoalLabel(i)); ret.addTransition(new Transition<String, Integer>(null, i, new Integer[] { start })); } // start is goal ret.setGoalState(start); return ret; } /** * Test NFA * * @param args */ public static void main(String[] args) { NFA n = new NFA(); n.createState(); n.setStartState(0); n.createState(); n.createState(); n.addTransition(new Transition<String, Integer>("a", 0, new Integer[] { 1 })); n.addTransition(new Transition<String, Integer>("b", 0, new Integer[] { 2 })); n.setGoalState(1); n.setGoalState(2); NFA m = new NFA(); m.createState(); m.setStartState(0); m.createState(); m.createState(); m.addTransition(new Transition<String, Integer>("c", 0, new Integer[] { 1 })); m.addTransition(new Transition<String, Integer>("d", 0, new Integer[] { 2 })); m.setGoalState(1); m.setGoalState(2); NFA l = new NFA(); l = (NFA) n.union(m); System.out.println(((NFA) (l.star())).concat(l)); } }