package org.simantics.scl.compiler.parser.regexp.automata; import gnu.trove.list.array.TIntArrayList; import gnu.trove.map.hash.TIntObjectHashMap; import gnu.trove.map.hash.TObjectIntHashMap; import gnu.trove.procedure.TIntIntProcedure; import gnu.trove.procedure.TIntObjectProcedure; import gnu.trove.procedure.TIntProcedure; import gnu.trove.set.hash.TIntHashSet; import java.util.ArrayList; public class NFA implements Automata { private static class State { TIntObjectHashMap transitions = new TIntObjectHashMap(); TIntArrayList epsilonTransitions = new TIntArrayList(); boolean accepts; private void addTransition(int symbol, int target) { TIntArrayList l = transitions.get(symbol); if(l == null) { l = new TIntArrayList(); l.add(target); transitions.put(symbol, l); } else if(!l.contains(target)) l.add(target); } private void addEpsilonTransition(int target) { if(!epsilonTransitions.contains(target)) epsilonTransitions.add(target); } } private ArrayList states = new ArrayList(); private int initialState; public int size() { return states.size(); } public void setInitialState(int initialState) { this.initialState = initialState; } public int getInitialState() { return initialState; } public int newState() { int id = states.size(); states.add(new State()); return id; } public void setAccepts(int id, boolean accepts) { states.get(id).accepts = accepts; } public boolean getAccepts(int id) { return states.get(id).accepts; } public void addTransition(int source, int symbol, int target) { states.get(source).addTransition(symbol, target); } public void forEachTransition(int source, final TIntIntProcedure proc) { states.get(source).transitions.forEachEntry(new TIntObjectProcedure() { @Override public boolean execute(int a, TIntArrayList b) { for(int i=0;i stack = new ArrayList(); final TObjectIntHashMap map = new TObjectIntHashMap(); { TIntHashSet initialSet = new TIntHashSet(4); initialSet.add(getInitialState()); TIntArrayList stateList = closure(initialSet); int stateId = aut.newState(); map.put(stateList, stateId); aut.setInitialState(stateId); stack.add(stateList); } while(!stack.isEmpty()) { TIntArrayList curList = stack.remove(stack.size()-1); int[] stateArray = curList.toArray(); final int id = map.get(curList); // Transitions final TIntObjectHashMap transitions = new TIntObjectHashMap(); TIntIntProcedure proc = new TIntIntProcedure() { @Override public boolean execute(int symbol, int b) { TIntHashSet set = transitions.get(symbol); if(set == null) { set = new TIntHashSet(); transitions.put(symbol, set); } set.add(b); return true; } }; for(int s : stateArray) forEachTransition(s, proc); // Create transition targets transitions.forEachEntry(new TIntObjectProcedure() { @Override public boolean execute(int symbol, TIntHashSet b) { TIntArrayList stateList = closure(b); if(map.containsKey(stateList)) aut.addTransition(id, symbol, map.get(stateList)); else { int stateId = aut.newState(); map.put(stateList, stateId); stack.add(stateList); aut.addTransition(id, symbol, stateId); } return true; } }); // Accepts for(int s : stateArray) if(getAccepts(s)) { aut.setAccepts(id, true); break; } } return aut; } }