1
2
3
4
5 package syntax
6
7
8
9
10
11
12
13
14 func (re *Regexp) Simplify() *Regexp {
15 if re == nil {
16 return nil
17 }
18 switch re.Op {
19 case OpCapture, OpConcat, OpAlternate:
20
21 nre := re
22 for i, sub := range re.Sub {
23 nsub := sub.Simplify()
24 if nre == re && nsub != sub {
25
26 nre = new(Regexp)
27 *nre = *re
28 nre.Rune = nil
29 nre.Sub = append(nre.Sub0[:0], re.Sub[:i]...)
30 }
31 if nre != re {
32 nre.Sub = append(nre.Sub, nsub)
33 }
34 }
35 return nre
36
37 case OpStar, OpPlus, OpQuest:
38 sub := re.Sub[0].Simplify()
39 return simplify1(re.Op, re.Flags, sub, re)
40
41 case OpRepeat:
42
43
44 if re.Min == 0 && re.Max == 0 {
45 return &Regexp{Op: OpEmptyMatch}
46 }
47
48
49 sub := re.Sub[0].Simplify()
50
51
52 if re.Max == -1 {
53
54 if re.Min == 0 {
55 return simplify1(OpStar, re.Flags, sub, nil)
56 }
57
58
59 if re.Min == 1 {
60 return simplify1(OpPlus, re.Flags, sub, nil)
61 }
62
63
64 nre := &Regexp{Op: OpConcat}
65 nre.Sub = nre.Sub0[:0]
66 for i := 0; i < re.Min-1; i++ {
67 nre.Sub = append(nre.Sub, sub)
68 }
69 nre.Sub = append(nre.Sub, simplify1(OpPlus, re.Flags, sub, nil))
70 return nre
71 }
72
73
74
75
76 if re.Min == 1 && re.Max == 1 {
77 return sub
78 }
79
80
81
82
83
84
85 var prefix *Regexp
86 if re.Min > 0 {
87 prefix = &Regexp{Op: OpConcat}
88 prefix.Sub = prefix.Sub0[:0]
89 for i := 0; i < re.Min; i++ {
90 prefix.Sub = append(prefix.Sub, sub)
91 }
92 }
93
94
95 if re.Max > re.Min {
96 suffix := simplify1(OpQuest, re.Flags, sub, nil)
97 for i := re.Min + 1; i < re.Max; i++ {
98 nre2 := &Regexp{Op: OpConcat}
99 nre2.Sub = append(nre2.Sub0[:0], sub, suffix)
100 suffix = simplify1(OpQuest, re.Flags, nre2, nil)
101 }
102 if prefix == nil {
103 return suffix
104 }
105 prefix.Sub = append(prefix.Sub, suffix)
106 }
107 if prefix != nil {
108 return prefix
109 }
110
111
112
113 return &Regexp{Op: OpNoMatch}
114 }
115
116 return re
117 }
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134 func simplify1(op Op, flags Flags, sub, re *Regexp) *Regexp {
135
136
137 if sub.Op == OpEmptyMatch {
138 return sub
139 }
140
141 if op == sub.Op && flags&NonGreedy == sub.Flags&NonGreedy {
142 return sub
143 }
144 if re != nil && re.Op == op && re.Flags&NonGreedy == flags&NonGreedy && sub == re.Sub[0] {
145 return re
146 }
147
148 re = &Regexp{Op: op, Flags: flags}
149 re.Sub = append(re.Sub0[:0], sub)
150 return re
151 }
152
View as plain text