You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
3.5 KiB
Go
134 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"slices"
|
|
"unicode"
|
|
)
|
|
|
|
var whitespaceChars = []rune{' ', '\t', '\n'}
|
|
var digitChars = []rune{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
|
|
var wordChars = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_")
|
|
var LBRACKET rune = 0xF0000
|
|
var RBRACKET rune = 0xF0001
|
|
var ANY_CHAR rune = 0xF0002 // Represents any character - used for states where the allChars flag is on.
|
|
var LPAREN_CHAR rune = 0xF0003 // Parentheses in regex are concatenated with this - it acts as a pseudio-parentheses
|
|
var RPAREN_CHAR rune = 0xF0004
|
|
var NONCAPLPAREN_CHAR rune = 0xF0005 // Represents a non-capturing group's LPAREN
|
|
|
|
// Returns true if str[idx] and str[idx-1] are separated by a word boundary.
|
|
func isWordBoundary(str []rune, idx int) bool {
|
|
str_runes := []rune(str)
|
|
wbounded := idx == 0 ||
|
|
idx >= len(str) ||
|
|
(!slices.Contains(wordChars, str_runes[idx-1]) && slices.Contains(wordChars, str_runes[idx])) ||
|
|
(slices.Contains(wordChars, str_runes[idx-1]) && !slices.Contains(wordChars, str_runes[idx]))
|
|
return wbounded
|
|
}
|
|
|
|
func isNormalChar(c rune) bool {
|
|
specialChars := []rune(`?*\^${}()+|[].~<>`)
|
|
specialChars = append(specialChars, LBRACKET, RBRACKET, NONCAPLPAREN_CHAR)
|
|
return !slices.Contains(specialChars, c)
|
|
}
|
|
|
|
func assert(cond bool) {
|
|
if cond != true {
|
|
panic("Assertion Failed")
|
|
}
|
|
}
|
|
|
|
func deleteFromSlice[T comparable](slc []T, val T) []T {
|
|
toReturn := make([]T, 0, len(slc))
|
|
for _, v := range slc {
|
|
if v != val {
|
|
toReturn = append(toReturn, v)
|
|
}
|
|
}
|
|
return toReturn
|
|
}
|
|
|
|
// Ensure that the given elements are only appended to the given slice if they
|
|
// don't already exist. Returns the new slice, and the number of unique items appended.
|
|
func unique_append[T comparable](slc []T, items ...T) ([]T, int) {
|
|
num_appended := 0
|
|
for _, item := range items {
|
|
if !slices.Contains(slc, item) {
|
|
slc = append(slc, item)
|
|
num_appended++
|
|
}
|
|
}
|
|
return slc, num_appended
|
|
}
|
|
|
|
// Returns true only if all the given elements are equal
|
|
func allEqual[T comparable](items ...T) bool {
|
|
first := items[0]
|
|
for _, item := range items {
|
|
if item != first {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// Returns all elements in slice A that are NOT in slice B
|
|
func setDifference[T comparable](s1 []T, s2 []T) []T {
|
|
toReturn := make([]T, 0, len(s1))
|
|
for _, val := range s1 {
|
|
if !slices.Contains(s2, val) {
|
|
toReturn = append(toReturn, val)
|
|
}
|
|
}
|
|
return toReturn
|
|
}
|
|
|
|
// Map function - convert a slice of T to a slice of V, based on a function
|
|
// that maps a T to a V
|
|
func Map[T, V any](slc []T, fn func(T) V) []V {
|
|
toReturn := make([]V, len(slc))
|
|
for i, val := range slc {
|
|
toReturn[i] = fn(val)
|
|
}
|
|
return toReturn
|
|
}
|
|
|
|
// Reduce function - reduces a slice of a type into a value of the type,
|
|
// based on the given function.
|
|
func Reduce[T any](slc []T, fn func(T, T) T) T {
|
|
if len(slc) == 0 {
|
|
panic("Reduce on empty slice.")
|
|
}
|
|
for len(slc) > 1 {
|
|
v1 := slc[0]
|
|
v2 := slc[1]
|
|
slc = slc[1:]
|
|
slc[0] = fn(v1, v2)
|
|
}
|
|
return slc[0]
|
|
}
|
|
|
|
// Generate numbers in a range - start (inclusive) to end (exclusive)
|
|
func genRange(start, end int) []int {
|
|
toRet := make([]int, end-start)
|
|
for i := start; i < end; i++ {
|
|
toRet[i-start] = i
|
|
}
|
|
return toRet
|
|
}
|
|
|
|
// Returns a rune-slice containing all possible cases of the given rune.
|
|
// At the moment, this includes:
|
|
// 1. Upper case
|
|
// 2. Lower case
|
|
// 3. Title case
|
|
func allCases(r rune) []rune {
|
|
return []rune{unicode.ToLower(r), unicode.ToUpper(r), unicode.ToTitle(r)}
|
|
}
|
|
|
|
// Expands a slice to the given length
|
|
func expandSlice[T any](slc []T, newSize int) []T {
|
|
toRet := make([]T, newSize)
|
|
copy(toRet, slc)
|
|
return toRet
|
|
}
|