replacerdata.go

 1package syntax
 2
 3import (
 4	"bytes"
 5	"errors"
 6)
 7
 8type ReplacerData struct {
 9	Rep     string
10	Strings []string
11	Rules   []int
12}
13
14const (
15	replaceSpecials     = 4
16	replaceLeftPortion  = -1
17	replaceRightPortion = -2
18	replaceLastGroup    = -3
19	replaceWholeString  = -4
20)
21
22//ErrReplacementError is a general error during parsing the replacement text
23var ErrReplacementError = errors.New("Replacement pattern error.")
24
25// NewReplacerData will populate a reusable replacer data struct based on the given replacement string
26// and the capture group data from a regexp
27func NewReplacerData(rep string, caps map[int]int, capsize int, capnames map[string]int, op RegexOptions) (*ReplacerData, error) {
28	p := parser{
29		options:  op,
30		caps:     caps,
31		capsize:  capsize,
32		capnames: capnames,
33	}
34	p.setPattern(rep)
35	concat, err := p.scanReplacement()
36	if err != nil {
37		return nil, err
38	}
39
40	if concat.t != ntConcatenate {
41		panic(ErrReplacementError)
42	}
43
44	sb := &bytes.Buffer{}
45	var (
46		strings []string
47		rules   []int
48	)
49
50	for _, child := range concat.children {
51		switch child.t {
52		case ntMulti:
53			child.writeStrToBuf(sb)
54
55		case ntOne:
56			sb.WriteRune(child.ch)
57
58		case ntRef:
59			if sb.Len() > 0 {
60				rules = append(rules, len(strings))
61				strings = append(strings, sb.String())
62				sb.Reset()
63			}
64			slot := child.m
65
66			if len(caps) > 0 && slot >= 0 {
67				slot = caps[slot]
68			}
69
70			rules = append(rules, -replaceSpecials-1-slot)
71
72		default:
73			panic(ErrReplacementError)
74		}
75	}
76
77	if sb.Len() > 0 {
78		rules = append(rules, len(strings))
79		strings = append(strings, sb.String())
80	}
81
82	return &ReplacerData{
83		Rep:     rep,
84		Strings: strings,
85		Rules:   rules,
86	}, nil
87}