-
Notifications
You must be signed in to change notification settings - Fork 0
/
util.go
136 lines (112 loc) · 2.92 KB
/
util.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package hre
import (
"regexp"
"strings"
)
// indexOf finds the index of the given value in a string array. It returns -1
// if not found. The time complexity is O(n).
func indexOf(val string, vals []string) int {
for i, _val := range vals {
if _val == val {
return i
}
}
return -1
}
// substr is a safe version of s[start:stop]. When start or stop is invalid,
// this function returns "" instead of panic().
func substr(s string, start int, stop int) string {
if start < 0 || stop < 0 {
return ""
}
n := len(s)
if start >= n {
return ""
}
if stop > n {
stop = n
}
if stop-start > 0 {
return s[start:stop]
}
return ""
}
// captured returns the captured substring by their group number.
func captured(s string, m []int, n int) string {
i := n * 2
return substr(s, m[i], m[i+1])
}
// noCapture removes capturing groups in a regexp string.
func noCapture(expr string) string {
return strings.Replace(expr, "(", "(?:", -1)
}
// -----------------------------------------------------------------------------
// Verbose Regexp
var (
// Match with a line starting with "---".
reComment = regexp.MustCompile(`---.*`)
// Match with a character or start of string before a whitespace.
reWhitespace = regexp.MustCompile(`(^|[^\\])\s+`)
)
// re compiles a verbose regular expression.
//
// The expression can be indented and described by comments. Every comment
// lines and whitespace except escaped "\ " will be removed before compiling.
//
// Example:
// var reEmail = re(`
// --- start of string
// ^
// --- user
// (
// [^@]+
// )
// --- at
// @
// --- host
// (
// [a-zA-Z0-9-_]+
// \.
// [a-zA-Z0-9-_.]+
// )
// --- end of string
// $
// `)
//
func re(verboseExpr string) *regexp.Regexp {
expr := reComment.ReplaceAllString(verboseExpr, ``)
// Remove all whitespace except "\ ".
expr = reWhitespace.ReplaceAllString(expr, `$1`)
return regexp.MustCompile(expr)
}
// -----------------------------------------------------------------------------
// Finding meaningful letters from Regexp
var (
reSpace = regexp.MustCompile(`\s`)
reGroup = regexp.MustCompile(`\(\?(:|P<.+?>)`)
reMeta = regexp.MustCompile(`/`)
reQuoted = regexp.MustCompile(`\\.`)
)
func regexpLetters(reExpr string) string {
letters := reExpr
// Remove spaces.
letters = reSpace.ReplaceAllString(letters, ``)
// Remove group starters "(?:", "(?P<...>".
letters = reGroup.ReplaceAllString(letters, ``)
// Remove meta characters.
letters = reMeta.ReplaceAllString(letters, ``)
// Remove escaped letters.
letters = reQuoted.ReplaceAllString(letters, ``)
// Quote Regexp meta letters.
letters = regexp.QuoteMeta(letters)
// Remove escaped letters again.
letters = reQuoted.ReplaceAllString(letters, ``)
return letters
}
func splitLetters(word string) []string {
var letters []string
for _, ch := range word {
letters = append(letters, string(ch))
}
return letters
}