baseparser.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. package api
  2. import (
  3. "fmt"
  4. "net/http"
  5. "regexp"
  6. "strings"
  7. "unicode"
  8. "github.com/antlr/antlr4/runtime/Go/antlr"
  9. )
  10. const (
  11. versionRegex = `(?m)"v[1-9][0-9]*"`
  12. importValueRegex = `(?m)"(/?[a-zA-Z0-9_#-])+\.api"`
  13. tagRegex = `(?m)\x60[a-z]+:".+"\x60`
  14. )
  15. var holder = struct{}{}
  16. var kind = map[string]struct{}{
  17. "bool": holder,
  18. "int": holder,
  19. "int8": holder,
  20. "int16": holder,
  21. "int32": holder,
  22. "int64": holder,
  23. "uint": holder,
  24. "uint8": holder,
  25. "uint16": holder,
  26. "uint32": holder,
  27. "uint64": holder,
  28. "uintptr": holder,
  29. "float32": holder,
  30. "float64": holder,
  31. "complex64": holder,
  32. "complex128": holder,
  33. "string": holder,
  34. "byte": holder,
  35. "rune": holder,
  36. }
  37. func match(p *ApiParserParser, text string) {
  38. v := getCurrentTokenText(p)
  39. if v != text {
  40. notifyErrorListeners(p, expecting(text, v))
  41. }
  42. }
  43. func checkVersion(p *ApiParserParser) {
  44. v := getCurrentTokenText(p)
  45. if !matchRegex(v, versionRegex) {
  46. notifyErrorListeners(p, mismatched("version", v))
  47. }
  48. }
  49. func checkImportValue(p *ApiParserParser) {
  50. v := getCurrentTokenText(p)
  51. if !matchRegex(v, importValueRegex) {
  52. notifyErrorListeners(p, mismatched("import value", v))
  53. }
  54. }
  55. func checkKeyValue(p *ApiParserParser) {
  56. v := getCurrentTokenText(p)
  57. if !strings.HasPrefix(v, ":") {
  58. notifyErrorListeners(p, mismatched(":", v))
  59. }
  60. v = strings.TrimPrefix(v, ":")
  61. v = strings.TrimFunc(v, func(r rune) bool {
  62. return unicode.IsSpace(r)
  63. })
  64. setCurrentTokenText(p, v)
  65. }
  66. func checkHttpMethod(p *ApiParserParser) {
  67. method := getCurrentTokenText(p)
  68. uppler := strings.ToUpper(method)
  69. switch uppler {
  70. case http.MethodPost, http.MethodGet, http.MethodHead,
  71. http.MethodPut, http.MethodPatch, http.MethodDelete,
  72. http.MethodConnect, http.MethodOptions, http.MethodTrace:
  73. if method != strings.ToLower(method) {
  74. notifyErrorListeners(p, expecting("http method lower case", method))
  75. }
  76. default:
  77. notifyErrorListeners(p, expecting("http method", method))
  78. }
  79. }
  80. func checkKeyword(p *ApiParserParser) {
  81. v := getCurrentTokenText(p)
  82. if IsGolangKeyWord(v) {
  83. notifyErrorListeners(p, fmt.Sprintf("expecting ID, found golang keyword: '%s'", v))
  84. }
  85. }
  86. func checkKey(p *ApiParserParser) {
  87. v := getCurrentTokenText(p)
  88. if IsGolangKeyWord(v) {
  89. notifyErrorListeners(p, fmt.Sprintf("expecting ID, found golang keyword: '%s'", v))
  90. }
  91. if _, ok := kind[v]; !ok {
  92. notifyErrorListeners(p, fmt.Sprintf("expecting golang basic type, found : '%s'", v))
  93. }
  94. }
  95. func IsBasicType(text string) bool {
  96. _, ok := kind[text]
  97. return ok
  98. }
  99. func IsGolangKeyWord(text string, excepts ...string) bool {
  100. for _, each := range excepts {
  101. if text == each {
  102. return false
  103. }
  104. }
  105. switch text {
  106. case "var", "const", "package", "import", "func", "return",
  107. "defer", "go", "select", "interface", "struct", "break", "case",
  108. "continue", "for", "fallthrough", "else", "if", "switch", "goto",
  109. "default", "chan", "type", "map", "range":
  110. return true
  111. default:
  112. return false
  113. }
  114. }
  115. func isNormal(p *ApiParserParser) bool {
  116. ct := p.GetTokenStream().(*antlr.CommonTokenStream)
  117. line := p.GetCurrentToken().GetLine()
  118. tokens := ct.GetAllTokens()
  119. var list []string
  120. for _, token := range tokens {
  121. if token.GetLine() == line {
  122. text := token.GetText()
  123. if strings.HasPrefix(text, "//") {
  124. continue
  125. }
  126. if strings.HasPrefix(text, "/*") {
  127. continue
  128. }
  129. if text == "<EOF>" {
  130. continue
  131. }
  132. if strings.TrimSpace(text) == "" {
  133. continue
  134. }
  135. list = append(list, text)
  136. }
  137. }
  138. if len(list) == 1 {
  139. t := strings.TrimPrefix(list[0], "*")
  140. if IsGolangKeyWord(t) {
  141. notifyErrorListeners(p, fmt.Sprintf("expecting ID, found golang keyword: '%s'", t))
  142. }
  143. }
  144. if len(list) > 1 {
  145. if list[0] == "*" {
  146. t := strings.TrimPrefix(list[1], "*")
  147. if IsGolangKeyWord(t) {
  148. notifyErrorListeners(p, fmt.Sprintf("expecting ID, found golang keyword: '%s'", t))
  149. }
  150. return false
  151. }
  152. }
  153. return len(list) > 1
  154. }
  155. func MatchTag(v string) bool {
  156. return matchRegex(v, tagRegex)
  157. }
  158. func isInterface(p *ApiParserParser) {
  159. v := getCurrentTokenText(p)
  160. if IsGolangKeyWord(v) {
  161. notifyErrorListeners(p, fmt.Sprintf("expecting ID, found golang keyword: '%s'", v))
  162. }
  163. }
  164. func getCurrentTokenText(p *ApiParserParser) string {
  165. token := p.GetCurrentToken()
  166. if token == nil {
  167. return ""
  168. }
  169. return token.GetText()
  170. }
  171. func setCurrentTokenText(p *ApiParserParser, text string) {
  172. token := p.GetCurrentToken()
  173. if token == nil {
  174. return
  175. }
  176. token.SetText(text)
  177. }
  178. func notifyErrorListeners(p *ApiParserParser, msg string) {
  179. p.NotifyErrorListeners(msg, nil, nil)
  180. }
  181. func matchRegex(text, str string) bool {
  182. re := regexp.MustCompile(str)
  183. v := re.FindString(text)
  184. text = strings.TrimFunc(text, func(r rune) bool {
  185. return unicode.IsSpace(r)
  186. })
  187. return v == text
  188. }
  189. func expecting(expecting, found string) string {
  190. return fmt.Sprintf(`expecting '%s', found input '%s'`, expecting, found)
  191. }
  192. func mismatched(expecting, found string) string {
  193. return fmt.Sprintf(`mismatched '%s', found input '%s'`, expecting, found)
  194. }