|
|
@ -6,29 +6,13 @@ import (
|
|
|
|
"fmt"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"os"
|
|
|
|
"slices"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/fatih/color"
|
|
|
|
"github.com/fatih/color"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
const CONCAT rune = '~'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var notDotChars []rune
|
|
|
|
var notDotChars []rune
|
|
|
|
var caseInsensitiveFlag *bool // Whether we are running in case-insensitive mode
|
|
|
|
var caseInsensitiveFlag *bool // Whether we are running in case-insensitive mode
|
|
|
|
|
|
|
|
|
|
|
|
func isOperator(c rune) bool {
|
|
|
|
|
|
|
|
if c == '+' || c == '?' || c == '*' || c == '|' || c == CONCAT {
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* priority returns the priority of the given operator */
|
|
|
|
|
|
|
|
func priority(op rune) int {
|
|
|
|
|
|
|
|
precedence := []rune{'|', CONCAT, '+', '*', '?'}
|
|
|
|
|
|
|
|
return slices.Index(precedence, op)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
func main() {
|
|
|
|
invertFlag := flag.Bool("v", false, "Invert match.")
|
|
|
|
invertFlag := flag.Bool("v", false, "Invert match.")
|
|
|
|
// This flag has two 'modes':
|
|
|
|
// This flag has two 'modes':
|
|
|
@ -83,7 +67,6 @@ func main() {
|
|
|
|
var re string
|
|
|
|
var re string
|
|
|
|
re = flag.Args()[0]
|
|
|
|
re = flag.Args()[0]
|
|
|
|
var test_str string
|
|
|
|
var test_str string
|
|
|
|
var test_runes []rune // Rune-slice representation of test_str
|
|
|
|
|
|
|
|
var err error
|
|
|
|
var err error
|
|
|
|
var linesRead bool // Whether or not we have read the lines in the file
|
|
|
|
var linesRead bool // Whether or not we have read the lines in the file
|
|
|
|
lineNum := 0 // Current line number
|
|
|
|
lineNum := 0 // Current line number
|
|
|
@ -91,8 +74,11 @@ func main() {
|
|
|
|
reader := bufio.NewReader(os.Stdin)
|
|
|
|
reader := bufio.NewReader(os.Stdin)
|
|
|
|
out := bufio.NewWriter(os.Stdout)
|
|
|
|
out := bufio.NewWriter(os.Stdout)
|
|
|
|
|
|
|
|
|
|
|
|
re_postfix := shuntingYard(re)
|
|
|
|
regComp, err := Compile(re)
|
|
|
|
startState, numGroups := thompson(re_postfix)
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
fmt.Println(err)
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
for true {
|
|
|
|
for true {
|
|
|
|
if linesRead {
|
|
|
|
if linesRead {
|
|
|
|
break
|
|
|
|
break
|
|
|
@ -129,15 +115,14 @@ func main() {
|
|
|
|
panic(err)
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
test_runes = []rune(test_str)
|
|
|
|
|
|
|
|
matchIndices := make([]Match, 0)
|
|
|
|
matchIndices := make([]Match, 0)
|
|
|
|
if matchNumFlagEnabled {
|
|
|
|
if matchNumFlagEnabled {
|
|
|
|
tmp, err := findNthMatch(startState, test_runes, numGroups, *matchNum)
|
|
|
|
tmp, err := findNthMatch(regComp, test_str, *matchNum)
|
|
|
|
if err == nil {
|
|
|
|
if err == nil {
|
|
|
|
matchIndices = append(matchIndices, tmp)
|
|
|
|
matchIndices = append(matchIndices, tmp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
matchIndices = findAllMatches(startState, test_runes, numGroups)
|
|
|
|
matchIndices = findAllMatches(regComp, test_str)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if *printMatchesFlag {
|
|
|
|
if *printMatchesFlag {
|
|
|
@ -172,7 +157,7 @@ func main() {
|
|
|
|
// Find all numbers from 0 to len(test_str) that are NOT in oldIndices.
|
|
|
|
// Find all numbers from 0 to len(test_str) that are NOT in oldIndices.
|
|
|
|
// These are the values we want to print, now that we have inverted the match.
|
|
|
|
// These are the values we want to print, now that we have inverted the match.
|
|
|
|
// Re-initialize indicesToPrint and add all of these values to it.
|
|
|
|
// Re-initialize indicesToPrint and add all of these values to it.
|
|
|
|
indicesToPrint.add(setDifference(genRange(0, len(test_runes)), oldIndices)...)
|
|
|
|
indicesToPrint.add(setDifference(genRange(0, len(test_str)), oldIndices)...)
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If lineFlag is enabled, we should only print something if:
|
|
|
|
// If lineFlag is enabled, we should only print something if:
|
|
|
@ -193,7 +178,7 @@ func main() {
|
|
|
|
// the corresponding end index.
|
|
|
|
// the corresponding end index.
|
|
|
|
// 3. If not, just print the character.
|
|
|
|
// 3. If not, just print the character.
|
|
|
|
if substituteFlagEnabled {
|
|
|
|
if substituteFlagEnabled {
|
|
|
|
for i := range test_runes {
|
|
|
|
for i := range test_str {
|
|
|
|
inMatchIndex := false
|
|
|
|
inMatchIndex := false
|
|
|
|
for _, m := range matchIndices {
|
|
|
|
for _, m := range matchIndices {
|
|
|
|
if i == m[0].startIdx {
|
|
|
|
if i == m[0].startIdx {
|
|
|
@ -204,11 +189,11 @@ func main() {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !inMatchIndex {
|
|
|
|
if !inMatchIndex {
|
|
|
|
fmt.Fprintf(out, "%c", test_runes[i])
|
|
|
|
fmt.Fprintf(out, "%c", test_str[i])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
for i, c := range test_runes {
|
|
|
|
for i, c := range test_str {
|
|
|
|
if indicesToPrint.contains(i) {
|
|
|
|
if indicesToPrint.contains(i) {
|
|
|
|
color.New(color.FgRed).Fprintf(out, "%c", c)
|
|
|
|
color.New(color.FgRed).Fprintf(out, "%c", c)
|
|
|
|
// Newline after every match - only if -o is enabled and -v is disabled.
|
|
|
|
// Newline after every match - only if -o is enabled and -v is disabled.
|
|
|
|