All checks were successful
Find and Upload Minecraft Server versions / build (push) Successful in 1m46s
79 lines
2.7 KiB
Go
79 lines
2.7 KiB
Go
package regex
|
|
|
|
import "regexp"
|
|
|
|
type Xpp struct {
|
|
regexp.Regexp
|
|
}
|
|
|
|
// FindAllGroups returns a map with each match group. The map key corresponds to the match group name.
|
|
// A nil return value indicates no matches.
|
|
func (re *Xpp) FindAllGroups(s string) map[string]string {
|
|
matches := re.FindStringSubmatch(s)
|
|
subnames := re.SubexpNames()
|
|
if matches == nil || len(matches) != len(subnames) {
|
|
return nil
|
|
}
|
|
|
|
matchMap := map[string]string{}
|
|
for i := 1; i < len(matches); i++ {
|
|
matchMap[subnames[i]] = matches[i]
|
|
}
|
|
|
|
return matchMap
|
|
}
|
|
|
|
// Compile parses a regular expression and returns, if successful,
|
|
// a [Regexp] object that can be used to match against text.
|
|
//
|
|
// When matching against text, the regexp returns a match that
|
|
// begins as early as possible in the input (leftmost), and among those
|
|
// it chooses the one that a backtracking search would have found first.
|
|
// This so-called leftmost-first matching is the same semantics
|
|
// that Perl, Python, and other implementations use, although this
|
|
// package implements it without the expense of backtracking.
|
|
// For POSIX leftmost-longest matching, see [CompilePOSIX].
|
|
func Compiler(expr string) (*Xpp, error) {
|
|
re, err := regexp.Compile(expr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &Xpp{*re}, nil
|
|
}
|
|
|
|
// CompilePOSIX is like [Compile] but restricts the regular expression
|
|
// to POSIX ERE (egrep) syntax and changes the match semantics to
|
|
// leftmost-longest.
|
|
//
|
|
// That is, when matching against text, the regexp returns a match that
|
|
// begins as early as possible in the input (leftmost), and among those
|
|
// it chooses a match that is as long as possible.
|
|
// This so-called leftmost-longest matching is the same semantics
|
|
// that early regular expression implementations used and that POSIX
|
|
// specifies.
|
|
//
|
|
// However, there can be multiple leftmost-longest matches, with different
|
|
// submatch choices, and here this package diverges from POSIX.
|
|
// Among the possible leftmost-longest matches, this package chooses
|
|
// the one that a backtracking search would have found first, while POSIX
|
|
// specifies that the match be chosen to maximize the length of the first
|
|
// subexpression, then the second, and so on from left to right.
|
|
// The POSIX rule is computationally prohibitive and not even well-defined.
|
|
// See https://swtch.com/~rsc/regexp/regexp2.html#posix for details.
|
|
func CompilePOSIX(expr string) (*Xpp, error) {
|
|
re, err := regexp.CompilePOSIX(expr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &Xpp{*re}, nil
|
|
}
|
|
|
|
// MustCompile is like [Compile] but panics if the expression cannot be parsed.
|
|
// It simplifies safe initialization of global variables holding compiled regular
|
|
// expressions.
|
|
func MustCompile(expr string) *Xpp {
|
|
re := regexp.MustCompile(expr)
|
|
return &Xpp{*re}
|
|
} |