Remove old proximity-specific parsing code.
[cql-java-moved-to-github.git] / src / org / z3950 / zing / cql / CQLParser.java
index 94e8b87..6d49c56 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: CQLParser.java,v 1.30 2007-06-28 00:24:48 mike Exp $
+// $Id: CQLParser.java,v 1.33 2007-06-29 12:27:08 mike Exp $
 
 package org.z3950.zing.cql;
 import java.io.IOException;
@@ -12,7 +12,7 @@ import java.io.FileNotFoundException;
 /**
  * Compiles CQL strings into parse trees of CQLNode subtypes.
  *
- * @version    $Id: CQLParser.java,v 1.30 2007-06-28 00:24:48 mike Exp $
+ * @version    $Id: CQLParser.java,v 1.33 2007-06-29 12:27:08 mike Exp $
  * @see                <A href="http://zing.z3950.org/cql/index.html"
  *                     >http://zing.z3950.org/cql/index.html</A>
  */
@@ -60,27 +60,20 @@ public class CQLParser {
        debug("in parseQuery()");
 
        CQLNode term = parseTerm(index, relation);
-       while (lexer.ttype != lexer.TT_EOF &&
-              lexer.ttype != ')') {
-           if (lexer.ttype == lexer.TT_AND) {
-               match(lexer.TT_AND);
+       while (lexer.ttype != lexer.TT_EOF && lexer.ttype != ')') {
+           if (lexer.ttype == lexer.TT_AND ||
+               lexer.ttype == lexer.TT_OR ||
+               lexer.ttype == lexer.TT_NOT ||
+               lexer.ttype == lexer.TT_PROX) {
+               int type = lexer.ttype;
+               String val = lexer.sval;
+               match(type);
+               ModifierSet ms = gatherModifiers(val);
                CQLNode term2 = parseTerm(index, relation);
-               term = new CQLAndNode(term, term2);
-           } else if (lexer.ttype == lexer.TT_OR) {
-               match(lexer.TT_OR);
-               CQLNode term2 = parseTerm(index, relation);
-               term = new CQLOrNode(term, term2);
-           } else if (lexer.ttype == lexer.TT_NOT) {
-               match(lexer.TT_NOT);
-               CQLNode term2 = parseTerm(index, relation);
-               term = new CQLNotNode(term, term2);
-           } else if (lexer.ttype == lexer.TT_PROX) {
-               match(lexer.TT_PROX);
-               CQLProxNode proxnode = new CQLProxNode(term);
-               gatherProxParameters(proxnode);
-               CQLNode term2 = parseTerm(index, relation);
-               proxnode.addSecondSubterm(term2);
-               term = (CQLNode) proxnode;
+               term = ((type == lexer.TT_AND) ? new CQLAndNode(term, term2, ms) :
+                       (type == lexer.TT_OR)  ? new CQLOrNode (term, term2, ms) :
+                       (type == lexer.TT_NOT) ? new CQLNotNode(term, term2, ms) :
+                                                new CQLProxNode(term, term2, ms));
            } else {
                throw new CQLParseException("expected boolean, got " +
                                            lexer.render());
@@ -91,6 +84,33 @@ public class CQLParser {
        return term;
     }
 
+    private ModifierSet gatherModifiers(String base)
+       throws CQLParseException, IOException {
+       debug("in gatherModifiers()");
+
+       ModifierSet ms = new ModifierSet(base);
+       while (lexer.ttype == '/') {
+           match('/');
+           if (lexer.ttype != lexer.TT_WORD)
+               throw new CQLParseException("expected modifier, "
+                                           + "got " + lexer.render());
+           String type = lexer.sval.toLowerCase();
+           match(lexer.ttype);
+           if (!isRelation()) {
+               // It's a simple modifier consisting of type only
+               ms.addModifier(type);
+           } else {
+               // It's a complex modifier of the form type=value
+               String comparision = lexer.render(lexer.ttype, false);
+               match(lexer.ttype);
+               String value = matchSymbol("modifier value");
+               ms.addModifier(type, comparision, value);
+           }
+       }
+
+       return ms;
+    }
+
     private CQLNode parseTerm(String index, CQLRelation relation)
        throws CQLParseException, IOException {
        debug("in parseTerm()");
@@ -114,37 +134,12 @@ public class CQLParser {
                break;
 
            index = word;
-           relation = new CQLRelation(lexer.ttype == lexer.TT_WORD ?
-                                      lexer.sval :
-                                      lexer.render(lexer.ttype, false));
+           String relstr = (lexer.ttype == lexer.TT_WORD ?
+                            lexer.sval : lexer.render(lexer.ttype, false));
+           relation = new CQLRelation(relstr);
            match(lexer.ttype);
-
-           while (lexer.ttype == '/') {
-               match('/');
-               if (lexer.ttype != lexer.TT_WORD)
-                   throw new CQLParseException("expected relation modifier, "
-                                               + "got " + lexer.render());
-               String type = lexer.sval.toLowerCase();
-               match(lexer.ttype);
-               if (!isRelation()) {
-                   // It's a simple modifier consisting of type only
-                   relation.addModifier(type);
-               } else {
-                   // It's a complex modifier of the form type=value
-                   String comparision = lexer.render(lexer.ttype, false);
-                   match(lexer.ttype);
-
-                   // Yuck
-                   String value = lexer.ttype == lexer.TT_WORD ? lexer.sval :
-                       (double) lexer.nval == (int) lexer.nval ?
-                       new Integer((int) lexer.nval).toString() :
-                       new Double((double) lexer.nval).toString();
-
-                   matchSymbol("relation-modifier value");
-                   relation.addModifier(type, comparision, value);
-               }
-           }
-
+           ModifierSet ms = gatherModifiers(relstr);
+           relation.setModifiers(ms);
            debug("index='" + index + ", " +
                  "relation='" + relation.toCQL() + "'");
        }
@@ -169,70 +164,7 @@ public class CQLParser {
        return new CQLPrefixNode(name, identifier, term);
     }
 
-    private void gatherProxParameters(CQLProxNode node)
-       throws CQLParseException, IOException {
-       for (int i = 0; i < 4; i++) {
-           if (lexer.ttype != '/')
-               return;         // end of proximity parameters
-
-           match('/');
-           if (lexer.ttype != '/') {
-               // not an omitted default
-               switch (i) {
-                   // Order should be: relation/distance/unit/ordering
-                   // For now, use MA's: unit/relation/distance/ordering
-               case 0: gatherProxRelation(node); break;
-               case 1: gatherProxDistance(node); break;
-               case 2: gatherProxUnit(node); break;
-               case 3: gatherProxOrdering(node); break;
-               }
-           }
-       }
-    }
-
-    private void gatherProxRelation(CQLProxNode node)
-       throws CQLParseException, IOException {
-       if (!isRelation())
-           throw new CQLParseException("expected proximity relation, got " +
-                                       lexer.render());
-       node.addModifier("relation", null, lexer.render(lexer.ttype, false));
-       match(lexer.ttype);
-       debug("gPR matched " + lexer.render(lexer.ttype, false));
-    }
-
-    private void gatherProxDistance(CQLProxNode node)
-       throws CQLParseException, IOException {
-       if (lexer.ttype != lexer.TT_NUMBER)
-           throw new CQLParseException("expected proximity distance, got " +
-                                       lexer.render());
-       node.addModifier("distance", null, lexer.render(lexer.ttype, false));
-       match(lexer.ttype);
-       debug("gPD matched " + lexer.render(lexer.ttype, false));
-    }
-
-    private void gatherProxUnit(CQLProxNode node)
-       throws CQLParseException, IOException {
-       if (lexer.ttype != lexer.TT_pWORD &&
-           lexer.ttype != lexer.TT_SENTENCE &&
-           lexer.ttype != lexer.TT_PARAGRAPH &&
-           lexer.ttype != lexer.TT_ELEMENT)
-           throw new CQLParseException("expected proximity unit, got " +
-                                       lexer.render());
-       node.addModifier("unit", null, lexer.render());
-       match(lexer.ttype);
-    }
-
-    private void gatherProxOrdering(CQLProxNode node)
-       throws CQLParseException, IOException {
-       if (lexer.ttype != lexer.TT_ORDERED &&
-           lexer.ttype != lexer.TT_UNORDERED)
-           throw new CQLParseException("expected proximity ordering, got " +
-                                       lexer.render());
-       node.addModifier("ordering", null, lexer.render());
-       match(lexer.ttype);
-    }
-
-    // Checks for a relation that may be used inside a prox operator
+    // Checks for a relation
     private boolean isRelation() {
        debug("isRelation: checking ttype=" + lexer.ttype +
              " (" + lexer.render() + ")");