parser.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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. var path = item
  37. if !util.FileExists(item) {
  38. path = filepath.Join(filepath.Dir(apiAbsPath), item)
  39. }
  40. content, err := ioutil.ReadFile(path)
  41. if err != nil {
  42. return nil, err
  43. }
  44. apiStruct.StructBody += "\n" + string(content)
  45. }
  46. }
  47. var buffer = new(bytes.Buffer)
  48. buffer.WriteString(apiStruct.Service)
  49. return &Parser{
  50. r: bufio.NewReader(buffer),
  51. typeDef: apiStruct.StructBody,
  52. api: apiStruct,
  53. }, nil
  54. }
  55. func (p *Parser) Parse() (api *spec.ApiSpec, err error) {
  56. api = new(spec.ApiSpec)
  57. var sp = StructParser{Src: p.typeDef}
  58. types, err := sp.Parse()
  59. if err != nil {
  60. return nil, err
  61. }
  62. api.Types = types
  63. var lineNumber = p.api.serviceBeginLine
  64. st := newRootState(p.r, &lineNumber)
  65. for {
  66. st, err = st.process(api)
  67. if err == io.EOF {
  68. return api, p.validate(api)
  69. }
  70. if err != nil {
  71. return nil, fmt.Errorf("near line: %d, %s", lineNumber, err.Error())
  72. }
  73. if st == nil {
  74. return api, p.validate(api)
  75. }
  76. }
  77. }