func NewAutomaton(a *tomato.Automaton, targets []*tomato.State) tomato.Transition { if len(a.Ends()) != len(targets) { panic("Automaton transition targets must have same length as automaton ending states") } return &automatonTransition{a, targets} }
// Transform any automaton to a synchronized and determinized automaton. func Determinize(a *tomato.Automaton) *tomato.Automaton { closures := []Closure{} states := []*tomato.State{} ends := []*tomato.State{} var collect func(state *tomato.State) *tomato.State collect = func(state *tomato.State) *tomato.State { closure := EpsilonClosure(state) // Make sure this closure hasn't been already processed for i, c := range closures { if closure.equals(c) { return states[i] } } // Create a new state for this closure state = tomato.NewState() // Collect this closure's transitons trs := closureTransitions(closure) // Add closure & new state to list closures = append(closures, closure) states = append(states, state) // Does this new state is an ending one? if closureIsEnd(closure, a.Ends()) { ends = append(ends, state) } // Add transitions to new state for _, tr := range trs { targets := tr.Targets() newTargets := make([]*tomato.State, len(targets)) for i, target := range targets { newTargets[i] = collect(target) } state.Add(tr.Duplicate(newTargets...)) } return state } root := collect(a.Root()) return tomato.NewAutomaton(root, ends) }