package main // match tries to match the regex represented by given start-state, with // the given string func match(start *State, str string) (startIdx int, endIdx int, matched bool) { currentStates := make([]*State, 0) tempStates := make([]*State, 0) // Used to store states that should be used in next loop iteration i := 0 // Index in string // Increment until we hit a character matching the start state if start.isEmpty == false { for int(str[i]) != start.content { i++ } } currentStates = append(currentStates, start) startIdx = i i++ // Advance to next character so that we can check for transitions // Main loop for i < len(str) { // If there are any 0-transitions, take those // TODO: Maybe I need to keep taking 0-transitions until I don't have anymore. Needs to be tested for _, state := range currentStates { if len(state.transitions[EPSILON]) > 0 { tempStates = append(tempStates, state.transitions[EPSILON]...) } } copy(currentStates, tempStates) tempStates = nil // Take any transitions corresponding to current character for _, state := range currentStates { if len(state.transitions[int(str[i])]) > 0 { tempStates = append(tempStates, state.transitions[int(str[i])]...) } else { // This enables the 'greedy' behavior - last-state status is only checked if we can't match anything else if state.isLast { endIdx = i return startIdx, endIdx, true } } } copy(currentStates, tempStates) tempStates = nil i++ } // End-of-string reached. Check if any of our states is in the end position. for _, state := range currentStates { if state.isLast { endIdx = i return startIdx, endIdx, true } else { return -1, -1, false } } // Default return -1, -1, false }