compiler.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. package compiler
  2. // TODO use constructor with all matchers, and to their structs private
  3. // TODO glue multiple Text nodes (like after QuoteMeta)
  4. import (
  5. "fmt"
  6. "reflect"
  7. "github.com/gobwas/glob/match"
  8. "github.com/gobwas/glob/syntax/ast"
  9. "github.com/gobwas/glob/util/runes"
  10. )
  11. func optimizeMatcher(matcher match.Matcher) match.Matcher {
  12. switch m := matcher.(type) {
  13. case match.Any:
  14. if len(m.Separators) == 0 {
  15. return match.NewSuper()
  16. }
  17. case match.AnyOf:
  18. if len(m.Matchers) == 1 {
  19. return m.Matchers[0]
  20. }
  21. return m
  22. case match.List:
  23. if m.Not == false && len(m.List) == 1 {
  24. return match.NewText(string(m.List))
  25. }
  26. return m
  27. case match.BTree:
  28. m.Left = optimizeMatcher(m.Left)
  29. m.Right = optimizeMatcher(m.Right)
  30. r, ok := m.Value.(match.Text)
  31. if !ok {
  32. return m
  33. }
  34. leftNil := m.Left == nil
  35. rightNil := m.Right == nil
  36. if leftNil && rightNil {
  37. return match.NewText(r.Str)
  38. }
  39. _, leftSuper := m.Left.(match.Super)
  40. lp, leftPrefix := m.Left.(match.Prefix)
  41. _, rightSuper := m.Right.(match.Super)
  42. rs, rightSuffix := m.Right.(match.Suffix)
  43. if leftSuper && rightSuper {
  44. return match.NewContains(r.Str, false)
  45. }
  46. if leftSuper && rightNil {
  47. return match.NewSuffix(r.Str)
  48. }
  49. if rightSuper && leftNil {
  50. return match.NewPrefix(r.Str)
  51. }
  52. if leftNil && rightSuffix {
  53. return match.NewPrefixSuffix(r.Str, rs.Suffix)
  54. }
  55. if rightNil && leftPrefix {
  56. return match.NewPrefixSuffix(lp.Prefix, r.Str)
  57. }
  58. return m
  59. }
  60. return matcher
  61. }
  62. func compileMatchers(matchers []match.Matcher) (match.Matcher, error) {
  63. if len(matchers) == 0 {
  64. return nil, fmt.Errorf("compile error: need at least one matcher")
  65. }
  66. if len(matchers) == 1 {
  67. return matchers[0], nil
  68. }
  69. if m := glueMatchers(matchers); m != nil {
  70. return m, nil
  71. }
  72. idx := -1
  73. maxLen := -1
  74. var val match.Matcher
  75. for i, matcher := range matchers {
  76. if l := matcher.Len(); l != -1 && l >= maxLen {
  77. maxLen = l
  78. idx = i
  79. val = matcher
  80. }
  81. }
  82. if val == nil { // not found matcher with static length
  83. r, err := compileMatchers(matchers[1:])
  84. if err != nil {
  85. return nil, err
  86. }
  87. return match.NewBTree(matchers[0], nil, r), nil
  88. }
  89. left := matchers[:idx]
  90. var right []match.Matcher
  91. if len(matchers) > idx+1 {
  92. right = matchers[idx+1:]
  93. }
  94. var l, r match.Matcher
  95. var err error
  96. if len(left) > 0 {
  97. l, err = compileMatchers(left)
  98. if err != nil {
  99. return nil, err
  100. }
  101. }
  102. if len(right) > 0 {
  103. r, err = compileMatchers(right)
  104. if err != nil {
  105. return nil, err
  106. }
  107. }
  108. return match.NewBTree(val, l, r), nil
  109. }
  110. func glueMatchers(matchers []match.Matcher) match.Matcher {
  111. if m := glueMatchersAsEvery(matchers); m != nil {
  112. return m
  113. }
  114. if m := glueMatchersAsRow(matchers); m != nil {
  115. return m
  116. }
  117. return nil
  118. }
  119. func glueMatchersAsRow(matchers []match.Matcher) match.Matcher {
  120. if len(matchers) <= 1 {
  121. return nil
  122. }
  123. var (
  124. c []match.Matcher
  125. l int
  126. )
  127. for _, matcher := range matchers {
  128. if ml := matcher.Len(); ml == -1 {
  129. return nil
  130. } else {
  131. c = append(c, matcher)
  132. l += ml
  133. }
  134. }
  135. return match.NewRow(l, c...)
  136. }
  137. func glueMatchersAsEvery(matchers []match.Matcher) match.Matcher {
  138. if len(matchers) <= 1 {
  139. return nil
  140. }
  141. var (
  142. hasAny bool
  143. hasSuper bool
  144. hasSingle bool
  145. min int
  146. separator []rune
  147. )
  148. for i, matcher := range matchers {
  149. var sep []rune
  150. switch m := matcher.(type) {
  151. case match.Super:
  152. sep = []rune{}
  153. hasSuper = true
  154. case match.Any:
  155. sep = m.Separators
  156. hasAny = true
  157. case match.Single:
  158. sep = m.Separators
  159. hasSingle = true
  160. min++
  161. case match.List:
  162. if !m.Not {
  163. return nil
  164. }
  165. sep = m.List
  166. hasSingle = true
  167. min++
  168. default:
  169. return nil
  170. }
  171. // initialize
  172. if i == 0 {
  173. separator = sep
  174. }
  175. if runes.Equal(sep, separator) {
  176. continue
  177. }
  178. return nil
  179. }
  180. if hasSuper && !hasAny && !hasSingle {
  181. return match.NewSuper()
  182. }
  183. if hasAny && !hasSuper && !hasSingle {
  184. return match.NewAny(separator)
  185. }
  186. if (hasAny || hasSuper) && min > 0 && len(separator) == 0 {
  187. return match.NewMin(min)
  188. }
  189. every := match.NewEveryOf()
  190. if min > 0 {
  191. every.Add(match.NewMin(min))
  192. if !hasAny && !hasSuper {
  193. every.Add(match.NewMax(min))
  194. }
  195. }
  196. if len(separator) > 0 {
  197. every.Add(match.NewContains(string(separator), true))
  198. }
  199. return every
  200. }
  201. func minimizeMatchers(matchers []match.Matcher) []match.Matcher {
  202. var done match.Matcher
  203. var left, right, count int
  204. for l := 0; l < len(matchers); l++ {
  205. for r := len(matchers); r > l; r-- {
  206. if glued := glueMatchers(matchers[l:r]); glued != nil {
  207. var swap bool
  208. if done == nil {
  209. swap = true
  210. } else {
  211. cl, gl := done.Len(), glued.Len()
  212. swap = cl > -1 && gl > -1 && gl > cl
  213. swap = swap || count < r-l
  214. }
  215. if swap {
  216. done = glued
  217. left = l
  218. right = r
  219. count = r - l
  220. }
  221. }
  222. }
  223. }
  224. if done == nil {
  225. return matchers
  226. }
  227. next := append(append([]match.Matcher{}, matchers[:left]...), done)
  228. if right < len(matchers) {
  229. next = append(next, matchers[right:]...)
  230. }
  231. if len(next) == len(matchers) {
  232. return next
  233. }
  234. return minimizeMatchers(next)
  235. }
  236. // minimizeAnyOf tries to apply some heuristics to minimize number of nodes in given tree
  237. func minimizeTree(tree *ast.Node) *ast.Node {
  238. switch tree.Kind {
  239. case ast.KindAnyOf:
  240. return minimizeTreeAnyOf(tree)
  241. default:
  242. return nil
  243. }
  244. }
  245. // minimizeAnyOf tries to find common children of given node of AnyOf pattern
  246. // it searches for common children from left and from right
  247. // if any common children are found – then it returns new optimized ast tree
  248. // else it returns nil
  249. func minimizeTreeAnyOf(tree *ast.Node) *ast.Node {
  250. if !areOfSameKind(tree.Children, ast.KindPattern) {
  251. return nil
  252. }
  253. commonLeft, commonRight := commonChildren(tree.Children)
  254. commonLeftCount, commonRightCount := len(commonLeft), len(commonRight)
  255. if commonLeftCount == 0 && commonRightCount == 0 { // there are no common parts
  256. return nil
  257. }
  258. var result []*ast.Node
  259. if commonLeftCount > 0 {
  260. result = append(result, ast.NewNode(ast.KindPattern, nil, commonLeft...))
  261. }
  262. var anyOf []*ast.Node
  263. for _, child := range tree.Children {
  264. reuse := child.Children[commonLeftCount : len(child.Children)-commonRightCount]
  265. var node *ast.Node
  266. if len(reuse) == 0 {
  267. // this pattern is completely reduced by commonLeft and commonRight patterns
  268. // so it become nothing
  269. node = ast.NewNode(ast.KindNothing, nil)
  270. } else {
  271. node = ast.NewNode(ast.KindPattern, nil, reuse...)
  272. }
  273. anyOf = appendIfUnique(anyOf, node)
  274. }
  275. switch {
  276. case len(anyOf) == 1 && anyOf[0].Kind != ast.KindNothing:
  277. result = append(result, anyOf[0])
  278. case len(anyOf) > 1:
  279. result = append(result, ast.NewNode(ast.KindAnyOf, nil, anyOf...))
  280. }
  281. if commonRightCount > 0 {
  282. result = append(result, ast.NewNode(ast.KindPattern, nil, commonRight...))
  283. }
  284. return ast.NewNode(ast.KindPattern, nil, result...)
  285. }
  286. func commonChildren(nodes []*ast.Node) (commonLeft, commonRight []*ast.Node) {
  287. if len(nodes) <= 1 {
  288. return
  289. }
  290. // find node that has least number of children
  291. idx := leastChildren(nodes)
  292. if idx == -1 {
  293. return
  294. }
  295. tree := nodes[idx]
  296. treeLength := len(tree.Children)
  297. // allocate max able size for rightCommon slice
  298. // to get ability insert elements in reverse order (from end to start)
  299. // without sorting
  300. commonRight = make([]*ast.Node, treeLength)
  301. lastRight := treeLength // will use this to get results as commonRight[lastRight:]
  302. var (
  303. breakLeft bool
  304. breakRight bool
  305. commonTotal int
  306. )
  307. for i, j := 0, treeLength-1; commonTotal < treeLength && j >= 0 && !(breakLeft && breakRight); i, j = i+1, j-1 {
  308. treeLeft := tree.Children[i]
  309. treeRight := tree.Children[j]
  310. for k := 0; k < len(nodes) && !(breakLeft && breakRight); k++ {
  311. // skip least children node
  312. if k == idx {
  313. continue
  314. }
  315. restLeft := nodes[k].Children[i]
  316. restRight := nodes[k].Children[j+len(nodes[k].Children)-treeLength]
  317. breakLeft = breakLeft || !treeLeft.Equal(restLeft)
  318. // disable searching for right common parts, if left part is already overlapping
  319. breakRight = breakRight || (!breakLeft && j <= i)
  320. breakRight = breakRight || !treeRight.Equal(restRight)
  321. }
  322. if !breakLeft {
  323. commonTotal++
  324. commonLeft = append(commonLeft, treeLeft)
  325. }
  326. if !breakRight {
  327. commonTotal++
  328. lastRight = j
  329. commonRight[j] = treeRight
  330. }
  331. }
  332. commonRight = commonRight[lastRight:]
  333. return
  334. }
  335. func appendIfUnique(target []*ast.Node, val *ast.Node) []*ast.Node {
  336. for _, n := range target {
  337. if reflect.DeepEqual(n, val) {
  338. return target
  339. }
  340. }
  341. return append(target, val)
  342. }
  343. func areOfSameKind(nodes []*ast.Node, kind ast.Kind) bool {
  344. for _, n := range nodes {
  345. if n.Kind != kind {
  346. return false
  347. }
  348. }
  349. return true
  350. }
  351. func leastChildren(nodes []*ast.Node) int {
  352. min := -1
  353. idx := -1
  354. for i, n := range nodes {
  355. if idx == -1 || (len(n.Children) < min) {
  356. min = len(n.Children)
  357. idx = i
  358. }
  359. }
  360. return idx
  361. }
  362. func compileTreeChildren(tree *ast.Node, sep []rune) ([]match.Matcher, error) {
  363. var matchers []match.Matcher
  364. for _, desc := range tree.Children {
  365. m, err := compile(desc, sep)
  366. if err != nil {
  367. return nil, err
  368. }
  369. matchers = append(matchers, optimizeMatcher(m))
  370. }
  371. return matchers, nil
  372. }
  373. func compile(tree *ast.Node, sep []rune) (m match.Matcher, err error) {
  374. switch tree.Kind {
  375. case ast.KindAnyOf:
  376. // todo this could be faster on pattern_alternatives_combine_lite (see glob_test.go)
  377. if n := minimizeTree(tree); n != nil {
  378. return compile(n, sep)
  379. }
  380. matchers, err := compileTreeChildren(tree, sep)
  381. if err != nil {
  382. return nil, err
  383. }
  384. return match.NewAnyOf(matchers...), nil
  385. case ast.KindPattern:
  386. if len(tree.Children) == 0 {
  387. return match.NewNothing(), nil
  388. }
  389. matchers, err := compileTreeChildren(tree, sep)
  390. if err != nil {
  391. return nil, err
  392. }
  393. m, err = compileMatchers(minimizeMatchers(matchers))
  394. if err != nil {
  395. return nil, err
  396. }
  397. case ast.KindAny:
  398. m = match.NewAny(sep)
  399. case ast.KindSuper:
  400. m = match.NewSuper()
  401. case ast.KindSingle:
  402. m = match.NewSingle(sep)
  403. case ast.KindNothing:
  404. m = match.NewNothing()
  405. case ast.KindList:
  406. l := tree.Value.(ast.List)
  407. m = match.NewList([]rune(l.Chars), l.Not)
  408. case ast.KindRange:
  409. r := tree.Value.(ast.Range)
  410. m = match.NewRange(r.Lo, r.Hi, r.Not)
  411. case ast.KindText:
  412. t := tree.Value.(ast.Text)
  413. m = match.NewText(t.Text)
  414. default:
  415. return nil, fmt.Errorf("could not compile tree: unknown node type")
  416. }
  417. return optimizeMatcher(m), nil
  418. }
  419. func Compile(tree *ast.Node, sep []rune) (match.Matcher, error) {
  420. m, err := compile(tree, sep)
  421. if err != nil {
  422. return nil, err
  423. }
  424. return m, nil
  425. }