parse.js 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. var AND_REGEXP = /^\s+and\s+(.*)/i
  2. var OR_REGEXP = /^(?:,\s*|\s+or\s+)(.*)/i
  3. function flatten(array) {
  4. if (!Array.isArray(array)) return [array]
  5. return array.reduce(function (a, b) {
  6. return a.concat(flatten(b))
  7. }, [])
  8. }
  9. function find(string, predicate) {
  10. for (var max = string.length, n = 1; n <= max; n++) {
  11. var parsed = string.substr(-n, n)
  12. if (predicate(parsed, n, max)) {
  13. return string.slice(0, -n)
  14. }
  15. }
  16. return ''
  17. }
  18. function matchQuery(all, query) {
  19. var node = { query: query }
  20. if (query.indexOf('not ') === 0) {
  21. node.not = true
  22. query = query.slice(4)
  23. }
  24. for (var name in all) {
  25. var type = all[name]
  26. var match = query.match(type.regexp)
  27. if (match) {
  28. node.type = name
  29. for (var i = 0; i < type.matches.length; i++) {
  30. node[type.matches[i]] = match[i + 1]
  31. }
  32. return node
  33. }
  34. }
  35. node.type = 'unknown'
  36. return node
  37. }
  38. function matchBlock(all, string, qs) {
  39. var node
  40. return find(string, function (parsed, n, max) {
  41. if (AND_REGEXP.test(parsed)) {
  42. node = matchQuery(all, parsed.match(AND_REGEXP)[1])
  43. node.compose = 'and'
  44. qs.unshift(node)
  45. return true
  46. } else if (OR_REGEXP.test(parsed)) {
  47. node = matchQuery(all, parsed.match(OR_REGEXP)[1])
  48. node.compose = 'or'
  49. qs.unshift(node)
  50. return true
  51. } else if (n === max) {
  52. node = matchQuery(all, parsed.trim())
  53. node.compose = 'or'
  54. qs.unshift(node)
  55. return true
  56. }
  57. return false
  58. })
  59. }
  60. module.exports = function parse(all, queries) {
  61. if (!Array.isArray(queries)) queries = [queries]
  62. return flatten(
  63. queries.map(function (block) {
  64. var qs = []
  65. do {
  66. block = matchBlock(all, block, qs)
  67. } while (block)
  68. return qs
  69. })
  70. )
  71. }