var State = { TERM_START: 10 , QUERY_START: 20 , OP_LT: 30 , OP_GT: 40 , QUERY_VALUE_START: 50 , QUERY_VALUE: 60 , QUERY_VALUE_DOUBLEQUOTED: 70 } function Term() { this.field = null this.op = null this.query = '' } Term.prototype.append = function(input) { this.query += input } Term.prototype.reset = function() { this.query = '' } function QueryParser() { this.terms = [] this.currentTerm = new Term() this.state = State.TERM_START } QueryParser.parse = function(input) { var parser = new QueryParser() return parser.parse(input) } QueryParser.prototype.parse = function(input) { var chars = input.split('') for (var i = 0, l = chars.length; i < l; ++i) { this.consume(chars[i]) } return this.terms } QueryParser.prototype.consume = function(input) { switch (this.state) { case State.TERM_START: if (this.isWhitespace(input)) { // Preceding whitespace, ignore. return } this.terms.push(this.currentTerm) this.state = State.QUERY_START return this.consume(input) case State.QUERY_START: if (this.isWhitespace(input)) { // Preceding whitespace, ignore. return } if (input === '<') { this.state = State.OP_LT return } if (input === '>') { this.state = State.OP_GT return } this.state = State.QUERY_VALUE_START return this.consume(input) case State.OP_LT: if (input === '=') { this.currentTerm.op = '<=' this.state = State.QUERY_VALUE_START return } this.currentTerm.op = '<' this.state = State.QUERY_VALUE_START return this.consume(input) case State.OP_GT: if (input === '=') { this.currentTerm.op = '>=' this.state = State.QUERY_VALUE_START return } this.currentTerm.op = '>' this.state = State.QUERY_VALUE_START return this.consume(input) case State.QUERY_VALUE_START: if (this.isWhitespace(input)) { // Preceding whitespace, ignore. return } if (input === '"') { this.state = State.QUERY_VALUE_DOUBLEQUOTED return } this.state = State.QUERY_VALUE return this.consume(input) case State.QUERY_VALUE: if (this.isWhitespace(input)) { return this.concludeTerm() } if (input === ':') { this.currentTerm.field = this.currentTerm.query this.currentTerm.reset() this.state = State.QUERY_START return } this.currentTerm.append(input) return case State.QUERY_VALUE_DOUBLEQUOTED: if (input === '\\') { return } if (input === '"') { return this.concludeTerm() } this.currentTerm.append(input) return } } QueryParser.prototype.concludeTerm = function() { this.currentTerm = new Term() this.state = State.TERM_START } QueryParser.prototype.isWhitespace = function(input) { return input === ' ' || input === '\t' || input === '\n' || input === '' } module.exports = QueryParser