// Package re implements a regular expression module.
package re import ( ) // Ns is the namespace for the re: module. var Ns = eval.NsBuilder{}.AddGoFns("re:", fns).Ns() var fns = map[string]interface{}{ "quote": regexp.QuoteMeta, "match": match, "find": find, "replace": replace, "split": split, } type matchOpts struct{ Posix bool } func (*matchOpts) () {} func ( matchOpts, , string) (bool, error) { , := makePattern(, .Posix, false) if != nil { return false, } return .MatchString(), nil } // Struct for holding options to find. Also used by split. type findOpts struct { Posix bool Longest bool Max int } func ( *findOpts) () { .Max = -1 } func ( *eval.Frame, findOpts, , string) error { := .OutputChan() , := makePattern(, .Posix, .Longest) if != nil { return } := .FindAllSubmatchIndex([]byte(), .Max) for , := range { , := [0], [1] := vector.Empty for := 0; < len(); += 2 { , := [], [+1] := "" // FindAllSubmatchIndex may return negative indices to indicate // that the pattern didn't appear in the text. if >= 0 && >= 0 { = [:] } = .Cons(submatchStruct{, , }) } <- matchStruct{[:], , , } } return nil } type replaceOpts struct { Posix bool Longest bool Literal bool } func (*replaceOpts) () {} func ( *eval.Frame, replaceOpts, string, interface{}, string) (string, error) { , := makePattern(, .Posix, .Longest) if != nil { return "", } if .Literal { , := .(string) if ! { return "", fmt.Errorf( "replacement must be string when literal is set, got %s", vals.Kind()) } return .ReplaceAllLiteralString(, ), nil } switch repl := .(type) { case string: return .ReplaceAllString(, ), nil case eval.Callable: var error := func( string) string { if != nil { return "" } , := .CaptureOutput(func( *eval.Frame) error { return .Call(, []interface{}{}, eval.NoOpts) }) if != nil { = return "" } if len() != 1 { = fmt.Errorf("replacement function must output exactly one value, got %d", len()) return "" } , := [0].(string) if ! { = fmt.Errorf( "replacement function must output one string, got %s", vals.Kind([0])) return "" } return } return .ReplaceAllStringFunc(, ), default: return "", fmt.Errorf( "replacement must be string or function, got %s", vals.Kind()) } } func ( *eval.Frame, findOpts, , string) error { := .OutputChan() , := makePattern(, .Posix, .Longest) if != nil { return } := .Split(, .Max) for , := range { <- } return nil } func ( string, , bool) (*regexp.Regexp, error) { , := compile(, ) if != nil { return nil, } if { .Longest() } return , nil } func ( string, bool) (*regexp.Regexp, error) { if { return regexp.CompilePOSIX() } return regexp.Compile() }