-
Notifications
You must be signed in to change notification settings - Fork 3
/
regex.go
57 lines (48 loc) · 1.25 KB
/
regex.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
/*
(c) 2019 Launix, Inh. Carl-Philip Hänsch
Author: Tim Kluge
Dual licensed with custom aggreements or GPLv3
*/
package packrat
import (
"regexp"
)
type RegexParser[T any] struct {
callback func (string) T
regex *regexp.Regexp
skipWs bool
rs string
}
func NewRegexParser[T any](callback func (string) T, rs string, caseInsensitive bool, skipWs bool) *RegexParser[T] {
prefix := ""
if caseInsensitive {
prefix += "(?i)"
}
prefix += "^"
r := regexp.MustCompile(prefix + rs)
return &RegexParser[T]{callback: callback, regex: r, skipWs: skipWs, rs: rs}
}
// Regex matches only the given regexp. If skipWs is set to true, leading whitespace according to the scanner's skip regexp is skipped, but not matched by the parser.
// Regex panics if rs is not a valid regex string.
func (p *RegexParser[T]) Match(s *Scanner[T]) (Node[T], bool) {
startPosition := s.position
if p.skipWs {
s.Skip()
if !s.isAtBreak() {
s.setPosition(startPosition)
return Node[T]{}, false
}
}
matched := s.MatchRegexp(p.regex)
if matched == nil {
s.setPosition(startPosition)
return Node[T]{}, false
}
if p.skipWs {
if !s.isAtBreak() {
s.setPosition(startPosition)
return Node[T]{}, false
}
}
return Node[T]{Payload: p.callback(*matched)}, true
}