github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/internal/pattern/inst.go (about) 1 package pattern 2 3 import ( 4 "fmt" 5 "unicode/utf8" 6 ) 7 8 type opCode rune 9 10 const ( 11 opMatch opCode = iota + utf8.MaxRune + 1 12 opJmp 13 opSplit 14 opBeginSave 15 opEndSave 16 opCapture 17 18 opAny 19 opLetter 20 opControl 21 opDigit 22 opGraphic 23 opLower 24 opPunct 25 opSpace 26 opUpper 27 opAlphaNum 28 opHexDigit 29 opZero 30 31 opNotLetter 32 opNotControl 33 opNotDigit 34 opNotGraphic 35 opNotLower 36 opNotPunct 37 opNotSpace 38 opNotUpper 39 opNotAlphaNum 40 opNotHexDigit 41 opNotZero 42 43 opSet 44 opFrontier 45 opBalance 46 ) 47 48 type instruction struct { 49 op opCode 50 x int 51 y int 52 } 53 54 func (inst instruction) String() string { 55 switch inst.op { 56 case opMatch: 57 return fmt.Sprintf("op: match") 58 case opJmp: 59 return fmt.Sprintf("op: jmp, x: %d", inst.x) 60 case opSplit: 61 return fmt.Sprintf("op: split, x: %d, y: %d", inst.x, inst.y) 62 case opBeginSave: 63 return fmt.Sprintf("op: begin save, x: %d", inst.x) 64 case opEndSave: 65 return fmt.Sprintf("op: end save, x: %d", inst.x) 66 case opCapture: 67 return fmt.Sprintf("op: capture") 68 69 case opAny: 70 return fmt.Sprintf("op: any") 71 case opLetter: 72 return fmt.Sprintf("op: letter") 73 case opControl: 74 return fmt.Sprintf("op: control") 75 case opDigit: 76 return fmt.Sprintf("op: digit") 77 case opGraphic: 78 return fmt.Sprintf("op: graphic") 79 case opLower: 80 return fmt.Sprintf("op: lower") 81 case opPunct: 82 return fmt.Sprintf("op: punctuation") 83 case opSpace: 84 return fmt.Sprintf("op: space") 85 case opUpper: 86 return fmt.Sprintf("op: upper") 87 case opAlphaNum: 88 return fmt.Sprintf("op: word") 89 case opHexDigit: 90 return fmt.Sprintf("op: hex digit") 91 case opZero: 92 return fmt.Sprintf("op: zero") 93 94 case opNotLetter: 95 return fmt.Sprintf("op: not letter") 96 case opNotControl: 97 return fmt.Sprintf("op: not control") 98 case opNotDigit: 99 return fmt.Sprintf("op: not digit") 100 case opNotGraphic: 101 return fmt.Sprintf("op: not graphic") 102 case opNotLower: 103 return fmt.Sprintf("op: not lower") 104 case opNotPunct: 105 return fmt.Sprintf("op: not punctuation") 106 case opNotSpace: 107 return fmt.Sprintf("op: not space") 108 case opNotUpper: 109 return fmt.Sprintf("op: not upper") 110 case opNotAlphaNum: 111 return fmt.Sprintf("op: not word") 112 case opNotHexDigit: 113 return fmt.Sprintf("op: not hex digit") 114 case opNotZero: 115 return fmt.Sprintf("op: not zero") 116 117 case opSet: 118 return fmt.Sprintf("op: set") 119 case opFrontier: 120 return fmt.Sprintf("op: frontier") 121 case opBalance: 122 return fmt.Sprintf("op: balance, x: %c, y: %c", rune(inst.x), rune(inst.y)) 123 124 default: 125 if 0 <= inst.op && inst.op <= utf8.MaxRune { 126 return fmt.Sprintf("op: %c", inst.op) 127 } 128 129 return fmt.Sprintf("op: unknown") 130 } 131 } 132 133 func instChar(r rune) instruction { 134 return instruction{op: opCode(r)} 135 } 136 137 func instAny() instruction { 138 return instruction{op: opAny} 139 } 140 141 func instClassOrEscChar(r rune) (instruction, bool) { 142 switch r { 143 case eos: 144 return instruction{}, false 145 case 'a': 146 return instruction{op: opLetter}, true 147 case 'A': 148 return instruction{op: opNotLetter}, true 149 case 'c': 150 return instruction{op: opControl}, true 151 case 'C': 152 return instruction{op: opNotControl}, true 153 case 'd': 154 return instruction{op: opDigit}, true 155 case 'D': 156 return instruction{op: opNotDigit}, true 157 case 'g': 158 return instruction{op: opGraphic}, true 159 case 'G': 160 return instruction{op: opNotGraphic}, true 161 case 'l': 162 return instruction{op: opLower}, true 163 case 'L': 164 return instruction{op: opNotLower}, true 165 case 'p': 166 return instruction{op: opPunct}, true 167 case 'P': 168 return instruction{op: opNotPunct}, true 169 case 's': 170 return instruction{op: opSpace}, true 171 case 'S': 172 return instruction{op: opNotSpace}, true 173 case 'u': 174 return instruction{op: opUpper}, true 175 case 'U': 176 return instruction{op: opNotUpper}, true 177 case 'w': 178 return instruction{op: opAlphaNum}, true 179 case 'W': 180 return instruction{op: opNotAlphaNum}, true 181 case 'x': 182 return instruction{op: opHexDigit}, true 183 case 'X': 184 return instruction{op: opNotHexDigit}, true 185 case 'z': 186 return instruction{op: opZero}, true 187 case 'Z': 188 return instruction{op: opNotZero}, true 189 default: 190 if !isAlphaNum(r) { 191 return instChar(r), true 192 } 193 return instruction{}, false 194 } 195 } 196 197 func instMatch() instruction { 198 return instruction{ 199 op: opMatch, 200 } 201 } 202 203 // x: next instruction, higher precedence than y 204 // y: next instruction 205 func instSplit(x, y int) instruction { 206 return instruction{ 207 op: opSplit, 208 x: x, 209 y: y, 210 } 211 } 212 213 // x: next instruction 214 func instJmp(x int) instruction { 215 return instruction{ 216 op: opJmp, 217 x: x, 218 } 219 } 220 221 // x: depth 222 func instBeginSave(x int) instruction { 223 return instruction{ 224 op: opBeginSave, 225 x: x, 226 } 227 } 228 229 // x: depth 230 // y: 1 if the paren is empty 231 func instEndSave(x, y int) instruction { 232 return instruction{ 233 op: opEndSave, 234 x: x, 235 y: y, 236 } 237 } 238 239 // x: capture number 240 func instCapture(x int) instruction { 241 return instruction{ 242 op: opCapture, 243 x: x, 244 } 245 } 246 247 func instSet(x int) instruction { 248 return instruction{ 249 op: opSet, 250 x: x, 251 } 252 } 253 254 func instFrontier(x int) instruction { 255 return instruction{ 256 op: opFrontier, 257 x: x, 258 } 259 } 260 261 func instBalance(x, y int) instruction { 262 return instruction{ 263 op: opBalance, 264 x: x, 265 y: y, 266 } 267 }