-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathprog.go
130 lines (115 loc) · 2.22 KB
/
prog.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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of The BSD 3-Clause License
// that can be found in the LICENSE file.
package uritemplate
import (
"bytes"
"strconv"
)
type progOpcode uint16
const (
// match
opRune progOpcode = iota
opRuneClass
opLineBegin
opLineEnd
// capture
opCapStart
opCapEnd
// stack
opSplit
opJmp
opJmpIfNotDefined
opJmpIfNotEmpty
opJmpIfNotFirst
// result
opEnd
// fake
opNoop
opcodeMax
)
var opcodeNames = []string{
// match
"opRune",
"opRuneClass",
"opLineBegin",
"opLineEnd",
// capture
"opCapStart",
"opCapEnd",
// stack
"opSplit",
"opJmp",
"opJmpIfNotDefined",
"opJmpIfNotEmpty",
"opJmpIfNotFirst",
// result
"opEnd",
}
func (code progOpcode) String() string {
if code >= opcodeMax {
return ""
}
return opcodeNames[code]
}
type progOp struct {
code progOpcode
r rune
rc runeClass
i uint32
name string
}
func dumpProgOp(b *bytes.Buffer, op *progOp) {
b.WriteString(op.code.String())
switch op.code {
case opRune:
b.WriteString("(")
b.WriteString(strconv.QuoteToASCII(string(op.r)))
b.WriteString(")")
case opRuneClass:
b.WriteString("(")
b.WriteString(op.rc.String())
b.WriteString(")")
case opCapStart, opCapEnd:
b.WriteString("(")
b.WriteString(strconv.QuoteToASCII(op.name))
b.WriteString(")")
case opSplit:
b.WriteString(" -> ")
b.WriteString(strconv.FormatInt(int64(op.i), 10))
case opJmp, opJmpIfNotFirst:
b.WriteString(" -> ")
b.WriteString(strconv.FormatInt(int64(op.i), 10))
case opJmpIfNotDefined, opJmpIfNotEmpty:
b.WriteString("(")
b.WriteString(strconv.QuoteToASCII(op.name))
b.WriteString(")")
b.WriteString(" -> ")
b.WriteString(strconv.FormatInt(int64(op.i), 10))
}
}
type prog struct {
op []progOp
numCap int
}
func dumpProg(b *bytes.Buffer, prog *prog, pc uint32) {
for i := range prog.op {
op := prog.op[i]
pos := strconv.Itoa(i)
if uint32(i) == pc {
pos = "*" + pos
}
b.WriteString(" "[len(pos):])
b.WriteString(pos)
b.WriteByte('\t')
dumpProgOp(b, &op)
b.WriteByte('\n')
}
}
func (p *prog) String() string {
b := bytes.Buffer{}
dumpProg(&b, p, 0)
return b.String()
}