1// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved.
2//
3// This program is free software; you can redistribute it and/or
4// modify it under the terms of The BSD 3-Clause License
5// that can be found in the LICENSE file.
6
7package uritemplate
8
9import (
10 "bytes"
11 "strconv"
12)
13
14type progOpcode uint16
15
16const (
17 // match
18 opRune progOpcode = iota
19 opRuneClass
20 opLineBegin
21 opLineEnd
22 // capture
23 opCapStart
24 opCapEnd
25 // stack
26 opSplit
27 opJmp
28 opJmpIfNotDefined
29 opJmpIfNotEmpty
30 opJmpIfNotFirst
31 // result
32 opEnd
33 // fake
34 opNoop
35 opcodeMax
36)
37
38var opcodeNames = []string{
39 // match
40 "opRune",
41 "opRuneClass",
42 "opLineBegin",
43 "opLineEnd",
44 // capture
45 "opCapStart",
46 "opCapEnd",
47 // stack
48 "opSplit",
49 "opJmp",
50 "opJmpIfNotDefined",
51 "opJmpIfNotEmpty",
52 "opJmpIfNotFirst",
53 // result
54 "opEnd",
55}
56
57func (code progOpcode) String() string {
58 if code >= opcodeMax {
59 return ""
60 }
61 return opcodeNames[code]
62}
63
64type progOp struct {
65 code progOpcode
66 r rune
67 rc runeClass
68 i uint32
69
70 name string
71}
72
73func dumpProgOp(b *bytes.Buffer, op *progOp) {
74 b.WriteString(op.code.String())
75 switch op.code {
76 case opRune:
77 b.WriteString("(")
78 b.WriteString(strconv.QuoteToASCII(string(op.r)))
79 b.WriteString(")")
80 case opRuneClass:
81 b.WriteString("(")
82 b.WriteString(op.rc.String())
83 b.WriteString(")")
84 case opCapStart, opCapEnd:
85 b.WriteString("(")
86 b.WriteString(strconv.QuoteToASCII(op.name))
87 b.WriteString(")")
88 case opSplit:
89 b.WriteString(" -> ")
90 b.WriteString(strconv.FormatInt(int64(op.i), 10))
91 case opJmp, opJmpIfNotFirst:
92 b.WriteString(" -> ")
93 b.WriteString(strconv.FormatInt(int64(op.i), 10))
94 case opJmpIfNotDefined, opJmpIfNotEmpty:
95 b.WriteString("(")
96 b.WriteString(strconv.QuoteToASCII(op.name))
97 b.WriteString(")")
98 b.WriteString(" -> ")
99 b.WriteString(strconv.FormatInt(int64(op.i), 10))
100 }
101}
102
103type prog struct {
104 op []progOp
105 numCap int
106}
107
108func dumpProg(b *bytes.Buffer, prog *prog, pc uint32) {
109 for i := range prog.op {
110 op := prog.op[i]
111
112 pos := strconv.Itoa(i)
113 if uint32(i) == pc {
114 pos = "*" + pos
115 }
116 b.WriteString(" "[len(pos):])
117 b.WriteString(pos)
118
119 b.WriteByte('\t')
120 dumpProgOp(b, &op)
121
122 b.WriteByte('\n')
123 }
124}
125
126func (p *prog) String() string {
127 b := bytes.Buffer{}
128 dumpProg(&b, p, 0)
129 return b.String()
130}