本站源代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 lines
2.9KB

  1. package ast
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/gobwas/glob/syntax/lexer"
  6. "unicode/utf8"
  7. )
  8. type Lexer interface {
  9. Next() lexer.Token
  10. }
  11. type parseFn func(*Node, Lexer) (parseFn, *Node, error)
  12. func Parse(lexer Lexer) (*Node, error) {
  13. var parser parseFn
  14. root := NewNode(KindPattern, nil)
  15. var (
  16. tree *Node
  17. err error
  18. )
  19. for parser, tree = parserMain, root; parser != nil; {
  20. parser, tree, err = parser(tree, lexer)
  21. if err != nil {
  22. return nil, err
  23. }
  24. }
  25. return root, nil
  26. }
  27. func parserMain(tree *Node, lex Lexer) (parseFn, *Node, error) {
  28. for {
  29. token := lex.Next()
  30. switch token.Type {
  31. case lexer.EOF:
  32. return nil, tree, nil
  33. case lexer.Error:
  34. return nil, tree, errors.New(token.Raw)
  35. case lexer.Text:
  36. Insert(tree, NewNode(KindText, Text{token.Raw}))
  37. return parserMain, tree, nil
  38. case lexer.Any:
  39. Insert(tree, NewNode(KindAny, nil))
  40. return parserMain, tree, nil
  41. case lexer.Super:
  42. Insert(tree, NewNode(KindSuper, nil))
  43. return parserMain, tree, nil
  44. case lexer.Single:
  45. Insert(tree, NewNode(KindSingle, nil))
  46. return parserMain, tree, nil
  47. case lexer.RangeOpen:
  48. return parserRange, tree, nil
  49. case lexer.TermsOpen:
  50. a := NewNode(KindAnyOf, nil)
  51. Insert(tree, a)
  52. p := NewNode(KindPattern, nil)
  53. Insert(a, p)
  54. return parserMain, p, nil
  55. case lexer.Separator:
  56. p := NewNode(KindPattern, nil)
  57. Insert(tree.Parent, p)
  58. return parserMain, p, nil
  59. case lexer.TermsClose:
  60. return parserMain, tree.Parent.Parent, nil
  61. default:
  62. return nil, tree, fmt.Errorf("unexpected token: %s", token)
  63. }
  64. }
  65. return nil, tree, fmt.Errorf("unknown error")
  66. }
  67. func parserRange(tree *Node, lex Lexer) (parseFn, *Node, error) {
  68. var (
  69. not bool
  70. lo rune
  71. hi rune
  72. chars string
  73. )
  74. for {
  75. token := lex.Next()
  76. switch token.Type {
  77. case lexer.EOF:
  78. return nil, tree, errors.New("unexpected end")
  79. case lexer.Error:
  80. return nil, tree, errors.New(token.Raw)
  81. case lexer.Not:
  82. not = true
  83. case lexer.RangeLo:
  84. r, w := utf8.DecodeRuneInString(token.Raw)
  85. if len(token.Raw) > w {
  86. return nil, tree, fmt.Errorf("unexpected length of lo character")
  87. }
  88. lo = r
  89. case lexer.RangeBetween:
  90. //
  91. case lexer.RangeHi:
  92. r, w := utf8.DecodeRuneInString(token.Raw)
  93. if len(token.Raw) > w {
  94. return nil, tree, fmt.Errorf("unexpected length of lo character")
  95. }
  96. hi = r
  97. if hi < lo {
  98. return nil, tree, fmt.Errorf("hi character '%s' should be greater than lo '%s'", string(hi), string(lo))
  99. }
  100. case lexer.Text:
  101. chars = token.Raw
  102. case lexer.RangeClose:
  103. isRange := lo != 0 && hi != 0
  104. isChars := chars != ""
  105. if isChars == isRange {
  106. return nil, tree, fmt.Errorf("could not parse range")
  107. }
  108. if isRange {
  109. Insert(tree, NewNode(KindRange, Range{
  110. Lo: lo,
  111. Hi: hi,
  112. Not: not,
  113. }))
  114. } else {
  115. Insert(tree, NewNode(KindList, List{
  116. Chars: chars,
  117. Not: not,
  118. }))
  119. }
  120. return parserMain, tree, nil
  121. }
  122. }
  123. }
上海开阖软件有限公司 沪ICP备12045867号-1