X-Git-Url: http://jsfdemo.indexdata.com/?a=blobdiff_plain;f=src%2Forg%2Fz3950%2Fzing%2Fcql%2FCQLParser.java;h=9ccb1398a89764fe857836332a6370a9654f2dd2;hb=0cf2302a18eacaa327f40743c4ac59cf6c630183;hp=6d49c56830a88b99478c8147a9ef7a5a0af0d9da;hpb=8e35f984081a29de9b53af7c1b2fbf981c474d88;p=cql-java-moved-to-github.git
diff --git a/src/org/z3950/zing/cql/CQLParser.java b/src/org/z3950/zing/cql/CQLParser.java
index 6d49c56..9ccb139 100644
--- a/src/org/z3950/zing/cql/CQLParser.java
+++ b/src/org/z3950/zing/cql/CQLParser.java
@@ -1,4 +1,4 @@
-// $Id: CQLParser.java,v 1.33 2007-06-29 12:27:08 mike Exp $
+// $Id: CQLParser.java,v 1.38 2007-07-03 16:40:41 mike Exp $
package org.z3950.zing.cql;
import java.io.IOException;
@@ -12,15 +12,44 @@ import java.io.FileNotFoundException;
/**
* Compiles CQL strings into parse trees of CQLNode subtypes.
*
- * @version $Id: CQLParser.java,v 1.33 2007-06-29 12:27:08 mike Exp $
+ * @version $Id: CQLParser.java,v 1.38 2007-07-03 16:40:41 mike Exp $
* @see http://zing.z3950.org/cql/index.html
*/
public class CQLParser {
private CQLLexer lexer;
+ private int compat; // When false, implement CQL 1.2
+ public static int V1POINT1 = 12368;
+ public static int V1POINT2 = 12369;
+ public static int V1POINT1SORT = 12370;
+
static private boolean DEBUG = false;
static private boolean LEXDEBUG = false;
+ /**
+ * The new parser implements a dialect of CQL specified by the
+ * compat argument:
+ *
+ * - V1POINT1 - CQL version 1.1
+ *
+ * - V1POINT2 - CQL version 1.2
+ *
+ * - V1POINT1SORT - CQL version 1.1 but including
+ * sortby as specified for CQL 1.2.
+ *
+ *
+ */
+ CQLParser(int compat) {
+ this.compat = compat;
+ }
+
+ /**
+ * The new parser implements CQL 1.2
+ */
+ CQLParser() {
+ this.compat = V1POINT2;
+ }
+
private static void debug(String str) {
if (DEBUG)
System.err.println("PARSEDEBUG: " + str);
@@ -48,19 +77,53 @@ public class CQLParser {
lexer.nextToken();
debug("about to parseQuery()");
- CQLNode root = parseQuery("srw.serverChoice", new CQLRelation("scr"));
+ CQLNode root = parseTopLevelPrefixes("cql.serverChoice",
+ new CQLRelation(compat == V1POINT2 ? "=" : "scr"));
if (lexer.ttype != lexer.TT_EOF)
throw new CQLParseException("junk after end: " + lexer.render());
return root;
}
+ private CQLNode parseTopLevelPrefixes(String index, CQLRelation relation)
+ throws CQLParseException, IOException {
+ debug("top-level prefix mapping");
+
+ if (lexer.ttype == '>') {
+ return parsePrefix(index, relation, true);
+ }
+
+ CQLNode node = parseQuery(index, relation);
+ if ((compat == V1POINT2 || compat == V1POINT1SORT) &&
+ lexer.ttype == lexer.TT_SORTBY) {
+ match(lexer.ttype);
+ debug("sortspec");
+
+ CQLSortNode sortnode = new CQLSortNode(node);
+ while (lexer.ttype != lexer.TT_EOF) {
+ String sortindex = matchSymbol("sort index");
+ ModifierSet ms = gatherModifiers(sortindex);
+ sortnode.addSortIndex(ms);
+ }
+
+ if (sortnode.keys.size() == 0) {
+ throw new CQLParseException("no sort keys");
+ }
+
+ node = sortnode;
+ }
+
+ return node;
+ }
+
private CQLNode parseQuery(String index, CQLRelation relation)
throws CQLParseException, IOException {
debug("in parseQuery()");
CQLNode term = parseTerm(index, relation);
- while (lexer.ttype != lexer.TT_EOF && lexer.ttype != ')') {
+ while (lexer.ttype != lexer.TT_EOF &&
+ lexer.ttype != ')' &&
+ lexer.ttype != lexer.TT_SORTBY) {
if (lexer.ttype == lexer.TT_AND ||
lexer.ttype == lexer.TT_OR ||
lexer.ttype == lexer.TT_NOT ||
@@ -124,8 +187,7 @@ public class CQLParser {
match(')');
return expr;
} else if (lexer.ttype == '>') {
- match('>');
- return parsePrefix(index, relation);
+ return parsePrefix(index, relation, false);
}
debug("non-parenthesised term");
@@ -149,10 +211,12 @@ public class CQLParser {
return node;
}
- private CQLNode parsePrefix(String index, CQLRelation relation)
+ private CQLNode parsePrefix(String index, CQLRelation relation,
+ boolean topLevel)
throws CQLParseException, IOException {
debug("prefix mapping");
+ match('>');
String name = null;
String identifier = matchSymbol("prefix-name");
if (lexer.ttype == '=') {
@@ -160,8 +224,11 @@ public class CQLParser {
name = identifier;
identifier = matchSymbol("prefix-identifer");
}
- CQLNode term = parseQuery(index, relation);
- return new CQLPrefixNode(name, identifier, term);
+ CQLNode node = topLevel ?
+ parseTopLevelPrefixes(index, relation) :
+ parseQuery(index, relation);
+
+ return new CQLPrefixNode(name, identifier, node);
}
// Checks for a relation
@@ -173,7 +240,8 @@ public class CQLParser {
lexer.ttype == '=' ||
lexer.ttype == lexer.TT_LE ||
lexer.ttype == lexer.TT_GE ||
- lexer.ttype == lexer.TT_NE);
+ lexer.ttype == lexer.TT_NE ||
+ lexer.ttype == lexer.TT_EQEQ);
}
private void match(int token)
@@ -205,12 +273,7 @@ public class CQLParser {
lexer.ttype == lexer.TT_OR ||
lexer.ttype == lexer.TT_NOT ||
lexer.ttype == lexer.TT_PROX ||
- lexer.ttype == lexer.TT_pWORD ||
- lexer.ttype == lexer.TT_SENTENCE ||
- lexer.ttype == lexer.TT_PARAGRAPH ||
- lexer.ttype == lexer.TT_ELEMENT ||
- lexer.ttype == lexer.TT_ORDERED ||
- lexer.ttype == lexer.TT_UNORDERED) {
+ lexer.ttype == lexer.TT_SORTBY) {
String symbol = (lexer.ttype == lexer.TT_NUMBER) ?
lexer.render() : lexer.sval;
match(lexer.ttype);
@@ -269,6 +332,10 @@ public class CQLParser {
* </triple>
*
*
+ * @param -1
+ * CQL version 1.1 (default version 1.2)
+ * @param -d
+ * Debug mode: extra output written to stderr.
* @param -c
* Causes the output to be written in CQL rather than XCQL - that
* is, a query equivalent to that which was input, is output. In
@@ -286,6 +353,12 @@ public class CQLParser {
argv.add(args[i]);
}
+ int compat = V1POINT2;
+ if (argv.size() > 0 && argv.get(0).equals("-1")) {
+ compat = V1POINT1;
+ argv.remove(0);
+ }
+
if (argv.size() > 0 && argv.get(0).equals("-d")) {
DEBUG = true;
argv.remove(0);
@@ -302,7 +375,8 @@ public class CQLParser {
}
if (argv.size() > 1) {
- System.err.println("Usage: CQLParser [-d] [-c] [-p []");
+ System.err.println("Usage: CQLParser [-1] [-d] [-c] " +
+ "[-p []");
System.err.println("If unspecified, query is read from stdin");
System.exit(1);
}
@@ -322,7 +396,7 @@ public class CQLParser {
cql = new String(bytes);
}
- CQLParser parser = new CQLParser();
+ CQLParser parser = new CQLParser(compat);
CQLNode root = null;
try {
root = parser.parse(cql);