AQLPlus Refactoring 2: AQL+ grammar generation and AQLPlusExpressionToPlanTranslator

 - Apply a systematic way of generating AQL+ grammar from AQL grammar instead of
   having a separate grammar file and updating it by hand.
 - Refactor AQLPlusExpressionToPlanTranslator so that it extends
   AQLExpressionToPlanTranslator. This makes this class now follows
   the current translation logic and it doesn't have to manually updated for
   AQL expressions.

Change-Id: I444dbf4f615c23ccd69a5e4bb1ead300d0a81451
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1434
Sonar-Qube: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Yingyi Bu <buyingyi@gmail.com>
diff --git a/asterixdb/asterix-algebra/pom.xml b/asterixdb/asterix-algebra/pom.xml
index 5a723b3..aa0ea27 100644
--- a/asterixdb/asterix-algebra/pom.xml
+++ b/asterixdb/asterix-algebra/pom.xml
@@ -40,6 +40,28 @@
   <build>
     <plugins>
       <plugin>
+        <groupId>org.apache.asterix</groupId>
+        <artifactId>asterix-grammar-extension-maven-plugin</artifactId>
+        <version>${project.version}</version>
+        <configuration>
+          <base>${project.basedir}</base>
+          <gbase>../asterix-lang-aql/src/main/javacc/AQL.jj</gbase>
+          <gextension>src/main/javacc/AQLPlusExtension.jj</gextension>
+          <output>target/generated-resources/javacc/AQLPlus.jj</output>
+          <parserClassModifier>public</parserClassModifier>
+          <parserClassName>AQLPlusParser</parserClassName>
+          <packageName>org.apache.asterix.aqlplus.parser</packageName>
+        </configuration>
+        <executions>
+          <execution>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>grammarix</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>javacc-maven-plugin</artifactId>
         <version>2.6</version>
@@ -51,6 +73,26 @@
             </goals>
             <configuration>
               <isStatic>false</isStatic>
+              <sourceDirectory>target/generated-resources/javacc</sourceDirectory>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <version>1.9</version>
+        <executions>
+          <execution>
+            <id>add-source</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>target/generated-sources/javacc/</source>
+              </sources>
             </configuration>
           </execution>
         </executions>
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/FuzzyJoinRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/FuzzyJoinRule.java
index 67c33d4..f3f5581 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/FuzzyJoinRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/FuzzyJoinRule.java
@@ -261,8 +261,7 @@
         }
         // The translator will compile metadata internally. Run this compilation
         // under the same transaction id as the "outer" compilation.
-        AqlPlusExpressionToPlanTranslator translator = new AqlPlusExpressionToPlanTranslator(
-                metadataProvider.getJobId(), metadataProvider, counter, null, null);
+        AqlPlusExpressionToPlanTranslator translator = new AqlPlusExpressionToPlanTranslator(metadataProvider, counter);
         context.setVarCounter(counter.get());
 
         LogicalOperatorDeepCopyWithNewVariablesVisitor deepCopyVisitor = new LogicalOperatorDeepCopyWithNewVariablesVisitor(
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslator.java
index 110c2b7..62b71df 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlExpressionToPlanTranslator.java
@@ -40,6 +40,7 @@
 import org.apache.commons.lang3.mutable.MutableObject;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
 import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.algebricks.core.algebra.base.Counter;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
 import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
@@ -64,7 +65,13 @@
 class AqlExpressionToPlanTranslator extends LangExpressionToPlanTranslator implements ILangExpressionToPlanTranslator,
         IAQLVisitor<Pair<ILogicalOperator, LogicalVariable>, Mutable<ILogicalOperator>> {
 
-    public AqlExpressionToPlanTranslator(MetadataProvider metadataProvider, int currentVarCounter)
+    public AqlExpressionToPlanTranslator(MetadataProvider metadataProvider, int currentVarCounterValue)
+            throws AlgebricksException {
+        super(metadataProvider, currentVarCounterValue);
+    }
+
+    // Keeps the given Counter if one is provided instead of a value.
+    public AqlExpressionToPlanTranslator(MetadataProvider metadataProvider, Counter currentVarCounter)
             throws AlgebricksException {
         super(metadataProvider, currentVarCounter);
     }
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlPlusExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlPlusExpressionToPlanTranslator.java
index 5eb5a5f..18304b3 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlPlusExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/AqlPlusExpressionToPlanTranslator.java
@@ -20,282 +20,58 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
-import java.util.Map.Entry;
-import java.util.logging.Logger;
 
-import org.apache.asterix.common.config.DatasetConfig.DatasetType;
 import org.apache.asterix.common.exceptions.CompilationException;
-import org.apache.asterix.common.functions.FunctionConstants;
-import org.apache.asterix.common.functions.FunctionSignature;
-import org.apache.asterix.common.transactions.JobId;
-import org.apache.asterix.formats.base.IDataFormat;
-import org.apache.asterix.lang.aql.clause.DistinctClause;
-import org.apache.asterix.lang.aql.clause.ForClause;
+import org.apache.asterix.common.exceptions.ErrorCode;
 import org.apache.asterix.lang.aql.clause.JoinClause;
 import org.apache.asterix.lang.aql.clause.MetaVariableClause;
-import org.apache.asterix.lang.aql.expression.FLWOGRExpression;
 import org.apache.asterix.lang.aql.expression.MetaVariableExpr;
-import org.apache.asterix.lang.aql.expression.UnionExpr;
 import org.apache.asterix.lang.aql.visitor.base.IAQLPlusVisitor;
 import org.apache.asterix.lang.common.base.Clause;
 import org.apache.asterix.lang.common.base.Expression;
-import org.apache.asterix.lang.common.base.Expression.Kind;
-import org.apache.asterix.lang.common.clause.GroupbyClause;
-import org.apache.asterix.lang.common.clause.LetClause;
-import org.apache.asterix.lang.common.clause.LimitClause;
-import org.apache.asterix.lang.common.clause.OrderbyClause;
-import org.apache.asterix.lang.common.clause.OrderbyClause.OrderModifier;
-import org.apache.asterix.lang.common.clause.UpdateClause;
-import org.apache.asterix.lang.common.clause.WhereClause;
-import org.apache.asterix.lang.common.expression.CallExpr;
-import org.apache.asterix.lang.common.expression.FieldAccessor;
-import org.apache.asterix.lang.common.expression.FieldBinding;
-import org.apache.asterix.lang.common.expression.GbyVariableExpressionPair;
-import org.apache.asterix.lang.common.expression.IfExpr;
-import org.apache.asterix.lang.common.expression.IndexAccessor;
-import org.apache.asterix.lang.common.expression.ListConstructor;
-import org.apache.asterix.lang.common.expression.ListConstructor.Type;
-import org.apache.asterix.lang.common.expression.LiteralExpr;
-import org.apache.asterix.lang.common.expression.OperatorExpr;
-import org.apache.asterix.lang.common.expression.OrderedListTypeDefinition;
-import org.apache.asterix.lang.common.expression.QuantifiedExpression;
-import org.apache.asterix.lang.common.expression.QuantifiedExpression.Quantifier;
-import org.apache.asterix.lang.common.expression.RecordConstructor;
-import org.apache.asterix.lang.common.expression.RecordTypeDefinition;
-import org.apache.asterix.lang.common.expression.TypeReferenceExpression;
-import org.apache.asterix.lang.common.expression.UnaryExpr;
-import org.apache.asterix.lang.common.expression.UnorderedListTypeDefinition;
 import org.apache.asterix.lang.common.expression.VariableExpr;
-import org.apache.asterix.lang.common.statement.CompactStatement;
-import org.apache.asterix.lang.common.statement.ConnectFeedStatement;
-import org.apache.asterix.lang.common.statement.CreateDataverseStatement;
-import org.apache.asterix.lang.common.statement.CreateFeedPolicyStatement;
-import org.apache.asterix.lang.common.statement.CreateFunctionStatement;
-import org.apache.asterix.lang.common.statement.CreateIndexStatement;
-import org.apache.asterix.lang.common.statement.CreatePrimaryFeedStatement;
-import org.apache.asterix.lang.common.statement.CreateSecondaryFeedStatement;
-import org.apache.asterix.lang.common.statement.DatasetDecl;
-import org.apache.asterix.lang.common.statement.DataverseDecl;
-import org.apache.asterix.lang.common.statement.DataverseDropStatement;
-import org.apache.asterix.lang.common.statement.DeleteStatement;
-import org.apache.asterix.lang.common.statement.DisconnectFeedStatement;
-import org.apache.asterix.lang.common.statement.DropDatasetStatement;
-import org.apache.asterix.lang.common.statement.FeedDropStatement;
-import org.apache.asterix.lang.common.statement.FeedPolicyDropStatement;
-import org.apache.asterix.lang.common.statement.FunctionDecl;
-import org.apache.asterix.lang.common.statement.FunctionDropStatement;
-import org.apache.asterix.lang.common.statement.IndexDropStatement;
-import org.apache.asterix.lang.common.statement.InsertStatement;
-import org.apache.asterix.lang.common.statement.LoadStatement;
-import org.apache.asterix.lang.common.statement.NodeGroupDropStatement;
-import org.apache.asterix.lang.common.statement.NodegroupDecl;
-import org.apache.asterix.lang.common.statement.Query;
-import org.apache.asterix.lang.common.statement.SetStatement;
-import org.apache.asterix.lang.common.statement.TypeDecl;
-import org.apache.asterix.lang.common.statement.TypeDropStatement;
-import org.apache.asterix.lang.common.statement.UpdateStatement;
-import org.apache.asterix.lang.common.statement.WriteStatement;
 import org.apache.asterix.lang.common.struct.Identifier;
-import org.apache.asterix.lang.common.struct.OperatorType;
-import org.apache.asterix.lang.common.struct.QuantifiedPair;
-import org.apache.asterix.lang.common.struct.UnaryExprType;
-import org.apache.asterix.lang.common.util.FunctionUtil;
-import org.apache.asterix.metadata.declared.FileSplitDataSink;
-import org.apache.asterix.metadata.declared.FileSplitSinkId;
 import org.apache.asterix.metadata.declared.MetadataProvider;
-import org.apache.asterix.metadata.entities.Dataset;
-import org.apache.asterix.metadata.utils.DatasetUtil;
-import org.apache.asterix.om.base.AString;
-import org.apache.asterix.om.constants.AsterixConstantValue;
-import org.apache.asterix.om.functions.BuiltinFunctions;
-import org.apache.asterix.om.functions.FunctionInfo;
-import org.apache.asterix.om.types.ARecordType;
-import org.apache.asterix.om.types.BuiltinType;
-import org.apache.asterix.om.types.IAType;
-import org.apache.asterix.translator.CompiledStatements.ICompiledDmlStatement;
-import org.apache.asterix.translator.util.FunctionCollection;
 import org.apache.commons.lang3.mutable.Mutable;
 import org.apache.commons.lang3.mutable.MutableObject;
 import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.common.exceptions.NotImplementedException;
 import org.apache.hyracks.algebricks.common.utils.Pair;
-import org.apache.hyracks.algebricks.common.utils.Triple;
 import org.apache.hyracks.algebricks.core.algebra.base.Counter;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
 import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
 import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
-import org.apache.hyracks.algebricks.core.algebra.base.OperatorAnnotations;
-import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
-import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression.FunctionKind;
-import org.apache.hyracks.algebricks.core.algebra.expressions.AggregateFunctionCallExpression;
-import org.apache.hyracks.algebricks.core.algebra.expressions.BroadcastExpressionAnnotation;
-import org.apache.hyracks.algebricks.core.algebra.expressions.BroadcastExpressionAnnotation.BroadcastSide;
-import org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
-import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
-import org.apache.hyracks.algebricks.core.algebra.expressions.UnnestingFunctionCallExpression;
 import org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
-import org.apache.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions;
-import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
-import org.apache.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.AggregateOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.DistinctOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.EmptyTupleSourceOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.GroupByOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.InnerJoinOperator;
 import org.apache.hyracks.algebricks.core.algebra.operators.logical.LeftOuterJoinOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.LimitOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.NestedTupleSourceOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator.IOrder;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.ProjectOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.SubplanOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.UnionAllOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.UnnestOperator;
-import org.apache.hyracks.algebricks.core.algebra.operators.logical.WriteOperator;
 import org.apache.hyracks.algebricks.core.algebra.plan.ALogicalPlanImpl;
-import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory;
 
 /**
- * Each visit returns a pair of an operator and a variable. The variable
- * corresponds to the new column, if any, added to the tuple flow. E.g., for
- * Unnest, the column is the variable bound to the elements in the list, for
- * Subplan it is null. The first argument of a visit method is the expression
- * which is translated. The second argument of a visit method is the tuple
- * source for the current subtree.
+ * This class is an extension of AQLExpressionToPlanTranslator. Specifically, it contains the visitor for
+ * three extensions (MetaVariable, MetaClause, and JoinClause) to AQL in AQL+.
+ * Meta-Variable ($$) refers the primary key or variable(s) in the logical plan.
+ * Meta-Clause (##) refers the operator in the logical plan.
+ * Join-Clause (join, loj) is required to build an explicit join in AQL level.
+ * For more details of AQL+, refer to this thesis: www.ics.uci.edu/~rares/pub/phd-thesis-vernica.pdf
  */
 
-public class AqlPlusExpressionToPlanTranslator extends AbstractLangTranslator
+public class AqlPlusExpressionToPlanTranslator extends AqlExpressionToPlanTranslator
         implements IAQLPlusVisitor<Pair<ILogicalOperator, LogicalVariable>, Mutable<ILogicalOperator>> {
 
-    private static final Logger LOGGER = Logger.getLogger(AqlPlusExpressionToPlanTranslator.class.getName());
-
-    private class MetaScopeLogicalVariable {
-        private HashMap<Identifier, LogicalVariable> map = new HashMap<Identifier, LogicalVariable>();
-
-        public VariableReferenceExpression getVariableReferenceExpression(Identifier id) throws CompilationException {
-            LogicalVariable var = map.get(id);
-            LOGGER.fine("get:" + id + ":" + var);
-            if (var == null) {
-                throw new CompilationException("Identifier " + id + " not found in AQL+ meta-scope.");
-            }
-            return new VariableReferenceExpression(var);
-        }
-
-        public void put(Identifier id, LogicalVariable var) {
-            LOGGER.fine("put:" + id + ":" + var);
-            map.put(id, var);
-        }
-    }
-
-    private class MetaScopeILogicalOperator {
-        private HashMap<Identifier, ILogicalOperator> map = new HashMap<Identifier, ILogicalOperator>();
-
-        public ILogicalOperator get(Identifier id) throws CompilationException {
-            ILogicalOperator op = map.get(id);
-            if (op == null) {
-                throw new CompilationException("Identifier " + id + " not found in AQL+ meta-scope.");
-            }
-            return op;
-        }
-
-        public void put(Identifier id, ILogicalOperator op) {
-            LOGGER.fine("put:" + id + ":" + op);
-            map.put(id, op);
-        }
-    }
-
-    private final JobId jobId;
-    private TranslationContext context;
-    private String outputDatasetName;
-    private ICompiledDmlStatement stmt;
-
     private MetaScopeLogicalVariable metaScopeExp = new MetaScopeLogicalVariable();
     private MetaScopeILogicalOperator metaScopeOp = new MetaScopeILogicalOperator();
-    private static LogicalVariable METADATA_DUMMY_VAR = new LogicalVariable(-1);
 
-    public AqlPlusExpressionToPlanTranslator(JobId jobId, MetadataProvider metadataProvider,
-            Counter currentVarCounter, String outputDatasetName, ICompiledDmlStatement stmt) {
-        this.jobId = jobId;
-        this.context = new TranslationContext(currentVarCounter);
-        this.outputDatasetName = outputDatasetName;
-        this.stmt = stmt;
+    public AqlPlusExpressionToPlanTranslator(MetadataProvider metadataProvider, Counter currentVarCounter)
+            throws AlgebricksException {
+        super(metadataProvider, currentVarCounter);
         this.context.setTopFlwor(false);
     }
 
-    public int getVarCounter() {
-        return context.getVarCounter();
-    }
-
-    public ILogicalPlan translate(Query expr) throws AlgebricksException, CompilationException {
-        return translate(expr, null);
-    }
-
-    public ILogicalPlan translate(Query expr, MetadataProvider metadata)
-            throws AlgebricksException, CompilationException {
-        IDataFormat format = metadata.getFormat();
-        if (format == null) {
-            throw new AlgebricksException("Data format has not been set.");
-        }
-        format.registerRuntimeFunctions(FunctionCollection.getFunctionDescriptorFactories());
-        Pair<ILogicalOperator, LogicalVariable> p =
-                expr.accept(this, new MutableObject<ILogicalOperator>(new EmptyTupleSourceOperator()));
-
-        ArrayList<Mutable<ILogicalOperator>> globalPlanRoots = new ArrayList<Mutable<ILogicalOperator>>();
-
-        boolean isTransactionalWrite = false;
-        ILogicalOperator topOp = p.first;
-        ProjectOperator project = (ProjectOperator) topOp;
-        LogicalVariable resVar = project.getVariables().get(0);
-        if (outputDatasetName == null) {
-            List<Mutable<ILogicalExpression>> writeExprList = new ArrayList<Mutable<ILogicalExpression>>(1);
-            writeExprList.add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(resVar)));
-            FileSplitSinkId fssi = new FileSplitSinkId(metadata.getOutputFile());
-            FileSplitDataSink sink = new FileSplitDataSink(fssi, null);
-            topOp = new WriteOperator(writeExprList, sink);
-            topOp.getInputs().add(new MutableObject<ILogicalOperator>(project));
-        } else {
-            Dataset dataset = metadata.findDataset(stmt.getDataverseName(), outputDatasetName);
-            if (dataset == null) {
-                throw new AlgebricksException("Cannot find dataset " + outputDatasetName);
-            }
-            if (dataset.getDatasetType() == DatasetType.EXTERNAL) {
-                throw new AlgebricksException("Cannot write output to an external dataset.");
-            }
-            ARecordType itemType =
-                    (ARecordType) metadata.findType(dataset.getItemTypeDataverseName(), dataset.getItemTypeName());
-            List<List<String>> partitioningKeys = DatasetUtil.getPartitioningKeys(dataset);
-            ArrayList<LogicalVariable> vars = new ArrayList<LogicalVariable>();
-            ArrayList<Mutable<ILogicalExpression>> exprs = new ArrayList<Mutable<ILogicalExpression>>();
-            List<Mutable<ILogicalExpression>> varRefsForLoading = new ArrayList<Mutable<ILogicalExpression>>();
-            for (List<String> partitioningKey : partitioningKeys) {
-                Triple<IScalarEvaluatorFactory, ScalarFunctionCallExpression, IAType> partitioner =
-                        format.partitioningEvaluatorFactory(itemType, partitioningKey);
-                AbstractFunctionCallExpression f = partitioner.second.cloneExpression();
-                f.substituteVar(METADATA_DUMMY_VAR, resVar);
-                exprs.add(new MutableObject<ILogicalExpression>(f));
-                LogicalVariable v = context.newVar();
-                vars.add(v);
-                varRefsForLoading.add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(v)));
-            }
-            AssignOperator assign = new AssignOperator(vars, exprs);
-            assign.getInputs().add(new MutableObject<ILogicalOperator>(project));
-        }
-
-        globalPlanRoots.add(new MutableObject<ILogicalOperator>(topOp));
-        ILogicalPlan plan = new ALogicalPlanImpl(globalPlanRoots);
-        return plan;
-    }
-
     public ILogicalPlan translate(List<Clause> clauses) throws AlgebricksException, CompilationException {
-
         if (clauses == null) {
             return null;
         }
@@ -317,933 +93,6 @@
     }
 
     @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(ForClause fc, Mutable<ILogicalOperator> tupSource)
