Initial support for multiple matching
This commit is contained in:
15
main.go
15
main.go
@@ -178,14 +178,21 @@ func main() {
|
|||||||
re_postfix := shuntingYard(re)
|
re_postfix := shuntingYard(re)
|
||||||
// fmt.Println(re_postfix)
|
// fmt.Println(re_postfix)
|
||||||
startState := thompson(re_postfix)
|
startState := thompson(re_postfix)
|
||||||
start, end, matched := match(startState, os.Args[2])
|
matchIndices := match(startState, os.Args[2])
|
||||||
if matched {
|
inColor := false
|
||||||
|
if len(matchIndices) > 0 {
|
||||||
for i, c := range os.Args[2] {
|
for i, c := range os.Args[2] {
|
||||||
if i >= start && i < end {
|
for _, indices := range matchIndices {
|
||||||
|
if i >= indices.startIdx && i < indices.endIdx {
|
||||||
color.New(color.FgRed).Printf("%c", c)
|
color.New(color.FgRed).Printf("%c", c)
|
||||||
} else {
|
inColor = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if inColor == false {
|
||||||
fmt.Printf("%c", c)
|
fmt.Printf("%c", c)
|
||||||
}
|
}
|
||||||
|
inColor = false
|
||||||
}
|
}
|
||||||
fmt.Printf("\n")
|
fmt.Printf("\n")
|
||||||
} else {
|
} else {
|
||||||
|
30
matching.go
30
matching.go
@@ -1,5 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
|
// a matchIndex represents a match. It contains the start index and end index of the match
|
||||||
|
type matchIndex struct {
|
||||||
|
startIdx int
|
||||||
|
endIdx int
|
||||||
|
}
|
||||||
|
|
||||||
// takeZeroState takes the 0-state (if such a transition exists) for all states in the
|
// takeZeroState takes the 0-state (if such a transition exists) for all states in the
|
||||||
// given slice. It returns the resulting states. If any of the resulting states is a 0-state,
|
// given slice. It returns the resulting states. If any of the resulting states is a 0-state,
|
||||||
// the second parameter is true.
|
// the second parameter is true.
|
||||||
@@ -19,7 +25,17 @@ func takeZeroState(states []*State) (rtv []*State, isZero bool) {
|
|||||||
|
|
||||||
// match tries to match the regex represented by given start-state, with
|
// match tries to match the regex represented by given start-state, with
|
||||||
// the given string
|
// the given string
|
||||||
func match(start *State, str string) (startIdx int, endIdx int, matched bool) {
|
func match(start *State, str string) (indices []matchIndex) {
|
||||||
|
return matchHelper(start, str, make([]matchIndex, 0), 0)
|
||||||
|
}
|
||||||
|
func matchHelper(start *State, str string, indices []matchIndex, offset int) []matchIndex {
|
||||||
|
// 'Base case' - exit if string is empty
|
||||||
|
if len(str) == 0 {
|
||||||
|
return indices
|
||||||
|
}
|
||||||
|
|
||||||
|
startIdx := 0
|
||||||
|
endIdx := 0
|
||||||
currentStates := make([]*State, 0)
|
currentStates := make([]*State, 0)
|
||||||
tempStates := make([]*State, 0) // Used to store states that should be used in next loop iteration
|
tempStates := make([]*State, 0) // Used to store states that should be used in next loop iteration
|
||||||
i := 0 // Index in string
|
i := 0 // Index in string
|
||||||
@@ -28,12 +44,12 @@ func match(start *State, str string) (startIdx int, endIdx int, matched bool) {
|
|||||||
for i < len(str) && int(str[i]) != start.content {
|
for i < len(str) && int(str[i]) != start.content {
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
startIdx = i
|
||||||
i++ // Advance to next character (if we aren't at a 0-state, which doesn't match anything), so that we can check for transitions. If we advance at a 0-state, we will never get a chance to match the first character
|
i++ // Advance to next character (if we aren't at a 0-state, which doesn't match anything), so that we can check for transitions. If we advance at a 0-state, we will never get a chance to match the first character
|
||||||
}
|
}
|
||||||
// TODO - If start state is kleene star, try to match the next state
|
// TODO - If start state is kleene star, try to match the next state
|
||||||
|
|
||||||
currentStates = append(currentStates, start)
|
currentStates = append(currentStates, start)
|
||||||
startIdx = i
|
|
||||||
|
|
||||||
// Main loop
|
// Main loop
|
||||||
for i < len(str) {
|
for i < len(str) {
|
||||||
@@ -57,8 +73,10 @@ func match(start *State, str string) (startIdx int, endIdx int, matched bool) {
|
|||||||
// This enables the 'greedy' behavior - last-state status is only checked if we can't match anything else
|
// This enables the 'greedy' behavior - last-state status is only checked if we can't match anything else
|
||||||
if state.isLast {
|
if state.isLast {
|
||||||
endIdx = i
|
endIdx = i
|
||||||
return startIdx, endIdx, true
|
indices = append(indices, matchIndex{startIdx + offset, endIdx + offset})
|
||||||
}
|
}
|
||||||
|
// Recursion - match with rest of string
|
||||||
|
return matchHelper(start, str[i:], indices, offset+i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
currentStates = make([]*State, len(tempStates))
|
currentStates = make([]*State, len(tempStates))
|
||||||
@@ -80,12 +98,10 @@ func match(start *State, str string) (startIdx int, endIdx int, matched bool) {
|
|||||||
for _, state := range currentStates {
|
for _, state := range currentStates {
|
||||||
if state.isLast {
|
if state.isLast {
|
||||||
endIdx = i
|
endIdx = i
|
||||||
return startIdx, endIdx, true
|
indices = append(indices, matchIndex{startIdx + offset, endIdx + offset})
|
||||||
} else {
|
|
||||||
return -1, -1, false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default
|
// Default
|
||||||
return -1, -1, false
|
return indices
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user