forked from yak-labs/chirp-lang
-
Notifications
You must be signed in to change notification settings - Fork 0
/
regexp.go
107 lines (88 loc) · 2.06 KB
/
regexp.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package chirp
import (
"fmt"
"regexp"
)
var regexpCache = make(map[string]*regexp.Regexp)
func regexpNoCase(exp string) string {
return fmt.Sprintf("(?i)%s", exp)
}
func regexpFromCache(exp string) *regexp.Regexp {
r, exists := regexpCache[exp]
if !exists {
r = regexp.MustCompile(exp)
regexpCache[exp] = r
}
return r
}
func Regexp(exp string, nocase bool) *regexp.Regexp {
if nocase {
exp = regexpNoCase(exp)
}
return regexpFromCache(exp)
}
func RegexpMatch(exp, str string, nocase bool) bool {
return Regexp(exp, nocase).MatchString(str)
}
func RegexpFindMatch(exp, str string, nocase bool) (bool, string) {
r := Regexp(exp, nocase)
return r.MatchString(str), r.FindString(str)
}
func RegexpFindSubmatch(exp, str string, nocase bool) (bool, []string) {
r := Regexp(exp, nocase)
return r.MatchString(str), r.FindStringSubmatch(str)
}
func cmdRegexp(fr *Frame, argv []T) T {
nocase := false
var exp string
var str string
if len(argv) < 2+1 {
panic(fmt.Sprintf(
"Expected 2 or more arguments, but got argv=%s",
Showv(argv)))
}
arg_idx := 1
if argv[arg_idx].String() == "-nocase" {
nocase = true
arg_idx++
exp = argv[arg_idx].String()
arg_idx++
str = argv[arg_idx].String()
arg_idx++
} else {
exp = argv[arg_idx].String()
arg_idx++
str = argv[arg_idx].String()
arg_idx++
}
if len(argv) == arg_idx {
return MkBool(RegexpMatch(exp, str, nocase))
} else if len(argv) == arg_idx+1 {
isMatch, match := RegexpFindMatch(exp, str, nocase)
if len(match) == 0 {
fr.SetVar(argv[arg_idx].String(), Empty)
} else {
fr.SetVar(argv[arg_idx].String(), MkString(match))
}
return MkBool(isMatch)
}
// else:
isMatch, submatches := RegexpFindSubmatch(exp, str, nocase)
sub_idx := 0
for arg_idx < len(argv) {
if sub_idx < len(submatches) {
fr.SetVar(argv[arg_idx].String(), MkString(submatches[sub_idx]))
} else {
fr.SetVar(argv[arg_idx].String(), Empty)
}
sub_idx++
arg_idx++
}
return MkBool(isMatch)
}
func init() {
if Safes == nil {
Safes = make(map[string]Command, 333)
}
Safes["regexp"] = cmdRegexp
}