entity.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. package parser
  2. import (
  3. "errors"
  4. "fmt"
  5. "strings"
  6. "zero/tools/goctl/api/spec"
  7. )
  8. type (
  9. entity struct {
  10. state *baseState
  11. api *spec.ApiSpec
  12. parser entityParser
  13. }
  14. entityParser interface {
  15. parseLine(line string, api *spec.ApiSpec, annos []spec.Annotation) error
  16. setEntityName(name string)
  17. }
  18. )
  19. func newEntity(state *baseState, api *spec.ApiSpec, parser entityParser) entity {
  20. return entity{
  21. state: state,
  22. api: api,
  23. parser: parser,
  24. }
  25. }
  26. func (s *entity) process() error {
  27. line, err := s.state.readLine()
  28. if err != nil {
  29. return err
  30. }
  31. fields := strings.Fields(line)
  32. if len(fields) < 2 {
  33. return fmt.Errorf("invalid type definition for %q",
  34. strings.TrimSpace(strings.Trim(string(line), "{")))
  35. }
  36. if len(fields) == 2 {
  37. if fields[1] != leftBrace {
  38. return fmt.Errorf("bad string %q after type", fields[1])
  39. }
  40. } else if len(fields) == 3 {
  41. if fields[1] != typeStruct {
  42. return fmt.Errorf("bad string %q after type", fields[1])
  43. }
  44. if fields[2] != leftBrace {
  45. return fmt.Errorf("bad string %q after type", fields[2])
  46. }
  47. }
  48. s.parser.setEntityName(fields[0])
  49. var annos []spec.Annotation
  50. memberLoop:
  51. for {
  52. ch, err := s.state.read()
  53. if err != nil {
  54. return err
  55. }
  56. var annoName string
  57. var builder strings.Builder
  58. switch {
  59. case ch == at:
  60. annotationLoop:
  61. for {
  62. next, err := s.state.read()
  63. if err != nil {
  64. return err
  65. }
  66. switch {
  67. case isSpace(next):
  68. if builder.Len() > 0 {
  69. annoName = builder.String()
  70. builder.Reset()
  71. }
  72. case isNewline(next):
  73. if builder.Len() == 0 {
  74. return errors.New("invalid annotation format")
  75. }
  76. case next == leftParenthesis:
  77. if builder.Len() == 0 {
  78. return errors.New("invalid annotation format")
  79. }
  80. annoName = builder.String()
  81. builder.Reset()
  82. if err := s.state.unread(); err != nil {
  83. return err
  84. }
  85. attrs, err := s.state.parseProperties()
  86. if err != nil {
  87. return err
  88. }
  89. annos = append(annos, spec.Annotation{
  90. Name: annoName,
  91. Properties: attrs,
  92. })
  93. break annotationLoop
  94. default:
  95. builder.WriteRune(next)
  96. }
  97. }
  98. case ch == rightBrace:
  99. break memberLoop
  100. case isLetterDigit(ch):
  101. if err := s.state.unread(); err != nil {
  102. return err
  103. }
  104. var line string
  105. line, err = s.state.readLine()
  106. if err != nil {
  107. return err
  108. }
  109. line = strings.TrimSpace(line)
  110. if err := s.parser.parseLine(line, s.api, annos); err != nil {
  111. return err
  112. }
  113. annos = nil
  114. }
  115. }
  116. return nil
  117. }