Navigation Menu

Skip to content

Commit

Permalink
bq: pass query as property instead of argument
Browse files Browse the repository at this point in the history
  • Loading branch information
kou committed Aug 3, 2012
1 parent 5098781 commit 6f79ed1
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 123 deletions.
204 changes: 99 additions & 105 deletions lib/bq-translator.js
Expand Up @@ -17,84 +17,81 @@
*/


function BooleanQueryTranslator() {
function BooleanQueryTranslator(query) {
this.query = query;
this.offset = 0;
this.defaultField = null;
}

function throwTranslateError(query, context, detail) {
var message = "";
message += "<";
message += query.substring(0, context.offset);
message += "|" + query[context.offset] + "|";
message += query.substring(context.offset + 1);
message += ">";
message += ": " + detail;
throw new Error(message);
};

BooleanQueryTranslator.prototype = {
translate: function(query, defaultField) {
var context = {
defaultField: defaultField,
offset: 0
};
translate: function() {
var expression;
if (query[0] == "(") {
expression = this.translateGroup(query, context);
if (this.query[0] == "(") {
expression = this.translateGroup();
} else {
expression = this.translateExpression(query, context);
expression = this.translateExpression();
}
if (context.offset != query.length) {
throwTranslateError(query, context,
"garbages exist after valid boolean query");
if (this.offset != this.query.length) {
this.throwTranslateError("garbages exist after valid boolean query");
}
return expression;
},
skipSpaces: function(query, context) {
for (; context.offset < query.length; context.offset++) {
if (query[context.offset] != " ") {
throwTranslateError: function(detail) {
var message = "";
message += "<";
message += this.query.substring(0, this.offset);
message += "|" + this.query[this.offset] + "|";
message += this.query.substring(this.offset + 1);
message += ">";
message += ": " + detail;
throw new Error(message);
},
skipSpaces: function() {
for (; this.offset < this.query.length; this.offset++) {
if (this.query[this.offset] != " ") {
return;
}
}
},
translateGroup: function(query, context) {
if (query[context.offset] != "(") {
translateGroup: function() {
if (this.query[this.offset] != "(") {
// TODO: report error
return "";
}

context.offset++;
this.offset++;
var operator = "";
for (; context.offset < query.length; context.offset++) {
var character = query[context.offset];
for (; this.offset < this.query.length; this.offset++) {
var character = this.query[this.offset];
if (/^[a-z]$/.test(character)) {
operator += character;
} else if (character == " ") {
this.skipSpaces(query, context);
this.skipSpaces();
var expression;
switch (operator) {
case "field":
expression = this.translateGroupField(query, context);
expression = this.translateGroupField();
break;
case "filter":
expression = this.translateGroupFilter(query, context);
expression = this.translateGroupFilter();
break;
case "and":
expression = this.translateGroupSetOperation(query, "&&", context);
expression = this.translateGroupSetOperation("&&");
break;
case "or":
expression = this.translateGroupSetOperation(query, "||", context);
expression = this.translateGroupSetOperation("||");
break;
default:
// TODO: report error: unknown operator
return "";
break;
}
this.skipSpaces(query, context);
if (query[context.offset] != ")") {
this.skipSpaces();
if (this.query[this.offset] != ")") {
// TODO: report error: have garbage
return "";
}
context.offset++;
this.offset++;
return expression;
} else if (character == ")") {
// TODO: report error: no arguments for operator
Expand All @@ -108,19 +105,17 @@ BooleanQueryTranslator.prototype = {
// TODO: report error: missing close paren <)>
return "";
},
translateGroupField: function(query, context) {
translateGroupField: function() {
var field = "";
for (; context.offset < query.length; context.offset++) {
var character = query[context.offset];
for (; this.offset < this.query.length; this.offset++) {
var character = this.query[this.offset];
if (/^[\-a-z0-9]$/.test(character)) {
field += character;
} else if (character == " ") {
this.skipSpaces(query, context);
var expression = this.translateExpressionValueString(query,
field,
context);
this.skipSpaces(query, context);
if (query[context.offset] != ")") {
this.skipSpaces();
var expression = this.translateExpressionValueString(field);
this.skipSpaces();
if (this.query[this.offset] != ")") {
// TODO: report error: have garbage
return "";
}
Expand All @@ -137,19 +132,17 @@ BooleanQueryTranslator.prototype = {
// TODO: report error: missing close paren <)>
return "";
},
translateGroupFilter: function(query, context) {
translateGroupFilter: function() {
var field = "";
for (; context.offset < query.length; context.offset++) {
var character = query[context.offset];
for (; this.offset < this.query.length; this.offset++) {
var character = this.query[this.offset];
if (/^[\-a-z0-9]$/.test(character)) {
field += character;
} else if (character == " ") {
this.skipSpaces(query, context);
var expression = this.translateExpressionValueUnsignedInteger(query,
field,
context);
this.skipSpaces(query, context);
if (query[context.offset] != ")") {
this.skipSpaces();
var expression = this.translateExpressionValueUnsignedInteger(field);
this.skipSpaces();
if (this.query[this.offset] != ")") {
// TODO: report error: have garbage
return "";
}
Expand All @@ -166,77 +159,77 @@ BooleanQueryTranslator.prototype = {
// TODO: report error: missing close paren <)>
return "";
},
translateGroupSetOperation: function(query, setOperator, context) {
translateGroupSetOperation: function(setOperator) {
var expressions = [];
while (context.offset < query.length) {
this.skipSpaces(query, context);
if (query[context.offset] == ")") {
while (this.offset < this.query.length) {
this.skipSpaces();
if (this.query[this.offset] == ")") {
return "(" + expressions.join(" " + setOperator + " ") + ")";
} else {
expressions.push(this.translateExpression(query, context));
expressions.push(this.translateExpression());
}
}

// TODO: report error: missing close paren <)>
return "";
},
translateExpression: function(query, context) {
if (query[context.offset] == "(") {
return this.translateGroup(query, context);
translateExpression: function() {
if (this.query[this.offset] == "(") {
return this.translateGroup();
}

var startOffset = context.offset;
var startOffset = this.offset;
var field;
if (/^[a-z0-9]$/.test(query[context.offset])) {
if (/^[a-z0-9]$/.test(this.query[this.offset])) {
field = "";
for (; context.offset < query.length; context.offset++) {
var character = query[context.offset];
for (; this.offset < this.query.length; this.offset++) {
var character = this.query[this.offset];
if (!/^[\-a-z0-9]$/.test(character)) {
break;
}
field += character;
}
if (query[context.offset] == ":") {
context.offset++;
if (this.query[this.offset] == ":") {
this.offset++;
} else {
var is_unsigned_integer_value = /^[0-9]+$/.test(field);
if (is_unsigned_integer_value) {
field = context.defaultField;
context.offset = startOffset;
field = this.defaultField;
this.offset = startOffset;
} else {
// TODO: report error: field and value separator ":" is missing
return "";
}
}
} else {
field = context.defaultField;
field = this.defaultField;
}

if (query[context.offset] == "'") {
return this.translateExpressionValueString(query, field, context);
if (this.query[this.offset] == "'") {
return this.translateExpressionValueString(field);
}
if (/^[0-9.]/.test(query[context.offset])) {
return this.translateExpressionValueUnsignedInteger(query, field, context);
if (/^[0-9.]/.test(this.query[this.offset])) {
return this.translateExpressionValueUnsignedInteger(field);
}
// TODO: report error
return "";
},
translateExpressionValueString: function(query, field, context) {
if (query[context.offset] != "'") {
translateExpressionValueString: function(field) {
if (this.query[this.offset] != "'") {
// TODO: report error
return "";
}
if (query[context.offset + 1] == "\"") {
return this.translateExpressionValuePhrase(query, field, context);
if (this.query[this.offset + 1] == "\"") {
return this.translateExpressionValuePhrase(field);
}

context.offset++;
this.offset++;
var values = [];
var value = "";
for (; context.offset < query.length; context.offset++) {
var character = query[context.offset];
for (; this.offset < this.query.length; this.offset++) {
var character = this.query[this.offset];
if (character == "'") {
context.offset++;
this.offset++;
values.push("\"" + value + "\"");
var expressions = values.map(function (value) {
return field + " @ " + value;
Expand All @@ -250,8 +243,8 @@ BooleanQueryTranslator.prototype = {
value = "";
}
} else if (character == "\\") {
context.offset++;
character = query[context.offset];
this.offset++;
character = this.query[this.offset];
value += character;
} else if (character == "\"") {
value += "\\\"";
Expand All @@ -263,32 +256,33 @@ BooleanQueryTranslator.prototype = {
// TODO: report error: missing close quote <'>
return "";
},
translateExpressionValuePhrase: function(query, field, context) {
if (!(query[context.offset] == "'" && query[context.offset + 1] == "\"")) {
translateExpressionValuePhrase: function(field) {
if (!(this.query[this.offset] == "'" &&
this.query[this.offset + 1] == "\"")) {
// TODO: report error
return "";
}

context.offset += 2;
this.offset += 2;
var value = "";
for (; context.offset < query.length; context.offset++) {
var character = query[context.offset];
for (; this.offset < this.query.length; this.offset++) {
var character = this.query[this.offset];
if (character == "'") {
// TODO: report error: missing close quote <">
return "";
}

if (character == "\\") {
context.offset++;
character = query[context.offset];
this.offset++;
character = this.query[this.offset];
value += character;
} else if (character == "\"") {
context.offset++;
if (query[context.offset] != "'") {
this.offset++;
if (this.query[this.offset] != "'") {
// TODO: report error: missing close quote <'> after <">
return "";
}
context.offset++;
this.offset++;
return field + " @ " + "\"" + value + "\"";
} else {
value += character;
Expand All @@ -298,22 +292,22 @@ BooleanQueryTranslator.prototype = {
// TODO: report error: missing close quote <"'>
return "";
},
translateExpressionValueUnsignedInteger: function(query, field, context) {
translateExpressionValueUnsignedInteger: function(field) {
var is_range = false;
var min = "";
var max = "";
for (; context.offset < query.length; context.offset++) {
var character = query[context.offset];
for (; this.offset < this.query.length; this.offset++) {
var character = this.query[this.offset];
if (!/^[0-9]$/.test(character)) {
break;
}
min += character;
}
if (query[context.offset] == "." && query[context.offset + 1] == ".") {
if (this.query[this.offset] == "." && this.query[this.offset + 1] == ".") {
is_range = true;
context.offset += 2;
for (; context.offset < query.length; context.offset++) {
var character = query[context.offset];
this.offset += 2;
for (; this.offset < this.query.length; this.offset++) {
var character = this.query[this.offset];
if (!/^[0-9]$/.test(character)) {
break;
}
Expand Down

0 comments on commit 6f79ed1

Please sign in to comment.