3 for (var i = 0; i < n; i++)
8 var CQLModifier = function () {
14 CQLModifier.prototype = {
15 toXCQL: function (n) {
16 var s = indent(n+1) + "<modifier>\n";
17 s = s + indent(n+2) + "<name>" + this.name + "</name>\n";
18 if (this.relation != null)
20 + "<relation>" + this.relation + "</relation>\n";
21 if (this.value != null)
23 + "<value>" + this.value +"</value>\n";
24 s = s + indent(n+1) + "</modifier>\n";
29 var CQLSearchClause = function (field, fielduri, relation, relationuri,
32 this.fielduri = fielduri;
33 this.relation = relation;
34 this.relationuri = relationuri;
35 this.modifiers = modifiers;
39 CQLSearchClause.prototype = {
40 toXCQL: function (n) {
41 var s = indent(n) + "<searchClause>\n";
42 if (this.fielduri.length > 0)
44 s = s + indent(n+1) + "<prefixes>\n" +
45 indent(n+2) + "<prefix>\n" +
46 indent(n+3) + "<identifier>" + this.fielduri +
48 indent(n+2) + "</prefix>\n" +
49 indent(n+1) + "</prefixes>\n";
51 s = s + indent(n+1) + "<index>" + this.field + "</index>\n";
52 s = s + indent(n+1) + "<relation>\n";
53 if (this.relationuri.length > 0) {
55 "<identifier>" + this.relationuri + "</identifier>\n";
57 s = s + indent(n+2) + "<value>" + this.relation + "</value>\n";
58 if (this.modifiers.length > 0) {
59 s = s + indent(n+2) + "<modifiers>\n";
60 for (var i = 0; i < this.modifiers.length; i++)
61 s = s + this.modifiers[i].toXCQL(n+2);
62 s = s + indent(n+2) + "</modifiers>\n";
64 s = s + indent(n+1) + "</relation>\n";
65 s = s + indent(n+1) + "<term>" + this.term + "</term>\n";
66 s = s + indent(n) + "</searchClause>\n";
71 var CQLBoolean = function() {
73 this.modifiers = null;
78 CQLBoolean.prototype = {
79 toXCQL: function (n) {
80 var s = indent(n) + "<triple>\n";
81 s = s + indent(n+1) + "<boolean>\n" +
82 indent(n+2) + "<value>" + this.op + "</value>\n";
83 if (this.modifiers.length > 0) {
84 s = s + indent(n+2) + "<modifiers>\n";
85 for (var i = 0; i < this.modifiers.length; i++)
86 s = s + this.modifiers[i].toXCQL(n+2);
87 s = s + indent(n+2) + "</modifiers>\n";
89 s = s + indent(n+1) + "</boolean>\n";
90 s = s + indent(n+1) + "<leftOperand>\n" +
91 this.left.toXCQL(n+2) + indent(n+1) + "</leftOperand>\n";
93 s = s + indent(n+1) + "<rightOperand>\n" +
94 this.right.toXCQL(n+2) + indent(n+1) + "</rightOperand>\n";
95 s = s + indent(n) + "</triple>\n";
100 var CQLParser = function () {
107 this.prefixes = new Object();
111 CQLParser.prototype = {
112 parse: function (query) {
114 throw new Error("The query to be parsed cannot be empty");
117 this.ql = this.qs.length;
120 this.tree = this._parseQuery("cql.serverChoice", "scr", new Array());
122 throw new Error("EOF expected");
124 toXCQL: function () {
125 return this.tree.toXCQL();
127 _parseQuery: function(field, relation, modifiers) {
128 var left = this._parseSearchClause(field, relation, modifiers);
129 while (this.look == "s" && (
130 this.lval == "and" ||
132 this.lval == "not" ||
133 this.lval == "prox")) {
134 var b = new CQLBoolean();
137 b.modifiers = this._parseModifiers();
139 b.right = this._parseSearchClause(field, relation, modifiers);
144 _parseModifiers: function() {
145 var ar = new Array();
146 while (this.look == "/") {
148 if (this.look != "s" && this.look != "q")
149 throw new Error("Invalid modifier.")
151 var name = this.lval;
153 if (this.look.length > 0
154 && this._strchr("<>=", this.look.charAt(0))) {
157 if (this.look != "s" && this.look != "q")
158 throw new Error("Invalid relation within the modifier.");
160 var m = new CQLModifier();
167 var m = new CQLModifier();
176 _parseSearchClause: function(field, relation, modifiers) {
177 if (this.look == "(") {
179 var b = this._parseQuery(field, relation, modifiers);
180 if (this.look == ")")
183 throw new Error("Missing closing parenthesis.");
186 } else if (this.look == "s" || this.look == "q") {
187 var first = this.val; // dont know if field or term yet
189 if (this.look == "q" ||
191 this.lval != "and" &&
193 this.lval != "not" &&
194 this.lval != "prox")) {
195 var rel = this.val; // string relation
197 return this._parseSearchClause(first, rel,
198 this._parseModifiers());
199 } else if (this.look.length > 0
200 && this._strchr("<>=", this.look.charAt(0))) {
201 var rel = this.look; // other relation <, = ,etc
203 return this._parseSearchClause(first, rel,
204 this._parseModifiers());
206 // it's a search term
207 var pos = field.indexOf('.');
210 pre = field.substring(0, pos);
212 var uri = this._lookupPrefix(pre);
214 field = field.substring(pos+1);
216 pos = relation.indexOf('.');
220 pre = relation.substring(0, pos);
222 var reluri = this._lookupPrefix(pre);
223 if (reluri.Length > 0)
224 relation = relation.Substring(pos+1);
226 var sc = new CQLSearchClause(field,
235 } else if (this.look == ">") {
237 if (this.look != "s" && this.look != "q")
238 throw new Error("Expecting string or a quoted expression.");
240 var first = this.lval;
242 if (this.look == "=")
245 if (this.look != "s" && this.look != "q")
246 throw new Error("Expecting string or a quoted expression.");
248 this._addPrefix(first, this.lval);
250 return this._parseQuery(field, relation, modifiers);
252 this._addPrefix("default", first);
253 return this._parseQuery(field, relation, modifiers);
256 throw new Error("Invalid search clause.");
261 while (this.qi < this.ql
262 && this._strchr(" \t\r\n", this.qs.charAt(this.qi)))
264 if (this.qi == this.ql) {
268 var c = this.qs.charAt(this.qi);
269 if (this._strchr("()/", c)) {
272 } else if (this._strchr("<>=", c)) {
275 while (this.qi < this.ql
276 && this._strchr("<>=", this.qs.charAt(this.qi))) {
277 this.look = this.look + this.qs.charAt(this.qi);
280 } else if (this._strchr("\"'", c)) {
285 while (this.qi < this.ql
286 && this.qs.charAt(this.qi) != mark) {
287 if (this.qs.charAt(this.qi) == '\\'
288 && this.qi < this.ql-1)
290 this.val = this.val + this.qs.charAt(this.qi);
293 this.lval = this.val.toLowerCase();
294 if (this.qi < this.ql)
299 while (this.qi < this.ql
300 && !this._strchr("()/<>= \t\r\n", this.qs.charAt(this.qi))) {
301 this.val = this.val + this.qs.charAt(this.qi);
304 this.lval = this.val.toLowerCase();
307 _strchr: function (s, ch) {
308 return s.indexOf(ch) >= 0
310 _lookupPrefix: function(name) {
311 return this.prefixes[name] ? this.prefixes[name] : "";
313 _addPrefix: function(name, value) {
314 //overwrite existing items
315 this.prefixes[name] = value;