rootstate.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. package parser
  2. import (
  3. "bufio"
  4. "fmt"
  5. "strings"
  6. "zero/tools/goctl/api/spec"
  7. )
  8. type rootState struct {
  9. *baseState
  10. }
  11. func newRootState(r *bufio.Reader, lineNumber *int) state {
  12. var state = newBaseState(r, lineNumber)
  13. return rootState{
  14. baseState: state,
  15. }
  16. }
  17. func (s rootState) process(api *spec.ApiSpec) (state, error) {
  18. var annos []spec.Annotation
  19. var builder strings.Builder
  20. for {
  21. ch, err := s.read()
  22. if err != nil {
  23. return nil, err
  24. }
  25. switch {
  26. case isSpace(ch):
  27. if builder.Len() == 0 {
  28. continue
  29. }
  30. token := builder.String()
  31. builder.Reset()
  32. return s.processToken(token, annos)
  33. case ch == at:
  34. if builder.Len() > 0 {
  35. return nil, fmt.Errorf("%q before %q", builder.String(), at)
  36. }
  37. var annoName string
  38. annoLoop:
  39. for {
  40. next, err := s.read()
  41. if err != nil {
  42. return nil, err
  43. }
  44. switch {
  45. case isSpace(next):
  46. if builder.Len() > 0 {
  47. annoName = builder.String()
  48. builder.Reset()
  49. }
  50. case next == leftParenthesis:
  51. if err := s.unread(); err != nil {
  52. return nil, err
  53. }
  54. if builder.Len() > 0 {
  55. annoName = builder.String()
  56. builder.Reset()
  57. }
  58. attrs, err := s.parseProperties()
  59. if err != nil {
  60. return nil, err
  61. }
  62. annos = append(annos, spec.Annotation{
  63. Name: annoName,
  64. Properties: attrs,
  65. })
  66. break annoLoop
  67. default:
  68. builder.WriteRune(next)
  69. }
  70. }
  71. case ch == leftParenthesis:
  72. if builder.Len() == 0 {
  73. return nil, fmt.Errorf("incorrect %q at the beginning of the line", leftParenthesis)
  74. }
  75. if err := s.unread(); err != nil {
  76. return nil, err
  77. }
  78. token := builder.String()
  79. builder.Reset()
  80. return s.processToken(token, annos)
  81. case isLetterDigit(ch):
  82. builder.WriteRune(ch)
  83. case isNewline(ch):
  84. if builder.Len() > 0 {
  85. return nil, fmt.Errorf("incorrect newline after %q", builder.String())
  86. }
  87. }
  88. }
  89. }
  90. func (s rootState) processToken(token string, annos []spec.Annotation) (state, error) {
  91. switch token {
  92. case infoDirective:
  93. return newInfoState(s.baseState), nil
  94. //case typeDirective:
  95. //return newTypeState(s.baseState, annos), nil
  96. case serviceDirective:
  97. return newServiceState(s.baseState, annos), nil
  98. default:
  99. return nil, fmt.Errorf("wrong directive %q", token)
  100. }
  101. }