annotate vendor/github.com/dlclark/regexp2/syntax/writer.go @ 66:787b5ee0289d draft

Use vendored modules Signed-off-by: Izuru Yakumo <yakumo.izuru@chaotic.ninja>
author yakumo.izuru
date Sun, 23 Jul 2023 13:18:53 +0000
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
66
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1 package syntax
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
3 import (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
4 "bytes"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
5 "fmt"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
6 "math"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
7 "os"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
8 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
9
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
10 func Write(tree *RegexTree) (*Code, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
11 w := writer{
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
12 intStack: make([]int, 0, 32),
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
13 emitted: make([]int, 2),
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
14 stringhash: make(map[string]int),
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
15 sethash: make(map[string]int),
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
16 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
17
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
18 code, err := w.codeFromTree(tree)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
19
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
20 if tree.options&Debug > 0 && code != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
21 os.Stdout.WriteString(code.Dump())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
22 os.Stdout.WriteString("\n")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
23 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
24
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
25 return code, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
26 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
27
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
28 type writer struct {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
29 emitted []int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
30
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
31 intStack []int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
32 curpos int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
33 stringhash map[string]int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
34 stringtable [][]rune
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
35 sethash map[string]int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
36 settable []*CharSet
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
37 counting bool
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
38 count int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
39 trackcount int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
40 caps map[int]int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
41 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
42
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
43 const (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
44 beforeChild nodeType = 64
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
45 afterChild = 128
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
46 //MaxPrefixSize is the largest number of runes we'll use for a BoyerMoyer prefix
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
47 MaxPrefixSize = 50
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
48 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
49
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
50 // The top level RegexCode generator. It does a depth-first walk
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
51 // through the tree and calls EmitFragment to emits code before
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
52 // and after each child of an interior node, and at each leaf.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
53 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
54 // It runs two passes, first to count the size of the generated
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
55 // code, and second to generate the code.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
56 //
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
57 // We should time it against the alternative, which is
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
58 // to just generate the code and grow the array as we go.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
59 func (w *writer) codeFromTree(tree *RegexTree) (*Code, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
60 var (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
61 curNode *regexNode
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
62 curChild int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
63 capsize int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
64 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
65 // construct sparse capnum mapping if some numbers are unused
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
66
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
67 if tree.capnumlist == nil || tree.captop == len(tree.capnumlist) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
68 capsize = tree.captop
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
69 w.caps = nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
70 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
71 capsize = len(tree.capnumlist)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
72 w.caps = tree.caps
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
73 for i := 0; i < len(tree.capnumlist); i++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
74 w.caps[tree.capnumlist[i]] = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
75 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
76 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
77
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
78 w.counting = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
79
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
80 for {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
81 if !w.counting {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
82 w.emitted = make([]int, w.count)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
83 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
84
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
85 curNode = tree.root
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
86 curChild = 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
87
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
88 w.emit1(Lazybranch, 0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
89
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
90 for {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
91 if len(curNode.children) == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
92 w.emitFragment(curNode.t, curNode, 0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
93 } else if curChild < len(curNode.children) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
94 w.emitFragment(curNode.t|beforeChild, curNode, curChild)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
95
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
96 curNode = curNode.children[curChild]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
97
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
98 w.pushInt(curChild)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
99 curChild = 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
100 continue
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
101 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
102
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
103 if w.emptyStack() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
104 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
105 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
106
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
107 curChild = w.popInt()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
108 curNode = curNode.next
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
109
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
110 w.emitFragment(curNode.t|afterChild, curNode, curChild)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
111 curChild++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
112 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
113
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
114 w.patchJump(0, w.curPos())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
115 w.emit(Stop)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
116
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
117 if !w.counting {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
118 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
119 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
120
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
121 w.counting = false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
122 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
123
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
124 fcPrefix := getFirstCharsPrefix(tree)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
125 prefix := getPrefix(tree)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
126 rtl := (tree.options & RightToLeft) != 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
127
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
128 var bmPrefix *BmPrefix
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
129 //TODO: benchmark string prefixes
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
130 if prefix != nil && len(prefix.PrefixStr) > 0 && MaxPrefixSize > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
131 if len(prefix.PrefixStr) > MaxPrefixSize {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
132 // limit prefix changes to 10k
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
133 prefix.PrefixStr = prefix.PrefixStr[:MaxPrefixSize]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
134 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
135 bmPrefix = newBmPrefix(prefix.PrefixStr, prefix.CaseInsensitive, rtl)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
136 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
137 bmPrefix = nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
138 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
139
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
140 return &Code{
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
141 Codes: w.emitted,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
142 Strings: w.stringtable,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
143 Sets: w.settable,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
144 TrackCount: w.trackcount,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
145 Caps: w.caps,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
146 Capsize: capsize,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
147 FcPrefix: fcPrefix,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
148 BmPrefix: bmPrefix,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
149 Anchors: getAnchors(tree),
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
150 RightToLeft: rtl,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
151 }, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
152 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
153
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
154 // The main RegexCode generator. It does a depth-first walk
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
155 // through the tree and calls EmitFragment to emits code before
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
156 // and after each child of an interior node, and at each leaf.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
157 func (w *writer) emitFragment(nodetype nodeType, node *regexNode, curIndex int) error {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
158 bits := InstOp(0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
159
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
160 if nodetype <= ntRef {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
161 if (node.options & RightToLeft) != 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
162 bits |= Rtl
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
163 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
164 if (node.options & IgnoreCase) != 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
165 bits |= Ci
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
166 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
167 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
168 ntBits := nodeType(bits)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
169
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
170 switch nodetype {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
171 case ntConcatenate | beforeChild, ntConcatenate | afterChild, ntEmpty:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
172 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
173
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
174 case ntAlternate | beforeChild:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
175 if curIndex < len(node.children)-1 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
176 w.pushInt(w.curPos())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
177 w.emit1(Lazybranch, 0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
178 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
179
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
180 case ntAlternate | afterChild:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
181 if curIndex < len(node.children)-1 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
182 lbPos := w.popInt()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
183 w.pushInt(w.curPos())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
184 w.emit1(Goto, 0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
185 w.patchJump(lbPos, w.curPos())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
186 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
187 for i := 0; i < curIndex; i++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
188 w.patchJump(w.popInt(), w.curPos())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
189 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
190 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
191 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
192
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
193 case ntTestref | beforeChild:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
194 if curIndex == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
195 w.emit(Setjump)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
196 w.pushInt(w.curPos())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
197 w.emit1(Lazybranch, 0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
198 w.emit1(Testref, w.mapCapnum(node.m))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
199 w.emit(Forejump)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
200 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
201
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
202 case ntTestref | afterChild:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
203 if curIndex == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
204 branchpos := w.popInt()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
205 w.pushInt(w.curPos())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
206 w.emit1(Goto, 0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
207 w.patchJump(branchpos, w.curPos())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
208 w.emit(Forejump)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
209 if len(node.children) <= 1 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
210 w.patchJump(w.popInt(), w.curPos())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
211 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
212 } else if curIndex == 1 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
213 w.patchJump(w.popInt(), w.curPos())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
214 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
215
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
216 case ntTestgroup | beforeChild:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
217 if curIndex == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
218 w.emit(Setjump)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
219 w.emit(Setmark)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
220 w.pushInt(w.curPos())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
221 w.emit1(Lazybranch, 0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
222 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
223
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
224 case ntTestgroup | afterChild:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
225 if curIndex == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
226 w.emit(Getmark)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
227 w.emit(Forejump)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
228 } else if curIndex == 1 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
229 Branchpos := w.popInt()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
230 w.pushInt(w.curPos())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
231 w.emit1(Goto, 0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
232 w.patchJump(Branchpos, w.curPos())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
233 w.emit(Getmark)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
234 w.emit(Forejump)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
235 if len(node.children) <= 2 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
236 w.patchJump(w.popInt(), w.curPos())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
237 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
238 } else if curIndex == 2 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
239 w.patchJump(w.popInt(), w.curPos())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
240 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
241
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
242 case ntLoop | beforeChild, ntLazyloop | beforeChild:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
243
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
244 if node.n < math.MaxInt32 || node.m > 1 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
245 if node.m == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
246 w.emit1(Nullcount, 0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
247 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
248 w.emit1(Setcount, 1-node.m)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
249 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
250 } else if node.m == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
251 w.emit(Nullmark)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
252 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
253 w.emit(Setmark)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
254 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
255
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
256 if node.m == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
257 w.pushInt(w.curPos())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
258 w.emit1(Goto, 0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
259 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
260 w.pushInt(w.curPos())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
261
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
262 case ntLoop | afterChild, ntLazyloop | afterChild:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
263
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
264 startJumpPos := w.curPos()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
265 lazy := (nodetype - (ntLoop | afterChild))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
266
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
267 if node.n < math.MaxInt32 || node.m > 1 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
268 if node.n == math.MaxInt32 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
269 w.emit2(InstOp(Branchcount+lazy), w.popInt(), math.MaxInt32)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
270 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
271 w.emit2(InstOp(Branchcount+lazy), w.popInt(), node.n-node.m)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
272 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
273 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
274 w.emit1(InstOp(Branchmark+lazy), w.popInt())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
275 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
276
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
277 if node.m == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
278 w.patchJump(w.popInt(), startJumpPos)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
279 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
280
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
281 case ntGroup | beforeChild, ntGroup | afterChild:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
282
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
283 case ntCapture | beforeChild:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
284 w.emit(Setmark)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
285
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
286 case ntCapture | afterChild:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
287 w.emit2(Capturemark, w.mapCapnum(node.m), w.mapCapnum(node.n))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
288
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
289 case ntRequire | beforeChild:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
290 // NOTE: the following line causes lookahead/lookbehind to be
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
291 // NON-BACKTRACKING. It can be commented out with (*)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
292 w.emit(Setjump)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
293
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
294 w.emit(Setmark)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
295
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
296 case ntRequire | afterChild:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
297 w.emit(Getmark)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
298
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
299 // NOTE: the following line causes lookahead/lookbehind to be
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
300 // NON-BACKTRACKING. It can be commented out with (*)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
301 w.emit(Forejump)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
302
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
303 case ntPrevent | beforeChild:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
304 w.emit(Setjump)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
305 w.pushInt(w.curPos())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
306 w.emit1(Lazybranch, 0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
307
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
308 case ntPrevent | afterChild:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
309 w.emit(Backjump)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
310 w.patchJump(w.popInt(), w.curPos())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
311 w.emit(Forejump)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
312
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
313 case ntGreedy | beforeChild:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
314 w.emit(Setjump)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
315
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
316 case ntGreedy | afterChild:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
317 w.emit(Forejump)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
318
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
319 case ntOne, ntNotone:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
320 w.emit1(InstOp(node.t|ntBits), int(node.ch))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
321
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
322 case ntNotoneloop, ntNotonelazy, ntOneloop, ntOnelazy:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
323 if node.m > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
324 if node.t == ntOneloop || node.t == ntOnelazy {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
325 w.emit2(Onerep|bits, int(node.ch), node.m)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
326 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
327 w.emit2(Notonerep|bits, int(node.ch), node.m)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
328 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
329 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
330 if node.n > node.m {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
331 if node.n == math.MaxInt32 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
332 w.emit2(InstOp(node.t|ntBits), int(node.ch), math.MaxInt32)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
333 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
334 w.emit2(InstOp(node.t|ntBits), int(node.ch), node.n-node.m)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
335 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
336 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
337
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
338 case ntSetloop, ntSetlazy:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
339 if node.m > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
340 w.emit2(Setrep|bits, w.setCode(node.set), node.m)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
341 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
342 if node.n > node.m {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
343 if node.n == math.MaxInt32 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
344 w.emit2(InstOp(node.t|ntBits), w.setCode(node.set), math.MaxInt32)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
345 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
346 w.emit2(InstOp(node.t|ntBits), w.setCode(node.set), node.n-node.m)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
347 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
348 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
349
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
350 case ntMulti:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
351 w.emit1(InstOp(node.t|ntBits), w.stringCode(node.str))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
352
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
353 case ntSet:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
354 w.emit1(InstOp(node.t|ntBits), w.setCode(node.set))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
355
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
356 case ntRef:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
357 w.emit1(InstOp(node.t|ntBits), w.mapCapnum(node.m))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
358
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
359 case ntNothing, ntBol, ntEol, ntBoundary, ntNonboundary, ntECMABoundary, ntNonECMABoundary, ntBeginning, ntStart, ntEndZ, ntEnd:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
360 w.emit(InstOp(node.t))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
361
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
362 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
363 return fmt.Errorf("unexpected opcode in regular expression generation: %v", nodetype)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
364 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
365
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
366 return nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
367 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
368
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
369 // To avoid recursion, we use a simple integer stack.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
370 // This is the push.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
371 func (w *writer) pushInt(i int) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
372 w.intStack = append(w.intStack, i)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
373 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
374
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
375 // Returns true if the stack is empty.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
376 func (w *writer) emptyStack() bool {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
377 return len(w.intStack) == 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
378 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
379
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
380 // This is the pop.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
381 func (w *writer) popInt() int {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
382 //get our item
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
383 idx := len(w.intStack) - 1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
384 i := w.intStack[idx]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
385 //trim our slice
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
386 w.intStack = w.intStack[:idx]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
387 return i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
388 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
389
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
390 // Returns the current position in the emitted code.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
391 func (w *writer) curPos() int {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
392 return w.curpos
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
393 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
394
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
395 // Fixes up a jump instruction at the specified offset
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
396 // so that it jumps to the specified jumpDest.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
397 func (w *writer) patchJump(offset, jumpDest int) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
398 w.emitted[offset+1] = jumpDest
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
399 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
400
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
401 // Returns an index in the set table for a charset
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
402 // uses a map to eliminate duplicates.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
403 func (w *writer) setCode(set *CharSet) int {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
404 if w.counting {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
405 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
406 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
407
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
408 buf := &bytes.Buffer{}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
409
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
410 set.mapHashFill(buf)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
411 hash := buf.String()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
412 i, ok := w.sethash[hash]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
413 if !ok {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
414 i = len(w.sethash)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
415 w.sethash[hash] = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
416 w.settable = append(w.settable, set)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
417 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
418 return i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
419 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
420
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
421 // Returns an index in the string table for a string.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
422 // uses a map to eliminate duplicates.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
423 func (w *writer) stringCode(str []rune) int {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
424 if w.counting {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
425 return 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
426 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
427
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
428 hash := string(str)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
429 i, ok := w.stringhash[hash]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
430 if !ok {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
431 i = len(w.stringhash)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
432 w.stringhash[hash] = i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
433 w.stringtable = append(w.stringtable, str)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
434 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
435
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
436 return i
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
437 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
438
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
439 // When generating code on a regex that uses a sparse set
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
440 // of capture slots, we hash them to a dense set of indices
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
441 // for an array of capture slots. Instead of doing the hash
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
442 // at match time, it's done at compile time, here.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
443 func (w *writer) mapCapnum(capnum int) int {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
444 if capnum == -1 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
445 return -1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
446 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
447
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
448 if w.caps != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
449 return w.caps[capnum]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
450 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
451
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
452 return capnum
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
453 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
454
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
455 // Emits a zero-argument operation. Note that the emit
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
456 // functions all run in two modes: they can emit code, or
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
457 // they can just count the size of the code.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
458 func (w *writer) emit(op InstOp) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
459 if w.counting {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
460 w.count++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
461 if opcodeBacktracks(op) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
462 w.trackcount++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
463 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
464 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
465 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
466 w.emitted[w.curpos] = int(op)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
467 w.curpos++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
468 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
469
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
470 // Emits a one-argument operation.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
471 func (w *writer) emit1(op InstOp, opd1 int) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
472 if w.counting {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
473 w.count += 2
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
474 if opcodeBacktracks(op) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
475 w.trackcount++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
476 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
477 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
478 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
479 w.emitted[w.curpos] = int(op)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
480 w.curpos++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
481 w.emitted[w.curpos] = opd1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
482 w.curpos++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
483 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
484
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
485 // Emits a two-argument operation.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
486 func (w *writer) emit2(op InstOp, opd1, opd2 int) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
487 if w.counting {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
488 w.count += 3
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
489 if opcodeBacktracks(op) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
490 w.trackcount++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
491 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
492 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
493 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
494 w.emitted[w.curpos] = int(op)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
495 w.curpos++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
496 w.emitted[w.curpos] = opd1
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
497 w.curpos++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
498 w.emitted[w.curpos] = opd2
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
499 w.curpos++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
500 }