parser.go 2.2 KB

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