mirror of
https://github.com/DeviceFarmer/stf.git
synced 2026-04-18 08:13:31 +02:00
132 lines
2.9 KiB
JavaScript
132 lines
2.9 KiB
JavaScript
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
|