X-Git-Url: http://git.indexdata.com/?p=cql-js-moved-to-github.git;a=blobdiff_plain;f=cql.js;h=37035d3b9611ef4b345324ad2fec0585510ebdc3;hp=1f9b1261b3597d7696d13e377a5e710668d97edf;hb=3cf1774e6fa716ecd6561ee11ca8c81ae105b047;hpb=9dd5dd0825d3a847cd1bb52f21b9ab5a50c2340e;ds=sidebyside
diff --git a/cql.js b/cql.js
index 1f9b126..37035d3 100644
--- a/cql.js
+++ b/cql.js
@@ -1,7 +1,12 @@
-function indent(n) {
+var EXPORTED_SYMBOLS = ["CQLParser"];
+
+var DEFAULT_SERVER_CHOICE_FIELD = 'cql.serverChoice';
+var DEFAULT_SERVER_CHOICE_RELATION = 'scr';
+
+function indent(n, c) {
var s = "";
for (var i = 0; i < n; i++)
- s = s + " ";
+ s = s + c;
return s;
}
// CQLModifier
@@ -16,16 +21,16 @@ CQLModifier.prototype = {
return this.name + this.relation + this.value;
},
- toXCQL: function (n) {
- var s = indent(n+1) + "\n";
- s = s + indent(n+2) + "" + this.name + "\n";
+ toXCQL: function (n, c) {
+ var s = indent(n+1, c) + "\n";
+ s = s + indent(n+2, c) + "" + this.name + "\n";
if (this.relation != null)
- s = s + indent(n+2)
+ s = s + indent(n+2, c)
+ "" + this.relation + "\n";
if (this.value != null)
- s = s + indent(n+2)
+ s = s + indent(n+2, c)
+ "" + this.value +"\n";
- s = s + indent(n+1) + "\n";
+ s = s + indent(n+1, c) + "\n";
return s;
},
@@ -40,59 +45,68 @@ CQLModifier.prototype = {
// CQLSearchClause
var CQLSearchClause = function (field, fielduri, relation, relationuri,
- modifiers, term) {
+ modifiers, term, scf, scr) {
this.field = field;
this.fielduri = fielduri;
this.relation = relation;
this.relationuri = relationuri;
this.modifiers = modifiers;
this.term = term;
+ this.scf = scf || DEFAULT_SERVER_CHOICE_FIELD;
+ this.scr = scr || DEFAULT_SERVER_CHOICE_RELATION;
}
CQLSearchClause.prototype = {
toString: function () {
- return (this.field ? this.field + ' ' : '') +
- (this.relation ? this.relation : '') +
+ var field = this.field;
+ var relation = this.relation;
+ if (field == this.scf && relation == this.scr) {
+ //avoid redundant field/relation
+ field = null;
+ relation = null;
+ }
+ return (field ? field + ' ' : '') +
+ (relation ? relation : '') +
(this.modifiers.length > 0 ? '/' + this.modifiers.join('/') : '') +
- (this.relation || this.modifiers.length ? ' ' : '') +
+ (relation || this.modifiers.length ? ' ' : '') +
'"' + this.term + '"';
},
- toXCQL: function (n) {
- var s = indent(n) + "\n";
+ toXCQL: function (n, c) {
+ var s = indent(n, c) + "\n";
if (this.fielduri.length > 0)
{
- s = s + indent(n+1) + "\n" +
- indent(n+2) + "\n" +
- indent(n+3) + "" + this.fielduri +
+ s = s + indent(n+1, c) + "\n" +
+ indent(n+2, c) + "\n" +
+ indent(n+3, c) + "" + this.fielduri +
"\n" +
- indent(n+2) + "\n" +
- indent(n+1) + "\n";
+ indent(n+2, c) + "\n" +
+ indent(n+1, c) + "\n";
}
- s = s + indent(n+1) + "" + this.field + "\n";
- s = s + indent(n+1) + "\n";
+ s = s + indent(n+1, c) + "" + this.field + "\n";
+ s = s + indent(n+1, c) + "\n";
if (this.relationuri.length > 0) {
- s = s + indent(n+2) +
+ s = s + indent(n+2, c) +
"" + this.relationuri + "\n";
}
- s = s + indent(n+2) + "" + this.relation + "\n";
+ s = s + indent(n+2, c) + "" + this.relation + "\n";
if (this.modifiers.length > 0) {
- s = s + indent(n+2) + "\n";
+ s = s + indent(n+2, c) + "\n";
for (var i = 0; i < this.modifiers.length; i++)
- s = s + this.modifiers[i].toXCQL(n+2);
- s = s + indent(n+2) + "\n";
+ s = s + this.modifiers[i].toXCQL(n+2, c);
+ s = s + indent(n+2, c) + "\n";
}
- s = s + indent(n+1) + "\n";
- s = s + indent(n+1) + "" + this.term + "\n";
- s = s + indent(n) + "\n";
+ s = s + indent(n+1, c) + "\n";
+ s = s + indent(n+1, c) + "" + this.term + "\n";
+ s = s + indent(n, c) + "\n";
return s;
},
toFQ: function () {
- var s = '{ "term": "'+this.term+'"';
- if (this.field.length > 0 && this.field != 'cql.serverChoice')
+ var s = '{"term": "'+this.term+'"';
+ if (this.field.length > 0 && this.field != this.scf)
s+= ', "field": "'+this.field+'"';
- if (this.relation.length > 0 && this.relation != 'scr')
+ if (this.relation.length > 0 && this.relation != this.scr)
s+= ', "relation": "'+this._mapRelation(this.relation)+'"';
for (var i = 0; i < this.modifiers.length; i++) {
//since modifiers are mapped to keys, ignore the reserved ones
@@ -102,7 +116,7 @@ CQLSearchClause.prototype = {
continue;
s += ', ' + this.modifiers[i].toFQ();
}
- s += ' }';
+ s += '}';
return s;
},
@@ -146,34 +160,35 @@ CQLBoolean.prototype = {
(this.modifiers.length > 0 ? '/' + this.modifiers.join('/') : '') +
' ' + (this.right.op ? '(' + this.right + ')' : this.right);;
},
- toXCQL: function (n) {
- var s = indent(n) + "\n";
- s = s + indent(n+1) + "\n" +
- indent(n+2) + "" + this.op + "\n";
+ toXCQL: function (n, c) {
+ var s = indent(n, c) + "\n";
+ s = s + indent(n+1, c) + "\n" +
+ indent(n+2, c) + "" + this.op + "\n";
if (this.modifiers.length > 0) {
- s = s + indent(n+2) + "\n";
+ s = s + indent(n+2, c) + "\n";
for (var i = 0; i < this.modifiers.length; i++)
- s = s + this.modifiers[i].toXCQL(n+2);
- s = s + indent(n+2) + "\n";
+ s = s + this.modifiers[i].toXCQL(n+2, c);
+ s = s + indent(n+2, c) + "\n";
}
- s = s + indent(n+1) + "\n";
- s = s + indent(n+1) + "\n" +
- this.left.toXCQL(n+2) + indent(n+1) + "\n";
+ s = s + indent(n+1, c) + "\n";
+ s = s + indent(n+1, c) + "\n" +
+ this.left.toXCQL(n+2, c) + indent(n+1, c) + "\n";
- s = s + indent(n+1) + "\n" +
- this.right.toXCQL(n+2) + indent(n+1) + "\n";
- s = s + indent(n) + "\n";
+ s = s + indent(n+1, c) + "\n" +
+ this.right.toXCQL(n+2, c) + indent(n+1, c) + "\n";
+ s = s + indent(n, c) + "\n";
return s;
},
- toFQ: function () {
- var s = ' { "op": "'+this.op+'"';
+ toFQ: function (n, c, nl) {
+ var s = '{"op": "'+this.op+'"';
//proximity modifiers
for (var i = 0; i < this.modifiers.length; i++)
s += ', ' + this.modifiers[i].toFQ();
- s += ', "s1": '+this.left.toFQ();
- s += ', "s2": '+this.right.toFQ();
- s += ' }'
+ s += ','+nl+indent(n, c)+' "s1": '+this.left.toFQ(n+1, c, nl);
+ s += ','+nl+indent(n, c)+' "s2": '+this.right.toFQ(n+1, c, nl);
+ var fill = n && c ? ' ' : '';
+ s += nl+indent(n-1, c)+fill+'}';
return s;
}
@@ -188,26 +203,35 @@ var CQLParser = function () {
this.val = null;
this.prefixes = new Object();
this.tree = null;
+ this.scf = null;
+ this.scr = null;
}
CQLParser.prototype = {
- parse: function (query) {
+ parse: function (query, scf, scr) {
if (!query)
throw new Error("The query to be parsed cannot be empty");
-
+ this.scf = typeof scf != 'string'
+ ? DEFAULT_SERVER_CHOICE_FIELD : scf;
+ this.scr = typeof scr != 'string'
+ ? DEFAULT_SERVER_CHOICE_RELATION : scr;
this.qs = query;
this.ql = this.qs.length;
this.qi = 0;
this._move();
- this.tree = this._parseQuery("cql.serverChoice", "scr", new Array());
+ this.tree = this._parseQuery(this.scf, this.scr, new Array());
if (this.look != "")
throw new Error("EOF expected");
},
- parseFromFQ: function (query) {
+ parseFromFQ: function (query, scf, scr) {
if (!query)
throw new Error("The query to be parsed cannot be empty");
if (typeof query == 'string')
query = JSON.parse(query);
+ this.scf = typeof scf != 'string'
+ ? DEFAULT_SERVER_CHOICE_FIELD : scf;
+ this.scr = typeof scr != 'string'
+ ? DEFAULT_SERVER_CHOICE_RELATION : scr;
this.tree = this._parseFromFQ(query);
},
_parseFromFQ: function (fq) {
@@ -236,10 +260,12 @@ CQLParser.prototype = {
if (fq.hasOwnProperty('term')) {
var node = new CQLSearchClause();
node.term = fq.term;
+ node.scf = this.scf;
+ node.scr = this.scr;
node.field = fq.hasOwnProperty('field')
- ? fq.field : 'cql.serverChoice';
+ ? fq.field : this.scf;
node.relation = fq.hasOwnProperty('relation')
- ? node._remapRelation(fq.relation) : 'scr';
+ ? node._remapRelation(fq.relation) : this.scr;
//include all other members as modifiers
node.relationuri = '';
node.fielduri = '';
@@ -257,11 +283,14 @@ CQLParser.prototype = {
}
throw new Error('Unknow node type; '+JSON.stringify(fq));
},
- toXCQL: function () {
- return this.tree.toXCQL();
+ toXCQL: function (c) {
+ c = typeof c == "undefined" ? ' ' : c;
+ return this.tree.toXCQL(0, c);
},
- toFQ: function () {
- return this.tree.toFQ();
+ toFQ: function (c, nl) {
+ c = typeof c == "undefined" ? ' ' : c;
+ nl = typeof nl == "undefined" ? '\n' : c;
+ return this.tree.toFQ(0, c, nl);
},
toString: function () {
return this.tree.toString();
@@ -370,7 +399,9 @@ CQLParser.prototype = {
relation,
reluri,
modifiers,
- first);
+ first,
+ this.scf,
+ this.scr);
return sc;
}
// prefixes
@@ -400,41 +431,55 @@ CQLParser.prototype = {
},
_move: function () {
+ //eat whitespace
while (this.qi < this.ql
&& this._strchr(" \t\r\n", this.qs.charAt(this.qi)))
this.qi++;
+ //eof
if (this.qi == this.ql) {
this.look = "";
return;
}
+ //current char
var c = this.qs.charAt(this.qi);
+ //separators
if (this._strchr("()/", c)) {
this.look = c;
this.qi++;
+ //comparitor
} else if (this._strchr("<>=", c)) {
this.look = c;
this.qi++;
+ //comparitors can repeat, could be if
while (this.qi < this.ql
&& this._strchr("<>=", this.qs.charAt(this.qi))) {
this.look = this.look + this.qs.charAt(this.qi);
this.qi++;
}
+ //quoted string
} else if (this._strchr("\"'", c)) {
this.look = "q";
+ //remember quote char
var mark = c;
this.qi++;
this.val = "";
- while (this.qi < this.ql
- && this.qs.charAt(this.qi) != mark) {
- if (this.qs.charAt(this.qi) == '\\'
- && this.qi < this.ql-1)
- this.qi++;
- this.val = this.val + this.qs.charAt(this.qi);
- this.qi++;
+ var escaped = false;
+ while (this.qi < this.ql) {
+ if (!escaped && this.qs.charAt(this.qi) == mark)
+ break;
+ if (!escaped && this.qs.charAt(this.qi) == '\\')
+ escaped = true;
+ else
+ escaped = false;
+ this.val += this.qs.charAt(this.qi);
+ this.qi++;
}
this.lval = this.val.toLowerCase();
if (this.qi < this.ql)
this.qi++;
+ else //unterminated
+ this.look = ""; //notify error
+ //unquoted string
} else {
this.look = "s";
this.val = "";