func jsonString() *tomato.Automaton { q0 := tomato.NewState() q1 := tomato.NewState() q2 := tomato.NewState() q2_1 := tomato.NewState() q2_1_1 := tomato.NewState() q3 := tomato.NewState() q4 := tomato.NewState() q0.Add(transition.NewRune('"', q1)) q1.Add(transition.NewEpsilon(q2)) q1.Add(transition.NewEpsilon(q3)) q2.Add(transition.NewRegexp("[^\\\"]+", q3)) q2.Add(transition.NewRune('\\', q2_1)) q2_1.Add(transition.NewRegexp("[\"\\/bfnrt]", q3)) q2_1.Add(transition.NewRune('u', q2_1_1)) q2_1_1.Add(transition.NewRegexp("[0-9a-f]{4}", q3)) q3.Add(transition.NewEpsilon(q2)) q3.Add(transition.NewRune('"', q4)) return tomato.NewAutomaton(q0, []*tomato.State{q4}) }
func jsonObject(str, value *tomato.Automaton) *tomato.Automaton { q0 := tomato.NewState() q1 := tomato.NewState() q2 := tomato.NewState() q3 := tomato.NewState() q4 := tomato.NewState() q5 := tomato.NewState() q6 := tomato.NewState() q7 := tomato.NewState() q0.Add(transition.NewRune('{', q1)) q1.Add(transition.NewEpsilon(q2)) q1.Add(transition.NewEpsilon(q6)) q2.Add(transition.NewAutomaton(str, []*tomato.State{q3})) q3.Add(transition.NewRune(':', q4)) q4.Add(transition.NewAutomaton(value, []*tomato.State{q5})) q5.Add(transition.NewRune(',', q2)) q5.Add(transition.NewEpsilon(q6)) q6.Add(transition.NewRune('}', q7)) return tomato.NewAutomaton(q0, []*tomato.State{q7}) }
func New(endsNbr int) (*tomato.Automaton, func(*tomato.Automaton)) { start := tomato.NewState() ends := make([]*tomato.State, endsNbr) for i := 0; i < endsNbr; i++ { ends[i] = tomato.NewState() } return tomato.NewAutomaton(start, ends), func(automaton *tomato.Automaton) { start.Reset() start.Add(transition.NewAutomaton(automaton, ends)) } }
func jsonValue(number, str, array, object *tomato.Automaton) *tomato.Automaton { q0 := tomato.NewState() q1 := tomato.NewState() q0.Add(transition.NewAutomaton(str, []*tomato.State{q1})) q0.Add(transition.NewAutomaton(number, []*tomato.State{q1})) q0.Add(transition.NewAutomaton(object, []*tomato.State{q1})) q0.Add(transition.NewAutomaton(array, []*tomato.State{q1})) q0.Add(transition.NewString("true", q1)) q0.Add(transition.NewString("false", q1)) q0.Add(transition.NewString("null", q1)) return tomato.NewAutomaton(q0, []*tomato.State{q1}) }
// 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) }
func jsonNumber() *tomato.Automaton { q0 := tomato.NewState() q1 := tomato.NewState() q1_1 := tomato.NewState() q2 := tomato.NewState() q3 := tomato.NewState() q4 := tomato.NewState() q5 := tomato.NewState() q5_1 := tomato.NewState() q5_2 := tomato.NewState() q5_3 := tomato.NewState() q6 := tomato.NewState() q0.Add(transition.NewRune('-', q1)) q0.Add(transition.NewEpsilon(q1)) q1.Add(transition.NewRune('0', q2)) q1.Add(transition.NewRegexp("[1-9]", q1_1)) q1_1.Add(transition.NewRegexp("[0-9]", q1_1)) q1_1.Add(transition.NewEpsilon(q2)) q2.Add(transition.NewEpsilon(q5)) q2.Add(transition.NewRune('.', q3)) q3.Add(transition.NewRegexp("[0-9]", q4)) q4.Add(transition.NewRegexp("[0-9]", q4)) q4.Add(transition.NewEpsilon(q5)) q5.Add(transition.NewRegexp("[eE]", q5_1)) q5.Add(transition.NewEpsilon(q6)) q5_1.Add(transition.NewRegexp("[+-]?", q5_2)) q5_2.Add(transition.NewRegexp("[0-9]", q5_3)) q5_3.Add(transition.NewRegexp("[0-9]", q5_3)) q5_3.Add(transition.NewEpsilon(q6)) return tomato.NewAutomaton(q0, []*tomato.State{q6}) }
func jsonArray(value *tomato.Automaton) *tomato.Automaton { q0 := tomato.NewState() q1 := tomato.NewState() q2 := tomato.NewState() q3 := tomato.NewState() q4 := tomato.NewState() q5 := tomato.NewState() q0.Add(transition.NewRune('[', q1)) q1.Add(transition.NewEpsilon(q2)) q1.Add(transition.NewEpsilon(q4)) q2.Add(transition.NewAutomaton(value, []*tomato.State{q3})) q3.Add(transition.NewRune(',', q2)) q3.Add(transition.NewEpsilon(q4)) q4.Add(transition.NewRune(']', q5)) return tomato.NewAutomaton(q0, []*tomato.State{q5}) }
// A simple automaton that recognizes words containing "ab". func TestContains(t *testing.T) { q0 := tomato.NewState() q1 := tomato.NewState() q2 := tomato.NewState() q0.Add(transition.NewRune('a', q1)) q0.Add(transition.NewRune('b', q0)) q0.Add(transition.NewRune('c', q0)) q1.Add(transition.NewRune('a', q1)) q1.Add(transition.NewRune('b', q2)) q1.Add(transition.NewRune('c', q0)) q2.Add(transition.NewRune('a', q2)) q2.Add(transition.NewRune('b', q2)) q2.Add(transition.NewRune('c', q2)) a := tomato.NewAutomaton(q0, []*tomato.State{q2}) items := []testCase{ {"ab", true}, {"abc", true}, {"cab", true}, {"cabc", true}, {"aaaab", true}, {"aba", true}, {"abab", true}, {"acab", true}, {"a", false}, {"b", false}, {"aa", false}, {"ba", false}, {"bbbaaa", false}, {"aca", false}, } testAll(t, a, items) }