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.
		
		
		
		
		
			
		
			
				
					79 lines
				
				1.7 KiB
			
		
		
			
		
	
	
					79 lines
				
				1.7 KiB
			| 
											3 years ago
										 | var AND_REGEXP = /^\s+and\s+(.*)/i | ||
|  | var OR_REGEXP = /^(?:,\s*|\s+or\s+)(.*)/i | ||
|  | 
 | ||
|  | function 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 n = 1, max = string.length; 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 | ||
|  |     }) | ||
|  |   ) | ||
|  | } |