ATLAS-2229: DSL implementation using Antlr

Signed-off-by: Madhan Neethiraj <mad...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/atlas/repo
Commit: http://git-wip-us.apache.org/repos/asf/atlas/commit/5bd5327c
Tree: http://git-wip-us.apache.org/repos/asf/atlas/tree/5bd5327c
Diff: http://git-wip-us.apache.org/repos/asf/atlas/diff/5bd5327c

Branch: refs/heads/master
Commit: 5bd5327c40e6dfc4454c2311165d5ee6b75f109a
Parents: 71a3087
Author: Ashutosh Mestry <ames...@hortonworks.com>
Authored: Sun Dec 10 12:51:34 2017 -0800
Committer: Madhan Neethiraj <mad...@apache.org>
Committed: Tue Dec 12 10:38:36 2017 -0800

----------------------------------------------------------------------
 3party-licenses/Antlr-LICENSE                   |   19 +
 pom.xml                                         |   29 +
 repository/pom.xml                              |    5 +
 .../atlas/discovery/EntityDiscoveryService.java |   91 +-
 .../java/org/apache/atlas/query/DSLVisitor.java |  127 +
 .../org/apache/atlas/query/Expressions.java     |   24 +-
 .../org/apache/atlas/query/GremlinQuery.java    |   28 +-
 .../apache/atlas/query/GremlinTranslator.java   |   15 +-
 .../org/apache/atlas/query/QueryParser.java     |   37 +-
 .../org/apache/atlas/query/QueryProcessor.java  |  553 +++-
 .../atlas/query/SelectExpressionHelper.java     |   30 -
 .../apache/atlas/query/antlr4/AtlasDSLLexer.g4  |  180 ++
 .../atlas/query/antlr4/AtlasDSLLexer.java       |  355 +++
 .../atlas/query/antlr4/AtlasDSLLexer.tokens     |   59 +
 .../apache/atlas/query/antlr4/AtlasDSLParser.g4 |  117 +
 .../atlas/query/antlr4/AtlasDSLParser.java      | 2441 ++++++++++++++++++
 .../atlas/query/antlr4/AtlasDSLParser.tokens    |   59 +
 .../query/antlr4/AtlasDSLParserBaseVisitor.java |  294 +++
 .../query/antlr4/AtlasDSLParserVisitor.java     |  253 ++
 .../org/apache/atlas/query/BasicTestSetup.java  |  358 +++
 .../org/apache/atlas/query/DSLQueriesTest.java  |  675 +++++
 .../apache/atlas/query/QueryProcessorTest.java  |  274 ++
 .../services/EntityDiscoveryServiceTest.java    |   56 +
 .../org/apache/atlas/examples/QuickStartV2.java |   42 +-
 24 files changed, 5993 insertions(+), 128 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/atlas/blob/5bd5327c/3party-licenses/Antlr-LICENSE
----------------------------------------------------------------------
diff --git a/3party-licenses/Antlr-LICENSE b/3party-licenses/Antlr-LICENSE
new file mode 100644
index 0000000..1aaf8a8
--- /dev/null
+++ b/3party-licenses/Antlr-LICENSE
@@ -0,0 +1,19 @@
+http://www.antlr.org/license.html
+
+[The BSD License]
+Copyright (c) 2012 Terence Parr and Sam Harwell
+All rights reserved.
+Redistribution and use in source and binary forms, with or without 
modification, are permitted provided that the following conditions are met:
+Redistributions of source code must retain the above copyright notice, this 
list of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this 
list of conditions and the following disclaimer in the documentation and/or 
other materials provided with the distribution.
+Neither the name of the author nor the names of its contributors may be used 
to endorse or promote products derived from this software without specific 
prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Developer's Certificate of Origin
+All contributors to ANTLR v4 must formally agree to abide by the certificate 
of origin by signing on the bottom of that document. To contribute:
+fork the ANTLR v4 github repository
+make your changes
+[first time contributors]: sign contributors.txt by adding your github userid, 
full name, email address (you can obscure your e-mail, but it must be 
computable by human), and date.
+commit your changes
+send a pull request
+After you have signed once, you don't have to sign future pull requests. We 
can merge by simply checking to see your name is in the contributors file.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/5bd5327c/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 233506c..3b9a464 100644
--- a/pom.xml
+++ b/pom.xml
@@ -552,6 +552,7 @@
         <javax.servlet.version>3.1.0</javax.servlet.version>
         <guava.version>19.0</guava.version>
         <scala.version>2.11.8</scala.version>
+        <antlr4.version>4.7</antlr4.version>
 
         <!-- Needed for hooks -->
         <aopalliance.version>1.0</aopalliance.version>
@@ -565,6 +566,7 @@
         <paranamer.version>2.7</paranamer.version>
         <zkclient.version>0.8</zkclient.version>
         <enunciate-maven-plugin.version>2.10.1</enunciate-maven-plugin.version>
+        <antlr4.plugin.version>4.5</antlr4.plugin.version>
 
         <PermGen>64m</PermGen>
         <MaxPermGen>512m</MaxPermGen>
@@ -791,6 +793,12 @@
     <dependencyManagement>
         <dependencies>
             <dependency>
+                <groupId>org.antlr</groupId>
+                <artifactId>antlr4-runtime</artifactId>
+                <version>${antlr4.version}</version>
+            </dependency>
+
+            <dependency>
                 <groupId>com.google.guava</groupId>
                 <artifactId>guava</artifactId>
                 <version>${guava.version}</version>
@@ -1609,6 +1617,26 @@
         <pluginManagement>
             <plugins>
                 <plugin>
+                    <groupId>org.antlr</groupId>
+                    <artifactId>antlr4-maven-plugin</artifactId>
+                    <version>${antlr4.plugin.version}</version>
+                    <configuration>
+                        <listener>false</listener>
+                        <visitor>true</visitor>
+                    </configuration>
+                    <executions>
+                        <execution>
+                            <goals>
+                                <goal>antlr4</goal>
+                            </goals>
+                            <phase>generate-sources</phase>
+                            <configuration>
+                                
<outputDirectory>src/main/java</outputDirectory>
+                            </configuration>
+                        </execution>
+                    </executions>
+                </plugin>
+                <plugin>
                     <groupId>org.codehaus.mojo</groupId>
                     <artifactId>buildnumber-maven-plugin</artifactId>
                     <version>1.4</version>
@@ -1871,6 +1899,7 @@
                     <useEclipseDefaultExcludes>true</useEclipseDefaultExcludes>
                     <excludeSubProjects>true</excludeSubProjects>
                     <excludes>
+                        <exclude>**/antlr4/**</exclude>
                         <exclude>**/dependency-reduced-pom.xml</exclude>
                         <exclude>**/javax.script.ScriptEngineFactory</exclude>
                         <exclude>.reviewboardrc</exclude>

http://git-wip-us.apache.org/repos/asf/atlas/blob/5bd5327c/repository/pom.xml
----------------------------------------------------------------------
diff --git a/repository/pom.xml b/repository/pom.xml
index 35b74e3..7096ddf 100755
--- a/repository/pom.xml
+++ b/repository/pom.xml
@@ -59,6 +59,11 @@
         </dependency>
 
         <dependency>
+            <groupId>org.antlr</groupId>
+            <artifactId>antlr4-runtime</artifactId>
+        </dependency>
+
+        <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
         </dependency>

http://git-wip-us.apache.org/repos/asf/atlas/blob/5bd5327c/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
----------------------------------------------------------------------
diff --git 
a/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
 
b/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
index 67aeb30..cbc08b8 100644
--- 
a/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
+++ 
b/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
@@ -33,15 +33,12 @@ import org.apache.atlas.model.discovery.SearchParameters;
 import org.apache.atlas.model.instance.AtlasEntityHeader;
 import org.apache.atlas.model.instance.AtlasObjectId;
 import org.apache.atlas.model.profile.AtlasUserSavedSearch;
-import org.apache.atlas.query.Expressions.AliasExpression;
 import org.apache.atlas.query.Expressions.Expression;
-import org.apache.atlas.query.Expressions.SelectExpression;
 import org.apache.atlas.query.GremlinQuery;
 import org.apache.atlas.query.GremlinTranslator;
 import org.apache.atlas.query.QueryParams;
 import org.apache.atlas.query.QueryParser;
 import org.apache.atlas.query.QueryProcessor;
-import org.apache.atlas.query.SelectExpressionHelper;
 import org.apache.atlas.repository.Constants;
 import org.apache.atlas.repository.graph.GraphBackedSearchIndexer;
 import org.apache.atlas.repository.graph.GraphHelper;
@@ -149,29 +146,29 @@ public class EntityDiscoveryService implements 
AtlasDiscoveryService {
                         LOG.warn("searchUsingDslQuery({}): expected an 
AtlasVertex; found unexpected entry in result {}", dslQuery, element);
                     }
                 }
