| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 | var AND_REGEXP = /^\s+and\s+(.*)/ivar OR_REGEXP = /^(?:,\s*|\s+or\s+)(.*)/ifunction flatten(array) {  if (!Array.isArray(array)) return [array]  return array.reduce(function (a, b) {    return a.concat(flatten(b))  }, [])}function find(string, predicate) {  for (var max = string.length, n = 1; n <= max; n++) {    var parsed = string.substr(-n, n)    if (predicate(parsed, n, max)) {      return string.slice(0, -n)    }  }  return ''}function matchQuery(all, query) {  var node = { query: query }  if (query.indexOf('not ') === 0) {    node.not = true    query = query.slice(4)  }  for (var name in all) {    var type = all[name]    var match = query.match(type.regexp)    if (match) {      node.type = name      for (var i = 0; i < type.matches.length; i++) {        node[type.matches[i]] = match[i + 1]      }      return node    }  }  node.type = 'unknown'  return node}function matchBlock(all, string, qs) {  var node  return find(string, function (parsed, n, max) {    if (AND_REGEXP.test(parsed)) {      node = matchQuery(all, parsed.match(AND_REGEXP)[1])      node.compose = 'and'      qs.unshift(node)      return true    } else if (OR_REGEXP.test(parsed)) {      node = matchQuery(all, parsed.match(OR_REGEXP)[1])      node.compose = 'or'      qs.unshift(node)      return true    } else if (n === max) {      node = matchQuery(all, parsed.trim())      node.compose = 'or'      qs.unshift(node)      return true    }    return false  })}module.exports = function parse(all, queries) {  if (!Array.isArray(queries)) queries = [queries]  return flatten(    queries.map(function (block) {      var qs = []      do {        block = matchBlock(all, block, qs)      } while (block)      return qs    })  )}
 |