parser.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package parser
  2. import (
  3. "bufio"
  4. "bytes"
  5. "fmt"
  6. "io"
  7. "io/ioutil"
  8. "path/filepath"
  9. "strings"
  10. "github.com/tal-tech/go-zero/tools/goctl/api/spec"
  11. "github.com/tal-tech/go-zero/tools/goctl/util"
  12. )
  13. type Parser struct {
  14. r *bufio.Reader
  15. typeDef string
  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. ip := strings.TrimSpace(item)
  33. if len(ip) > 0 {
  34. item := strings.TrimPrefix(item, "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, err
  45. }
  46. apiStruct.StructBody += "\n" + string(content)
  47. }
  48. }
  49. var buffer = new(bytes.Buffer)
  50. buffer.WriteString(apiStruct.Service)
  51. return &Parser{
  52. r: bufio.NewReader(buffer),
  53. typeDef: apiStruct.StructBody,
  54. api: apiStruct,
  55. }, nil
  56. }
  57. func (p *Parser) Parse() (api *spec.ApiSpec, err error) {
  58. api = new(spec.ApiSpec)
  59. var sp = StructParser{Src: p.typeDef}
  60. types, err := sp.Parse()
  61. if err != nil {
  62. return nil, err
  63. }
  64. api.Types = types
  65. var lineNumber = p.api.serviceBeginLine
  66. st := newRootState(p.r, &lineNumber)
  67. for {
  68. st, err = st.process(api)
  69. if err == io.EOF {
  70. return api, p.validate(api)
  71. }
  72. if err != nil {
  73. return nil, fmt.Errorf("near line: %d, %s", lineNumber, err.Error())
  74. }
  75. if st == nil {
  76. return api, p.validate(api)
  77. }
  78. }
  79. }