github.com/Comcast/plax@v0.8.32/dsl/regexp.go (about) 1 package dsl 2 3 import ( 4 "fmt" 5 "regexp" 6 "strings" 7 "unicode" 8 9 "github.com/Comcast/sheens/match" 10 ) 11 12 // RegexpMatch compiles the given pattern (as Go regular expression, 13 // matches the target against that pattern, and returns the results as 14 // a list of match.Bindings. 15 // 16 // A matched named group becomes a binding. If the name starts with an 17 // uppercase rune, then the binding variable starts with '?'. 18 // Otherwise, the variable starts with '?*' 19 func RegexpMatch(pat string, target interface{}) ([]match.Bindings, error) { 20 pat = strings.TrimRight(pat, "\n\r") 21 22 r, err := regexp.Compile(pat) 23 if err != nil { 24 return nil, err 25 } 26 27 s, is := target.(string) 28 if !is { 29 return nil, fmt.Errorf("RegexpMatch wants a %T target, not a %T", s, target) 30 } 31 32 ss := r.FindStringSubmatch(s) 33 34 if ss == nil { 35 return nil, nil 36 } 37 38 bss := make([]match.Bindings, 1) 39 bs := make(match.Bindings) 40 bss[0] = bs 41 for i, name := range r.SubexpNames() { 42 if i == 0 { 43 continue 44 } 45 if name == "" { 46 // Unnamed group 47 continue 48 } 49 50 val := ss[i] 51 52 sym := "?" 53 if first, has := FirstRune(name); has { 54 if unicode.IsLower(first) { 55 sym += "*" 56 } 57 } 58 sym += name 59 60 bs[sym] = val 61 } 62 63 return bss, nil 64 } 65 66 // FirstRune returns the first rune or false (if the string has zero 67 // length). 68 func FirstRune(s string) (rune, bool) { 69 for _, r := range s { 70 return r, true 71 } 72 return ' ', false 73 }