src/lib/rqlParse.c 1.5

1.5 2009/12/03 19:26:04 kent
Making rqlParser handle arrays and field-separating-dots. Evaluation handles arrays but not dots yet.
Index: src/lib/rqlParse.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/lib/rqlParse.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -b -B -U 4 -r1.4 -r1.5
--- src/lib/rqlParse.c	3 Dec 2009 18:19:28 -0000	1.4
+++ src/lib/rqlParse.c	3 Dec 2009 19:26:04 -0000	1.5
@@ -18,16 +18,8 @@
     case rqlOpLiteral:
 	return "rqlOpLiteral";
     case rqlOpSymbol:
 	return "rqlOpSymbol";
-    case rqlOpEq:
-	return "rqlOpEq";
-    case rqlOpNe:
-	return "rqlOpNe";
-    case rqlOpAnd:
-	return "rqlOpAnd";
-    case rqlOpOr:
-	return "rqlOpOr";
     
     case rqlOpStringToBoolean:
         return "rqlOpStringToBoolean";
     case rqlOpIntToBoolean:
@@ -35,22 +27,23 @@
     case rqlOpDoubleToBoolean:
         return "rqlOpDoubleToBoolean";
     case rqlOpStringToInt:
         return "rqlOpStringToInt";
-    case rqlOpStringToDouble:
-        return "rqlOpStringToDouble";
+    case rqlOpDoubleToInt:
+        return "rqlOpDoubleToInt";
     case rqlOpBooleanToInt:
         return "rqlOpBooleanToInt";
+    case rqlOpStringToDouble:
+        return "rqlOpStringToDouble";
     case rqlOpBooleanToDouble:
         return "rqlOpBooleanToDouble";
     case rqlOpIntToDouble:
         return "rqlOpIntToDouble";
 
-    case rqlOpUnaryMinusInt:
-        return "rqlOpUnaryMinusInt";
-    case rqlOpUnaryMinusDouble:
-        return "rqlOpUnaryMinusDouble";
-
+    case rqlOpEq:
+	return "rqlOpEq";
+    case rqlOpNe:
+	return "rqlOpNe";
     case rqlOpGt:
         return "rqlOpGt";
     case rqlOpLt:
         return "rqlOpLt";
@@ -60,11 +53,25 @@
         return "rqlOpLe";
     case rqlOpLike:
 	return "rqlOpLike";
 
+    case rqlOpAnd:
+	return "rqlOpAnd";
+    case rqlOpOr:
+	return "rqlOpOr";
     case rqlOpNot:
         return "rqlOpNot";
 
+    case rqlOpUnaryMinusInt:
+        return "rqlOpUnaryMinusInt";
+    case rqlOpUnaryMinusDouble:
+        return "rqlOpUnaryMinusDouble";
+
+    case rqlOpArrayIx:
+        return "rqlOpArrayIx";
+    case rqlOpSubDot:
+        return "rqlSubDot";
+
     default:
 	return "rqlOpUnknown";
     }
 }
@@ -216,8 +223,10 @@
     case rqlTypeString:
         return rqlOpStringToInt;
     case rqlTypeBoolean:
         return rqlOpBooleanToInt;
+    case rqlTypeDouble:
+        return rqlOpDoubleToInt;
     default:
         internalErr();
 	return rqlOpUnknown;
     }
@@ -270,15 +279,51 @@
     return cast;
     }
 }
 
+static struct rqlParse *rqlParsePartSelect(struct tokenizer *tkz)
+/* Handle the . in this.that or the [] in this[6] */
+{
+struct rqlParse *collection = rqlParseAtom(tkz);
+struct rqlParse *p = collection;
+char *tok = tokenizerNext(tkz);
+if (tok == NULL)
+    tokenizerReuse(tkz);
+else if (tok[0] == '[')
+    {
+    // struct rqlParse *index = rqlParseExpression(tkz);
+    struct rqlParse *index = rqlParseAtom(tkz);
+    index = rqlParseCoerce(index, rqlTypeInt);
+    skipOverRequired(tkz, "]");
+    AllocVar(p);
+    p->op = rqlOpArrayIx;
+    p->type = rqlTypeString;
+    p->children = collection;
+    collection->next = index;
+    }
+else if (tok[0] == '.')
+    {
+    struct rqlParse *field = rqlParseExpression(tkz);
+    field = rqlParseCoerce(field, rqlTypeString);
+    AllocVar(p);
+    p->op = rqlOpSubDot;
+    p->type = rqlTypeString;
+    p->children = collection;
+    collection->next = field;
+    }
+else
+    tokenizerReuse(tkz);
+return p;
+}
+
+
 static struct rqlParse *rqlParseUnaryMinus(struct tokenizer *tkz)
 /* Return unary minus sort of parse tree if there's a leading '-' */
 {
 char *tok = tokenizerMustHaveNext(tkz);
 if (tok[0] == '-')
     {
-    struct rqlParse *c = rqlParseAtom(tkz);
+    struct rqlParse *c = rqlParsePartSelect(tkz);
     struct rqlParse *p;
     AllocVar(p);
     if (c->type == rqlTypeInt)
         {
@@ -296,9 +341,9 @@
     }
 else
     {
     tokenizerReuse(tkz);
-    return rqlParseAtom(tkz);
+    return rqlParsePartSelect(tkz);
     }
 }
 
 static boolean eatMatchingTok(struct tokenizer *tkz, char *s)
@@ -427,11 +472,10 @@
 
 static struct rqlParse *rqlParseAnd(struct tokenizer *tkz)
 /* Parse out and or or. */
 {
-struct rqlParse *l = rqlParseCoerce(rqlParseNot(tkz), rqlTypeBoolean);
+struct rqlParse *p = rqlParseNot(tkz);
 struct rqlParse *parent = NULL;
-struct rqlParse *p = l;
 for (;;)
     {
     char *tok = tokenizerNext(tkz);
     if (tok == NULL || !sameString(tok, "and"))
@@ -442,8 +486,9 @@
     else
         {
 	if (parent == NULL)
 	    {
+	    p = rqlParseCoerce(p, rqlTypeBoolean);
 	    AllocVar(parent);
 	    parent->op = rqlOpAnd;
 	    parent->type = rqlTypeBoolean;
 	    parent->children = p;
@@ -457,11 +502,10 @@
 
 static struct rqlParse *rqlParseOr(struct tokenizer *tkz)
 /* Parse out and or or. */
 {
-struct rqlParse *l = rqlParseCoerce(rqlParseAnd(tkz), rqlTypeBoolean);
+struct rqlParse *p = rqlParseAnd(tkz);
 struct rqlParse *parent = NULL;
-struct rqlParse *p = l;
 for (;;)
     {
     char *tok = tokenizerNext(tkz);
     if (tok == NULL || !sameString(tok, "or"))
@@ -472,8 +516,9 @@
     else
         {
 	if (parent == NULL)
 	    {
+	    p = rqlParseCoerce(p, rqlTypeBoolean);
 	    AllocVar(parent);
 	    parent->op = rqlOpOr;
 	    parent->type = rqlTypeBoolean;
 	    parent->children = p;