-            } else if (firstElement instanceof Map &&
-                       (((Map)firstElement).containsKey("theInstance") || 
((Map)firstElement).containsKey("theTrait"))) {
+            } else if (gremlinQuery.hasSelectList()) {
+                ret.setAttributes(toAttributesResult(queryResult, 
gremlinQuery));
+            } else if (firstElement instanceof Map) {
                 for (Object element : queryResult) {
                     if (element instanceof Map) {
                         Map map = (Map)element;
 
-                        if (map.containsKey("theInstance")) {
-                            Object value = map.get("theInstance");
+                        for (Object key : map.keySet()) {
+                            Object value = map.get(key);
 
                             if (value instanceof List && 
CollectionUtils.isNotEmpty((List)value)) {
-                                Object entry = ((List)value).get(0);
-
-                                if (entry instanceof AtlasVertex) {
-                                    
ret.addEntity(entityRetriever.toAtlasEntityHeader((AtlasVertex)entry));
+                                for (Object o : (List) value) {
+                                    Object entry = o;
+                                    if (entry instanceof AtlasVertex) {
+                                        
ret.addEntity(entityRetriever.toAtlasEntityHeader((AtlasVertex) entry));
+                                    }
                                 }
                             }
                         }
-                    } else {
-                        LOG.warn("searchUsingDslQuery({}): expected a trait 
result; found unexpected entry in result {}", dslQuery, element);
                     }
                 }
-            } else if (gremlinQuery.hasSelectList()) {
-                ret.setAttributes(toAttributesResult(queryResult, 
gremlinQuery));
+            } else {
+                LOG.warn("searchUsingDslQuery({}/{}): found unexpected entry 
in result {}", dslQuery, dslQuery, gremlinQuery.queryStr());
             }
         }
 
@@ -681,15 +678,16 @@ public class EntityDiscoveryService implements 
AtlasDiscoveryService {
     }
 
     private GremlinQuery toGremlinQuery(String query, int limit, int offset) 
throws AtlasBaseException {
-        QueryParams params = validateSearchParams(limit, offset);
-        Expression expression = QueryParser.apply(query, params);
+        QueryParams params     = validateSearchParams(limit, offset);
+        Expression  expression = QueryParser.apply(query, params);
 
         if (expression == null) {
             throw new AtlasBaseException(DISCOVERY_QUERY_FAILED, query);
         }
 
-        Expression   validExpression = QueryProcessor.validate(expression);
-        GremlinQuery gremlinQuery    = new 
GremlinTranslator(validExpression).translate();
+        QueryProcessor queryProcessor  = new QueryProcessor(typeRegistry);
+        Expression     validExpression = queryProcessor.validate(expression);
+        GremlinQuery   gremlinQuery    = new GremlinTranslator(queryProcessor, 
validExpression).translate();
 
         if (LOG.isDebugEnabled()) {
             LOG.debug("Translated Gremlin Query: {}", gremlinQuery.queryStr());
@@ -722,41 +720,68 @@ public class EntityDiscoveryService implements 
AtlasDiscoveryService {
 
     private AttributeSearchResult toAttributesResult(List results, 
GremlinQuery query) {
         AttributeSearchResult ret = new AttributeSearchResult();
-        List<String> names = new ArrayList<>();
-        List<List<Object>> values = new ArrayList<>();
+        List<String> names = extractNames(results);
+        List<List<Object>> values = extractValues(results);
 
-        // extract select attributes from gremlin query
-        SelectExpression selectExpr = 
SelectExpressionHelper.extractSelectExpression(query.expr());
-        if (selectExpr != null) {
-            List<AliasExpression> aliases = selectExpr.toJavaList();
+        ret.setName(names);
+        ret.setValues(values);
+        return ret;
+    }
 
-            if (CollectionUtils.isNotEmpty(aliases)) {
-                for (AliasExpression alias : aliases) {
-                    names.add(alias.alias());
+    private List<String> extractNames(List results) {
+        List<String> names = new ArrayList<>();
+        for (Object obj : results) {
+            if (obj instanceof Map) {
+                Map map = (Map) obj;
+                if (MapUtils.isNotEmpty(map)) {
+                    for (Object key : map.keySet()) {
+                        names.add((String) key);
+                    }
+                    return names;
+                }
+            } else if (obj instanceof List) {
+                List list = (List) obj;
+                if (CollectionUtils.isNotEmpty(list)) {
+                    for(Object o : list) {
+                        names.add((String) o);
+                    }
                 }
-                ret.setName(names);
             }
         }
 
+        return names;
+    }
+
+    private List<List<Object>> extractValues(List results) {
+        List<List<Object>> values = new ArrayList<>();
+
         for (Object obj : results) {
             if (obj instanceof Map) {
                 Map map = (Map) obj;
+                List<Object> list = new ArrayList<>();
                 if (MapUtils.isNotEmpty(map)) {
                     for (Object key : map.keySet()) {
                        Object vals = map.get(key);
-                       values.add((List<Object>) vals);
+                       if(vals instanceof List) {
+                           List l = (List) vals;
+                           for(Object o : l) {
+                               list.add(o);
+                           }
+                       }
+
                     }
-                    ret.setValues(values);
+
+                    values.add(list);
                 }
             } else if (obj instanceof List) {
                 List list = (List) obj;
                 if (CollectionUtils.isNotEmpty(list)) {
                     values.add(list);
                 }
-                ret.setValues(values);
             }
         }
-        return ret;
+
+        return values;
     }
 
     private boolean skipDeletedEntities(boolean excludeDeletedEntities, 
AtlasVertex<?, ?> vertex) {

http://git-wip-us.apache.org/repos/asf/atlas/blob/5bd5327c/repository/src/main/java/org/apache/atlas/query/DSLVisitor.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/query/DSLVisitor.java 
b/repository/src/main/java/org/apache/atlas/query/DSLVisitor.java
new file mode 100644
index 0000000..a2c6b98
--- /dev/null
+++ b/repository/src/main/java/org/apache/atlas/query/DSLVisitor.java
@@ -0,0 +1,127 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+package org.apache.atlas.query;
+
+import org.apache.atlas.query.antlr4.AtlasDSLParser.*;
+import org.apache.atlas.query.antlr4.AtlasDSLParserBaseVisitor;
+import org.apache.commons.collections.CollectionUtils;
+
+public class DSLVisitor extends AtlasDSLParserBaseVisitor<String> {
+    private final QueryProcessor queryProcessor;
+
+    public DSLVisitor(QueryProcessor queryProcessor) {
+        this.queryProcessor = queryProcessor;
+    }
+
+    @Override
+    public String visitFromExpression(final FromExpressionContext ctx) {
+        FromSrcContext fromSrc = ctx.fromSrc();
+        AliasExprContext aliasExpr = fromSrc.aliasExpr();
+
+        if (aliasExpr != null) {
+            queryProcessor.addFromAlias(aliasExpr.identifier(0).getText(), 
aliasExpr.identifier(1).getText());
+        } else {
+            if (fromSrc.identifier() != null) {
+                queryProcessor.addFrom(fromSrc.identifier().getText());
+            } else {
+                queryProcessor.addFrom(fromSrc.literal().getText());
+            }
+        }
+        return super.visitFromExpression(ctx);
+    }
+
+    @Override
+    public String visitWhereClause(WhereClauseContext ctx) {
+        ExprContext expr = ctx.expr();
+        processExpr(expr.compE());
+
+        if (CollectionUtils.isNotEmpty(expr.exprRight())) {
+            for (ExprRightContext exprRight : expr.exprRight()) {
+                if (exprRight.K_AND() != null) {
+                    // AND expression
+                    processExpr(exprRight.compE());
+                }
+                // OR is tricky
+            }
+        }
+        return super.visitWhereClause(ctx);
+    }
+
+    private void processExpr(final CompEContext compE) {
+        if (compE != null && compE.isClause() == null && compE.hasClause() == 
null && compE.isClause() == null) {
+            ComparisonClauseContext comparisonClause = 
compE.comparisonClause();
+            if(comparisonClause == null) {
+                comparisonClause = 
compE.arithE().multiE().atomE().expr().compE().comparisonClause();
+            }
+
+            if (comparisonClause != null) {
+                String lhs = comparisonClause.arithE(0).getText();
+                String op = 
comparisonClause.operator().getText().toUpperCase();
+                String rhs = comparisonClause.arithE(1).getText();
+
+                queryProcessor.addWhere(lhs, op, rhs);
+            }
+        }
+    }
+
+    @Override
+    public String visitSelectExpr(SelectExprContext ctx) {
+        if (!(ctx.getParent() instanceof GroupByExpressionContext)) {
+            String[] items = new String[ctx.selectExpression().size()];
+            for (int i = 0; i < ctx.selectExpression().size(); i++) {
+                items[i] = ctx.selectExpression(i).expr().getText();
+            }
+
+            queryProcessor.addSelect(items);
+        }
+        return super.visitSelectExpr(ctx);
+    }
+
+    @Override
+    public String visitLimitOffset(LimitOffsetContext ctx) {
+        queryProcessor.addLimit(ctx.limitClause().NUMBER().toString(),
+                (ctx.offsetClause() == null ? "0" : 
ctx.offsetClause().NUMBER().getText()));
+        return super.visitLimitOffset(ctx);
+    }
+
+    @Override
+    public String visitOrderByExpr(OrderByExprContext ctx) {
+        queryProcessor.addOrderBy(ctx.expr().getText(), (ctx.sortOrder() != 
null && ctx.sortOrder().getText().equalsIgnoreCase("desc")));
+        return super.visitOrderByExpr(ctx);
+    }
+
+    @Override
+    public String visitIsClause(IsClauseContext ctx) {
+        queryProcessor.addFromIsA(ctx.arithE().getText(), 
ctx.identifier().getText());
+        return super.visitIsClause(ctx);
+    }
+
+    @Override
+    public String visitHasClause(HasClauseContext ctx) {
+        queryProcessor.addFromProperty(ctx.arithE().getText(), 
ctx.identifier().getText());
+        return super.visitHasClause(ctx);
+    }
+
+    @Override
+    public String visitGroupByExpression(GroupByExpressionContext ctx) {
+        String s = ctx.selectExpr().getText();
+        queryProcessor.addGroupBy(s);
+        return super.visitGroupByExpression(ctx);
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/5bd5327c/repository/src/main/java/org/apache/atlas/query/Expressions.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/query/Expressions.java 
b/repository/src/main/java/org/apache/atlas/query/Expressions.java
index 9e93ce4..77350f0 100644
--- a/repository/src/main/java/org/apache/atlas/query/Expressions.java
+++ b/repository/src/main/java/org/apache/atlas/query/Expressions.java
@@ -18,28 +18,24 @@
 package org.apache.atlas.query;
 
 
-import java.util.List;
+import org.apache.atlas.query.antlr4.AtlasDSLParser.QueryContext;
+
 
 public class Expressions {
     public static class Expression {
+        private final QueryContext parsedQuery;
 
-    }
-
-    public static class AliasExpression {
-        public String alias() {
-            String ret = null;
 
-            return ret;
+        public Expression(QueryContext q) {
+            parsedQuery = q;
         }
 
-    }
-
-    public static class SelectExpression {
-        public List<AliasExpression> toJavaList() {
-            List<AliasExpression> ret = null;
-
-            return ret;
+        public Expression isReady() {
+            return (parsedQuery != null ? this : null);
         }
 
+        public void accept(DSLVisitor qv) {
+            qv.visit(parsedQuery);
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/atlas/blob/5bd5327c/repository/src/main/java/org/apache/atlas/query/GremlinQuery.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/query/GremlinQuery.java 
b/repository/src/main/java/org/apache/atlas/query/GremlinQuery.java
index fcb1f48..3b8de08 100644
--- a/repository/src/main/java/org/apache/atlas/query/GremlinQuery.java
+++ b/repository/src/main/java/org/apache/atlas/query/GremlinQuery.java
@@ -6,9 +6,9 @@
  * 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
- *
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
  * 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.
@@ -17,26 +17,22 @@
  */
 package org.apache.atlas.query;
 
-import org.apache.atlas.query.Expressions.Expression;
-
-
 public class GremlinQuery {
 
-    public boolean hasSelectList() {
-        boolean ret = false;
+    private final String queryStr;
+    private final boolean hasSelect;
 
-        return ret;
+    public GremlinQuery(String text, boolean hasSelect) {
+        this.queryStr = text;
+        this.hasSelect = hasSelect;
     }
 
-    public String queryStr() {
-        String ret = null;
 
-        return ret;
+    public boolean hasSelectList() {
+        return this.hasSelect;
     }
 
-    public Expression expr() {
-        Expression ret = null;
-
-        return ret;
+    public String queryStr() {
+        return queryStr;
     }
 }

http://git-wip-us.apache.org/repos/asf/atlas/blob/5bd5327c/repository/src/main/java/org/apache/atlas/query/GremlinTranslator.java
----------------------------------------------------------------------
diff --git 
a/repository/src/main/java/org/apache/atlas/query/GremlinTranslator.java 
b/repository/src/main/java/org/apache/atlas/query/GremlinTranslator.java
index 5395ddd..6ce90e6 100644
--- a/repository/src/main/java/org/apache/atlas/query/GremlinTranslator.java
+++ b/repository/src/main/java/org/apache/atlas/query/GremlinTranslator.java
@@ -19,16 +19,23 @@ package org.apache.atlas.query;
 
 import org.apache.atlas.query.Expressions.Expression;
 
+
 public class GremlinTranslator {
-    private Expression expression;
+    private final QueryProcessor queryProcessor;
+    private       Expression     expression;
 
-    public GremlinTranslator(Expression expression) {
-        this.expression = expression;
+    public GremlinTranslator(QueryProcessor queryProcessor, Expression 
expression) {
+        this.expression     = expression;
+        this.queryProcessor = queryProcessor;
     }
 
     public GremlinQuery translate() {
-        GremlinQuery ret = null;
+        DSLVisitor qv = new DSLVisitor(queryProcessor);
+
+        expression.accept(qv);
+        queryProcessor.close();
 
+        GremlinQuery ret = new GremlinQuery(queryProcessor.getText(), 
queryProcessor.hasSelect());
         return ret;
     }
 }

http://git-wip-us.apache.org/repos/asf/atlas/blob/5bd5327c/repository/src/main/java/org/apache/atlas/query/QueryParser.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/query/QueryParser.java 
b/repository/src/main/java/org/apache/atlas/query/QueryParser.java
index 1e5e5ff..6e378a1 100644
--- a/repository/src/main/java/org/apache/atlas/query/QueryParser.java
+++ b/repository/src/main/java/org/apache/atlas/query/QueryParser.java
@@ -6,9 +6,9 @@
  * 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
- *
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
  * 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.
@@ -17,19 +17,30 @@
  */
 package org.apache.atlas.query;
 
+import org.antlr.v4.runtime.CharStreams;
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.antlr.v4.runtime.TokenStream;
 import org.apache.atlas.query.Expressions.Expression;
+import org.apache.atlas.query.antlr4.AtlasDSLLexer;
+import org.apache.atlas.query.antlr4.AtlasDSLParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Set;
 
-
 public class QueryParser {
+    private static final Logger LOG = 
LoggerFactory.getLogger(QueryParser.class);
+
     private static final Set<String> RESERVED_KEYWORDS =
             new HashSet<>(Arrays.asList("[", "]", "(", ")", "=", "<", ">", 
"!=", "<=", ">=", ",", "and", "or", "+", "-",
-                                        "*", "/", ".", "select", "from", 
"where", "groupby", "loop", "isa", "is", "has",
-                                        "as", "times", "withPath", "limit", 
"offset", "orderby", "count", "max", "min",
-                                        "sum", "by", "order", "like"));
+                    "*", "/", ".", "select", "from", "where", "groupby", 
"loop", "isa", "is", "has",
+                    "as", "times", "withPath", "limit", "offset", "orderby", 
"count", "max", "min",
+                    "sum", "by", "order", "like"));
 
     public static boolean isKeyword(String word) {
         return RESERVED_KEYWORDS.contains(word);
@@ -38,6 +49,18 @@ public class QueryParser {
     public static Expression apply(String queryStr, QueryParams params) {
         Expression ret = null;
 
+        try {
+            InputStream    stream           = new 
ByteArrayInputStream(queryStr.getBytes());
+            AtlasDSLLexer lexer            = new 
AtlasDSLLexer(CharStreams.fromStream(stream));
+            TokenStream    inputTokenStream = new CommonTokenStream(lexer);
+            AtlasDSLParser parser           = new 
AtlasDSLParser(inputTokenStream);
+
+            ret = new Expression(parser.query());
+        } catch (IOException e) {
+            ret = null;
+            LOG.error(e.getMessage(), e);
+        }
+
         return ret;
     }
 }

http://git-wip-us.apache.org/repos/asf/atlas/blob/5bd5327c/repository/src/main/java/org/apache/atlas/query/QueryProcessor.java
----------------------------------------------------------------------
diff --git 
a/repository/src/main/java/org/apache/atlas/query/QueryProcessor.java 
b/repository/src/main/java/org/apache/atlas/query/QueryProcessor.java
index 04cf0b4..60480a1 100644
--- a/repository/src/main/java/org/apache/atlas/query/QueryProcessor.java
+++ b/repository/src/main/java/org/apache/atlas/query/QueryProcessor.java
@@ -6,9 +6,9 @@
  * 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
- *
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
  * 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.
@@ -17,12 +17,555 @@
  */
 package org.apache.atlas.query;
 
+import com.google.common.annotations.VisibleForTesting;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.TypeCategory;
+import org.apache.atlas.model.discovery.SearchParameters;
 import org.apache.atlas.query.Expressions.Expression;
+import org.apache.atlas.type.AtlasArrayType;
+import org.apache.atlas.type.AtlasBuiltInTypes;
+import org.apache.atlas.type.AtlasEntityType;
+import org.apache.atlas.type.AtlasStructType;
+import org.apache.atlas.type.AtlasType;
+import org.apache.atlas.type.AtlasTypeRegistry;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 public class QueryProcessor {
-    public static Expression validate(Expression expression) {
-        Expressions.Expression ret = null;
+    private static final Logger LOG = 
LoggerFactory.getLogger(QueryProcessor.class);
+
+    private final int DEFAULT_QUERY_RESULT_LIMIT = 25;
+
+    private final Pattern SINGLE_QUOTED_IDENTIFIER   = 
Pattern.compile("'(\\w[\\w\\d\\.\\s]*)'");
+    private final Pattern DOUBLE_QUOTED_IDENTIFIER   = 
Pattern.compile("\"(\\w[\\w\\d\\.\\s]*)\"");
+    private final Pattern BACKTICK_QUOTED_IDENTIFIER = 
Pattern.compile("`(\\w[\\w\\d\\.\\s]*)`");
+
+    private final List<String> errorList         = new ArrayList<>();
+    private final GremlinClauseList queryClauses = new 
GremlinClauseList(errorList);
+    private int currentStep;
+    private final TypeRegistryLookup registryLookup;
+
+    @Inject
+    public QueryProcessor(AtlasTypeRegistry typeRegistry) {
+        registryLookup = new TypeRegistryLookup(errorList, typeRegistry);
+        init();
+    }
+
+    @VisibleForTesting
+    public QueryProcessor(TypeRegistryLookup lookup) {
+        registryLookup = lookup;
+        init();
+    }
+
+    private void init() {
+        add(GremlinClause.G);
+        add(GremlinClause.V);
+    }
+
+    public Expression validate(Expression expression) {
+        return expression.isReady();
+    }
+
+    public void addFrom(String typeName) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("addFrom(typeName={})", typeName);
+        }
+
+        String actualTypeName = extractIdentifier(typeName);
+
+        if(registryLookup.isTypeTrait(actualTypeName)) {
+            addTraitAndRegister(actualTypeName);
+        } else if (!registryLookup.hasActiveType()) {
+            registryLookup.registerActive(actualTypeName);
+            if(registryLookup.doesActiveTypeHaveSubTypes()) {
+                add(GremlinClause.HAS_TYPE_WITHIN, 
registryLookup.getActiveTypeAndSubTypes());
+            } else {
+                add(GremlinClause.HAS_TYPE, actualTypeName);
+            }
+        } else {
+            add(GremlinClause.OUT, 
registryLookup.getRelationshipEdgeLabelForActiveType(actualTypeName));
+            
registryLookup.registerActive(registryLookup.getTypeFromEdge(actualTypeName));
+        }
+    }
+
+    private void addTraitAndRegister(String typeName) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("addTraitAndRegister(typeName={})", typeName);
+        }
+
+        add(GremlinClause.TRAIT, typeName);
+        registryLookup.registerActive(typeName);
+    }
+
+    public void addFromIsA(String typeName, String trait) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("addFromIsA(typeName={}, trait={})", typeName, trait);
+        }
+
+        if(!registryLookup.hasActiveType()) {
+            addFrom(typeName);
+        }
+
+        add(GremlinClause.TRAIT, trait);
+    }
+
+    public void addFromProperty(String typeName, String attribute) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("addFromIsA(typeName={}, attribute={})", typeName, 
attribute);
+        }
+
+        if(registryLookup.isSameAsActive(typeName) == false) {
+            addFrom(typeName);
+        }
+
+        add(GremlinClause.HAS_PROPERTY, 
registryLookup.getQualifiedAttributeName(attribute));
+    }
+
+    public void addFromAlias(String typeName, String alias) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("addFromAlias(typeName={}, alias={})", typeName, alias);
+        }
+
+        addFrom(typeName);
+        addAsClause(alias);
+    }
+
+    public void addWhere(String lhs, String operator, String rhs) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("addWhere(lhs={}, operator={}, rhs={})", lhs, operator, 
rhs);
+        }
+
+        lhs = registryLookup.getQualifiedAttributeName(lhs);
+
+        SearchParameters.Operator op = 
SearchParameters.Operator.fromString(operator);
+        switch (op) {
+            case LT:
+                add(GremlinClause.HAS_OPERATOR, lhs, "lt", rhs);
+                break;
+            case GT:
+                add(GremlinClause.HAS_OPERATOR, lhs, "gt", rhs);
+                break;
+            case LTE:
+                add(GremlinClause.HAS_OPERATOR, lhs, "lte", rhs);
+                break;
+            case GTE:
+                add(GremlinClause.HAS_OPERATOR, lhs, "gte", rhs);
+                break;
+            case EQ:
+                add(GremlinClause.HAS_OPERATOR, lhs, "eq", rhs);
+                break;
+            case NEQ:
+                add(GremlinClause.HAS_OPERATOR, lhs, "neq", rhs);
+                break;
+            case IN:
+                // TODO: Handle multiple RHS values
+                add(GremlinClause.HAS_OPERATOR, lhs, "within", rhs);
+                break;
+            case LIKE:
+                add(GremlinClause.TEXT_CONTAINS, lhs, rhs.replace("*", 
".*").replace('?', '.'));
+                break;
+        }
+    }
+
+    public void addSelect(String[] items) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("addSelect(items.length={})", items != null ? 
items.length : -1);
+        }
+
+        StringBuilder sb = new StringBuilder();
+
+        for (int i = 0; i < items.length; i++) {
+            String s = registryLookup.getQualifiedAttributeName(items[i]);
+
+            if (items[i].contains(".") || 
registryLookup.isAttributePrimitiveTypeForActiveType(items[i])) {
+                sb.append(String.format("'%s'", s));
+
+                if (i != items.length - 1) {
+                    sb.append(", ");
+                }
+            } else {
+                add(GremlinClause.OUT, 
registryLookup.getRelationshipEdgeLabelForActiveType(items[i]));
+                add(GremlinClause.AS, getCurrentStep());
+                addSelectClause(getCurrentStep());
+                incrementCurrentStep();
+            }
+        }
+
+        if (!StringUtils.isEmpty(sb.toString())) {
+            addValueMapClause(sb.toString());
+        }
+    }
+
+    public void addLimit(String limit, String offset) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("addLimit(limit={}, offset={})", limit, offset);
+        }
+
+        add(GremlinClause.ORDER);
+
+        if (offset.equalsIgnoreCase("0")) {
+            add(GremlinClause.LIMIT, limit);
+        } else {
+            addRangeClause(offset, limit);
+        }
+    }
+
+    public void addGroupBy(String item) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("addGroupBy(item={})", item);
+        }
+
+        add(GremlinClause.GROUP);
+        addByClause(item, false);
+    }
+
+    private void addRangeClause(String startIndex, String endIndex) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("addRangeClause(startIndex={}, endIndex={})", 
startIndex, endIndex);
+        }
+
+        add(GremlinClause.RANGE, startIndex, startIndex, endIndex);
+    }
+
+    public String getText() {
+        String[] items = new String[queryClauses.size()];
+
+        for (int i = 0; i < queryClauses.size(); i++) {
+            items[i] = queryClauses.getValue(i);
+        }
+
+        String ret = StringUtils.join(items, ".");
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("getText() => {}", ret);
+        }
 
         return ret;
     }
+
+    public void close() {
+        if(queryClauses.hasClause(GremlinClause.LIMIT) == -1) {
+            add(GremlinClause.LIMIT, "" + DEFAULT_QUERY_RESULT_LIMIT);
+        }
+        add(GremlinClause.TO_LIST);
+    }
+
+    public boolean hasSelect() {
+        return (queryClauses.hasClause(GremlinClause.VALUE_MAP) != -1);
+    }
+
+    public void addAsClause(String stepName) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("addAsClause(stepName={})", stepName);
+        }
+
+        add(GremlinClause.AS, stepName);
+        registryLookup.registerStepType(stepName);
+    }
+
+    public void addOrderBy(String name, boolean isDesc) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("addOrderBy(name={}, isDesc={})", name, isDesc);
+        }
+
+        add(GremlinClause.ORDER);
+        addByClause(registryLookup.getQualifiedAttributeName(name), isDesc);
+    }
+
+    private void addValueMapClause(String s) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("addValueMapClause(s={})", s);
+        }
+
+        add(GremlinClause.VALUE_MAP, s);
+    }
+
+    private void addSelectClause(String s) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("addSelectClause(s={})", s);
+        }
+
+        add(GremlinClause.SELECT, s);
+    }
+
+    private void addByClause(String name, boolean descr) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("addByClause(name={})", name, descr);
+        }
+
+        add((!descr) ? GremlinClause.BY : GremlinClause.BY_DESC,
+                registryLookup.getQualifiedAttributeName(name));
+    }
+
+    private String getCurrentStep() {
+        return String.format("s%d", currentStep);
+    }
+
+    private void incrementCurrentStep() {
+        currentStep++;
+    }
+
+    private void add(GremlinClause clause, String... args) {
+        queryClauses.add(new GremlinClauseValue(clause, clause.get(args)));
+    }
+
+    private String extractIdentifier(String quotedIdentifier) {
+        String ret;
+
+        if (quotedIdentifier.charAt(0) == '`') {
+            ret = extract(BACKTICK_QUOTED_IDENTIFIER, quotedIdentifier);
+        } else if (quotedIdentifier.charAt(0) == '\'') {
+            ret = extract(SINGLE_QUOTED_IDENTIFIER, quotedIdentifier);
+        } else if (quotedIdentifier.charAt(0) == '"') {
+            ret = extract(DOUBLE_QUOTED_IDENTIFIER, quotedIdentifier);
+        } else {
+            ret = quotedIdentifier;
+        }
+
+        return ret;
+    }
+
+    private String extract(Pattern p, String s) {
+        Matcher m = p.matcher(s);
+        return m.find() ? m.group(1) : s;
+    }
+
+    private enum GremlinClause {
+        AS("as('%s')"),
+        BY("by('%s')"),
+        BY_DESC("by('%s', decr)"),
+        G("g"),
+        GROUP("group()"),
+        HAS("has('%s', %s)"),
+        HAS_OPERATOR("has('%s', %s(%s))"),
+        HAS_PROPERTY("has('%s')"),
+        HAS_NOT_PROPERTY("hasNot('%s')"),
+        HAS_TYPE("has('__typeName', '%s')"),
+        HAS_TYPE_WITHIN("has('__typeName', within(%s))"),
+        HAS_WITHIN("has('%s', within(%s))"),
+        IN("in()"),
+        LIMIT("limit(%s)"),
+        ORDER("order()"),
+        OUT("out('%s')"),
+        RANGE("range(%s, %s + %s)"),
+        SELECT("select('%s')"),
+        TO_LIST("toList()"),
+        TEXT_CONTAINS("has('%s', 
org.janusgraph.core.attribute.Text.textRegex(%s))"),
+        TEXT_PREFIX("has('%s', 
org.janusgraph.core.attribute.Text.textPrefix(%s))"),
+        TEXT_SUFFIX("has('%s', 
org.janusgraph.core.attribute.Text.textRegex(\".*\" + %s))"),
+        TRAIT("has('__traitNames', within('%s'))"),
+        V("V()"),
+        VALUE_MAP("valueMap(%s)");
+
+        private final String format;
+
+        GremlinClause(String format) {
+            this.format = format;
+        }
+
+        String get(String... args) {
+            return (args == null || args.length == 0) ?
+                    format :
+                    String.format(format, args);
+        }
+    }
+
+    private static class GremlinClauseValue {
+        private final GremlinClause clause;
+        private final String value;
+
+        public GremlinClauseValue(GremlinClause clause, String value) {
+            this.clause = clause;
+            this.value = value;
+        }
+
+        public GremlinClause getClause() {
+            return clause;
+        }
+
+        public String getValue() {
+            return value;
+        }
+    }
+
+    private static class GremlinClauseList {
+        private final List<String> errorList;
+        private AtlasEntityType activeType;
+
+        private final List<GremlinClauseValue> list;
+
+        private GremlinClauseList(List<String> errorList) {
+            this.errorList = errorList;
+            this.list = new LinkedList<>();
+        }
+
+        public void add(GremlinClauseValue g) {
+            list.add(g);
+        }
+
+        public void add(GremlinClauseValue g, AtlasEntityType t) {
+            add(g);
+            activeType = t;
+        }
+
+        public void add(GremlinClause clause, String... args) {
+            list.add(new GremlinClauseValue(clause, clause.get(args)));
+        }
+
+        public String getValue(int i) {
+            return list.get(i).value;
+        }
+
+        public int size() {
+            return list.size();
+        }
+
+        public int hasClause(GremlinClause clause) {
+            for (int i = 0; i < list.size(); i++) {
+                if (list.get(i).getClause() == clause)
+                    return i;
+            }
+
+            return -1;
+        }
+    }
+
+    @VisibleForTesting
+    static class TypeRegistryLookup {
+        private final List<String> errorList;
+        private final AtlasTypeRegistry typeRegistry;
+
+        private AtlasEntityType activeType;
+        private final Map<String, AtlasEntityType> asClauseContext = new 
HashMap<>();
+
+        public TypeRegistryLookup(List<String> errorList, AtlasTypeRegistry 
typeRegistry) {
+            this.errorList = errorList;
+            this.typeRegistry = typeRegistry;
+        }
+
+        public void registerActive(String typeName) {
+            activeType = typeRegistry.getEntityTypeByName(typeName);
+        }
+
+        public boolean hasActiveType() {
+            return (activeType != null);
+        }
+
+        public void registerStepType(String stepName) {
+            if (!asClauseContext.containsKey(stepName)) {
+                asClauseContext.put(stepName, activeType);
+            } else {
+                addError(String.format("Multiple steps with same name 
detected: %s", stepName));
+            }
+        }
+
+        protected void addError(String s) {
+            errorList.add(s);
+        }
+
+        public String getRelationshipEdgeLabelForActiveType(String item) {
+            return getRelationshipEdgeLabel(activeType, item);
+        }
+
+        private String getRelationshipEdgeLabel(AtlasEntityType t, String 
item) {
+            if(t == null) {
+                return "";
+            }
+
+            AtlasStructType.AtlasAttribute attr = t.getAttribute(item);
+            return (attr != null) ? attr.getRelationshipEdgeLabel() : "";
+        }
+
+        protected boolean isAttributePrimitiveTypeForActiveType(String name) {
+            return isAttributePrimitiveType(activeType, name);
+        }
+
+        private boolean isAttributePrimitiveType(AtlasEntityType t, String 
name) {
+            if (activeType == null) {
+                return false;
+            }
+
+            AtlasType attrType = t.getAttributeType(name);
+            TypeCategory attrTypeCategory = attrType.getTypeCategory();
+
+            return (attrTypeCategory == TypeCategory.PRIMITIVE || 
attrTypeCategory == TypeCategory.ENUM);
+        }
+
+        public boolean isTypeTrait(String name) {
+            return (typeRegistry.getClassificationTypeByName(name) != null);
+        }
+
+        public String getQualifiedAttributeName(String item) {
+            if (item.contains(".")) {
+                String[] keyValue = StringUtils.split(item, ".");
+
+                if (!asClauseContext.containsKey(keyValue[0])) {
+                    return item;
+                } else {
+                    String s = getStitchedString(keyValue, 1, keyValue.length 
- 1);
+                    return getQualifiedAttributeNameFromType(
+                            asClauseContext.get(keyValue[0]), s);
+                }
+            }
+
+            return getQualifiedAttributeNameFromType(activeType, item);
+        }
+
+        protected String getStitchedString(String[] keyValue, int startIndex, 
int endIndex) {
+            if(startIndex == endIndex) {
+                return keyValue[startIndex];
+            }
+
+            return StringUtils.join(keyValue, ".", startIndex, endIndex);
+        }
+
+        private String getQualifiedAttributeNameFromType(AtlasEntityType t, 
String item) {
+            try {
+                return (t != null) ? t.getQualifiedAttributeName(item) : item;
+            } catch (AtlasBaseException e) {
+                addError(e.getMessage());
+            }
+
+            return item;
+        }
+
+        public String getTypeFromEdge(String item) {
+            AtlasType at = activeType.getAttribute(item).getAttributeType();
+            if(at.getTypeCategory() == TypeCategory.ARRAY) {
+                AtlasArrayType arrType = ((AtlasArrayType)at);
+                return ((AtlasBuiltInTypes.AtlasObjectIdType) 
arrType.getElementType()).getObjectType();
+            }
+
+            return activeType.getAttribute(item).getTypeName();
+        }
+
+        public boolean doesActiveTypeHaveSubTypes() {
+            return (activeType.getAllSubTypes().size() != 0);
+        }
+
+        public String getActiveTypeAndSubTypes() {
+            Set<String> set = activeType.getTypeAndAllSubTypes();
+            String[] str = set.toArray(new String[]{});
+            for (int i = 0; i < str.length; i++) {
+                str[i] = String.format("'%s'", str[i]);
+            }
+
+            return StringUtils.join(str, ",");
+        }
+
+        public boolean isSameAsActive(String typeName) {
+            return (activeType != null) && 
activeType.getTypeName().equalsIgnoreCase(typeName);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/atlas/blob/5bd5327c/repository/src/main/java/org/apache/atlas/query/SelectExpressionHelper.java
----------------------------------------------------------------------
diff --git 
a/repository/src/main/java/org/apache/atlas/query/SelectExpressionHelper.java 
b/repository/src/main/java/org/apache/atlas/query/SelectExpressionHelper.java
deleted file mode 100644
index a8748ef..0000000
--- 
a/repository/src/main/java/org/apache/atlas/query/SelectExpressionHelper.java
+++ /dev/null
@@ -1,30 +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.
- */
-package org.apache.atlas.query;
-
-import org.apache.atlas.query.Expressions.Expression;
-import org.apache.atlas.query.Expressions.SelectExpression;
-
-
-public class SelectExpressionHelper {
-    public static SelectExpression extractSelectExpression(Expression expr) {
-        SelectExpression ret = null;
-
-        return ret;
-    }
-}

http://git-wip-us.apache.org/repos/asf/atlas/blob/5bd5327c/repository/src/main/java/org/apache/atlas/query/antlr4/AtlasDSLLexer.g4
----------------------------------------------------------------------
diff --git 
a/repository/src/main/java/org/apache/atlas/query/antlr4/AtlasDSLLexer.g4 
b/repository/src/main/java/org/apache/atlas/query/antlr4/AtlasDSLLexer.g4
new file mode 100644
index 0000000..376dcea
--- /dev/null
+++ b/repository/src/main/java/org/apache/atlas/query/antlr4/AtlasDSLLexer.g4
@@ -0,0 +1,180 @@
+/**
+ * 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.
+ */
+
+lexer grammar AtlasDSLLexer;
+
+fragment A: ('A'|'a');
+fragment B: ('B'|'b');
+fragment C: ('C'|'c');
+fragment D: ('D'|'d');
+fragment E: ('E'|'e');
+fragment F: ('F'|'f');
+fragment G: ('G'|'g');
+fragment H: ('H'|'h');
+fragment I: ('I'|'i');
+fragment J: ('J'|'j');
+fragment K: ('K'|'k');
+fragment L: ('L'|'l');
+fragment M: ('M'|'m');
+fragment N: ('N'|'n');
+fragment O: ('O'|'o');
+fragment P: ('P'|'p');
+fragment Q: ('Q'|'q');
+fragment R: ('R'|'r');
+fragment S: ('S'|'s');
+fragment T: ('T'|'t');
+fragment U: ('U'|'u');
+fragment V: ('V'|'v');
+fragment W: ('W'|'w');
+fragment X: ('X'|'x');
+fragment Y: ('Y'|'y');
+fragment Z: ('Z'|'z');
+
+fragment DIGIT: [0-9];
+
+fragment LETTER: 'a'..'z'| 'A'..'Z' | '_';
+
+// Comment skipping
+SINGLE_LINE_COMMENT: '--' ~[\r\n]* -> channel(HIDDEN) ;
+
+MULTILINE_COMMENT : '/*' .*? ( '*/' | EOF ) -> channel(HIDDEN) ;
+
+WS: (' ' ' '* | [ \n\t\r]+) -> channel(HIDDEN) ;
+
+// Lexer rules
+NUMBER: (K_PLUS | K_MINUS)? DIGIT DIGIT* (E (K_PLUS | K_MINUS)? DIGIT DIGIT*)? 
;
+
+FLOATING_NUMBER: (K_PLUS | K_MINUS)? DIGIT+ K_DOT DIGIT+ (E (K_PLUS | 
K_MINUS)? DIGIT DIGIT*)? ;
+
+BOOL: K_TRUE | K_FALSE ;
+
+K_COMMA: ',' ;
+
+K_PLUS: '+' ;
+
+K_MINUS: '-' ;
+
+K_STAR: '*' ;
+
+K_DIV: '/' ;
+
+K_DOT: '.' ;
+
+K_LIKE: L I K E ;
+
+K_AND: A N D ;
+
+K_OR: O R ;
+
+K_LPAREN: '(' ;
+
+K_LBRACKET: '[' ;
+
+K_RPAREN: ')' ;
+
+K_RBRACKET: ']' ;
+
+K_LT: '<' | L T ;
+
+K_LTE: '<=' | L T E ;
+
+K_EQ: '=' | E Q ;
+
+K_NEQ: '!=' | N E Q ;
+
+K_GT: '>' | G T ;
+
+K_GTE: '>=' | G T E ;
+
+K_FROM: F R O M ;
+
+K_WHERE: W H E R E ;
+
+K_ORDERBY: O R D E R B Y ;
+
+K_GROUPBY: G R O U P B Y ;
+
+K_LIMIT: L I M I T ;
+
+K_SELECT: S E L E C T ;
+
+K_MAX: M A X ;
+
+K_MIN: M I N ;
+
+K_SUM: S U M ;
+
+K_COUNT: C O U N T ;
+
+K_LOOP: L O O P ;
+
+K_OFFSET: O F F S E T ;
+
+K_AS: A S ;
+
+K_ISA: I S A ;
+
+K_IS: I S ;
+
+K_HAS: H A S ;
+
+K_ASC: A S C ;
+
+K_DESC: D E S C ;
+
+K_WITHPATH: W I T H P A T H ;
+
+K_TRUE: T R U E ;
+
+K_FALSE: F A L S E ;
+
+KEYWORD: K_LIKE
+        | K_DOT
+        | K_SELECT
+        | K_AS
+        | K_HAS
+        | K_IS
+        | K_ISA
+        | K_WHERE
+        | K_LIMIT
+        | K_TRUE
+        | K_FALSE
+        | K_AND
+        | K_OR
+        | K_GROUPBY
+        | K_ORDERBY
+        | K_WITHPATH
+        | K_SUM
+        | K_MIN
+        | K_MAX
+        | K_OFFSET
+        | K_LOOP
+        | K_FROM
+        | K_DESC
+        | K_ASC
+        | K_COUNT
+        ;
+
+ID: STRING
+    |LETTER (LETTER|DIGIT)*
+    | LETTER (LETTER|DIGIT)* KEYWORD KEYWORD*
+    | KEYWORD KEYWORD* LETTER (LETTER|DIGIT)*
+    | LETTER (LETTER|DIGIT)* KEYWORD KEYWORD* LETTER (LETTER|DIGIT)*
+    ;
+
+STRING: '"' ~('"')* '"' | '\'' ~('\'')* '\'' | '`' ~('`')* '`';
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/5bd5327c/repository/src/main/java/org/apache/atlas/query/antlr4/AtlasDSLLexer.java
----------------------------------------------------------------------
diff --git 
a/repository/src/main/java/org/apache/atlas/query/antlr4/AtlasDSLLexer.java 
b/repository/src/main/java/org/apache/atlas/query/antlr4/AtlasDSLLexer.java
new file mode 100644
index 0000000..85f8d61
--- /dev/null
+++ b/repository/src/main/java/org/apache/atlas/query/antlr4/AtlasDSLLexer.java
@@ -0,0 +1,355 @@
+// Generated from AtlasDSLLexer.g4 by ANTLR 4.7
+package org.apache.atlas.query.antlr4;
+import org.antlr.v4.runtime.Lexer;
+import org.antlr.v4.runtime.CharStream;
+import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.TokenStream;
+import org.antlr.v4.runtime.*;
+import org.antlr.v4.runtime.atn.*;
+import org.antlr.v4.runtime.dfa.DFA;
+import org.antlr.v4.runtime.misc.*;
+
+@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
+public class AtlasDSLLexer extends Lexer {
+       static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); }
+
+       protected static final DFA[] _decisionToDFA;
+       protected static final PredictionContextCache _sharedContextCache =
+               new PredictionContextCache();
+       public static final int
+               SINGLE_LINE_COMMENT=1, MULTILINE_COMMENT=2, WS=3, NUMBER=4, 
FLOATING_NUMBER=5, 
+               BOOL=6, K_COMMA=7, K_PLUS=8, K_MINUS=9, K_STAR=10, K_DIV=11, 
K_DOT=12, 
+               K_LIKE=13, K_AND=14, K_OR=15, K_LPAREN=16, K_LBRACKET=17, 
K_RPAREN=18, 
+               K_RBRACKET=19, K_LT=20, K_LTE=21, K_EQ=22, K_NEQ=23, K_GT=24, 
K_GTE=25, 
+               K_FROM=26, K_WHERE=27, K_ORDERBY=28, K_GROUPBY=29, K_LIMIT=30, 
K_SELECT=31, 
+               K_MAX=32, K_MIN=33, K_SUM=34, K_COUNT=35, K_LOOP=36, 
K_OFFSET=37, K_AS=38, 
+               K_ISA=39, K_IS=40, K_HAS=41, K_ASC=42, K_DESC=43, 
K_WITHPATH=44, K_TRUE=45, 
+               K_FALSE=46, KEYWORD=47, ID=48, STRING=49;
+       public static String[] channelNames = {
+               "DEFAULT_TOKEN_CHANNEL", "HIDDEN"
+       };
+
+       public static String[] modeNames = {
+               "DEFAULT_MODE"
+       };
+
+       public static final String[] ruleNames = {
+               "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", 
"M", "N", 
+               "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", 
"DIGIT", "LETTER", 
+               "SINGLE_LINE_COMMENT", "MULTILINE_COMMENT", "WS", "NUMBER", 
"FLOATING_NUMBER", 
+               "BOOL", "K_COMMA", "K_PLUS", "K_MINUS", "K_STAR", "K_DIV", 
"K_DOT", "K_LIKE", 
+               "K_AND", "K_OR", "K_LPAREN", "K_LBRACKET", "K_RPAREN", 
"K_RBRACKET", "K_LT", 
+               "K_LTE", "K_EQ", "K_NEQ", "K_GT", "K_GTE", "K_FROM", "K_WHERE", 
"K_ORDERBY", 
+               "K_GROUPBY", "K_LIMIT", "K_SELECT", "K_MAX", "K_MIN", "K_SUM", 
"K_COUNT", 
+               "K_LOOP", "K_OFFSET", "K_AS", "K_ISA", "K_IS", "K_HAS", 
"K_ASC", "K_DESC", 
+               "K_WITHPATH", "K_TRUE", "K_FALSE", "KEYWORD", "ID", "STRING"
+       };
+
+       private static final String[] _LITERAL_NAMES = {
+               null, null, null, null, null, null, null, "','", "'+'", "'-'", 
"'*'", 
+               "'/'", "'.'", null, null, null, "'('", "'['", "')'", "']'"
+       };
+       private static final String[] _SYMBOLIC_NAMES = {
+               null, "SINGLE_LINE_COMMENT", "MULTILINE_COMMENT", "WS", 
"NUMBER", "FLOATING_NUMBER", 
+               "BOOL", "K_COMMA", "K_PLUS", "K_MINUS", "K_STAR", "K_DIV", 
"K_DOT", "K_LIKE", 
+               "K_AND", "K_OR", "K_LPAREN", "K_LBRACKET", "K_RPAREN", 
"K_RBRACKET", "K_LT", 
+               "K_LTE", "K_EQ", "K_NEQ", "K_GT", "K_GTE", "K_FROM", "K_WHERE", 
"K_ORDERBY", 
+               "K_GROUPBY", "K_LIMIT", "K_SELECT", "K_MAX", "K_MIN", "K_SUM", 
"K_COUNT", 
+               "K_LOOP", "K_OFFSET", "K_AS", "K_ISA", "K_IS", "K_HAS", 
"K_ASC", "K_DESC", 
+               "K_WITHPATH", "K_TRUE", "K_FALSE", "KEYWORD", "ID", "STRING"
+       };
+       public static final Vocabulary VOCABULARY = new 
VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
+
+       /**
+        * @deprecated Use {@link #VOCABULARY} instead.
+        */
+       @Deprecated
+       public static final String[] tokenNames;
+       static {
+               tokenNames = new String[_SYMBOLIC_NAMES.length];
+               for (int i = 0; i < tokenNames.length; i++) {
+                       tokenNames[i] = VOCABULARY.getLiteralName(i);
+                       if (tokenNames[i] == null) {
+                               tokenNames[i] = VOCABULARY.getSymbolicName(i);
+                       }
+
+                       if (tokenNames[i] == null) {
+                               tokenNames[i] = "<INVALID>";
+                       }
+               }
+       }
+
+       @Override
+       @Deprecated
+       public String[] getTokenNames() {
+               return tokenNames;
+       }
+
+       @Override
+
+       public Vocabulary getVocabulary() {
+               return VOCABULARY;
+       }
+
+
+       public AtlasDSLLexer(CharStream input) {
+               super(input);
+               _interp = new 
LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
+       }
+
+       @Override
+       public String getGrammarFileName() { return "AtlasDSLLexer.g4"; }
+
+       @Override
+       public String[] getRuleNames() { return ruleNames; }
+
+       @Override
+       public String getSerializedATN() { return _serializedATN; }
+
+       @Override
+       public String[] getChannelNames() { return channelNames; }
+
+       @Override
+       public String[] getModeNames() { return modeNames; }
+
+       @Override
+       public ATN getATN() { return _ATN; }
+
+       public static final String _serializedATN =
+               
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\63\u026a\b\1\4\2"+
+               
"\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4"+
+               
"\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22"+
+               
"\t\22\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31"+
+               
"\t\31\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t"+
+               " 
\4!\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t"+
+               
"+\4,\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62\4\63\t\63\4\64"+
+               
"\t\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\4:\t:\4;\t;\4<\t<\4=\t"+
+               
"=\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\4E\tE\4F\tF\4G\tG\4H\tH\4"+
+               
"I\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6"+
+               
"\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n\3\13\3\13\3\f\3\f\3\r\3\r\3\16\3"+
+               
"\16\3\17\3\17\3\20\3\20\3\21\3\21\3\22\3\22\3\23\3\23\3\24\3\24\3\25\3"+
+               
"\25\3\26\3\26\3\27\3\27\3\30\3\30\3\31\3\31\3\32\3\32\3\33\3\33\3\34\3"+
+               
"\34\3\35\3\35\3\36\3\36\3\36\3\36\7\36\u00da\n\36\f\36\16\36\u00dd\13"+
+               
"\36\3\36\3\36\3\37\3\37\3\37\3\37\7\37\u00e5\n\37\f\37\16\37\u00e8\13"+
+               "\37\3\37\3\37\3\37\5\37\u00ed\n\37\3\37\3\37\3 \3 \7 \u00f3\n 
\f \16 "+
+               "\u00f6\13 \3 \6 \u00f9\n \r \16 \u00fa\5 \u00fd\n \3 \3 
\3!\3!\5!\u0103"+
+               
"\n!\3!\3!\7!\u0107\n!\f!\16!\u010a\13!\3!\3!\3!\5!\u010f\n!\3!\3!\7!\u0113"+
+               
"\n!\f!\16!\u0116\13!\5!\u0118\n!\3\"\3\"\5\"\u011c\n\"\3\"\6\"\u011f\n"+
+               
"\"\r\"\16\"\u0120\3\"\3\"\6\"\u0125\n\"\r\"\16\"\u0126\3\"\3\"\3\"\5\""+
+               
"\u012c\n\"\3\"\3\"\7\"\u0130\n\"\f\"\16\"\u0133\13\"\5\"\u0135\n\"\3#"+
+               
"\3#\5#\u0139\n#\3$\3$\3%\3%\3&\3&\3\'\3\'\3(\3(\3)\3)\3*\3*\3*\3*\3*\3"+
+               
"+\3+\3+\3+\3,\3,\3,\3-\3-\3.\3.\3/\3/\3\60\3\60\3\61\3\61\3\61\3\61\5"+
+               
"\61\u015f\n\61\3\62\3\62\3\62\3\62\3\62\3\62\5\62\u0167\n\62\3\63\3\63"+
+               
"\3\63\3\63\5\63\u016d\n\63\3\64\3\64\3\64\3\64\3\64\3\64\5\64\u0175\n"+
+               
"\64\3\65\3\65\3\65\3\65\5\65\u017b\n\65\3\66\3\66\3\66\3\66\3\66\3\66"+
+               
"\5\66\u0183\n\66\3\67\3\67\3\67\3\67\3\67\38\38\38\38\38\38\39\39\39\3"+
+               
"9\39\39\39\39\3:\3:\3:\3:\3:\3:\3:\3:\3;\3;\3;\3;\3;\3;\3<\3<\3<\3<\3"+
+               
"<\3<\3<\3=\3=\3=\3=\3>\3>\3>\3>\3?\3?\3?\3?\3@\3@\3@\3@\3@\3@\3A\3A\3"+
+               
"A\3A\3A\3B\3B\3B\3B\3B\3B\3B\3C\3C\3C\3D\3D\3D\3D\3E\3E\3E\3F\3F\3F\3"+
+               
"F\3G\3G\3G\3G\3H\3H\3H\3H\3H\3I\3I\3I\3I\3I\3I\3I\3I\3I\3J\3J\3J\3J\3"+
+               
"J\3K\3K\3K\3K\3K\3K\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3"+
+               
"L\3L\3L\3L\3L\3L\3L\3L\3L\5L\u020f\nL\3M\3M\3M\3M\7M\u0215\nM\fM\16M\u0218"+
+               
"\13M\3M\3M\3M\7M\u021d\nM\fM\16M\u0220\13M\3M\3M\7M\u0224\nM\fM\16M\u0227"+
+               
"\13M\3M\3M\7M\u022b\nM\fM\16M\u022e\13M\3M\3M\3M\7M\u0233\nM\fM\16M\u0236"+
+               
"\13M\3M\3M\3M\7M\u023b\nM\fM\16M\u023e\13M\3M\3M\7M\u0242\nM\fM\16M\u0245"+
+               
"\13M\3M\3M\3M\7M\u024a\nM\fM\16M\u024d\13M\5M\u024f\nM\3N\3N\7N\u0253"+
+               
"\nN\fN\16N\u0256\13N\3N\3N\3N\7N\u025b\nN\fN\16N\u025e\13N\3N\3N\3N\7"+
+               
"N\u0263\nN\fN\16N\u0266\13N\3N\5N\u0269\nN\3\u00e6\2O\3\2\5\2\7\2\t\2"+
+               
"\13\2\r\2\17\2\21\2\23\2\25\2\27\2\31\2\33\2\35\2\37\2!\2#\2%\2\'\2)\2"+
+               
"+\2-\2/\2\61\2\63\2\65\2\67\29\2;\3=\4?\5A\6C\7E\bG\tI\nK\13M\fO\rQ\16"+
+               
"S\17U\20W\21Y\22[\23]\24_\25a\26c\27e\30g\31i\32k\33m\34o\35q\36s\37u"+
+               " 
w!y\"{#}$\177%\u0081&\u0083\'\u0085(\u0087)\u0089*\u008b+\u008d,\u008f"+
+               
"-\u0091.\u0093/\u0095\60\u0097\61\u0099\62\u009b\63\3\2#\4\2CCcc\4\2D"+
+               
"Ddd\4\2EEee\4\2FFff\4\2GGgg\4\2HHhh\4\2IIii\4\2JJjj\4\2KKkk\4\2LLll\4"+
+               
"\2MMmm\4\2NNnn\4\2OOoo\4\2PPpp\4\2QQqq\4\2RRrr\4\2SSss\4\2TTtt\4\2UUu"+
+               
"u\4\2VVvv\4\2WWww\4\2XXxx\4\2YYyy\4\2ZZzz\4\2[[{{\4\2\\\\||\3\2\62;\5"+
+               
"\2C\\aac|\4\2\f\f\17\17\5\2\13\f\17\17\"\"\3\2$$\3\2))\3\2bb\2\u0297\2"+
+               
";\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3"+
+               
"\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2"+
+               
"\2\2U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2"+
+               
"a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3"+
+               
"\2\2\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2"+
+               
"\2\2{\3\2\2\2\2}\3\2\2\2\2\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2"+
+               
"\2\u0085\3\2\2\2\2\u0087\3\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d"+
+               
"\3\2\2\2\2\u008f\3\2\2\2\2\u0091\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2"+
+               
"\2\2\u0097\3\2\2\2\2\u0099\3\2\2\2\2\u009b\3\2\2\2\3\u009d\3\2\2\2\5\u009f"+
+               
"\3\2\2\2\7\u00a1\3\2\2\2\t\u00a3\3\2\2\2\13\u00a5\3\2\2\2\r\u00a7\3\2"+
+               
"\2\2\17\u00a9\3\2\2\2\21\u00ab\3\2\2\2\23\u00ad\3\2\2\2\25\u00af\3\2\2"+
+               
"\2\27\u00b1\3\2\2\2\31\u00b3\3\2\2\2\33\u00b5\3\2\2\2\35\u00b7\3\2\2\2"+
+               
"\37\u00b9\3\2\2\2!\u00bb\3\2\2\2#\u00bd\3\2\2\2%\u00bf\3\2\2\2\'\u00c1"+
+               
"\3\2\2\2)\u00c3\3\2\2\2+\u00c5\3\2\2\2-\u00c7\3\2\2\2/\u00c9\3\2\2\2\61"+
+               
"\u00cb\3\2\2\2\63\u00cd\3\2\2\2\65\u00cf\3\2\2\2\67\u00d1\3\2\2\29\u00d3"+
+               
"\3\2\2\2;\u00d5\3\2\2\2=\u00e0\3\2\2\2?\u00fc\3\2\2\2A\u0102\3\2\2\2C"+
+               
"\u011b\3\2\2\2E\u0138\3\2\2\2G\u013a\3\2\2\2I\u013c\3\2\2\2K\u013e\3\2"+
+               
"\2\2M\u0140\3\2\2\2O\u0142\3\2\2\2Q\u0144\3\2\2\2S\u0146\3\2\2\2U\u014b"+
+               
"\3\2\2\2W\u014f\3\2\2\2Y\u0152\3\2\2\2[\u0154\3\2\2\2]\u0156\3\2\2\2_"+
+               
"\u0158\3\2\2\2a\u015e\3\2\2\2c\u0166\3\2\2\2e\u016c\3\2\2\2g\u0174\3\2"+
+               
"\2\2i\u017a\3\2\2\2k\u0182\3\2\2\2m\u0184\3\2\2\2o\u0189\3\2\2\2q\u018f"+
+               
"\3\2\2\2s\u0197\3\2\2\2u\u019f\3\2\2\2w\u01a5\3\2\2\2y\u01ac\3\2\2\2{"+
+               
"\u01b0\3\2\2\2}\u01b4\3\2\2\2\177\u01b8\3\2\2\2\u0081\u01be\3\2\2\2\u0083"+
+               
"\u01c3\3\2\2\2\u0085\u01ca\3\2\2\2\u0087\u01cd\3\2\2\2\u0089\u01d1\3\2"+
+               
"\2\2\u008b\u01d4\3\2\2\2\u008d\u01d8\3\2\2\2\u008f\u01dc\3\2\2\2\u0091"+
+               
"\u01e1\3\2\2\2\u0093\u01ea\3\2\2\2\u0095\u01ef\3\2\2\2\u0097\u020e\3\2"+
+               
"\2\2\u0099\u024e\3\2\2\2\u009b\u0268\3\2\2\2\u009d\u009e\t\2\2\2\u009e"+
+               
"\4\3\2\2\2\u009f\u00a0\t\3\2\2\u00a0\6\3\2\2\2\u00a1\u00a2\t\4\2\2\u00a2"+
+               
"\b\3\2\2\2\u00a3\u00a4\t\5\2\2\u00a4\n\3\2\2\2\u00a5\u00a6\t\6\2\2\u00a6"+
+               
"\f\3\2\2\2\u00a7\u00a8\t\7\2\2\u00a8\16\3\2\2\2\u00a9\u00aa\t\b\2\2\u00aa"+
+               
"\20\3\2\2\2\u00ab\u00ac\t\t\2\2\u00ac\22\3\2\2\2\u00ad\u00ae\t\n\2\2\u00ae"+
+               
"\24\3\2\2\2\u00af\u00b0\t\13\2\2\u00b0\26\3\2\2\2\u00b1\u00b2\t\f\2\2"+
+               
"\u00b2\30\3\2\2\2\u00b3\u00b4\t\r\2\2\u00b4\32\3\2\2\2\u00b5\u00b6\t\16"+
+               
"\2\2\u00b6\34\3\2\2\2\u00b7\u00b8\t\17\2\2\u00b8\36\3\2\2\2\u00b9\u00ba"+
+               "\t\20\2\2\u00ba 
\3\2\2\2\u00bb\u00bc\t\21\2\2\u00bc\"\3\2\2\2\u00bd\u00be"+
+               
"\t\22\2\2\u00be$\3\2\2\2\u00bf\u00c0\t\23\2\2\u00c0&\3\2\2\2\u00c1\u00c2"+
+               
"\t\24\2\2\u00c2(\3\2\2\2\u00c3\u00c4\t\25\2\2\u00c4*\3\2\2\2\u00c5\u00c6"+
+               
"\t\26\2\2\u00c6,\3\2\2\2\u00c7\u00c8\t\27\2\2\u00c8.\3\2\2\2\u00c9\u00ca"+
+               
"\t\30\2\2\u00ca\60\3\2\2\2\u00cb\u00cc\t\31\2\2\u00cc\62\3\2\2\2\u00cd"+
+               
"\u00ce\t\32\2\2\u00ce\64\3\2\2\2\u00cf\u00d0\t\33\2\2\u00d0\66\3\2\2\2"+
+               
"\u00d1\u00d2\t\34\2\2\u00d28\3\2\2\2\u00d3\u00d4\t\35\2\2\u00d4:\3\2\2"+
+               
"\2\u00d5\u00d6\7/\2\2\u00d6\u00d7\7/\2\2\u00d7\u00db\3\2\2\2\u00d8\u00da"+
+               
"\n\36\2\2\u00d9\u00d8\3\2\2\2\u00da\u00dd\3\2\2\2\u00db\u00d9\3\2\2\2"+
+               
"\u00db\u00dc\3\2\2\2\u00dc\u00de\3\2\2\2\u00dd\u00db\3\2\2\2\u00de\u00df"+
+               
"\b\36\2\2\u00df<\3\2\2\2\u00e0\u00e1\7\61\2\2\u00e1\u00e2\7,\2\2\u00e2"+
+               
"\u00e6\3\2\2\2\u00e3\u00e5\13\2\2\2\u00e4\u00e3\3\2\2\2\u00e5\u00e8\3"+
+               
"\2\2\2\u00e6\u00e7\3\2\2\2\u00e6\u00e4\3\2\2\2\u00e7\u00ec\3\2\2\2\u00e8"+
+               
"\u00e6\3\2\2\2\u00e9\u00ea\7,\2\2\u00ea\u00ed\7\61\2\2\u00eb\u00ed\7\2"+
+               
"\2\3\u00ec\u00e9\3\2\2\2\u00ec\u00eb\3\2\2\2\u00ed\u00ee\3\2\2\2\u00ee"+
+               
"\u00ef\b\37\2\2\u00ef>\3\2\2\2\u00f0\u00f4\7\"\2\2\u00f1\u00f3\7\"\2\2"+
+               
"\u00f2\u00f1\3\2\2\2\u00f3\u00f6\3\2\2\2\u00f4\u00f2\3\2\2\2\u00f4\u00f5"+
+               
"\3\2\2\2\u00f5\u00fd\3\2\2\2\u00f6\u00f4\3\2\2\2\u00f7\u00f9\t\37\2\2"+
+               
"\u00f8\u00f7\3\2\2\2\u00f9\u00fa\3\2\2\2\u00fa\u00f8\3\2\2\2\u00fa\u00fb"+
+               
"\3\2\2\2\u00fb\u00fd\3\2\2\2\u00fc\u00f0\3\2\2\2\u00fc\u00f8\3\2\2\2\u00fd"+
+               "\u00fe\3\2\2\2\u00fe\u00ff\b 
\2\2\u00ff@\3\2\2\2\u0100\u0103\5I%\2\u0101"+
+               
"\u0103\5K&\2\u0102\u0100\3\2\2\2\u0102\u0101\3\2\2\2\u0102\u0103\3\2\2"+
+               
"\2\u0103\u0104\3\2\2\2\u0104\u0108\5\67\34\2\u0105\u0107\5\67\34\2\u0106"+
+               
"\u0105\3\2\2\2\u0107\u010a\3\2\2\2\u0108\u0106\3\2\2\2\u0108\u0109\3\2"+
+               
"\2\2\u0109\u0117\3\2\2\2\u010a\u0108\3\2\2\2\u010b\u010e\5\13\6\2\u010c"+
+               
"\u010f\5I%\2\u010d\u010f\5K&\2\u010e\u010c\3\2\2\2\u010e\u010d\3\2\2\2"+
+               
"\u010e\u010f\3\2\2\2\u010f\u0110\3\2\2\2\u0110\u0114\5\67\34\2\u0111\u0113"+
+               
"\5\67\34\2\u0112\u0111\3\2\2\2\u0113\u0116\3\2\2\2\u0114\u0112\3\2\2\2"+
+               
"\u0114\u0115\3\2\2\2\u0115\u0118\3\2\2\2\u0116\u0114\3\2\2\2\u0117\u010b"+
+               
"\3\2\2\2\u0117\u0118\3\2\2\2\u0118B\3\2\2\2\u0119\u011c\5I%\2\u011a\u011c"+
+               
"\5K&\2\u011b\u0119\3\2\2\2\u011b\u011a\3\2\2\2\u011b\u011c\3\2\2\2\u011c"+
+               
"\u011e\3\2\2\2\u011d\u011f\5\67\34\2\u011e\u011d\3\2\2\2\u011f\u0120\3"+
+               
"\2\2\2\u0120\u011e\3\2\2\2\u0120\u0121\3\2\2\2\u0121\u0122\3\2\2\2\u0122"+
+               
"\u0124\5Q)\2\u0123\u0125\5\67\34\2\u0124\u0123\3\2\2\2\u0125\u0126\3\2"+
+               
"\2\2\u0126\u0124\3\2\2\2\u0126\u0127\3\2\2\2\u0127\u0134\3\2\2\2\u0128"+
+               
"\u012b\5\13\6\2\u0129\u012c\5I%\2\u012a\u012c\5K&\2\u012b\u0129\3\2\2"+
+               
"\2\u012b\u012a\3\2\2\2\u012b\u012c\3\2\2\2\u012c\u012d\3\2\2\2\u012d\u0131"+
+               
"\5\67\34\2\u012e\u0130\5\67\34\2\u012f\u012e\3\2\2\2\u0130\u0133\3\2\2"+
+               
"\2\u0131\u012f\3\2\2\2\u0131\u0132\3\2\2\2\u0132\u0135\3\2\2\2\u0133\u0131"+
+               
"\3\2\2\2\u0134\u0128\3\2\2\2\u0134\u0135\3\2\2\2\u0135D\3\2\2\2\u0136"+
+               
"\u0139\5\u0093J\2\u0137\u0139\5\u0095K\2\u0138\u0136\3\2\2\2\u0138\u0137"+
+               
"\3\2\2\2\u0139F\3\2\2\2\u013a\u013b\7.\2\2\u013bH\3\2\2\2\u013c\u013d"+
+               
"\7-\2\2\u013dJ\3\2\2\2\u013e\u013f\7/\2\2\u013fL\3\2\2\2\u0140\u0141\7"+
+               
",\2\2\u0141N\3\2\2\2\u0142\u0143\7\61\2\2\u0143P\3\2\2\2\u0144\u0145\7"+
+               
"\60\2\2\u0145R\3\2\2\2\u0146\u0147\5\31\r\2\u0147\u0148\5\23\n\2\u0148"+
+               
"\u0149\5\27\f\2\u0149\u014a\5\13\6\2\u014aT\3\2\2\2\u014b\u014c\5\3\2"+
+               
"\2\u014c\u014d\5\35\17\2\u014d\u014e\5\t\5\2\u014eV\3\2\2\2\u014f\u0150"+
+               
"\5\37\20\2\u0150\u0151\5%\23\2\u0151X\3\2\2\2\u0152\u0153\7*\2\2\u0153"+
+               
"Z\3\2\2\2\u0154\u0155\7]\2\2\u0155\\\3\2\2\2\u0156\u0157\7+\2\2\u0157"+
+               
"^\3\2\2\2\u0158\u0159\7_\2\2\u0159`\3\2\2\2\u015a\u015f\7>\2\2\u015b\u015c"+
+               
"\5\31\r\2\u015c\u015d\5)\25\2\u015d\u015f\3\2\2\2\u015e\u015a\3\2\2\2"+
+               
"\u015e\u015b\3\2\2\2\u015fb\3\2\2\2\u0160\u0161\7>\2\2\u0161\u0167\7?"+
+               
"\2\2\u0162\u0163\5\31\r\2\u0163\u0164\5)\25\2\u0164\u0165\5\13\6\2\u0165"+
+               
"\u0167\3\2\2\2\u0166\u0160\3\2\2\2\u0166\u0162\3\2\2\2\u0167d\3\2\2\2"+
+               
"\u0168\u016d\7?\2\2\u0169\u016a\5\13\6\2\u016a\u016b\5#\22\2\u016b\u016d"+
+               
"\3\2\2\2\u016c\u0168\3\2\2\2\u016c\u0169\3\2\2\2\u016df\3\2\2\2\u016e"+
+               
"\u016f\7#\2\2\u016f\u0175\7?\2\2\u0170\u0171\5\35\17\2\u0171\u0172\5\13"+
+               
"\6\2\u0172\u0173\5#\22\2\u0173\u0175\3\2\2\2\u0174\u016e\3\2\2\2\u0174"+
+               
"\u0170\3\2\2\2\u0175h\3\2\2\2\u0176\u017b\7@\2\2\u0177\u0178\5\17\b\2"+
+               
"\u0178\u0179\5)\25\2\u0179\u017b\3\2\2\2\u017a\u0176\3\2\2\2\u017a\u0177"+
+               
"\3\2\2\2\u017bj\3\2\2\2\u017c\u017d\7@\2\2\u017d\u0183\7?\2\2\u017e\u017f"+
+               
"\5\17\b\2\u017f\u0180\5)\25\2\u0180\u0181\5\13\6\2\u0181\u0183\3\2\2\2"+
+               
"\u0182\u017c\3\2\2\2\u0182\u017e\3\2\2\2\u0183l\3\2\2\2\u0184\u0185\5"+
+               
"\r\7\2\u0185\u0186\5%\23\2\u0186\u0187\5\37\20\2\u0187\u0188\5\33\16\2"+
+               
"\u0188n\3\2\2\2\u0189\u018a\5/\30\2\u018a\u018b\5\21\t\2\u018b\u018c\5"+
+               
"\13\6\2\u018c\u018d\5%\23\2\u018d\u018e\5\13\6\2\u018ep\3\2\2\2\u018f"+
+               
"\u0190\5\37\20\2\u0190\u0191\5%\23\2\u0191\u0192\5\t\5\2\u0192\u0193\5"+
+               
"\13\6\2\u0193\u0194\5%\23\2\u0194\u0195\5\5\3\2\u0195\u0196\5\63\32\2"+
+               
"\u0196r\3\2\2\2\u0197\u0198\5\17\b\2\u0198\u0199\5%\23\2\u0199\u019a\5"+
+               
"\37\20\2\u019a\u019b\5+\26\2\u019b\u019c\5!\21\2\u019c\u019d\5\5\3\2\u019d"+
+               
"\u019e\5\63\32\2\u019et\3\2\2\2\u019f\u01a0\5\31\r\2\u01a0\u01a1\5\23"+
+               
"\n\2\u01a1\u01a2\5\33\16\2\u01a2\u01a3\5\23\n\2\u01a3\u01a4\5)\25\2\u01a4"+
+               
"v\3\2\2\2\u01a5\u01a6\5\'\24\2\u01a6\u01a7\5\13\6\2\u01a7\u01a8\5\31\r"+
+               
"\2\u01a8\u01a9\5\13\6\2\u01a9\u01aa\5\7\4\2\u01aa\u01ab\5)\25\2\u01ab"+
+               
"x\3\2\2\2\u01ac\u01ad\5\33\16\2\u01ad\u01ae\5\3\2\2\u01ae\u01af\5\61\31"+
+               
"\2\u01afz\3\2\2\2\u01b0\u01b1\5\33\16\2\u01b1\u01b2\5\23\n\2\u01b2\u01b3"+
+               
"\5\35\17\2\u01b3|\3\2\2\2\u01b4\u01b5\5\'\24\2\u01b5\u01b6\5+\26\2\u01b6"+
+               
"\u01b7\5\33\16\2\u01b7~\3\2\2\2\u01b8\u01b9\5\7\4\2\u01b9\u01ba\5\37\20"+
+               
"\2\u01ba\u01bb\5+\26\2\u01bb\u01bc\5\35\17\2\u01bc\u01bd\5)\25\2\u01bd"+
+               
"\u0080\3\2\2\2\u01be\u01bf\5\31\r\2\u01bf\u01c0\5\37\20\2\u01c0\u01c1"+
+               
"\5\37\20\2\u01c1\u01c2\5!\21\2\u01c2\u0082\3\2\2\2\u01c3\u01c4\5\37\20"+
+               
"\2\u01c4\u01c5\5\r\7\2\u01c5\u01c6\5\r\7\2\u01c6\u01c7\5\'\24\2\u01c7"+
+               
"\u01c8\5\13\6\2\u01c8\u01c9\5)\25\2\u01c9\u0084\3\2\2\2\u01ca\u01cb\5"+
+               
"\3\2\2\u01cb\u01cc\5\'\24\2\u01cc\u0086\3\2\2\2\u01cd\u01ce\5\23\n\2\u01ce"+
+               
"\u01cf\5\'\24\2\u01cf\u01d0\5\3\2\2\u01d0\u0088\3\2\2\2\u01d1\u01d2\5"+
+               
"\23\n\2\u01d2\u01d3\5\'\24\2\u01d3\u008a\3\2\2\2\u01d4\u01d5\5\21\t\2"+
+               
"\u01d5\u01d6\5\3\2\2\u01d6\u01d7\5\'\24\2\u01d7\u008c\3\2\2\2\u01d8\u01d9"+
+               
"\5\3\2\2\u01d9\u01da\5\'\24\2\u01da\u01db\5\7\4\2\u01db\u008e\3\2\2\2"+
+               
"\u01dc\u01dd\5\t\5\2\u01dd\u01de\5\13\6\2\u01de\u01df\5\'\24\2\u01df\u01e0"+
+               
"\5\7\4\2\u01e0\u0090\3\2\2\2\u01e1\u01e2\5/\30\2\u01e2\u01e3\5\23\n\2"+
+               
"\u01e3\u01e4\5)\25\2\u01e4\u01e5\5\21\t\2\u01e5\u01e6\5!\21\2\u01e6\u01e7"+
+               
"\5\3\2\2\u01e7\u01e8\5)\25\2\u01e8\u01e9\5\21\t\2\u01e9\u0092\3\2\2\2"+
+               
"\u01ea\u01eb\5)\25\2\u01eb\u01ec\5%\23\2\u01ec\u01ed\5+\26\2\u01ed\u01ee"+
+               
"\5\13\6\2\u01ee\u0094\3\2\2\2\u01ef\u01f0\5\r\7\2\u01f0\u01f1\5\3\2\2"+
+               
"\u01f1\u01f2\5\31\r\2\u01f2\u01f3\5\'\24\2\u01f3\u01f4\5\13\6\2\u01f4"+
+               
"\u0096\3\2\2\2\u01f5\u020f\5S*\2\u01f6\u020f\5Q)\2\u01f7\u020f\5w<\2\u01f8"+
+               
"\u020f\5\u0085C\2\u01f9\u020f\5\u008bF\2\u01fa\u020f\5\u0089E\2\u01fb"+
+               
"\u020f\5\u0087D\2\u01fc\u020f\5o8\2\u01fd\u020f\5u;\2\u01fe\u020f\5\u0093"+
+               
"J\2\u01ff\u020f\5\u0095K\2\u0200\u020f\5U+\2\u0201\u020f\5W,\2\u0202\u020f"+
+               
"\5s:\2\u0203\u020f\5q9\2\u0204\u020f\5\u0091I\2\u0205\u020f\5}?\2\u0206"+
+               
"\u020f\5{>\2\u0207\u020f\5y=\2\u0208\u020f\5\u0083B\2\u0209\u020f\5\u0081"+
+               
"A\2\u020a\u020f\5m\67\2\u020b\u020f\5\u008fH\2\u020c\u020f\5\u008dG\2"+
+               
"\u020d\u020f\5\177@\2\u020e\u01f5\3\2\2\2\u020e\u01f6\3\2\2\2\u020e\u01f7"+
+               
"\3\2\2\2\u020e\u01f8\3\2\2\2\u020e\u01f9\3\2\2\2\u020e\u01fa\3\2\2\2\u020e"+
+               
"\u01fb\3\2\2\2\u020e\u01fc\3\2\2\2\u020e\u01fd\3\2\2\2\u020e\u01fe\3\2"+
+               
"\2\2\u020e\u01ff\3\2\2\2\u020e\u0200\3\2\2\2\u020e\u0201\3\2\2\2\u020e"+
+               
"\u0202\3\2\2\2\u020e\u0203\3\2\2\2\u020e\u0204\3\2\2\2\u020e\u0205\3\2"+
+               
"\2\2\u020e\u0206\3\2\2\2\u020e\u0207\3\2\2\2\u020e\u0208\3\2\2\2\u020e"+
+               
"\u0209\3\2\2\2\u020e\u020a\3\2\2\2\u020e\u020b\3\2\2\2\u020e\u020c\3\2"+
+               
"\2\2\u020e\u020d\3\2\2\2\u020f\u0098\3\2\2\2\u0210\u024f\5\u009bN\2\u0211"+
+               
"\u0216\59\35\2\u0212\u0215\59\35\2\u0213\u0215\5\67\34\2\u0214\u0212\3"+
+               
"\2\2\2\u0214\u0213\3\2\2\2\u0215\u0218\3\2\2\2\u0216\u0214\3\2\2\2\u0216"+
+               
"\u0217\3\2\2\2\u0217\u024f\3\2\2\2\u0218\u0216\3\2\2\2\u0219\u021e\59"+
+               
"\35\2\u021a\u021d\59\35\2\u021b\u021d\5\67\34\2\u021c\u021a\3\2\2\2\u021c"+
+               
"\u021b\3\2\2\2\u021d\u0220\3\2\2\2\u021e\u021c\3\2\2\2\u021e\u021f\3\2"+
+               
"\2\2\u021f\u0221\3\2\2\2\u0220\u021e\3\2\2\2\u0221\u0225\5\u0097L\2\u0222"+
+               
"\u0224\5\u0097L\2\u0223\u0222\3\2\2\2\u0224\u0227\3\2\2\2\u0225\u0223"+
+               
"\3\2\2\2\u0225\u0226\3\2\2\2\u0226\u024f\3\2\2\2\u0227\u0225\3\2\2\2\u0228"+
+               
"\u022c\5\u0097L\2\u0229\u022b\5\u0097L\2\u022a\u0229\3\2\2\2\u022b\u022e"+
+               
"\3\2\2\2\u022c\u022a\3\2\2\2\u022c\u022d\3\2\2\2\u022d\u022f\3\2\2\2\u022e"+
+               
"\u022c\3\2\2\2\u022f\u0234\59\35\2\u0230\u0233\59\35\2\u0231\u0233\5\67"+
+               
"\34\2\u0232\u0230\3\2\2\2\u0232\u0231\3\2\2\2\u0233\u0236\3\2\2\2\u0234"+
+               
"\u0232\3\2\2\2\u0234\u0235\3\2\2\2\u0235\u024f\3\2\2\2\u0236\u0234\3\2"+
+               
"\2\2\u0237\u023c\59\35\2\u0238\u023b\59\35\2\u0239\u023b\5\67\34\2\u023a"+
+               
"\u0238\3\2\2\2\u023a\u0239\3\2\2\2\u023b\u023e\3\2\2\2\u023c\u023a\3\2"+
+               
"\2\2\u023c\u023d\3\2\2\2\u023d\u023f\3\2\2\2\u023e\u023c\3\2\2\2\u023f"+
+               
"\u0243\5\u0097L\2\u0240\u0242\5\u0097L\2\u0241\u0240\3\2\2\2\u0242\u0245"+
+               
"\3\2\2\2\u0243\u0241\3\2\2\2\u0243\u0244\3\2\2\2\u0244\u0246\3\2\2\2\u0245"+
+               
"\u0243\3\2\2\2\u0246\u024b\59\35\2\u0247\u024a\59\35\2\u0248\u024a\5\67"+
+               
"\34\2\u0249\u0247\3\2\2\2\u0249\u0248\3\2\2\2\u024a\u024d\3\2\2\2\u024b"+
+               
"\u0249\3\2\2\2\u024b\u024c\3\2\2\2\u024c\u024f\3\2\2\2\u024d\u024b\3\2"+
+               
"\2\2\u024e\u0210\3\2\2\2\u024e\u0211\3\2\2\2\u024e\u0219\3\2\2\2\u024e"+
+               
"\u0228\3\2\2\2\u024e\u0237\3\2\2\2\u024f\u009a\3\2\2\2\u0250\u0254\7$"+
+               "\2\2\u0251\u0253\n 
\2\2\u0252\u0251\3\2\2\2\u0253\u0256\3\2\2\2\u0254"+
+               
"\u0252\3\2\2\2\u0254\u0255\3\2\2\2\u0255\u0257\3\2\2\2\u0256\u0254\3\2"+
+               
"\2\2\u0257\u0269\7$\2\2\u0258\u025c\7)\2\2\u0259\u025b\n!\2\2\u025a\u0259"+
+               
"\3\2\2\2\u025b\u025e\3\2\2\2\u025c\u025a\3\2\2\2\u025c\u025d\3\2\2\2\u025d"+
+               
"\u025f\3\2\2\2\u025e\u025c\3\2\2\2\u025f\u0269\7)\2\2\u0260\u0264\7b\2"+
+               
"\2\u0261\u0263\n\"\2\2\u0262\u0261\3\2\2\2\u0263\u0266\3\2\2\2\u0264\u0262"+
+               
"\3\2\2\2\u0264\u0265\3\2\2\2\u0265\u0267\3\2\2\2\u0266\u0264\3\2\2\2\u0267"+
+               
"\u0269\7b\2\2\u0268\u0250\3\2\2\2\u0268\u0258\3\2\2\2\u0268\u0260\3\2"+
+               
"\2\2\u0269\u009c\3\2\2\2.\2\u00db\u00e6\u00ec\u00f4\u00fa\u00fc\u0102"+
+               
"\u0108\u010e\u0114\u0117\u011b\u0120\u0126\u012b\u0131\u0134\u0138\u015e"+
+               
"\u0166\u016c\u0174\u017a\u0182\u020e\u0214\u0216\u021c\u021e\u0225\u022c"+
+               
"\u0232\u0234\u023a\u023c\u0243\u0249\u024b\u024e\u0254\u025c\u0264\u0268"+
+               "\3\2\3\2";
+       public static final ATN _ATN =
+               new ATNDeserializer().deserialize(_serializedATN.toCharArray());
+       static {
+               _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
+               for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
+                       _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), 
i);
+               }
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/5bd5327c/repository/src/main/java/org/apache/atlas/query/antlr4/AtlasDSLLexer.tokens
----------------------------------------------------------------------
diff --git 
a/repository/src/main/java/org/apache/atlas/query/antlr4/AtlasDSLLexer.tokens 
b/repository/src/main/java/org/apache/atlas/query/antlr4/AtlasDSLLexer.tokens
new file mode 100644
index 0000000..8c147b4
--- /dev/null
+++ 
b/repository/src/main/java/org/apache/atlas/query/antlr4/AtlasDSLLexer.tokens
@@ -0,0 +1,59 @@
+SINGLE_LINE_COMMENT=1
+MULTILINE_COMMENT=2
+WS=3
+NUMBER=4
+FLOATING_NUMBER=5
+BOOL=6
+K_COMMA=7
+K_PLUS=8
+K_MINUS=9
+K_STAR=10
+K_DIV=11
+K_DOT=12
+K_LIKE=13
+K_AND=14
+K_OR=15
+K_LPAREN=16
+K_LBRACKET=17
+K_RPAREN=18
+K_RBRACKET=19
+K_LT=20
+K_LTE=21
+K_EQ=22
+K_NEQ=23
+K_GT=24
+K_GTE=25
+K_FROM=26
+K_WHERE=27
+K_ORDERBY=28
+K_GROUPBY=29
+K_LIMIT=30
+K_SELECT=31
+K_MAX=32
+K_MIN=33
+K_SUM=34
+K_COUNT=35
+K_LOOP=36
+K_OFFSET=37
+K_AS=38
+K_ISA=39
+K_IS=40
+K_HAS=41
+K_ASC=42
+K_DESC=43
+K_WITHPATH=44
+K_TRUE=45
+K_FALSE=46
+KEYWORD=47
+ID=48
+STRING=49
+','=7
+'+'=8
+'-'=9
+'*'=10
+'/'=11
+'.'=12
+'('=16
+'['=17
+')'=18
+']'=19

http://git-wip-us.apache.org/repos/asf/atlas/blob/5bd5327c/repository/src/main/java/org/apache/atlas/query/antlr4/AtlasDSLParser.g4
----------------------------------------------------------------------
diff --git 
a/repository/src/main/java/org/apache/atlas/query/antlr4/AtlasDSLParser.g4 
b/repository/src/main/java/org/apache/atlas/query/antlr4/AtlasDSLParser.g4
new file mode 100644
index 0000000..bf6b7e3
--- /dev/null
+++ b/repository/src/main/java/org/apache/atlas/query/antlr4/AtlasDSLParser.g4
@@ -0,0 +1,117 @@
+/**
+ * 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.
+ */
+
+parser grammar AtlasDSLParser;
+
+options { tokenVocab=AtlasDSLLexer; }
+
+// Start of rules, bottom-up (rules at the end are built using the core rules)
+
+// Core rules
+identifier: ID ;
+
+operator: (K_LT | K_LTE | K_EQ | K_NEQ | K_GT | K_GTE | K_LIKE) ;
+
+sortOrder: K_ASC | K_DESC ;
+
+valueArray: K_LBRACKET STRING (K_COMMA STRING)* K_RBRACKET ;
+
+literal: BOOL | NUMBER | FLOATING_NUMBER | (STRING | valueArray) ;
+
+// Composite rules
+limitClause: K_LIMIT NUMBER ;
+
+offsetClause: K_OFFSET NUMBER ;
+
+atomE: (identifier | literal) | K_LPAREN expr K_RPAREN ;
+
+multiERight: (K_STAR | K_DIV) atomE ;
+
+multiE: atomE multiERight* ;
+
+arithERight: (K_PLUS | K_MINUS) multiE ;
+
+arithE: multiE arithERight* ;
+
+comparisonClause: arithE operator arithE ;
+
+isClause: arithE (K_ISA | K_IS) identifier ;
+
+hasClause: arithE K_HAS identifier ;
+
+countClause: K_COUNT K_LPAREN K_RPAREN ;
+
+maxClause: K_MAX K_LPAREN expr K_RPAREN ;
+
+minClause: K_MIN K_LPAREN expr K_RPAREN ;
+
+sumClause: K_SUM K_LPAREN expr K_RPAREN ;
+
+exprRight: (K_AND | K_OR) compE ;
+
+compE: comparisonClause
+    | isClause
+    | hasClause
+    | arithE
+    | countClause
+    | maxClause
+    | minClause
+    | sumClause
+    ;
+
+expr: compE exprRight* ;
+
+limitOffset: limitClause offsetClause? ;
+
+selectExpression: expr (K_AS identifier)? ;
+
+selectExpr: selectExpression (K_COMMA selectExpression)* ;
+
+aliasExpr: (identifier | literal) K_AS identifier ;
+
+orderByExpr: K_ORDERBY expr sortOrder? ;
+
+fromSrc: aliasExpr | (identifier | literal) ;
+
+whereClause: K_WHERE expr ;
+
+fromExpression: fromSrc whereClause? ;
+
+fromClause: K_FROM fromExpression ;
+
+selectClause: K_SELECT selectExpr ;
+
+singleQrySrc: fromClause | whereClause | fromExpression | expr ;
+
+loopExpression: K_LOOP K_LPAREN query K_RPAREN NUMBER? (K_AS identifier)? ;
+
+groupByExpression: K_GROUPBY K_LPAREN selectExpr K_RPAREN ;
+
+commaDelimitedQueries: singleQrySrc (K_COMMA singleQrySrc)* ;
+
+spaceDelimitedQueries: singleQrySrc singleQrySrc* ;
+
+querySrc: commaDelimitedQueries | spaceDelimitedQueries ;
+
+query: querySrc loopExpression?
+                groupByExpression?
+                selectClause?
+                orderByExpr?
+                limitOffset? ;
+
+queryWithPath: query (K_WITHPATH)? ;

Reply via email to