prog.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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. package uritemplate
  7. import (
  8. "bytes"
  9. "strconv"
  10. )
  11. type progOpcode uint16
  12. const (
  13. // match
  14. opRune progOpcode = iota
  15. opRuneClass
  16. opLineBegin
  17. opLineEnd
  18. // capture
  19. opCapStart
  20. opCapEnd
  21. // stack
  22. opSplit
  23. opJmp
  24. opJmpIfNotDefined
  25. opJmpIfNotEmpty
  26. opJmpIfNotFirst
  27. // result
  28. opEnd
  29. // fake
  30. opNoop
  31. opcodeMax
  32. )
  33. var opcodeNames = []string{
  34. // match
  35. "opRune",
  36. "opRuneClass",
  37. "opLineBegin",
  38. "opLineEnd",
  39. // capture
  40. "opCapStart",
  41. "opCapEnd",
  42. // stack
  43. "opSplit",
  44. "opJmp",
  45. "opJmpIfNotDefined",
  46. "opJmpIfNotEmpty",
  47. "opJmpIfNotFirst",
  48. // result
  49. "opEnd",
  50. }
  51. func (code progOpcode) String() string {
  52. if code >= opcodeMax {
  53. return ""
  54. }
  55. return opcodeNames[code]
  56. }
  57. type progOp struct {
  58. code progOpcode
  59. r rune
  60. rc runeClass
  61. i uint32
  62. name string
  63. }
  64. func dumpProgOp(b *bytes.Buffer, op *progOp) {
  65. b.WriteString(op.code.String())
  66. switch op.code {
  67. case opRune:
  68. b.WriteString("(")
  69. b.WriteString(strconv.QuoteToASCII(string(op.r)))
  70. b.WriteString(")")
  71. case opRuneClass:
  72. b.WriteString("(")
  73. b.WriteString(op.rc.String())
  74. b.WriteString(")")
  75. case opCapStart, opCapEnd:
  76. b.WriteString("(")
  77. b.WriteString(strconv.QuoteToASCII(op.name))
  78. b.WriteString(")")
  79. case opSplit:
  80. b.WriteString(" -> ")
  81. b.WriteString(strconv.FormatInt(int64(op.i), 10))
  82. case opJmp, opJmpIfNotFirst:
  83. b.WriteString(" -> ")
  84. b.WriteString(strconv.FormatInt(int64(op.i), 10))
  85. case opJmpIfNotDefined, opJmpIfNotEmpty:
  86. b.WriteString("(")
  87. b.WriteString(strconv.QuoteToASCII(op.name))
  88. b.WriteString(")")
  89. b.WriteString(" -> ")
  90. b.WriteString(strconv.FormatInt(int64(op.i), 10))
  91. }
  92. }
  93. type prog struct {
  94. op []progOp
  95. numCap int
  96. }
  97. func dumpProg(b *bytes.Buffer, prog *prog, pc uint32) {
  98. for i := range prog.op {
  99. op := prog.op[i]
  100. pos := strconv.Itoa(i)
  101. if uint32(i) == pc {
  102. pos = "*" + pos
  103. }
  104. b.WriteString(" "[len(pos):])
  105. b.WriteString(pos)
  106. b.WriteByte('\t')
  107. dumpProgOp(b, &op)
  108. b.WriteByte('\n')
  109. }
  110. }
  111. func (p *prog) String() string {
  112. b := bytes.Buffer{}
  113. dumpProg(&b, p, 0)
  114. return b.String()
  115. }