parser.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package parser
  2. import (
  3. "bufio"
  4. "bytes"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "io/ioutil"
  9. "path/filepath"
  10. "strings"
  11. "github.com/tal-tech/go-zero/tools/goctl/api/spec"
  12. "github.com/tal-tech/go-zero/tools/goctl/util"
  13. )
  14. type Parser struct {
  15. r *bufio.Reader
  16. api *ApiStruct
  17. }
  18. func NewParser(filename string) (*Parser, error) {
  19. apiAbsPath, err := filepath.Abs(filename)
  20. if err != nil {
  21. return nil, err
  22. }
  23. api, err := ioutil.ReadFile(filename)
  24. if err != nil {
  25. return nil, err
  26. }
  27. apiStruct, err := ParseApi(string(api))
  28. if err != nil {
  29. return nil, err
  30. }
  31. for _, item := range strings.Split(apiStruct.Imports, "\n") {
  32. importLine := strings.TrimSpace(item)
  33. if len(importLine) > 0 {
  34. item := strings.TrimPrefix(importLine, "import")
  35. item = strings.TrimSpace(item)
  36. item = strings.TrimPrefix(item, `"`)
  37. item = strings.TrimSuffix(item, `"`)
  38. var path = item
  39. if !util.FileExists(item) {
  40. path = filepath.Join(filepath.Dir(apiAbsPath), item)
  41. }
  42. content, err := ioutil.ReadFile(path)
  43. if err != nil {
  44. return nil, errors.New("import api file not exist: " + item)
  45. }
  46. importStruct, err := ParseApi(string(content))
  47. if err != nil {
  48. return nil, err
  49. }
  50. if len(importStruct.Imports) > 0 {
  51. return nil, errors.New("import api should not import another api file recursive")
  52. }
  53. apiStruct.Type += "\n" + importStruct.Type
  54. apiStruct.Service += "\n" + importStruct.Service
  55. }
  56. }
  57. if len(strings.TrimSpace(apiStruct.Service)) == 0 {
  58. return nil, errors.New("api has no service defined")
  59. }
  60. var buffer = new(bytes.Buffer)
  61. buffer.WriteString(apiStruct.Service)
  62. return &Parser{
  63. r: bufio.NewReader(buffer),
  64. api: apiStruct,
  65. }, nil
  66. }
  67. func (p *Parser) Parse() (api *spec.ApiSpec, err error) {
  68. api = new(spec.ApiSpec)
  69. var sp = StructParser{Src: p.api.Type}
  70. types, err := sp.Parse()
  71. if err != nil {
  72. return nil, err
  73. }
  74. api.Types = types
  75. var lineNumber = p.api.serviceBeginLine
  76. st := newRootState(p.r, &lineNumber)
  77. for {
  78. st, err = st.process(api)
  79. if err == io.EOF {
  80. return api, p.validate(api)
  81. }
  82. if err != nil {
  83. return nil, fmt.Errorf("near line: %d, %s", lineNumber, err.Error())
  84. }
  85. if st == nil {
  86. return api, p.validate(api)
  87. }
  88. }
  89. }