-            throws CompilationException {
-        LogicalVariable v = context.newVar(fc.getVarExpr());
-
-        Expression inExpr = fc.getInExpr();
-        Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo = aqlExprToAlgExpression(inExpr, tupSource);
-        ILogicalOperator returnedOp;
-
-        if (fc.getPosVarExpr() == null) {
-            returnedOp = new UnnestOperator(v, new MutableObject<ILogicalExpression>(makeUnnestExpression(eo.first)));
-        } else {
-            LogicalVariable pVar = context.newVar(fc.getPosVarExpr());
-            returnedOp = new UnnestOperator(v, new MutableObject<ILogicalExpression>(makeUnnestExpression(eo.first)),
-                    pVar, BuiltinType.AINT32, new PositionWriter());
-        }
-        returnedOp.getInputs().add(eo.second);
-
-        return new Pair<ILogicalOperator, LogicalVariable>(returnedOp, v);
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(LetClause lc, Mutable<ILogicalOperator> tupSource)
-            throws CompilationException {
-        LogicalVariable v;
-        ILogicalOperator returnedOp;
-
-        switch (lc.getBindingExpr().getKind()) {
-            case VARIABLE_EXPRESSION: {
-                v = context.newVar(lc.getVarExpr());
-                LogicalVariable prev = context.getVar(((VariableExpr) lc.getBindingExpr()).getVar().getId());
-                returnedOp = new AssignOperator(v,
-                        new MutableObject<ILogicalExpression>(new VariableReferenceExpression(prev)));
-                returnedOp.getInputs().add(tupSource);
-                break;
-            }
-            default: {
-                Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo =
-                        aqlExprToAlgExpression(lc.getBindingExpr(), tupSource);
-                v = context.newVar(lc.getVarExpr());
-                returnedOp = new AssignOperator(v, new MutableObject<ILogicalExpression>(eo.first));
-                returnedOp.getInputs().add(eo.second);
-                break;
-            }
-        }
-        return new Pair<ILogicalOperator, LogicalVariable>(returnedOp, v);
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(FLWOGRExpression flwor, Mutable<ILogicalOperator> tupSource)
-            throws CompilationException {
-        Mutable<ILogicalOperator> flworPlan = tupSource;
-        boolean isTop = context.isTopFlwor();
-        if (isTop) {
-            context.setTopFlwor(false);
-        }
-        for (Clause c : flwor.getClauseList()) {
-            Pair<ILogicalOperator, LogicalVariable> pC = c.accept(this, flworPlan);
-            flworPlan = new MutableObject<ILogicalOperator>(pC.first);
-        }
-
-        Expression r = flwor.getReturnExpr();
-        boolean noFlworClause = flwor.noForClause();
-
-        if (r.getKind() == Kind.VARIABLE_EXPRESSION) {
-            VariableExpr v = (VariableExpr) r;
-            LogicalVariable var = context.getVar(v.getVar().getId());
-
-            return produceFlwrResult(noFlworClause, isTop, flworPlan, var);
-
-        } else {
-            Mutable<ILogicalOperator> baseOp = new MutableObject<ILogicalOperator>(flworPlan.getValue());
-            Pair<ILogicalOperator, LogicalVariable> rRes = r.accept(this, baseOp);
-            ILogicalOperator rOp = rRes.first;
-            ILogicalOperator resOp;
-            if (expressionNeedsNoNesting(r)) {
-                baseOp.setValue(flworPlan.getValue());
-                resOp = rOp;
-            } else {
-                SubplanOperator s = new SubplanOperator(rOp);
-                s.getInputs().add(flworPlan);
-                resOp = s;
-                baseOp.setValue(new NestedTupleSourceOperator(new MutableObject<ILogicalOperator>(s)));
-            }
-            Mutable<ILogicalOperator> resOpRef = new MutableObject<ILogicalOperator>(resOp);
-            return produceFlwrResult(noFlworClause, isTop, resOpRef, rRes.second);
-        }
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(FieldAccessor fa, Mutable<ILogicalOperator> tupSource)
-            throws CompilationException {
-        Pair<ILogicalExpression, Mutable<ILogicalOperator>> p = aqlExprToAlgExpression(fa.getExpr(), tupSource);
-        LogicalVariable v = context.newVar();
-        AbstractFunctionCallExpression fldAccess = new ScalarFunctionCallExpression(
-                FunctionUtil.getFunctionInfo(BuiltinFunctions.FIELD_ACCESS_BY_NAME));
-        fldAccess.getArguments().add(new MutableObject<ILogicalExpression>(p.first));
-        ILogicalExpression faExpr =
-                new ConstantExpression(new AsterixConstantValue(new AString(fa.getIdent().getValue())));
-        fldAccess.getArguments().add(new MutableObject<ILogicalExpression>(faExpr));
-        AssignOperator a = new AssignOperator(v, new MutableObject<ILogicalExpression>(fldAccess));
-        a.getInputs().add(p.second);
-        return new Pair<ILogicalOperator, LogicalVariable>(a, v);
-
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(IndexAccessor ia, Mutable<ILogicalOperator> tupSource)
-            throws CompilationException {
-        Pair<ILogicalExpression, Mutable<ILogicalOperator>> p = aqlExprToAlgExpression(ia.getExpr(), tupSource);
-        LogicalVariable v = context.newVar();
-        AbstractFunctionCallExpression f;
-        if (ia.isAny()) {
-            f = new ScalarFunctionCallExpression(
-                    FunctionUtil.getFunctionInfo(BuiltinFunctions.ANY_COLLECTION_MEMBER));
-            f.getArguments().add(new MutableObject<ILogicalExpression>(p.first));
-        } else {
-            Pair<ILogicalExpression, Mutable<ILogicalOperator>> indexPair =
-                    aqlExprToAlgExpression(ia.getIndexExpr(), tupSource);
-            f = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.GET_ITEM));
-            f.getArguments().add(new MutableObject<ILogicalExpression>(p.first));
-            f.getArguments().add(new MutableObject<ILogicalExpression>(indexPair.first));
-        }
-        AssignOperator a = new AssignOperator(v, new MutableObject<ILogicalExpression>(f));
-        a.getInputs().add(p.second);
-        return new Pair<ILogicalOperator, LogicalVariable>(a, v);
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(CallExpr fcall, Mutable<ILogicalOperator> tupSource)
-            throws CompilationException {
-        LogicalVariable v = context.newVar();
-        FunctionSignature signature = fcall.getFunctionSignature();
-        List<Mutable<ILogicalExpression>> args = new ArrayList<Mutable<ILogicalExpression>>();
-        Mutable<ILogicalOperator> topOp = tupSource;
-
-        for (Expression expr : fcall.getExprList()) {
-            switch (expr.getKind()) {
-                case VARIABLE_EXPRESSION: {
-                    LogicalVariable var = context.getVar(((VariableExpr) expr).getVar().getId());
-                    args.add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(var)));
-                    break;
-                }
-                case LITERAL_EXPRESSION: {
-                    LiteralExpr val = (LiteralExpr) expr;
-                    args.add(new MutableObject<ILogicalExpression>(new ConstantExpression(
-                            new AsterixConstantValue(ConstantHelper.objectFromLiteral(val.getValue())))));
-                    break;
-                }
-                default: {
-                    Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo = aqlExprToAlgExpression(expr, topOp);
-                    AbstractLogicalOperator o1 = (AbstractLogicalOperator) eo.second.getValue();
-                    args.add(new MutableObject<ILogicalExpression>(eo.first));
-                    if (o1 != null && !(o1.getOperatorTag() == LogicalOperatorTag.ASSIGN && hasOnlyChild(o1, topOp))) {
-                        topOp = eo.second;
-                    }
-                    break;
-                }
-            }
-        }
-
-        FunctionIdentifier fi = new FunctionIdentifier(AlgebricksBuiltinFunctions.ALGEBRICKS_NS, signature.getName());
-        FunctionInfo afi = BuiltinFunctions.lookupFunction(fi);
-        FunctionIdentifier builtinAquafi = afi == null ? null : afi.getFunctionIdentifier();
-
-        if (builtinAquafi != null) {
-            fi = builtinAquafi;
-        } else {
-            fi = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, signature.getName());
-            FunctionIdentifier builtinAsterixFi = BuiltinFunctions.getBuiltinFunctionIdentifier(fi);
-            if (builtinAsterixFi != null) {
-                fi = builtinAsterixFi;
-            }
-        }
-        AbstractFunctionCallExpression f;
-        if (BuiltinFunctions.isBuiltinAggregateFunction(fi)) {
-            f = BuiltinFunctions.makeAggregateFunctionExpression(fi, args);
-        } else if (BuiltinFunctions.isBuiltinUnnestingFunction(fi)) {
-            UnnestingFunctionCallExpression ufce =
-                    new UnnestingFunctionCallExpression(FunctionUtil.getFunctionInfo(fi), args);
-            ufce.setReturnsUniqueValues(BuiltinFunctions.returnsUniqueValues(fi));
-            f = ufce;
-        } else {
-            f = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(fi), args);
-        }
-        AssignOperator op = new AssignOperator(v, new MutableObject<ILogicalExpression>(f));
-        if (topOp != null) {
-            op.getInputs().add(topOp);
-        }
-
-        return new Pair<ILogicalOperator, LogicalVariable>(op, v);
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(FunctionDecl fd, Mutable<ILogicalOperator> tupSource) {
-        // TODO Auto-generated method stub
-        throw new NotImplementedException();
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(GroupbyClause gc, Mutable<ILogicalOperator> tupSource)
-            throws CompilationException {
-        GroupByOperator gOp = new GroupByOperator();
-        Mutable<ILogicalOperator> topOp = tupSource;
-        for (GbyVariableExpressionPair ve : gc.getGbyPairList()) {
-            LogicalVariable v;
-            VariableExpr vexpr = ve.getVar();
-            if (vexpr != null) {
-                v = context.newVar(vexpr);
-            } else {
-                v = context.newVar();
-            }
-            Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo = aqlExprToAlgExpression(ve.getExpr(), topOp);
-            gOp.addGbyExpression(v, eo.first);
-            topOp = eo.second;
-        }
-        for (GbyVariableExpressionPair ve : gc.getDecorPairList()) {
-            LogicalVariable v;
-            VariableExpr vexpr = ve.getVar();
-            if (vexpr != null) {
-                v = context.newVar(vexpr);
-            } else {
-                v = context.newVar();
-            }
-            Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo = aqlExprToAlgExpression(ve.getExpr(), topOp);
-            gOp.addDecorExpression(v, eo.first);
-            topOp = eo.second;
-        }
-        gOp.getInputs().add(topOp);
-
-        for (Entry<Expression, VariableExpr> entry : gc.getWithVarMap().entrySet()) {
-            LogicalVariable aggVar = context.newVar();
-            Pair<ILogicalExpression, Mutable<ILogicalOperator>> listifyInput = aqlExprToAlgExpression(entry.getKey(),
-                    new MutableObject<>(new NestedTupleSourceOperator(new MutableObject<ILogicalOperator>(gOp))));
-            List<Mutable<ILogicalExpression>> flArgs = new ArrayList<>(1);
-            flArgs.add(new MutableObject<>(listifyInput.first));
-            AggregateFunctionCallExpression fListify =
-                    BuiltinFunctions.makeAggregateFunctionExpression(BuiltinFunctions.LISTIFY, flArgs);
-            AggregateOperator agg = new AggregateOperator(mkSingletonArrayList(aggVar),
-                    mkSingletonArrayList(new MutableObject<>(fListify)));
-            agg.getInputs().add(listifyInput.second);
-            ILogicalPlan plan = new ALogicalPlanImpl(new MutableObject<>(agg));
-            gOp.getNestedPlans().add(plan);
-            // Hide the variable that was part of the "with", replacing it with
-            // the one bound by the aggregation op.
-            context.setVar(entry.getValue(), aggVar);
-        }
-        gOp.setGroupAll(gc.isGroupAll());
-        gOp.getAnnotations().put(OperatorAnnotations.USE_HASH_GROUP_BY, gc.hasHashGroupByHint());
-        return new Pair<ILogicalOperator, LogicalVariable>(gOp, null);
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(IfExpr ifexpr, Mutable<ILogicalOperator> tupSource)
-            throws CompilationException {
-        // In the most general case, IfThenElse is translated in the following
-        // way.
-        //
-        // We assign the result of the condition to one variable varCond.
-        // We create one subplan which contains the plan for the "then" branch,
-        // on top of which there is a selection whose condition is varCond.
-        // Similarly, we create one subplan for the "else" branch, in which the
-        // selection is not(varCond).
-        // Finally, we concatenate the results. (??)
-
-        Pair<ILogicalOperator, LogicalVariable> pCond = ifexpr.getCondExpr().accept(this, tupSource);
-        ILogicalOperator opCond = pCond.first;
-        LogicalVariable varCond = pCond.second;
-
-        SubplanOperator sp = new SubplanOperator();
-        Mutable<ILogicalOperator> nestedSource = new MutableObject<ILogicalOperator>(
-                new NestedTupleSourceOperator(new MutableObject<ILogicalOperator>(sp)));
-
-        Pair<ILogicalOperator, LogicalVariable> pThen = ifexpr.getThenExpr().accept(this, nestedSource);
-        SelectOperator sel1 = new SelectOperator(
-                new MutableObject<ILogicalExpression>(new VariableReferenceExpression(varCond)), false, null);
-        sel1.getInputs().add(new MutableObject<ILogicalOperator>(pThen.first));
-
-        Pair<ILogicalOperator, LogicalVariable> pElse = ifexpr.getElseExpr().accept(this, nestedSource);
-        AbstractFunctionCallExpression notVarCond =
-                new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(AlgebricksBuiltinFunctions.NOT),
-                        new MutableObject<ILogicalExpression>(new VariableReferenceExpression(varCond)));
-        SelectOperator sel2 = new SelectOperator(new MutableObject<ILogicalExpression>(notVarCond), false, null);
-        sel2.getInputs().add(new MutableObject<ILogicalOperator>(pElse.first));
-
-        ILogicalPlan p1 = new ALogicalPlanImpl(new MutableObject<ILogicalOperator>(sel1));
-        sp.getNestedPlans().add(p1);
-        ILogicalPlan p2 = new ALogicalPlanImpl(new MutableObject<ILogicalOperator>(sel2));
-        sp.getNestedPlans().add(p2);
-
-        Mutable<ILogicalOperator> opCondRef = new MutableObject<ILogicalOperator>(opCond);
-        sp.getInputs().add(opCondRef);
-
-        LogicalVariable resV = context.newVar();
-        AbstractFunctionCallExpression concatNonNull =
-                new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.CONCAT_NON_NULL),
-                        new MutableObject<ILogicalExpression>(new VariableReferenceExpression(pThen.second)),
-                        new MutableObject<ILogicalExpression>(new VariableReferenceExpression(pElse.second)));
-        AssignOperator a = new AssignOperator(resV, new MutableObject<ILogicalExpression>(concatNonNull));
-        a.getInputs().add(new MutableObject<ILogicalOperator>(sp));
-
-        return new Pair<ILogicalOperator, LogicalVariable>(a, resV);
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(LiteralExpr l, Mutable<ILogicalOperator> tupSource) {
-        LogicalVariable var = context.newVar();
-        AssignOperator a = new AssignOperator(var, new MutableObject<ILogicalExpression>(
-                new ConstantExpression(new AsterixConstantValue(ConstantHelper.objectFromLiteral(l.getValue())))));
-        if (tupSource != null) {
-            a.getInputs().add(tupSource);
-        }
-        return new Pair<ILogicalOperator, LogicalVariable>(a, var);
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(OperatorExpr op, Mutable<ILogicalOperator> tupSource)
-            throws CompilationException {
-        List<OperatorType> ops = op.getOpList();
-        int nOps = ops.size();
-
-        if (nOps > 0 && (ops.get(0) == OperatorType.AND || ops.get(0) == OperatorType.OR)) {
-            return visitAndOrOperator(op, tupSource);
-        }
-
-        List<Expression> exprs = op.getExprList();
-
-        Mutable<ILogicalOperator> topOp = tupSource;
-
-        ILogicalExpression currExpr = null;
-        for (int i = 0; i <= nOps; i++) {
-
-            Pair<ILogicalExpression, Mutable<ILogicalOperator>> p = aqlExprToAlgExpression(exprs.get(i), topOp);
-            topOp = p.second;
-            ILogicalExpression e = p.first;
-            // now look at the operator
-            if (i < nOps) {
-                if (OperatorExpr.opIsComparison(ops.get(i))) {
-                    AbstractFunctionCallExpression c = createComparisonExpression(ops.get(i));
-
-                    // chain the operators
-                    if (i == 0) {
-                        c.getArguments().add(new MutableObject<ILogicalExpression>(e));
-                        currExpr = c;
-                        if (op.isBroadcastOperand(i)) {
-                            BroadcastExpressionAnnotation bcast = new BroadcastExpressionAnnotation();
-                            bcast.setObject(BroadcastSide.LEFT);
-                            c.getAnnotations().put(BroadcastExpressionAnnotation.BROADCAST_ANNOTATION_KEY, bcast);
-                        }
-                    } else {
-                        ((AbstractFunctionCallExpression) currExpr).getArguments()
-                                .add(new MutableObject<ILogicalExpression>(e));
-                        c.getArguments().add(new MutableObject<ILogicalExpression>(currExpr));
-                        currExpr = c;
-                        if (i == 1 && op.isBroadcastOperand(i)) {
-                            BroadcastExpressionAnnotation bcast = new BroadcastExpressionAnnotation();
-                            bcast.setObject(BroadcastSide.RIGHT);
-                            c.getAnnotations().put(BroadcastExpressionAnnotation.BROADCAST_ANNOTATION_KEY, bcast);
-                        }
-                    }
-                } else {
-                    AbstractFunctionCallExpression f = createFunctionCallExpressionForBuiltinOperator(ops.get(i));
-
-                    if (i == 0) {
-                        f.getArguments().add(new MutableObject<ILogicalExpression>(e));
-                        currExpr = f;
-                    } else {
-                        ((AbstractFunctionCallExpression) currExpr).getArguments()
-                                .add(new MutableObject<ILogicalExpression>(e));
-                        f.getArguments().add(new MutableObject<ILogicalExpression>(currExpr));
-                        currExpr = f;
-                    }
-                }
-            } else { // don't forget the last expression...
-                ((AbstractFunctionCallExpression) currExpr).getArguments()
-                        .add(new MutableObject<ILogicalExpression>(e));
-                if (i == 1 && op.isBroadcastOperand(i)) {
-                    BroadcastExpressionAnnotation bcast = new BroadcastExpressionAnnotation();
-                    bcast.setObject(BroadcastSide.RIGHT);
-                    ((AbstractFunctionCallExpression) currExpr).getAnnotations()
-                            .put(BroadcastExpressionAnnotation.BROADCAST_ANNOTATION_KEY, bcast);
-                }
-            }
-        }
-
-        LogicalVariable assignedVar = context.newVar();
-        AssignOperator a = new AssignOperator(assignedVar, new MutableObject<ILogicalExpression>(currExpr));
-
-        a.getInputs().add(topOp);
-
-        return new Pair<ILogicalOperator, LogicalVariable>(a, assignedVar);
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(OrderbyClause oc, Mutable<ILogicalOperator> tupSource)
-            throws CompilationException {
-
-        OrderOperator ord = new OrderOperator();
-        Iterator<OrderModifier> modifIter = oc.getModifierList().iterator();
-        Mutable<ILogicalOperator> topOp = tupSource;
-        for (Expression e : oc.getOrderbyList()) {
-            Pair<ILogicalExpression, Mutable<ILogicalOperator>> p = aqlExprToAlgExpression(e, topOp);
-            OrderModifier m = modifIter.next();
-            OrderOperator.IOrder comp = (m == OrderModifier.ASC) ? OrderOperator.ASC_ORDER : OrderOperator.DESC_ORDER;
-            ord.getOrderExpressions().add(new Pair<IOrder, Mutable<ILogicalExpression>>(comp,
-                    new MutableObject<ILogicalExpression>(p.first)));
-            topOp = p.second;
-        }
-        ord.getInputs().add(topOp);
-        if (oc.getNumTuples() > 0) {
-            ord.getAnnotations().put(OperatorAnnotations.CARDINALITY, oc.getNumTuples());
-        }
-        if (oc.getNumFrames() > 0) {
-            ord.getAnnotations().put(OperatorAnnotations.MAX_NUMBER_FRAMES, oc.getNumFrames());
-        }
-        return new Pair<ILogicalOperator, LogicalVariable>(ord, null);
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(QuantifiedExpression qe, Mutable<ILogicalOperator> tupSource)
-            throws CompilationException {
-        Mutable<ILogicalOperator> topOp = tupSource;
-
-        ILogicalOperator firstOp = null;
-        Mutable<ILogicalOperator> lastOp = null;
-
-        for (QuantifiedPair qt : qe.getQuantifiedList()) {
-            Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo1 = aqlExprToAlgExpression(qt.getExpr(), topOp);
-            topOp = eo1.second;
-            LogicalVariable uVar = context.newVar(qt.getVarExpr());
-            ILogicalOperator u =
-                    new UnnestOperator(uVar, new MutableObject<ILogicalExpression>(makeUnnestExpression(eo1.first)));
-
-            if (firstOp == null) {
-                firstOp = u;
-            }
-            if (lastOp != null) {
-                u.getInputs().add(lastOp);
-            }
-            lastOp = new MutableObject<ILogicalOperator>(u);
-        }
-
-        // We make all the unnest correspond. to quantif. vars. sit on top
-        // in the hope of enabling joins & other optimiz.
-        firstOp.getInputs().add(topOp);
-        topOp = lastOp;
-
-        Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo2 = aqlExprToAlgExpression(qe.getSatisfiesExpr(), topOp);
-
-        AggregateFunctionCallExpression fAgg;
-        SelectOperator s;
-        if (qe.getQuantifier() == Quantifier.SOME) {
-            s = new SelectOperator(new MutableObject<ILogicalExpression>(eo2.first), false, null);
-            s.getInputs().add(eo2.second);
-            fAgg = BuiltinFunctions.makeAggregateFunctionExpression(BuiltinFunctions.NON_EMPTY_STREAM,
-                    new ArrayList<Mutable<ILogicalExpression>>());
-        } else { // EVERY
-            List<Mutable<ILogicalExpression>> satExprList = new ArrayList<Mutable<ILogicalExpression>>(1);
-            satExprList.add(new MutableObject<ILogicalExpression>(eo2.first));
-            s = new SelectOperator(new MutableObject<ILogicalExpression>(new ScalarFunctionCallExpression(
-                    FunctionUtil.getFunctionInfo(AlgebricksBuiltinFunctions.NOT), satExprList)), false, null);
-            s.getInputs().add(eo2.second);
-            fAgg = BuiltinFunctions.makeAggregateFunctionExpression(BuiltinFunctions.EMPTY_STREAM,
-                    new ArrayList<Mutable<ILogicalExpression>>());
-        }
-        LogicalVariable qeVar = context.newVar();
-        AggregateOperator a = new AggregateOperator(mkSingletonArrayList(qeVar),
-                (List) mkSingletonArrayList(new MutableObject<ILogicalExpression>(fAgg)));
-        a.getInputs().add(new MutableObject<ILogicalOperator>(s));
-        return new Pair<ILogicalOperator, LogicalVariable>(a, qeVar);
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(Query q, Mutable<ILogicalOperator> tupSource)
-            throws CompilationException {
-        return q.getBody().accept(this, tupSource);
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(RecordConstructor rc, Mutable<ILogicalOperator> tupSource)
-            throws CompilationException {
-        AbstractFunctionCallExpression f = new ScalarFunctionCallExpression(
-                FunctionUtil.getFunctionInfo(BuiltinFunctions.OPEN_RECORD_CONSTRUCTOR));
-        LogicalVariable v1 = context.newVar();
-        AssignOperator a = new AssignOperator(v1, new MutableObject<ILogicalExpression>(f));
-        Mutable<ILogicalOperator> topOp = tupSource;
-        for (FieldBinding fb : rc.getFbList()) {
-            Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo1 = aqlExprToAlgExpression(fb.getLeftExpr(), topOp);
-            f.getArguments().add(new MutableObject<ILogicalExpression>(eo1.first));
-            topOp = eo1.second;
-            Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo2 = aqlExprToAlgExpression(fb.getRightExpr(), topOp);
-            f.getArguments().add(new MutableObject<ILogicalExpression>(eo2.first));
-            topOp = eo2.second;
-        }
-        a.getInputs().add(topOp);
-        return new Pair<ILogicalOperator, LogicalVariable>(a, v1);
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(ListConstructor lc, Mutable<ILogicalOperator> tupSource)
-            throws CompilationException {
-        FunctionIdentifier fid = (lc.getType() == Type.ORDERED_LIST_CONSTRUCTOR)
-                ? BuiltinFunctions.ORDERED_LIST_CONSTRUCTOR : BuiltinFunctions.UNORDERED_LIST_CONSTRUCTOR;
-        AbstractFunctionCallExpression f = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(fid));
-        LogicalVariable v1 = context.newVar();
-        AssignOperator a = new AssignOperator(v1, new MutableObject<ILogicalExpression>(f));
-        Mutable<ILogicalOperator> topOp = tupSource;
-        for (Expression expr : lc.getExprList()) {
-            Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo = aqlExprToAlgExpression(expr, topOp);
-            f.getArguments().add(new MutableObject<ILogicalExpression>(eo.first));
-            topOp = eo.second;
-        }
-        a.getInputs().add(topOp);
-        return new Pair<ILogicalOperator, LogicalVariable>(a, v1);
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(UnaryExpr u, Mutable<ILogicalOperator> tupSource)
-            throws CompilationException {
-        Expression expr = u.getExpr();
-        Pair<ILogicalExpression, Mutable<ILogicalOperator>> eo = aqlExprToAlgExpression(expr, tupSource);
-        LogicalVariable v1 = context.newVar();
-        AssignOperator a;
-        if (u.getExprType() == UnaryExprType.POSITIVE) {
-            a = new AssignOperator(v1, new MutableObject<ILogicalExpression>(eo.first));
-        } else {
-            AbstractFunctionCallExpression m = new ScalarFunctionCallExpression(
-                    FunctionUtil.getFunctionInfo(BuiltinFunctions.NUMERIC_UNARY_MINUS));
-            m.getArguments().add(new MutableObject<ILogicalExpression>(eo.first));
-            a = new AssignOperator(v1, new MutableObject<ILogicalExpression>(m));
-        }
-        a.getInputs().add(eo.second);
-        return new Pair<ILogicalOperator, LogicalVariable>(a, v1);
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(VariableExpr v, Mutable<ILogicalOperator> tupSource) {
-        // Should we ever get to this method?
-        LogicalVariable var = context.newVar();
-        LogicalVariable oldV = context.getVar(v.getVar().getId());
-        AssignOperator a =
-                new AssignOperator(var, new MutableObject<ILogicalExpression>(new VariableReferenceExpression(oldV)));
-        a.getInputs().add(tupSource);
-        return new Pair<ILogicalOperator, LogicalVariable>(a, var);
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(WhereClause w, Mutable<ILogicalOperator> tupSource)
-            throws CompilationException {
-        Pair<ILogicalExpression, Mutable<ILogicalOperator>> p = aqlExprToAlgExpression(w.getWhereExpr(), tupSource);
-        SelectOperator s = new SelectOperator(new MutableObject<ILogicalExpression>(p.first), false, null);
-        s.getInputs().add(p.second);
-
-        return new Pair<ILogicalOperator, LogicalVariable>(s, null);
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(LimitClause lc, Mutable<ILogicalOperator> tupSource)
-            throws CompilationException {
-        Pair<ILogicalExpression, Mutable<ILogicalOperator>> p1 = aqlExprToAlgExpression(lc.getLimitExpr(), tupSource);
-        LimitOperator opLim;
-        Expression offset = lc.getOffset();
-        if (offset != null) {
-            Pair<ILogicalExpression, Mutable<ILogicalOperator>> p2 = aqlExprToAlgExpression(offset, p1.second);
-            opLim = new LimitOperator(p1.first, p2.first);
-            opLim.getInputs().add(p2.second);
-        } else {
-            opLim = new LimitOperator(p1.first);
-            opLim.getInputs().add(p1.second);
-        }
-        return new Pair<ILogicalOperator, LogicalVariable>(opLim, null);
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(DistinctClause dc, Mutable<ILogicalOperator> tupSource)
-            throws CompilationException {
-        List<Mutable<ILogicalExpression>> exprList = new ArrayList<Mutable<ILogicalExpression>>();
-        Mutable<ILogicalOperator> input = null;
-        for (Expression expr : dc.getDistinctByExpr()) {
-            Pair<ILogicalExpression, Mutable<ILogicalOperator>> p = aqlExprToAlgExpression(expr, tupSource);
-            exprList.add(new MutableObject<ILogicalExpression>(p.first));
-            input = p.second;
-        }
-        DistinctOperator opDistinct = new DistinctOperator(exprList);
-        opDistinct.getInputs().add(input);
-        return new Pair<ILogicalOperator, LogicalVariable>(opDistinct, null);
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(UnionExpr unionExpr, Mutable<ILogicalOperator> tupSource)
-            throws CompilationException {
-        Mutable<ILogicalOperator> ts = tupSource;
-        ILogicalOperator lastOp = null;
-        LogicalVariable lastVar = null;
-        boolean first = true;
-        for (Expression e : unionExpr.getExprs()) {
-            if (first) {
-                first = false;
-            } else {
-                ts = new MutableObject<ILogicalOperator>(new EmptyTupleSourceOperator());
-            }
-            Pair<ILogicalOperator, LogicalVariable> p1 = e.accept(this, ts);
-            if (lastOp == null) {
-                lastOp = p1.first;
-                lastVar = p1.second;
-            } else {
-                LogicalVariable unnestVar1 = context.newVar();
-                UnnestOperator unnest1 = new UnnestOperator(unnestVar1, new MutableObject<ILogicalExpression>(
-                        makeUnnestExpression(new VariableReferenceExpression(lastVar))));
-                unnest1.getInputs().add(new MutableObject<ILogicalOperator>(lastOp));
-                LogicalVariable unnestVar2 = context.newVar();
-                UnnestOperator unnest2 = new UnnestOperator(unnestVar2, new MutableObject<ILogicalExpression>(
-                        makeUnnestExpression(new VariableReferenceExpression(p1.second))));
-                unnest2.getInputs().add(new MutableObject<ILogicalOperator>(p1.first));
-                List<Triple<LogicalVariable, LogicalVariable, LogicalVariable>> varMap = new ArrayList<>(1);
-                LogicalVariable resultVar = context.newVar();
-                Triple<LogicalVariable, LogicalVariable, LogicalVariable> triple =
-                        new Triple<>(unnestVar1, unnestVar2, resultVar);
-                varMap.add(triple);
-                UnionAllOperator unionOp = new UnionAllOperator(varMap);
-                unionOp.getInputs().add(new MutableObject<ILogicalOperator>(unnest1));
-                unionOp.getInputs().add(new MutableObject<ILogicalOperator>(unnest2));
-                lastVar = resultVar;
-                lastOp = unionOp;
-            }
-        }
-        LogicalVariable aggVar = context.newVar();
-        ArrayList<LogicalVariable> aggregVars = new ArrayList<LogicalVariable>(1);
-        aggregVars.add(aggVar);
-        List<Mutable<ILogicalExpression>> afcExprs = new ArrayList<Mutable<ILogicalExpression>>(1);
-        afcExprs.add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(lastVar)));
-        AggregateFunctionCallExpression afc =
-                BuiltinFunctions.makeAggregateFunctionExpression(BuiltinFunctions.LISTIFY, afcExprs);
-        ArrayList<Mutable<ILogicalExpression>> aggregExprs = new ArrayList<Mutable<ILogicalExpression>>(1);
-        aggregExprs.add(new MutableObject<ILogicalExpression>(afc));
-        AggregateOperator agg = new AggregateOperator(aggregVars, aggregExprs);
-        agg.getInputs().add(new MutableObject<ILogicalOperator>(lastOp));
-        return new Pair<ILogicalOperator, LogicalVariable>(agg, aggVar);
-    }
-
-    private AbstractFunctionCallExpression createComparisonExpression(OperatorType t) {
-        FunctionIdentifier fi = operatorTypeToFunctionIdentifier(t);
-        IFunctionInfo finfo = FunctionUtil.getFunctionInfo(fi);
-        return new ScalarFunctionCallExpression(finfo);
-    }
-
-    private FunctionIdentifier operatorTypeToFunctionIdentifier(OperatorType t) {
-        switch (t) {
-            case EQ: {
-                return AlgebricksBuiltinFunctions.EQ;
-            }
-            case NEQ: {
-                return AlgebricksBuiltinFunctions.NEQ;
-            }
-            case GT: {
-                return AlgebricksBuiltinFunctions.GT;
-            }
-            case GE: {
-                return AlgebricksBuiltinFunctions.GE;
-            }
-            case LT: {
-                return AlgebricksBuiltinFunctions.LT;
-            }
-            case LE: {
-                return AlgebricksBuiltinFunctions.LE;
-            }
-            default: {
-                throw new IllegalStateException();
-            }
-        }
-    }
-
-    private AbstractFunctionCallExpression createFunctionCallExpressionForBuiltinOperator(OperatorType t)
-            throws CompilationException {
-
-        FunctionIdentifier fid = null;
-        switch (t) {
-            case PLUS: {
-                fid = AlgebricksBuiltinFunctions.NUMERIC_ADD;
-                break;
-            }
-            case MINUS: {
-                fid = BuiltinFunctions.NUMERIC_SUBTRACT;
-                break;
-            }
-            case MUL: {
-                fid = BuiltinFunctions.NUMERIC_MULTIPLY;
-                break;
-            }
-            case DIV: {
-                fid = BuiltinFunctions.NUMERIC_DIVIDE;
-                break;
-            }
-            case MOD: {
-                fid = BuiltinFunctions.NUMERIC_MOD;
-                break;
-            }
-            case IDIV: {
-                fid = BuiltinFunctions.NUMERIC_IDIV;
-                break;
-            }
-            case CARET: {
-                fid = BuiltinFunctions.CARET;
-                break;
-            }
-            case AND: {
-                fid = AlgebricksBuiltinFunctions.AND;
-                break;
-            }
-            case OR: {
-                fid = AlgebricksBuiltinFunctions.OR;
-                break;
-            }
-            case FUZZY_EQ: {
-                fid = BuiltinFunctions.FUZZY_EQ;
-                break;
-            }
-
-            default: {
-                throw new NotImplementedException("Operator " + t + " is not yet implemented");
-            }
-        }
-        return new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(fid));
-    }
-
-    private static boolean hasOnlyChild(ILogicalOperator parent, Mutable<ILogicalOperator> childCandidate) {
-        List<Mutable<ILogicalOperator>> inp = parent.getInputs();
-        if (inp == null || inp.size() != 1) {
-            return false;
-        }
-        return inp.get(0) == childCandidate;
-    }
-
-    private Pair<ILogicalExpression, Mutable<ILogicalOperator>> aqlExprToAlgExpression(Expression expr,
-            Mutable<ILogicalOperator> topOp) throws CompilationException {
-        switch (expr.getKind()) {
-            case VARIABLE_EXPRESSION: {
-                VariableReferenceExpression ve =
-                        new VariableReferenceExpression(context.getVar(((VariableExpr) expr).getVar().getId()));
-                return new Pair<ILogicalExpression, Mutable<ILogicalOperator>>(ve, topOp);
-            }
-            case METAVARIABLE_EXPRESSION: {
-                ILogicalExpression le = metaScopeExp.getVariableReferenceExpression(((VariableExpr) expr).getVar());
-                return new Pair<ILogicalExpression, Mutable<ILogicalOperator>>(le, topOp);
-            }
-            case LITERAL_EXPRESSION: {
-                LiteralExpr val = (LiteralExpr) expr;
-                return new Pair<ILogicalExpression, Mutable<ILogicalOperator>>(new ConstantExpression(
-                        new AsterixConstantValue(ConstantHelper.objectFromLiteral(val.getValue()))), topOp);
-            }
-            default: {
-                // Mutable<ILogicalExpression> src = new
-                // Mutable<ILogicalExpression>();
-                // Mutable<ILogicalExpression> src = topOp;
-                if (expressionNeedsNoNesting(expr)) {
-                    Pair<ILogicalOperator, LogicalVariable> p = expr.accept(this, topOp);
-                    ILogicalExpression exp = ((AssignOperator) p.first).getExpressions().get(0).getValue();
-                    return new Pair<ILogicalExpression, Mutable<ILogicalOperator>>(exp, p.first.getInputs().get(0));
-                } else {
-                    Mutable<ILogicalOperator> src = new MutableObject<ILogicalOperator>();
-
-                    Pair<ILogicalOperator, LogicalVariable> p = expr.accept(this, src);
-
-                    if (((AbstractLogicalOperator) p.first).getOperatorTag() == LogicalOperatorTag.SUBPLAN) {
-                        // src.setOperator(topOp.getOperator());
-                        Mutable<ILogicalOperator> top2 = new MutableObject<ILogicalOperator>(p.first);
-                        return new Pair<ILogicalExpression, Mutable<ILogicalOperator>>(
-                                new VariableReferenceExpression(p.second), top2);
-                    } else {
-                        SubplanOperator s = new SubplanOperator();
-                        s.getInputs().add(topOp);
-                        src.setValue(new NestedTupleSourceOperator(new MutableObject<ILogicalOperator>(s)));
-                        Mutable<ILogicalOperator> planRoot = new MutableObject<ILogicalOperator>(p.first);
-                        s.setRootOp(planRoot);
-                        return new Pair<ILogicalExpression, Mutable<ILogicalOperator>>(
-                                new VariableReferenceExpression(p.second), new MutableObject<ILogicalOperator>(s));
-                    }
-                }
-            }
-        }
-
-    }
-
-    private Pair<ILogicalOperator, LogicalVariable> produceFlwrResult(boolean noForClause, boolean isTop,
-            Mutable<ILogicalOperator> resOpRef, LogicalVariable resVar) {
-        if (isTop) {
-            ProjectOperator pr = new ProjectOperator(resVar);
-            pr.getInputs().add(resOpRef);
-            return new Pair<ILogicalOperator, LogicalVariable>(pr, resVar);
-
-        } else if (noForClause) {
-            return new Pair<ILogicalOperator, LogicalVariable>(resOpRef.getValue(), resVar);
-        } else {
-            return aggListify(resVar, resOpRef, false);
-        }
-    }
-
-    private Pair<ILogicalOperator, LogicalVariable> aggListify(LogicalVariable var, Mutable<ILogicalOperator> opRef,
-            boolean bProject) {
-        AggregateFunctionCallExpression funAgg = BuiltinFunctions.makeAggregateFunctionExpression(
-                BuiltinFunctions.LISTIFY, new ArrayList<Mutable<ILogicalExpression>>());
-        funAgg.getArguments().add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(var)));
-        LogicalVariable varListified = context.newVar();
-        AggregateOperator agg = new AggregateOperator(mkSingletonArrayList(varListified),
-                (List) mkSingletonArrayList(new MutableObject<ILogicalExpression>(funAgg)));
-        agg.getInputs().add(opRef);
-        ILogicalOperator res;
-        if (bProject) {
-            ProjectOperator pr = new ProjectOperator(varListified);
-            pr.getInputs().add(new MutableObject<ILogicalOperator>(agg));
-            res = pr;
-        } else {
-            res = agg;
-        }
-        return new Pair<ILogicalOperator, LogicalVariable>(res, varListified);
-    }
-
-    private Pair<ILogicalOperator, LogicalVariable> visitAndOrOperator(OperatorExpr op,
-            Mutable<ILogicalOperator> tupSource) throws CompilationException {
-        List<OperatorType> ops = op.getOpList();
-        int nOps = ops.size();
-
-        List<Expression> exprs = op.getExprList();
-
-        Mutable<ILogicalOperator> topOp = tupSource;
-
-        OperatorType opLogical = ops.get(0);
-        AbstractFunctionCallExpression f = createFunctionCallExpressionForBuiltinOperator(opLogical);
-
-        for (int i = 0; i <= nOps; i++) {
-            Pair<ILogicalExpression, Mutable<ILogicalOperator>> p = aqlExprToAlgExpression(exprs.get(i), topOp);
-            topOp = p.second;
-            // now look at the operator
-            if (i < nOps) {
-                if (ops.get(i) != opLogical) {
-                    throw new TranslationException(
-                            "Unexpected operator " + ops.get(i) + " in an OperatorExpr starting with " + opLogical);
-                }
-            }
-            f.getArguments().add(new MutableObject<ILogicalExpression>(p.first));
-        }
-
-        LogicalVariable assignedVar = context.newVar();
-        AssignOperator a = new AssignOperator(assignedVar, new MutableObject<ILogicalExpression>(f));
-        a.getInputs().add(topOp);
-
-        return new Pair<ILogicalOperator, LogicalVariable>(a, assignedVar);
-
-    }
-
-    private static boolean expressionNeedsNoNesting(Expression expr) {
-        Kind k = expr.getKind();
-        return k == Kind.LITERAL_EXPRESSION || k == Kind.LIST_CONSTRUCTOR_EXPRESSION
-                || k == Kind.RECORD_CONSTRUCTOR_EXPRESSION || k == Kind.VARIABLE_EXPRESSION || k == Kind.CALL_EXPRESSION
-                || k == Kind.OP_EXPRESSION || k == Kind.FIELD_ACCESSOR_EXPRESSION || k == Kind.INDEX_ACCESSOR_EXPRESSION
-                || k == Kind.UNARY_EXPRESSION;
-    }
-
-    private <T> ArrayList<T> mkSingletonArrayList(T item) {
-        ArrayList<T> array = new ArrayList<T>(1);
-        array.add(item);
-        return array;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(TypeDecl td, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(RecordTypeDefinition tre, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(TypeReferenceExpression tre, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(NodegroupDecl ngd, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(LoadStatement stmtLoad, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(DropDatasetStatement del, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(CreateIndexStatement cis, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(OrderedListTypeDefinition olte, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(UnorderedListTypeDefinition ulte,
-            Mutable<ILogicalOperator> arg) throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
     public Pair<ILogicalOperator, LogicalVariable> visitMetaVariableClause(MetaVariableClause mc,
             Mutable<ILogicalOperator> tupSource) throws CompilationException {
         return new Pair<ILogicalOperator, LogicalVariable>(metaScopeOp.get(mc.getVar()), null);
@@ -1252,8 +101,6 @@
     @Override
     public Pair<ILogicalOperator, LogicalVariable> visitJoinClause(JoinClause jc, Mutable<ILogicalOperator> tupSource)
             throws CompilationException {
-        // Pair<ILogicalOperator, LogicalVariable> leftSide =
-        // jc.getLeftExpr().accept(this, tupSource);
         Mutable<ILogicalOperator> opRef = tupSource;
         Pair<ILogicalOperator, LogicalVariable> leftSide = null;
         for (Clause c : jc.getLeftClauses()) {
@@ -1261,8 +108,6 @@
             opRef = new MutableObject<ILogicalOperator>(leftSide.first);
         }
 
-        // Pair<ILogicalOperator, LogicalVariable> rightSide =
-        // jc.getRightExpr().accept(this, tupSource);
         opRef = tupSource;
         Pair<ILogicalOperator, LogicalVariable> rightSide = null;
         for (Clause c : jc.getRightClauses()) {
@@ -1271,21 +116,18 @@
         }
 
         Pair<ILogicalExpression, Mutable<ILogicalOperator>> whereCond =
-                aqlExprToAlgExpression(jc.getWhereExpr(), tupSource);
+                langExprToAlgExpression(jc.getWhereExpr(), tupSource);
 
         AbstractBinaryJoinOperator join;
         switch (jc.getKind()) {
-            case INNER: {
+            case INNER:
                 join = new InnerJoinOperator(new MutableObject<ILogicalExpression>(whereCond.first));
                 break;
-            }
-            case LEFT_OUTER: {
+            case LEFT_OUTER:
                 join = new LeftOuterJoinOperator(new MutableObject<ILogicalExpression>(whereCond.first));
                 break;
-            }
-            default: {
-                throw new IllegalStateException();
-            }
+            default:
+                throw new CompilationException(ErrorCode.COMPILATION_AQLPLUS_NO_SUCH_JOIN_TYPE);
         }
         join.getInputs().add(new MutableObject<ILogicalOperator>(leftSide.first));
         join.getInputs().add(new MutableObject<ILogicalOperator>(rightSide.first));
@@ -1302,195 +144,64 @@
         return new Pair<ILogicalOperator, LogicalVariable>(a, var);
     }
 
-    public void addOperatorToMetaScope(Identifier id, ILogicalOperator op) {
-        metaScopeOp.put(id, op);
-    }
 
     public void addVariableToMetaScope(Identifier id, LogicalVariable var) {
         metaScopeExp.put(id, var);
     }
 
-    private ILogicalExpression makeUnnestExpression(ILogicalExpression expr) {
-        switch (expr.getExpressionTag()) {
-            case VARIABLE: {
-                return new UnnestingFunctionCallExpression(
-                        FunctionUtil.getFunctionInfo(BuiltinFunctions.SCAN_COLLECTION),
-                        new MutableObject<ILogicalExpression>(expr));
-            }
-            case FUNCTION_CALL: {
-                AbstractFunctionCallExpression fce = (AbstractFunctionCallExpression) expr;
-                if (fce.getKind() == FunctionKind.UNNEST) {
-                    return expr;
-                } else {
-                    return new UnnestingFunctionCallExpression(
-                            FunctionUtil.getFunctionInfo(BuiltinFunctions.SCAN_COLLECTION),
-                            new MutableObject<ILogicalExpression>(expr));
-                }
-            }
-            default: {
-                return expr;
-            }
+    public void addOperatorToMetaScope(Identifier id, ILogicalOperator op) {
+        metaScopeOp.put(id, op);
+    }
+
+    // This method was overridden because of METAVARIABLE_EXPRESSION case.
+    @Override
+    protected Pair<ILogicalExpression, Mutable<ILogicalOperator>> langExprToAlgExpression(Expression expr,
+            Mutable<ILogicalOperator> topOpRef) throws CompilationException {
+        switch (expr.getKind()) {
+            case METAVARIABLE_EXPRESSION:
+                ILogicalExpression le = metaScopeExp.getVariableReferenceExpression(((VariableExpr) expr).getVar());
+                return new Pair<ILogicalExpression, Mutable<ILogicalOperator>>(le, topOpRef);
+            default:
+                return super.langExprToAlgExpression(expr, topOpRef);
         }
     }
 
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(InsertStatement insert, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
+    /**
+     * This class refers to the primary-key or other variables in the given plan in AQL+ statements level.
+     */
+    private class MetaScopeLogicalVariable {
+        private HashMap<Identifier, LogicalVariable> map = new HashMap<Identifier, LogicalVariable>();
+
+        public VariableReferenceExpression getVariableReferenceExpression(Identifier id) throws CompilationException {
+            LogicalVariable var = map.get(id);
+            if (var == null) {
+                throw new CompilationException(ErrorCode.COMPILATION_AQLPLUS_IDENTIFIER_NOT_FOUND, id.toString());
+            }
+            return new VariableReferenceExpression(var);
+        }
+
+        public void put(Identifier id, LogicalVariable var) {
+            map.put(id, var);
+        }
     }
 
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(DeleteStatement del, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
+    /**
+     * This class refers to the operators in the given plan in AQL+ statements level.
+     */
+    private class MetaScopeILogicalOperator {
+        private HashMap<Identifier, ILogicalOperator> map = new HashMap<Identifier, ILogicalOperator>();
+
+        public ILogicalOperator get(Identifier id) throws CompilationException {
+            ILogicalOperator op = map.get(id);
+            if (op == null) {
+                throw new CompilationException(ErrorCode.COMPILATION_AQLPLUS_IDENTIFIER_NOT_FOUND, id.toString());
+            }
+            return op;
+        }
+
+        public void put(Identifier id, ILogicalOperator op) {
+            map.put(id, op);
+        }
     }
 
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(UpdateStatement update, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(UpdateClause del, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(DataverseDecl dv, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(DatasetDecl dd, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(SetStatement ss, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(WriteStatement ws, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(CreateDataverseStatement del, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(IndexDropStatement del, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(NodeGroupDropStatement del, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(DataverseDropStatement del, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(TypeDropStatement del, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(DisconnectFeedStatement del, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(CreateFunctionStatement cfs, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(FunctionDropStatement del, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(ConnectFeedStatement del, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(FeedDropStatement del, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(CompactStatement del, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(CreatePrimaryFeedStatement del, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(CreateSecondaryFeedStatement del,
-            Mutable<ILogicalOperator> arg) throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(CreateFeedPolicyStatement cfps, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Pair<ILogicalOperator, LogicalVariable> visit(FeedPolicyDropStatement dfs, Mutable<ILogicalOperator> arg)
-            throws CompilationException {
-        // TODO Auto-generated method stub
-        return null;
-    }
 }
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
index 741ce56..c4cc486 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/LangExpressionToPlanTranslator.java
@@ -177,9 +177,17 @@
     private static final AtomicLong outputFileID = new AtomicLong(0);
     private static final String OUTPUT_FILE_PREFIX = "OUTPUT_";
 
-    public LangExpressionToPlanTranslator(MetadataProvider metadataProvider, int currentVarCounter)
+    public LangExpressionToPlanTranslator(MetadataProvider metadataProvider, int currentVarCounterValue)
             throws AlgebricksException {
-        this.context = new TranslationContext(new Counter(currentVarCounter));
+        this.context = new TranslationContext(new Counter(currentVarCounterValue));
+        this.metadataProvider = metadataProvider;
+        FormatUtils.getDefaultFormat().registerRuntimeFunctions(FunctionCollection.getFunctionDescriptorFactories());
+    }
+
+    // Keeps the given Counter if one is provided instead of a value.
+    public LangExpressionToPlanTranslator(MetadataProvider metadataProvider, Counter currentVarCounter)
+            throws AlgebricksException {
+        this.context = new TranslationContext(currentVarCounter);
         this.metadataProvider = metadataProvider;
         FormatUtils.getDefaultFormat().registerRuntimeFunctions(FunctionCollection.getFunctionDescriptorFactories());
     }
diff --git a/asterixdb/asterix-algebra/src/main/javacc/AQLPlus.jj b/asterixdb/asterix-algebra/src/main/javacc/AQLPlus.jj
deleted file mode 100644
index b44e1bc..0000000
--- a/asterixdb/asterix-algebra/src/main/javacc/AQLPlus.jj
+++ /dev/null
@@ -1,1701 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-options {
-
-
-       STATIC = false;
-
-}
-
-
-PARSER_BEGIN(AQLPlusParser)
-
-package org.apache.asterix.aqlplus.parser;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.asterix.common.exceptions.CompilationException;
-import org.apache.asterix.common.functions.FunctionSignature;
-import org.apache.asterix.lang.aql.clause.DistinctClause;
-import org.apache.asterix.lang.aql.clause.ForClause;
-import org.apache.asterix.lang.aql.clause.JoinClause;
-import org.apache.asterix.lang.aql.clause.MetaVariableClause;
-import org.apache.asterix.lang.aql.expression.FLWOGRExpression;
-import org.apache.asterix.lang.aql.expression.MetaVariableExpr;
-import org.apache.asterix.lang.aql.expression.UnionExpr;
-import org.apache.asterix.lang.common.base.Clause;
-import org.apache.asterix.lang.common.base.Expression;
-import org.apache.asterix.lang.common.base.Literal;
-import org.apache.asterix.lang.common.base.Statement;
-import org.apache.asterix.lang.common.clause.GroupbyClause;
-import org.apache.asterix.lang.common.clause.LetClause;
-import org.apache.asterix.lang.common.clause.LimitClause;
-import org.apache.asterix.lang.common.clause.OrderbyClause;
-import org.apache.asterix.lang.common.clause.WhereClause;
-import org.apache.asterix.lang.common.context.RootScopeFactory;
-import org.apache.asterix.lang.common.context.Scope;
-import org.apache.asterix.lang.common.expression.AbstractAccessor;
-import org.apache.asterix.lang.common.expression.CallExpr;
-import org.apache.asterix.lang.common.expression.FieldAccessor;
-import org.apache.asterix.lang.common.expression.FieldBinding;
-import org.apache.asterix.lang.common.expression.GbyVariableExpressionPair;
-import org.apache.asterix.lang.common.expression.IfExpr;
-import org.apache.asterix.lang.common.expression.IndexAccessor;
-import org.apache.asterix.lang.common.expression.ListConstructor;
-import org.apache.asterix.lang.common.expression.LiteralExpr;
-import org.apache.asterix.lang.common.expression.OperatorExpr;
-import org.apache.asterix.lang.common.expression.OrderedListTypeDefinition;
-import org.apache.asterix.lang.common.expression.QuantifiedExpression;
-import org.apache.asterix.lang.common.expression.RecordConstructor;
-import org.apache.asterix.lang.common.expression.RecordTypeDefinition;
-import org.apache.asterix.lang.common.expression.TypeExpression;
-import org.apache.asterix.lang.common.expression.TypeReferenceExpression;
-import org.apache.asterix.lang.common.expression.UnaryExpr;
-import org.apache.asterix.lang.common.expression.UnorderedListTypeDefinition;
-import org.apache.asterix.lang.common.expression.VariableExpr;
-import org.apache.asterix.lang.common.literal.DoubleLiteral;
-import org.apache.asterix.lang.common.literal.FalseLiteral;
-import org.apache.asterix.lang.common.literal.FloatLiteral;
-import org.apache.asterix.lang.common.literal.IntegerLiteral;
-import org.apache.asterix.lang.common.literal.LongIntegerLiteral;
-import org.apache.asterix.lang.common.literal.NullLiteral;
-import org.apache.asterix.lang.common.literal.StringLiteral;
-import org.apache.asterix.lang.common.literal.TrueLiteral;
-import org.apache.asterix.lang.common.parser.ScopeChecker;
-import org.apache.asterix.lang.common.statement.DataverseDecl;
-import org.apache.asterix.lang.common.statement.FunctionDecl;
-import org.apache.asterix.lang.common.statement.LoadStatement;
-import org.apache.asterix.lang.common.statement.Query;
-import org.apache.asterix.lang.common.statement.SetStatement;
-import org.apache.asterix.lang.common.statement.TypeDecl;
-import org.apache.asterix.lang.common.statement.WriteStatement;
-import org.apache.asterix.lang.common.struct.Identifier;
-import org.apache.asterix.lang.common.struct.QuantifiedPair;
-import org.apache.asterix.lang.common.struct.VarIdentifier;
-import org.apache.asterix.metadata.utils.MetadataConstants;
-import org.apache.hyracks.algebricks.common.utils.Pair;
-import org.apache.hyracks.algebricks.core.algebra.expressions.IndexedNLJoinExpressionAnnotation;
-
-
-public class AQLPlusParser extends ScopeChecker {
-
-/*
-    private void printHints(Token t) {
-       //System.err.println("token="+t.image+"\t special="+t.specialToken);
-       if (t.specialToken == null) return;
-       Token tmp_t = t.specialToken;
-       while (tmp_t.specialToken != null) tmp_t = tmp_t.specialToken;
-       while (tmp_t != null) {
-         System.out.println(tmp_t.image);
-         tmp_t = tmp_t.next;
-       }
-    }
-*/
-
-    private static final String HASH_GROUP_BY_HINT = "hash";
-    private static final String BROADCAST_JOIN_HINT = "bcast";
-    private static final String INMEMORY_HINT = "inmem";
-    private static final String INDEXED_NESTED_LOOP_JOIN_HINT = "indexnl";
-
-
-
-    private static String getHint(Token t) {
-       if (t.specialToken == null) {
-         return null;
-       }
-       String s = t.specialToken.image;
-       int n = s.length();
-       if (n < 2) {
-         return null;
-       }
-       return s.substring(1).trim();
-    }
-
-    public static void main(String args[]) throws ParseException, TokenMgrError, IOException, FileNotFoundException, CompilationException {
-            File file = new File(args[0]);
-            Reader fis = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
-            AQLPlusParser parser = new AQLPlusParser(fis);
-            List<Statement> st = parser.Statement();
-    }
-
-    public void initScope() {
-            scopeStack.push(RootScopeFactory.createRootScope(this));
-    }
-}
-
-PARSER_END(AQLPlusParser)
-
-
-List<Statement> Statement() throws ParseException:
-{
-  Query query = null;
-  // scopeStack.push(RootScopeFactory.createRootScope(this));
-  initScope();
-  List<Statement> decls = new ArrayList<Statement>();
-}
-{
-    (
-      (
-        (
-          "use"
-            {
-              decls.add(DataverseDeclaration());
-            }
-          | "declare"
-            (   "function" {
-                              decls.add(FunctionDeclaration());
-                           }
-              | "type"     {
-                              decls.add(TypeDeclaration());
-                           }
-            )
-          | "load" {
-                       decls.add(LoadStatement());
-                   }
-
-          | "write" {
-                       decls.add(WriteStatement());
-                    }
-          | "set" {
-                       decls.add(SetStatement());
-                    }
-          |
-            {
-             decls.add(Query()) ;
-           } ";"
-
-
-        )*
-      )
-
-      <EOF>
-    )
-    {
-
-     return decls;
-    }
-}
-
-Statement SetStatement() throws ParseException:
-{
-  String pn = null;
-  Statement stmt = null;
-}
-{
-  <IDENTIFIER>  { pn = token.image; }
-  <STRING_LITERAL>
-    { String pv = removeQuotesAndEscapes(token.image); }
-    ";"
-  {
-    return new SetStatement(pn, pv);
-  }
-}
-
-Statement WriteStatement() throws ParseException:
-{
-  Identifier nodeName = null;
-  String fileName = null;
-  Identifier datasetName = null;
-  Statement stmt = null;
-  Query query;
-}
-{
-  ( "output" "to"
-    <IDENTIFIER> { nodeName = new Identifier(token.image); }
-    ":" <STRING_LITERAL> {
-             fileName = removeQuotesAndEscapes(token.image);
-             stmt = new WriteStatement(nodeName, fileName, null);
-         }
-  ) ";"
-    {
-      return stmt;
-    }
-}
-
-DataverseDecl DataverseDeclaration() throws ParseException:
-{
-  Identifier dvName = null;
-}
-{
-  "dataverse" <IDENTIFIER> { defaultDataverse = token.image;}
-  ";"
-  {
-    return new DataverseDecl(new Identifier(defaultDataverse));
-  }
-}
-
-LoadStatement LoadStatement() throws ParseException:
-{
-  Identifier datasetName = null;
-  boolean alreadySorted = false;
-  String adapter;
-  Map<String,String> properties = new HashMap<String,String>();
-  String name;
-  String value;
-}
-{
-   <DATASET> <IDENTIFIER> { datasetName = new Identifier(token.image); }
-
-   "using"
-  (
-    <STRING_LITERAL>
-    {
-      adapter = removeQuotesAndEscapes(token.image);
-    }
-    <LEFTPAREN>
-    (
-      (
-        <LEFTPAREN>
-        (
-          <STRING_LITERAL>
-          {
-            name = removeQuotesAndEscapes(token.image);
-          }
-          "=" <STRING_LITERAL>
-          {
-            value = removeQuotesAndEscapes(token.image);
-          }
-        )
-        <RIGHTPAREN>
-        {
-            properties.put(name, value);
-        }
-      )
-      (
-        "," <LEFTPAREN>
-        (
-          <STRING_LITERAL>
-          {
-            name = removeQuotesAndEscapes(token.image);
-          }
-          "=" <STRING_LITERAL>
-          {
-            value = removeQuotesAndEscapes(token.image);
-          }
-        )
-        <RIGHTPAREN>
-        {
-            properties.put(name, value);
-        }
-      )*
-    )?
-    <RIGHTPAREN>
-  )
-
-    ("pre-sorted"
-      {  alreadySorted = true; }
-    )?
-
-  ";"
-  {
-     return new LoadStatement(null, datasetName, adapter, properties, alreadySorted);
-  }
-}
-
-TypeDecl TypeDeclaration() throws ParseException:
-{
-  Identifier ident;
-  TypeExpression typeExpr;
-}
-{
-  <IDENTIFIER>
-  {
-    ident = new Identifier(token.image.toString());
-  }
-  "as"
-  ( typeExpr = TypeExpr() )
-  {
-    return new TypeDecl(null, ident, typeExpr);
-  }
-}
-
-TypeExpression TypeExpr() throws ParseException:
-{
-  TypeExpression typeExpr = null;
-}
-{
-  (
-      typeExpr = RecordTypeDef()
-    | typeExpr = TypeReference()
-    | typeExpr = OrderedListTypeDef()
-    | typeExpr = UnorderedListTypeDef()
-  )
-  {
-    return typeExpr;
-  }
-}
-
-RecordTypeDefinition RecordTypeDef() throws ParseException:
-{
-  RecordTypeDefinition recType = new RecordTypeDefinition();
-  RecordTypeDefinition.RecordKind recordKind = null;
-}
-{
-  ( "closed" { recordKind = RecordTypeDefinition.RecordKind.CLOSED; }
-    | "open" { recordKind = RecordTypeDefinition.RecordKind.OPEN; } )?
-   "{"
-        (
-          RecordField(recType)
-          ( ","  RecordField(recType) )*
-        )?
-   "}"
-   {
-      if (recordKind == null) {
-        recordKind = RecordTypeDefinition.RecordKind.OPEN;
-      }
-      recType.setRecordKind(recordKind);
-      return recType;
-   }
-}
-
-void RecordField(RecordTypeDefinition recType) throws ParseException:
-{
-        String fieldName;
-        TypeExpression type = null;
-        boolean nullable = false;
-}
-{
-      <IDENTIFIER>
-          {
-         Token t = getToken(0);
-         fieldName = t.toString();
-        }
-      ":"
-      ( type =  TypeExpr() )
-      ("?" { nullable = true; } )?
-      {
-
-         recType.addField(fieldName, type, nullable);
-      }
-}
-
-TypeReferenceExpression TypeReference() throws ParseException:
-{}
-{
-  <IDENTIFIER>
-      {
-      Token t = getToken(0);
-      Identifier id;
-      if (t.toString().equalsIgnoreCase("int")) {
-          id = new Identifier("int64");
-      } else {
-          id = new Identifier(t.toString());
-      }
-          return new TypeReferenceExpression(new Pair<Identifier,Identifier>(null,id));
-    }
-}
-
-OrderedListTypeDefinition OrderedListTypeDef() throws ParseException:
-{
-  TypeExpression type = null;
-}
-{
-  "["
-    ( type =  TypeExpr() )
-  "]"
-  {
-    return new OrderedListTypeDefinition(type);
-  }
-}
-
-
-UnorderedListTypeDefinition UnorderedListTypeDef() throws ParseException:
-{
-  TypeExpression type = null;
-}
-{
-  "<"
-    ( type =  TypeExpr() )
-  ">"
-  {
-    return new UnorderedListTypeDefinition(type);
-  }
-}
-
-
-FunctionDecl FunctionDeclaration() throws ParseException:
-{
-  FunctionDecl funcDecl;
-  FunctionSignature signature;
-  String functionName;
-  int arity = 0;
-  List<VarIdentifier> paramList = new ArrayList<VarIdentifier>();
-  Expression funcBody;
-  VarIdentifier var = null;
-  createNewScope();
-}
-{
-
-    <IDENTIFIER>
-    {
-      Token t = getToken(0);
-      functionName = t.toString();
-      if (functionName.equalsIgnoreCase("int")) {
-          functionName = "int64";
-      }
-    }
-    <LEFTPAREN> (<VARIABLE>
-    {
-      var = new VarIdentifier();
-      var.setValue(getToken(0).toString());
-      paramList.add(var);
-      getCurrentScope().addNewVarSymbolToScope(var);
-      arity++;
-    }
-    ("," <VARIABLE>
-    {
-      var = new VarIdentifier();
-      var.setValue(getToken(0).toString());
-      paramList.add(var);
-      getCurrentScope().addNewVarSymbolToScope(var);
-      arity++;
-    })*)? <RIGHTPAREN> "{" funcBody = Expression() "}"
-
-    {
-      signature = new FunctionSignature(defaultDataverse, functionName, arity);
-      getCurrentScope().addFunctionDescriptor(signature, false);
-      funcDecl = new FunctionDecl(signature, paramList, funcBody);
-      return funcDecl;
-    }
-}
-
-Query Query()throws ParseException:
-{
-  Query query = new Query(false);
-  Expression expr;
-}
-{
-    expr = Expression()
-
-    {
-      query.setBody(expr);
-      return query;
-    }
-}
-
-
-
-Expression Expression():
-{
-  Expression expr = null;
-  Expression exprP = null;
-}
-{
-(
-
-//OperatorExpr | IfThenElse | FLWOGRExpression | QuantifiedExpression
-    expr = OperatorExpr()
-    | expr = IfThenElse()
-    | expr = FLWOGR()
-    | expr = QuantifiedExpression()
-
-
-)
-    {
-      return (exprP==null) ? expr : exprP;
-    }
-}
-
-
-
-Expression OperatorExpr()throws ParseException:
-{
-  OperatorExpr op = null;
-  Expression operand = null;
-}
-{
-    operand = AndExpr()
-    (
-
-      "or"
-      {
-        if (op == null) {
-          op = new OperatorExpr();
-          op.addOperand(operand);
-        op.setCurrentop(true);
-        }
-        Token t = getToken(0);
-        try{
-          op.addOperator(t.toString());
-        } catch (Exception e){
-          throw new ParseException(e.getMessage());
-        }
-    }
-
-    operand = AndExpr()
-    {
-      op.addOperand(operand);
-    }
-
-    )*
-
-    {
-      return op==null? operand: op;
-    }
-}
-
-Expression AndExpr()throws ParseException:
-{
-  OperatorExpr op = null;
-  Expression operand = null;
-}
-{
-    operand = RelExpr()
-    (
-
-      "and"
-      {
-        if (op == null) {
-          op = new OperatorExpr();
-          op.addOperand(operand);
-        op.setCurrentop(true);
-        }
-        Token t = getToken(0);
-        try{
-          op.addOperator(t.toString());
-        } catch (Exception e){
-          throw new ParseException(e.getMessage());
-        }
-    }
-
-    operand = RelExpr()
-    {
-      op.addOperand(operand);
-    }
-
-    )*
-
-    {
-      return op==null? operand: op;
-    }
-}
-
-
-
-Expression RelExpr()throws ParseException:
-{
-  OperatorExpr op = null;
-  Expression operand = null;
-  boolean broadcast = false;
-}
-{
-    operand = AddExpr()
-    {
-      if (operand instanceof VariableExpr) {
-        String hint = getHint(token);
-        if (hint != null && hint.equals(BROADCAST_JOIN_HINT)) {
-          broadcast = true;
-        }
-      }
-    }
-
-    (
-      LOOKAHEAD(2)( "<" | ">" | "<=" | ">=" | "=" | "!=" |"~=")
-        {
-          if (op == null) {
-            op = new OperatorExpr();
-            op.addOperand(operand, broadcast);
-          op.setCurrentop(true);
-          broadcast = false;
-          }
-          Token t = getToken(0);
-          try{
-            op.addOperator(t.toString());
-          } catch (Exception e){
-            throw new ParseException(e.getMessage());
-          }
-      }
-
-       operand = AddExpr()
-      {
-         broadcast = false;
-         if (operand instanceof VariableExpr) {
-           String hint = getHint(token);
-           if (hint != null && hint.equals(BROADCAST_JOIN_HINT)) {
-             broadcast = true;
-           }
-         }
-         op.addOperand(operand, broadcast);
-      }
-    )?
-
-     {
-       return op==null? operand: op;
-     }
-}
-
-Expression AddExpr()throws ParseException:
-{
-  OperatorExpr op = null;
-  Expression operand = null;
-}
-{
-    operand = MultExpr()
-
-    ( ("+" | "-")
-      {
-        if (op == null) {
-          op = new OperatorExpr();
-        op.addOperand(operand);
-        op.setCurrentop(true);
-        }
-        Token t = getToken(0);
-      try{
-          ((OperatorExpr)op).addOperator(t.toString());
-      } catch (Exception e){
-          throw new ParseException(e.getMessage());
-      }
-    }
-
-    operand = MultExpr()
-    {
-      op.addOperand(operand);
-    }
-    )*
-
-    {
-       return op==null? operand: op;
-     }
-}
-
-Expression MultExpr()throws ParseException:
-{
-  OperatorExpr op = null;
-  Expression operand = null;
-}
-{
-    operand = UnionExpr()
-
-    (( "*" | "/" | "%" | <CARET> | "idiv")
-      {
-        if (op == null) {
-          op = new OperatorExpr();
-        op.addOperand(operand);
-        op.setCurrentop(true);
-        }
-        Token t = getToken(0);
-        try{
-          op.addOperator(t.toString());
-        } catch (CompilationException e){
-          throw new ParseException(e.getMessage());
-        }
-    }
-    operand = UnionExpr()
-    {
-       op.addOperand(operand);
-    }
-    )*
-
-     {
-       return op==null?operand:op;
-     }
-}
-
-Expression UnionExpr() throws ParseException:
-{
-    UnionExpr union = null;
-    Expression operand1 = null;
-    Expression operand2 = null;
-}
-{
-   operand1 = UnaryExpr()
-   ("union"
-       (operand2 = UnaryExpr()) {
-          if (union == null) {
-             union = new UnionExpr();
-             union.addExpr(operand1);
-          }
-          union.addExpr(operand2);
-       } )*
-   {
-     return (union == null)? operand1: union;
-   }
-}
-
-Expression UnaryExpr() throws ParseException:
-{
-    UnaryExpr uexpr = null;
-    Expression expr = null;
-}
-{
-    ( ("+"|"-")
-    {
-          uexpr = new UnaryExpr();
-          try{
-            uexpr.setExprType(token.image);
-          } catch (CompilationException e){
-            throw new ParseException(e.getMessage());
-          }
-    }
-    )?
-
-    expr = ValueExpr()
-    {
-        if(uexpr!=null){
-            ((UnaryExpr)uexpr).setExpr(expr);
-            return uexpr;
-        }
-        else{
-            return expr;
-        }
-    }
-}
-
-Expression ValueExpr() throws ParseException:
-{
-  Expression expr;
-}
-{
-  expr = FieldOrIndexAccessor()
-  {
-    return expr;
-  }
-}
-
-
-Expression FieldOrIndexAccessor()throws ParseException:
-{
-  Expression expr = null;
-  Identifier ident = null;
-  AbstractAccessor fa = null;
-  Expression indexExpr = null;
-
-}
-{
-    ( expr = PrimaryExpr()
-
-    )
-
-
-    (
-    (
-          ident = Field()
-    {
-          if(fa == null)
-              fa = new FieldAccessor(expr, ident);
-          else
-              fa = new FieldAccessor(fa, ident);
-    }
-    )
-    | (
-        indexExpr = Index()
-        {
-          if(fa == null)
-            fa = new IndexAccessor(expr, indexExpr);
-          else
-            fa = new IndexAccessor(fa, indexExpr);
-        }
-    )
-    )*
-
-
-      {
-       return fa==null?expr:fa;
-     }
-}
-
-Identifier Field() throws ParseException:
-{
-  Identifier ident = null;
-
-}
-{
-  "." < IDENTIFIER >
-      {
-
-      ident = new Identifier();
-    ident.setValue(getToken(0).toString());
-
-      return ident;
-    }
-}
-
-Expression Index() throws ParseException:
-{
-    Expression expr = null;
-}
-{
-  "[" ( expr = Expression()
-    {
-        if(expr.getKind() == Expression.Kind.LITERAL_EXPRESSION)
-        {
-            Literal lit = ((LiteralExpr)expr).getValue();
-            if(lit.getLiteralType() != Literal.Type.INTEGER &&
-               lit.getLiteralType() != Literal.Type.LONG) {
-                throw new ParseException("Index should be an INTEGER");
-            }
-        }
-    }
-
-      | "?" // ANY
-
-      )
-
-   "]"
-    {
-      return expr;
-    }
-}
-
-
-Expression PrimaryExpr()throws ParseException:
-{
-  Expression expr = null;
-}
-{
-  //Literal | VariableRef | ListConstructor | RecordConstructor | FunctionCallExpr | ParenthesizedExpression
-    (
-      expr =Literal()
-       | expr = FunctionCallExpr()
-       | expr =VariableRef()
-
-    {
-      if(((VariableExpr)expr).getIsNewVar() == true)
-          throw new ParseException("can't find variable " + ((VariableExpr)expr).getVar());
-    }
-           | expr = ListConstructor()
-       | expr = RecordConstructor()
-       | expr = ParenthesizedExpression()
-       | expr = MetaVariableRef()
-    )
-     {
-       return expr;
-     }
-}
-
-Expression Literal() throws ParseException:
-{
-
-  LiteralExpr lit = new LiteralExpr();
-  Token t;
-}
-{
-(
-      <STRING_LITERAL>
-    {
-      t= getToken(0);
-      lit.setValue( new StringLiteral(removeQuotesAndEscapes(t.image)));
-    }
-
-      | <INTEGER_LITERAL>
-    {
-      t= getToken(0);
-      try {
-          lit.setValue(new IntegerLiteral(new Integer(t.image)));
-      } catch(NumberFormatException ex) {
-          lit.setValue(new LongIntegerLiteral(new Long(t.image)));
-      }
-    }
-     | < FLOAT_LITERAL >
-    {
-      t= getToken(0);
-      lit.setValue(new FloatLiteral(new Float(t.image)));
-    }
-     | < DOUBLE_LITERAL >
-    {
-      t= getToken(0);
-      lit.setValue(new DoubleLiteral(new Double(t.image)));
-    }
-      | <NULL>
-    {
-      t= getToken(0);
-      lit.setValue(NullLiteral.INSTANCE);
-    }
-        | <TRUE>
-    {
-      t= getToken(0);
-      lit.setValue(TrueLiteral.INSTANCE);
-    }
-        | <FALSE>
-    {
-      t= getToken(0);
-      lit.setValue(FalseLiteral.INSTANCE);
-    }
-)
-    {
-      return lit;
-    }
-}
-
-
-VariableExpr VariableRef() throws ParseException:
-{
-    VariableExpr varExp = new VariableExpr();
-    VarIdentifier var = new VarIdentifier();
-    Token t;
-}
-{
-      <VARIABLE>
-    {
-     t = getToken(0);//get current token
-     String varName = t.toString();
-     Identifier ident = lookupSymbol(varName);
-     if (isInForbiddenScopes(varName)) {
-       throw new ParseException("Inside limit clauses, it is disallowed to reference a variable having the same name as any variable bound in the same scope as the limit clause.");
-     }
-     if(ident != null) { // exist such ident
-       varExp.setIsNewVar(false);
-       varExp.setVar((VarIdentifier)ident);
-     } else {
-       varExp.setVar(var);
-     }
-     var.setValue(t.toString());
-     return varExp;
-    }
-}
-
-
-VariableExpr Variable() throws ParseException:
-{
-    VariableExpr varExp = new VariableExpr();
-    VarIdentifier var = new VarIdentifier();
-    Token t;
-}
-{
-      <VARIABLE>
-    {
-     t = getToken(0);//get current token
-     Identifier ident = lookupSymbol(t.toString());
-     if(ident != null) { // exist such ident
-       varExp.setIsNewVar(false);
-     }
-     varExp.setVar(var);
-     var.setValue(t.toString());
-     return varExp;
-    }
-}
-
-MetaVariableExpr MetaVariableRef() throws ParseException:
-{
-    MetaVariableExpr metaVarExp = new MetaVariableExpr();
-    VarIdentifier var = new VarIdentifier();
-    Token t;
-}
-{
-      <METAVARIABLE>
-    {
-     t = getToken(0);//get current token
-     metaVarExp.setVar(var);
-     var.setValue(t.toString());
-     return metaVarExp;
-    }
-}
-
-Expression ListConstructor() throws ParseException:
-{
-    Expression expr = null;
-}
-{
-    (
-        expr = OrderedListConstructor() | expr = UnorderedListConstructor()
-    )
-
-    {
-      return expr;
-    }
-}
-
-
-ListConstructor OrderedListConstructor() throws ParseException:
-{
-      ListConstructor expr = new ListConstructor();
-      Expression tmp = null;
-      List<Expression> exprList = new ArrayList<Expression>();
-      expr.setType(ListConstructor.Type.ORDERED_LIST_CONSTRUCTOR);
-}
-{
-
-    "["
-        ( tmp = Expression()
-            {
-              exprList.add(tmp);
-            }
-
-            ("," tmp = Expression() { exprList.add(tmp);  })*
-        )?
-
-    "]"
-
-    {
-      expr.setExprList(exprList);
-      return expr;
-    }
-}
-
-ListConstructor UnorderedListConstructor() throws ParseException:
-{
-      ListConstructor expr = new ListConstructor();
-      Expression tmp = null;
-      List<Expression> exprList = new ArrayList<Expression>();
-      expr.setType(ListConstructor.Type.UNORDERED_LIST_CONSTRUCTOR);
-}
-{
-
-    "{{" ( tmp = Expression()
-    {
-      exprList.add(tmp);
-    }
-    ("," tmp = Expression() { exprList.add(tmp);  })*)? "}}"
-    {
-      expr.setExprList(exprList);
-      return expr;
-    }
-}
-
-RecordConstructor RecordConstructor() throws ParseException:
-{
-      RecordConstructor expr = new RecordConstructor();
-      FieldBinding tmp = null;
-      List<FieldBinding> fbList = new ArrayList<FieldBinding>();
-}
-{
-    "{" (tmp = FieldBinding()
-    {
-      fbList.add(tmp);
-    }
-    ("," tmp = FieldBinding() { fbList.add(tmp);  })*)? "}"
-    {
-      expr.setFbList(fbList);
-      return expr;
-    }
-}
-
-FieldBinding FieldBinding() throws ParseException:
-{
-    FieldBinding fb = new FieldBinding();
-    Expression left, right;
-}
-{
-    left = Expression() ":" right = Expression()
-    {
-      fb.setLeftExpr(left);
-      fb.setRightExpr(right);
-      return fb;
-    }
-}
-
-Expression FunctionCallExpr() throws ParseException:
-{
-  CallExpr callExpr;
-  List<Expression> argList = new ArrayList<Expression>();
-  Expression tmp;
-  int arity = 0;
-  String funcName;
-  String dataverse;
-  String hint=null;
-  String id1=null;
-  String id2=null;
-}
-{
-    ( <IDENTIFIER> { dataverse = defaultDataverse; funcName = token.image;}
-     ("." <IDENTIFIER> { dataverse = funcName; funcName = token.image;})?
-     |
-     <DATASET> {dataverse = MetadataConstants.METADATA_DATAVERSE_NAME; funcName = getToken(0).toString();}
-    )
-    {
-       hint=getHint(token);
-    }
-     <LEFTPAREN> (tmp = Expression()
-     {
-       argList.add(tmp);
-       arity ++;
-     } ("," tmp = Expression() { argList.add(tmp); arity++; })*)? <RIGHTPAREN>
-
-     {
-       FunctionSignature signature = lookupFunctionSignature(dataverse, funcName.toString(), arity);
-             if(signature == null)
-             {
-                signature = new FunctionSignature(dataverse, funcName.toString(), arity);
-             }
-       callExpr = new CallExpr(signature,argList);
-       if (hint != null && hint.startsWith(INDEXED_NESTED_LOOP_JOIN_HINT)) {
-          callExpr.addHint(IndexedNLJoinExpressionAnnotation.INSTANCE);
-        }
-       return callExpr;
-     }
-}
-
-
-Expression ParenthesizedExpression() throws ParseException:
-{
-  Expression expr;
-}
-{
-    <LEFTPAREN> expr = Expression() <RIGHTPAREN>
-    {
-      return expr;
-    }
-}
-
-Expression IfThenElse() throws ParseException:
-{
-  Expression condExpr;
-  Expression thenExpr;
-  Expression elseExpr;
-  IfExpr ifExpr = new IfExpr();
-}
-{
-    "if" <LEFTPAREN> condExpr = Expression() <RIGHTPAREN> "then" thenExpr = Expression() "else" elseExpr = Expression()
-
-    {
-      ifExpr.setCondExpr(condExpr);
-      ifExpr.setThenExpr(thenExpr);
-      ifExpr.setElseExpr(elseExpr);
-      return ifExpr;
-    }
-}
-
-Expression  FLWOGR() throws ParseException:
-{
-    FLWOGRExpression flworg = new FLWOGRExpression();
-    List<Clause> clauseList = new ArrayList<Clause>();
-    Expression returnExpr;
-    Clause tmp;
-    createNewScope();
-}
-{
-     (tmp = ForClause()  {clauseList.add(tmp);} | tmp = LetClause() {clauseList.add(tmp);} | tmp = MetaVariableClause() {clauseList.add(tmp);})
-      (tmp = Clause() {clauseList.add(tmp);})* "return" returnExpr = Expression()
-
-     {
-       flworg.setClauseList(clauseList);
-       flworg.setReturnExpr(returnExpr);
-       removeCurrentScope();
-       return flworg;
-     }
-}
-
-List<Clause> Clauses() throws ParseException:
-{
-    List<Clause> clauses = new ArrayList<Clause>();
-    Clause c = null;
-}
-{
-    (
-        (
-            c = Clause() {
-                clauses.add(c);
-            }
-        )*
-    )
-    {
-        return clauses;
-    }
-}
-
-Clause Clause() throws ParseException :
-{
-  Clause clause;
-}
-{
-    (
-         clause = ForClause()
-       | clause = LetClause()
-       | clause = WhereClause()
-       | clause = OrderbyClause()
-       | clause = GroupClause()
-       | clause = LimitClause()
-       | clause = DistinctClause()
-       | clause = MetaVariableClause()
-       | clause = JoinClause()
-    )
-    {
-      return clause;
-    }
-}
-
-Clause MetaVariableClause() throws ParseException :
-{
-    MetaVariableClause mc = new MetaVariableClause();
-    VarIdentifier var = new VarIdentifier();
-    Token t;
-}
-{
-    <METAVARIABLECLAUSE>
-    {
-      t = getToken(0);
-      mc.setVar(var);
-      var.setValue(t.toString());
-      return mc;
-    }
-}
-
-Clause JoinClause() throws ParseException :
-{
-    Expression whereExpr;
-    List<Clause> leftClauses, rightClauses;
-    JoinClause.JoinKind kind = JoinClause.JoinKind.INNER;
-}
-{
-    ("join" | "loj" { kind = JoinClause.JoinKind.LEFT_OUTER; } )
-      <LEFTPAREN> <LEFTPAREN> leftClauses = Clauses() <RIGHTPAREN> ","
-      <LEFTPAREN> rightClauses = Clauses() <RIGHTPAREN> ","
-      whereExpr = Expression() <RIGHTPAREN>
-    {
-      JoinClause jc = new JoinClause(kind);
-      jc.setLeftClauses(leftClauses);
-      jc.setRightClauses(rightClauses);
-      jc.setWhereExpr(whereExpr);
-      return jc;
-    }
-}
-
-Clause ForClause()throws ParseException :
-{
-    ForClause fc = new ForClause();
-    VariableExpr varExp;
-    VariableExpr varPos = null;
-    Expression inExp;
-    extendCurrentScope();
-}
-{
-    "for" varExp = Variable()
-    {
-         getCurrentScope().addNewVarSymbolToScope(varExp.getVar());
-    }
-    ("at" varPos = Variable()
-      {
-         getCurrentScope().addNewVarSymbolToScope(varPos.getVar());
-      }
-     )?
-      "in" ( inExp = Expression() )
-    {
-      fc.setVarExpr(varExp);
-      fc.setInExpr(inExp);
-      if (varPos != null) {
-        fc.setPosExpr(varPos);
-      }
-      return fc;
-    }
-}
-
-Clause LetClause() throws ParseException:
-{
-    LetClause lc = new LetClause();
-    VariableExpr varExp;
-    Expression beExp;
-    extendCurrentScope();
-}
-{
-    "let" varExp = Variable() ":=" beExp = Expression()
-    {
-      getCurrentScope().addNewVarSymbolToScope(varExp.getVar());
-      lc.setVarExpr(varExp);
-      lc.setBindingExpr(beExp);
-      return lc;
-    }
-}
-
-Clause WhereClause()throws ParseException :
-{
-  WhereClause wc = new WhereClause();
-  Expression whereExpr;
-}
-{
-    "where" whereExpr = Expression()
-    {
-      wc.setWhereExpr(whereExpr);
-      return wc;
-    }
-}
-
-Clause OrderbyClause()throws ParseException :
-{
-  OrderbyClause oc = new OrderbyClause();
-  Expression orderbyExpr;
-  List<Expression> orderbyList = new ArrayList<Expression>();
-  List<OrderbyClause.OrderModifier> modifierList = new ArrayList<OrderbyClause.OrderModifier >();
-  int numOfOrderby = 0;
-}
-{
-  (
-    "order"
-      {
-         String hint = getHint(token);
-         if (hint != null && hint.startsWith(INMEMORY_HINT)) {
-           String splits[] = hint.split(" +");
-           int numFrames = Integer.parseInt(splits[1]);
-           int numTuples = Integer.parseInt(splits[2]);
-           oc.setNumFrames(numFrames);
-           oc.setNumTuples(numTuples);
-         }
-      }
-    "by" orderbyExpr = Expression()
-    {
-      orderbyList.add(orderbyExpr);
-      OrderbyClause.OrderModifier modif = OrderbyClause.OrderModifier.ASC;
-    }
-    ( ("asc" { modif = OrderbyClause.OrderModifier.ASC; })
-    | ("desc" { modif = OrderbyClause.OrderModifier.DESC; }))?
-    {
-      modifierList.add(modif);
-    }
-
-    ("," orderbyExpr = Expression()
-    {
-      orderbyList.add(orderbyExpr);
-      modif = OrderbyClause.OrderModifier.ASC;
-    }
-    ( ("asc" { modif = OrderbyClause.OrderModifier.ASC; })
-    | ("desc" { modif = OrderbyClause.OrderModifier.DESC; }))?
-    {
-      modifierList.add(modif);
-    }
-    )*
-)
-    {
-      oc.setModifierList(modifierList);
-      oc.setOrderbyList(orderbyList);
-      return oc;
-    }
-}
-Clause GroupClause()throws ParseException :
-{
-      GroupbyClause gbc = new GroupbyClause();
-      // GbyVariableExpressionPair pair = new GbyVariableExpressionPair();
-     List<GbyVariableExpressionPair> vePairList = new ArrayList<GbyVariableExpressionPair>();
-    List<GbyVariableExpressionPair> decorPairList = new ArrayList<GbyVariableExpressionPair>();
-    Map<Expression, VariableExpr> withVarMap= new HashMap<Expression, VariableExpr>();
-    VariableExpr var = null;
-    VariableExpr withVar = null;
-    Expression expr = null;
-    VariableExpr decorVar = null;
-    Expression decorExpr = null;
-}
-{
-      {
-        Scope newScope = extendCurrentScopeNoPush(true);
-        // extendCurrentScope(true);
-      }
-    "group"
-      {
-         String hint = getHint(token);
-         if (hint != null && hint.equals(HASH_GROUP_BY_HINT)) {
-           gbc.setHashGroupByHint(true);
-         }
-      }
-    "by" (LOOKAHEAD(2)  var = Variable()
-    {
-      newScope.addNewVarSymbolToScope(var.getVar());
-    } ":=")?
-    expr = Expression()
-       {
-         GbyVariableExpressionPair pair1 = new GbyVariableExpressionPair(var, expr);
-         vePairList.add(pair1);
-       }
-    ("," ( LOOKAHEAD(2) var = Variable()
-    {
-      newScope.addNewVarSymbolToScope(var.getVar());
-    } ":=")?
-        expr = Expression()
-         {
-           GbyVariableExpressionPair pair2 = new GbyVariableExpressionPair(var, expr);
-           vePairList.add(pair2);
-         }
-        )*
-    ("decor" decorVar = Variable() ":=" decorExpr = Expression()
-       {
-         newScope.addNewVarSymbolToScope(decorVar.getVar());
-         GbyVariableExpressionPair pair3 = new GbyVariableExpressionPair(decorVar, decorExpr);
-         decorPairList.add(pair3);
-       }
-      ("," "decor" decorVar = Variable() ":=" decorExpr = Expression()
-           {
-             newScope.addNewVarSymbolToScope(decorVar.getVar());
-             GbyVariableExpressionPair pair4 = new GbyVariableExpressionPair(decorVar, decorExpr);
-             decorPairList.add(pair4);
-           }
-       )*
-    )?
-    "with" withVar = VariableRef()
-    {
-      if(withVar.getIsNewVar()==true)
-          throw new ParseException("can't find variable " + withVar.getVar());
-      withVarMap.put(withVar, withVar);
-      newScope.addNewVarSymbolToScope(withVar.getVar());
-    }
-    ("," withVar = VariableRef()
-    {
-      if(withVar.getIsNewVar()==true)
-          throw new ParseException("can't find variable " + withVar.getVar());
-      withVarMap.put(withVar, withVar);
-      newScope.addNewVarSymbolToScope(withVar.getVar());
-    })*
-    {
-      gbc.setGbyPairList(vePairList);
-      gbc.setDecorPairList(decorPairList);
-      gbc.setWithVarMap(withVarMap);
-      replaceCurrentScope(newScope);
-      return gbc;
-    }
-}
-
-
-LimitClause LimitClause() throws ParseException:
-{
-    LimitClause lc = new LimitClause();
-    Expression expr;
-    pushForbiddenScope(getCurrentScope());
-}
-{
-    "limit" expr = Expression()    { lc.setLimitExpr(expr);    }
-    ("offset" expr = Expression() { lc.setOffset(expr);    })?
-
-  {
-    popForbiddenScope();
-    return lc;
-  }
-}
-
-DistinctClause DistinctClause() throws ParseException:
-{
-  List<Expression> exprs = new ArrayList<Expression>();
-  Expression expr;
-}
-{
-  "distinct" "by" expr = Expression()
-  {
-    exprs.add(expr);
-  }
-  ("," expr = Expression()
-      {
-          exprs.add(expr);
-      }
-  )*
-  {
-      return new DistinctClause(exprs);
-  }
-}
-
-
-QuantifiedExpression QuantifiedExpression()throws ParseException:
-{
-  QuantifiedExpression qc = new QuantifiedExpression();
-  List<QuantifiedPair> quantifiedList = new ArrayList<QuantifiedPair>();
-  Expression satisfiesExpr;
-  VariableExpr var;
-  Expression inExpr;
-  QuantifiedPair pair;
-}
-{
-  {
-    createNewScope();
-  }
-
-   (      ("some"  {  qc.setQuantifier(QuantifiedExpression.Quantifier.SOME);    })
-        | ("every" {  qc.setQuantifier(QuantifiedExpression.Quantifier.EVERY);    }))
-    var = Variable() "in" inExpr = Expression()
-    {
-      pair = new QuantifiedPair(var, inExpr);
-      getCurrentScope().addNewVarSymbolToScope(var.getVar());
-      quantifiedList.add(pair);
-    }
-    (
-    "," var = Variable() "in" inExpr = Expression()
-    {
-      pair = new QuantifiedPair(var, inExpr);
-      getCurrentScope().addNewVarSymbolToScope(var.getVar());
-      quantifiedList.add(pair);
-    }
-    )*
-     "satisfies" satisfiesExpr = Expression()
-     {
-       qc.setSatisfiesExpr(satisfiesExpr);
-       qc.setQuantifiedList(quantifiedList);
-       removeCurrentScope();
-       return qc;
-     }
-}
-
-TOKEN_MGR_DECLS:
-{
-        public int commentDepth = 0;
-}
-
-<DEFAULT>
-TOKEN :
-{
-   <CARET : "^"  >
-}
-
-<DEFAULT>
-TOKEN :
-{
-   <DATASET : "dataset"  >
-}
-
-<DEFAULT>
-TOKEN :
-{
-   <LEFTPAREN : "("  >
-}
-
-<DEFAULT>
-TOKEN :
-{
-   <RIGHTPAREN : ")"  >
-}
-
-
-<DEFAULT>
-TOKEN :
-{
-    <INTEGER_LITERAL : (<DIGIT>)+ >
-}
-
-
-<DEFAULT>
-TOKEN :
-{
-    <NULL : "null">
-}
-
-<DEFAULT>
-TOKEN :
-{
-    <TRUE : "true">
-}
-
-<DEFAULT>
-TOKEN :
-{
-    <FALSE : "false">
-}
-
-<DEFAULT>
-TOKEN :
-{
-    <#DIGIT : ["0" - "9"]>
-}
-
-
-TOKEN:
-{
-  < DOUBLE_LITERAL: <INTEGER>
-        | <INTEGER> ( "." <INTEGER> )?
-        | "." <INTEGER>
-  >
-  |
-  < FLOAT_LITERAL: <INTEGER> ( "f" | "F" )
-        | <INTEGER> ( "." <INTEGER> ( "f" | "F" ) )?
-        | "." <INTEGER> ( "f" | "F" )
-  >
-  |
-  <INTEGER : (<DIGIT>)+ >
-}
-
-<DEFAULT>
-TOKEN :
-{
-    <#LETTER : ["A" - "Z", "a" - "z"]>
-}
-
-<DEFAULT>
-TOKEN :
-{
-    <SPECIALCHARS : ["$", "_", "-"]  >
-}
-
-<DEFAULT>
-TOKEN :
-{
-    <STRING_LITERAL : ("\"" (<EscapeQuot> | ~["\""])* "\"") | ("\'"(<EscapeApos> | ~["\'"])* "\'")>
-    |
-    < #EscapeQuot: "\\\"" >
-    |
-    < #EscapeApos: "\\\'" >
-}
-
-<DEFAULT>
-TOKEN :
-{
-    <IDENTIFIER : (<LETTER>)+ (<LETTER> | <DIGIT> | <SPECIALCHARS>)*>
-}
-
-<DEFAULT>
-TOKEN :
-{
-    <VARIABLE : "$" <IDENTIFIER> >
-}
-
-<DEFAULT>
-TOKEN :
-{
-    <METAVARIABLECLAUSE : "#" <IDENTIFIER> >
-}
-
-<DEFAULT>
-TOKEN :
-{
-    <METAVARIABLE : "$$" <IDENTIFIER> >
-}
-
-SKIP:
-{
-    " "
-|   "\t"
-|   "\r"
-|   "\n"
-}
-
-SKIP:
-{
-    <"//" (~["\n"])* "\n">
-}
-
-SKIP:
-{
-    <"//" (~["\n","\r"])* ("\n"|"\r"|"\r\n")?>
-}
-
-
-SKIP:
-{
-        <"/*"> {commentDepth=1;}: INSIDE_COMMENT
-}
-
-<INSIDE_COMMENT>
-SPECIAL_TOKEN:
-{
-       <"+"(" ")*(~["/","*"])*>
-}
-
-<INSIDE_COMMENT>
-SKIP:
-{
-        <"/*"> {commentDepth++;}
-}
-
-<INSIDE_COMMENT>
-SKIP:
-{
-        <"*/"> {commentDepth--; if (commentDepth == 0) SwitchTo(DEFAULT);}
-|       <~[]>
-}
diff --git a/asterixdb/asterix-algebra/src/main/javacc/AQLPlusExtension.jj b/asterixdb/asterix-algebra/src/main/javacc/AQLPlusExtension.jj
new file mode 100644
index 0000000..4024342
--- /dev/null
+++ b/asterixdb/asterix-algebra/src/main/javacc/AQLPlusExtension.jj
@@ -0,0 +1,175 @@
+// This is not a complete javacc file.
+// This file is used by asterix-grammar-extension-maven-plugin to extend the AQL grammar to AQL+ grammar.
+// For more details about how to use this plugin, refer to asterix-grammar-extension-maven-plugin.
+
+// If you want to put an additional import, just add import statements like the following.
+// import package name
+import org.apache.asterix.lang.aql.clause.JoinClause;
+import org.apache.asterix.lang.aql.clause.MetaVariableClause;
+import org.apache.asterix.lang.aql.expression.MetaVariableExpr;
+
+// To remove an import, use the keyword unimport
+// unimport package name
+
+// If you want to add a method in the class definition (before PARSER_END), use the following phrase and attach
+// new method right after the phrase.
+// @new_at_the_end
+@new_at_the_class_def
+    public void initScope() {
+            scopeStack.push(RootScopeFactory.createRootScope(this));
+    }
+
+// Merging of non-terminals can only be done on non-terminals which conform to the following structure.
+// Content will simply be prepended or appended to the base blocks.
+// Note: refrain from using the strings "before:" and "after:" in the merge areas as that will break the merge.
+// As a workaround, you can always override
+// one additional possible change is direct replacement and it can be done through the followin syntax:
+// @merge replace "base phrase" with "extension phrase" true/false
+// Here, true/false tells whether the tool needs to process the three blocks.
+// If true, like normal @merge case, before and after clause in each block will be processed
+// after "base phrase" in the blocks have been replaced with "new phrase".
+// If false, then it just expects the blank form that consists of three blocks and not process them.
+// Only, "base phrase" in the blocks will be replaced with "new phrase".
+@merge
+Clause Clause() throws ParseException :
+{
+  // merge area 1
+  before:
+  after:
+}
+{
+  (
+    // merge area 2
+    before:
+    after:    | clause = MetaVariableClause()
+              | clause = JoinClause())
+  {
+    // merge area 3
+  }
+}
+
+@merge
+Expression PrimaryExpr()throws ParseException:
+{
+  // merge area 1
+  before:
+  after:
+}
+{
+  (
+    // merge area 2
+    before:
+    after:    | expr = MetaVariableRef())
+  {
+    // merge area 3
+  }
+}
+
+// In the following case, all instances of "tmp = LetClause() {clauseList.add(tmp);}" will be replaced
+// with "tmp = LetClause() {clauseList.add(tmp);} | tmp = MetaVariableClause() {clauseList.add(tmp);}".
+// Also, we don't check "before:" and "after:" section of each area. That check will be ignored since
+// the last parameter is set to false.
+@merge replace "tmp = LetClause() {clauseList.add(tmp);}" with "tmp = LetClause() {clauseList.add(tmp);} | tmp = MetaVariableClause() {clauseList.add(tmp);}" false
+Expression FLWOGR() throws ParseException:
+{
+  // merge area 1
+}
+{
+    (
+    // merge area 2
+    )
+    {
+      // merge area 3
+    }
+}
+
+// The default option when you don't specify any @optiontype.
+// Adding a new node. if a node exists, it will throw an exception.
+@new
+Clause MetaVariableClause() throws ParseException :
+{
+    MetaVariableClause mc = new MetaVariableClause();
+    VarIdentifier var = new VarIdentifier();
+}
+{
+    <METAVARIABLECLAUSE>
+    {
+      mc.setVar(var);
+      var.setValue(token.image);
+      return mc;
+    }
+}
+
+@new
+MetaVariableExpr MetaVariableRef() throws ParseException:
+{
+    MetaVariableExpr metaVarExp = new MetaVariableExpr();
+    VarIdentifier var = new VarIdentifier();
+}
+{
+      <METAVARIABLE>
+    {
+     metaVarExp.setVar(var);
+     var.setValue(token.image);
+     return metaVarExp;
+    }
+}
+
+@new
+Clause JoinClause() throws ParseException :
+{
+    Expression whereExpr;
+    List<Clause> leftClauses, rightClauses;
+    JoinClause.JoinKind kind = JoinClause.JoinKind.INNER;
+}
+{
+    ("join" | "loj" { kind = JoinClause.JoinKind.LEFT_OUTER; } )
+      <LEFTPAREN> <LEFTPAREN> leftClauses = Clauses() <RIGHTPAREN> <COMMA>
+      <LEFTPAREN> rightClauses = Clauses() <RIGHTPAREN> <COMMA>
+      whereExpr = Expression() <RIGHTPAREN>
+    {
+      JoinClause jc = new JoinClause(kind);
+      jc.setLeftClauses(leftClauses);
+      jc.setRightClauses(rightClauses);
+      jc.setWhereExpr(whereExpr);
+      return jc;
+    }
+}
+
+@new
+List<Clause> Clauses() throws ParseException:
+{
+    List<Clause> clauses = new ArrayList<Clause>();
+    Clause c = null;
+}
+{
+    (
+        (
+            c = Clause() {
+                clauses.add(c);
+            }
+        )*
+    )
+    {
+        return clauses;
+    }
+}
+
+// Overriding a non-terminal. if exists in base, it will be overriden, otherwise, it will be added.
+// @override
+
+
+// If something needs to be added at the end of file, you can use @new_at_the_end like the following.
+@new_at_the_end
+<DEFAULT,IN_DBL_BRACE>
+TOKEN :
+{
+    <METAVARIABLE : "$$" <IDENTIFIER> >
+}
+
+@new_at_the_end
+<DEFAULT,IN_DBL_BRACE>
+TOKEN :
+{
+   <METAVARIABLECLAUSE : "##" <IDENTIFIER> >
+}
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
index 5ae313d..dd7c8e4 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/exceptions/ErrorCode.java
@@ -77,6 +77,8 @@
     public static final int COMPILATION_PRIMARY_KEY_CANNOT_BE_NULLABLE = 1021;
     public static final int COMPILATION_ILLEGAL_PRIMARY_KEY_TYPE = 1022;
     public static final int COMPILATION_CANT_DROP_ACTIVE_DATASET = 1023;
+    public static final int COMPILATION_AQLPLUS_IDENTIFIER_NOT_FOUND = 1024;
+    public static final int COMPILATION_AQLPLUS_NO_SUCH_JOIN_TYPE = 1025;
 
     // Feed errors
     public static final int DATAFLOW_ILLEGAL_STATE = 3001;
diff --git a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
index 440e2d3..3e96972 100644
--- a/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
+++ b/asterixdb/asterix-common/src/main/resources/asx_errormsg/en.properties
@@ -62,6 +62,8 @@
 1021 = The primary key field \"%1$s\" cannot be nullable
 1022 = Field of type %1$s cannot be used as a primary key field
 1023 = Can't drop dataset %1$s since it is connected to active entity: %2$s
+1024 = Identifier %1$s is not found in AQL+ meta-scope
+1025 = There is no such join type in AQL+
 
 # Feed Errors
 3001 = Illegal state.
diff --git a/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj b/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj
index 4b2091c..e5af86f 100644
--- a/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj
+++ b/asterixdb/asterix-lang-aql/src/main/javacc/AQL.jj
@@ -2302,6 +2302,9 @@
     }
 }
 
+// Note: if you modify this part: "tmp = LetClause() {clauseList.add(tmp);}", please also apply the necessary
+// change to the AQLPlusExtension.jj file since it refers to this string part and may behave incorrectly if this
+// part is modified. For more details, please refer to AQLPlusExtension.jj file.
 Expression FLWOGR() throws ParseException:
 {
     FLWOGRExpression flworg = new FLWOGRExpression();