package re
import (
)
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
}
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]
:= ""
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()
}