parser.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package strftime
  2. import "unicode/utf8"
  3. type parser struct {
  4. format func(spec, flag byte) error
  5. literal func(byte) error
  6. }
  7. func (p *parser) parse(fmt string) error {
  8. const (
  9. initial = iota
  10. percent
  11. flagged
  12. modified
  13. )
  14. var flag, modifier byte
  15. var err error
  16. state := initial
  17. start := 0
  18. for i, b := range []byte(fmt) {
  19. switch state {
  20. default:
  21. if b == '%' {
  22. state = percent
  23. start = i
  24. continue
  25. }
  26. err = p.literal(b)
  27. case percent:
  28. if b == '-' || b == ':' {
  29. state = flagged
  30. flag = b
  31. continue
  32. }
  33. if b == 'E' || b == 'O' {
  34. state = modified
  35. modifier = b
  36. flag = 0
  37. continue
  38. }
  39. err = p.format(b, 0)
  40. state = initial
  41. case flagged:
  42. if b == 'E' || b == 'O' {
  43. state = modified
  44. modifier = b
  45. continue
  46. }
  47. err = p.format(b, flag)
  48. state = initial
  49. case modified:
  50. if okModifier(modifier, b) {
  51. err = p.format(b, flag)
  52. } else {
  53. err = p.literals(fmt[start : i+1])
  54. }
  55. state = initial
  56. }
  57. if err != nil {
  58. if err, ok := err.(formatError); ok {
  59. err.setDirective(fmt, start, i)
  60. return err
  61. }
  62. return err
  63. }
  64. }
  65. if state != initial {
  66. return p.literals(fmt[start:])
  67. }
  68. return nil
  69. }
  70. func (p *parser) literals(literal string) error {
  71. for _, b := range []byte(literal) {
  72. if err := p.literal(b); err != nil {
  73. return err
  74. }
  75. }
  76. return nil
  77. }
  78. type literalErr string
  79. func (e literalErr) Error() string {
  80. return "strftime: unsupported literal: " + string(e)
  81. }
  82. type formatError struct {
  83. message string
  84. directive string
  85. }
  86. func (e formatError) Error() string {
  87. return "strftime: unsupported directive: " + e.directive + " " + e.message
  88. }
  89. func (e *formatError) setDirective(str string, i, j int) {
  90. _, n := utf8.DecodeRuneInString(str[j:])
  91. e.directive = str[i : j+n]
  92. }