[hibernate-commits] Hibernate SVN: r15693 - in core/branches/SQL_GEN_REDESIGN: src/main/antlr and 9 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Sat Dec 13 11:25:05 EST 2008


Author: steve.ebersole at jboss.com
Date: 2008-12-13 11:25:05 -0500 (Sat, 13 Dec 2008)
New Revision: 15693

Added:
   core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/
   core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/parse.g
   core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/resolve.g
   core/branches/SQL_GEN_REDESIGN/src/main/antlr/sql/
   core/branches/SQL_GEN_REDESIGN/src/main/antlr/sql/common.g
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/hql/ast/phase/
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/hql/ast/phase/parse/
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/hql/ast/phase/parse/ASTFactoryImpl.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/hql/ast/phase/parse/HqlParser.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/hql/ast/phase/parse/PathCollector.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/DetailedSemanticException.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/QuerySyntaxException.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/AbstractToken.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/CommonHibernateLexer.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/JoinType.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/Node.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/NumericLiteralToken.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/PanicException.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/TokenImpl.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTAppender.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTIterator.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTParentsFirstIterator.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTPrinter.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTUtil.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/DisplayableNode.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ErrorCounter.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ErrorReporter.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/NodeTraverser.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ParseErrorHandler.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/PathHelper.java
Modified:
   core/branches/SQL_GEN_REDESIGN/pom.xml
Log:
initial working parse.g

Modified: core/branches/SQL_GEN_REDESIGN/pom.xml
===================================================================
--- core/branches/SQL_GEN_REDESIGN/pom.xml	2008-12-12 20:48:49 UTC (rev 15692)
+++ core/branches/SQL_GEN_REDESIGN/pom.xml	2008-12-13 16:25:05 UTC (rev 15693)
@@ -2,19 +2,13 @@
 
     <modelVersion>4.0.0</modelVersion>
 
-    <parent>
-        <groupId>org.hibernate</groupId>
-        <artifactId>hibernate-parent</artifactId>
-        <version>3.4.0-SNAPSHOT</version>
-        <relativePath>../parent/pom.xml</relativePath>
-    </parent>
-
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate-core</artifactId>
+    <version>3.4.0.SQL_GEN_REDESIGN</version>
     <packaging>jar</packaging>
 
-    <name>Hibernate Core</name>
-    <description>The core functionality of Hibernate</description>
+    <name>Hibernate Core (SQL Generation Redesign)</name>
+    <description>The core functionality of Hibernate (with redesign of SQL generation)</description>
 
     <dependencies>
         <dependency>
@@ -29,6 +23,10 @@
             <groupId>dom4j</groupId>
             <artifactId>dom4j</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
 
         <dependency>
             <!-- YUCK, YUCK, YUCK!!!! -->
@@ -68,71 +66,148 @@
             <version>2.1_3</version>
             <optional>true</optional>
         </dependency>
+        <!-- test-scoped dependencies for common testing dependencies -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>3.8.1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>jcl-over-slf4j</artifactId>
+            <version>1.5.2</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <version>1.5.2</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+            <version>1.2.14</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+            <version>99.0-does-not-exist</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging-api</artifactId>
+            <version>99.0-does-not-exist</version>
+            <scope>test</scope>
+        </dependency>
+        <!-- / test-scoped dependencies for common testing dependencies -->
     </dependencies>
 
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-api</artifactId>
+                <version>1.5.2</version>
+            </dependency>
+            <dependency>
+                <groupId>antlr</groupId>
+                <artifactId>antlr</artifactId>
+                <version>2.7.6</version>
+            </dependency>
+            <dependency>
+                <groupId>commons-collections</groupId>
+                <artifactId>commons-collections</artifactId>
+                <version>3.1</version>
+            </dependency>
+            <dependency>
+                <groupId>dom4j</groupId>
+                <artifactId>dom4j</artifactId>
+                <version>1.6.1</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <distributionManagement>
+        <repository>
+            <!-- Copy the dist to the local checkout of the JBoss maven2 repo ${maven.repository.root} -->
+            <!-- It is anticipated that ${maven.repository.root} be set in user's settings.xml -->
+            <!-- todo : replace this with direct svn access once the svnkit providers are available -->
+            <id>repository.jboss.org</id>
+            <url>file://${maven.repository.root}</url>
+        </repository>
+        <snapshotRepository>
+            <id>snapshots.jboss.org</id>
+            <name>JBoss Snapshot Repository</name>
+            <url>dav:https://snapshots.jboss.org/maven2</url>
+        </snapshotRepository>
+    </distributionManagement>
+
     <build>
         <plugins>
             <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>antlr-maven-plugin</artifactId>
-                <version>${antlrPluginVersion}</version>
-                <configuration>
-                    <grammars>hql.g,hql-sql.g,sql-gen.g,order-by.g,order-by-render.g</grammars>
-                </configuration>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-enforcer-plugin</artifactId>
                 <executions>
                     <execution>
+                        <id>enforce-java</id>
                         <goals>
-                            <goal>generate</goal>
+                            <goal>enforce</goal>
                         </goals>
+                        <configuration>
+                            <rules>
+                                <requireJavaVersion>
+                                    <version>[1.5,)</version>
+                                </requireJavaVersion>
+                                <requireMavenVersion>
+                                    <version>(2.0.7,)</version>
+                                </requireMavenVersion>
+                            </rules>
+                        </configuration>
                     </execution>
                 </executions>
             </plugin>
-        </plugins>
-    </build>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.4</source>
+                    <target>1.4</target>
+                </configuration>
+            </plugin>
 
-    <reporting>
-        <plugins>
             <plugin>
                 <groupId>org.codehaus.mojo</groupId>
                 <artifactId>antlr-maven-plugin</artifactId>
                 <version>${antlrPluginVersion}</version>
                 <configuration>
-                    <!-- eventually should be based on the second phase grammar -->
-                    <grammars>hql.g</grammars>
+                    <traceParser>true</traceParser>
+                    <grammarDefs>
+                        <grammar>
+                          <name>sql/common.g</name>
+                        </grammar>
+                        <grammar>
+                            <name>hql/parse.g</name>
+                            <glib>sql/common.g</glib>
+                        </grammar>
+                    </grammarDefs>
                 </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate</goal>
+                        </goals>
+                    </execution>
+                </executions>
             </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-javadoc-plugin</artifactId>
-                <configuration>
-                    <!-- 
-                    for the time being, gonna ignore the custom stylesheet (what did it do anyway???) 
-                    <stylesheetfile>xyz</stylesheetfile>
-                    -->
-                    <groups>
-                        <group>
-                            <title>Core API</title>
-                            <packages>org.hibernate:org.hibernate.classic:org.hibernate.criterion:org.hibernate.metadata:org.hibernate.cfg:org.hibernate.usertype</packages>
-                        </group>
-                        <group>
-                            <title>Extension API</title>
-                            <packages>org.hibernate.id:org.hibernate.connection:org.hibernate.transaction:org.hibernate.type:org.hibernate.dialect*:org.hibernate.cache*:org.hibernate.event*:org.hibernate.action:org.hibernate.property:org.hibernate.loader*:org.hibernate.persister*:org.hibernate.proxy:org.hibernate.tuple:org.hibernate.transform:org.hibernate.collection:org.hibernate.jdbc</packages>
-                        </group>
-                        <group>
-                            <title>Miscellaneous API</title>
-                            <packages>org.hibernate.stat:org.hibernate.tool.hbm2ddl:org.hibernate.jmx:org.hibernate.mapping:org.hibernate.tool.instrument</packages>
-                        </group>
-                        <group>
-                            <title>Internal Implementation</title>
-			    <packages>org.hibernate.engine:org.hibernate.impl:org.hibernate.sql:org.hibernate.lob:org.hibernate.util:org.hibernate.exception:org.hibernate.hql:org.hibernate.hql.ast:org.hibernate.hql.antlr:org.hibernate.hql.classic:org.hibernate.intercept:org.hibernate.secure:org.hibernate.pretty</packages>
-                        </group>
-                    </groups>
-                </configuration>
-            </plugin>
+
         </plugins>
-    </reporting>
+    </build>
 
     <properties>
         <antlrPluginVersion>2.1</antlrPluginVersion>
     </properties>
-</project>
\ No newline at end of file
+</project>

Added: core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/parse.g
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/parse.g	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/parse.g	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,1138 @@
+header {
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ * Portions of SQL grammar parsing copyright (C) 2003 by Lubos Vnuk.  All rights
+ * reserved.  These portions are distributed under license by Red Hat Middleware
+ * LLC and are covered by the above LGPL notice.  If you redistribute this material,
+ * with or without modification, you must preserve this copyright notice in its
+ * entirety.
+ */
+package org.hibernate.hql.ast.phase.parse;
+
+import antlr.collections.AST;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.sql.ast.common.CommonHibernateParserSupport;
+}
+
+/**
+ * An Antlr stream parser for building a syntax AST representing an input Hibernate Query Language (HQL) query.
+ *
+ * @author Lubos Vnuk
+ * @author Joshua Davis
+ * @author Steve Ebersole
+ */
+class GeneratedHqlParser extends CommonHibernateParserSupport;
+
+options {
+    importVocab = Sql92;
+	exportVocab = HqlParse;
+	buildAST = true;
+	k = 3;
+}
+
+tokens {
+    // Various synthetic tokens used to simplify or disambiguate the tree
+	ALIAS;
+	ALIAS_REF;
+	ARG_LIST;
+	ASSIGNMENT_OP;
+	CLASS_NAME;
+	CONSTRUCTOR;
+	COLLECTION_ROLE;
+	ENTITY_NAME;
+	FILTER_ENTITY;
+	GENERIC_FUNCTION;
+	INDEX_OP;
+	INSERTABILITY_SPEC;
+	IN_LIST;
+	IS_NOT_NULL;
+	IS_NULL;
+	JAVA_CONSTANT;
+	JPA_PARAM;
+	NAMED_PARAM;
+	NOT_BETWEEN;
+	NOT_IN;
+	NOT_LIKE;
+    ORDER_SPEC;
+	PROP_FETCH;
+	QUERY;
+    REGISTERED_FUNCTION;
+	SELECT_FROM;
+    SORT_KEY;
+    SORT_SPEC;
+    SQL_TOKEN;
+	UNARY_MINUS;
+	UNARY_PLUS;
+	PERSISTER_SPACE;
+//	WEIRD_IDENT;
+
+//    AGGREGATE;
+	EXPR_LIST;
+//	ROW_STAR;
+	VECTOR_EXPR;
+}
+
+{
+    private static Logger log = LoggerFactory.getLogger( GeneratedHqlParser99.class );
+
+    protected String extractText(AST node) {
+        return node.getText();
+    }
+
+    protected String extractPath(AST node) {
+        return extractText( node );
+    }
+
+	protected boolean isJavaConstant(String test) {
+		return false;
+	}
+
+	protected AST processEqualityExpression(AST node) throws RecognitionException {
+		return node;
+	}
+
+	protected AST processMemberOf(AST path, AST notNode) {
+	    return path;
+	}
+
+	protected AST processIsEmpty(AST collection, AST notNode) {
+	    return null;
+    }
+
+	/**
+	 * This method is overriden in the sub class in order to provide the
+	 * 'keyword as identifier' hack.
+	 * @param token The token to retry as an identifier.
+	 * @param ex The exception to throw if it cannot be retried as an identifier.
+	 */
+	protected AST handleIdentifierError(Token token,RecognitionException ex) throws RecognitionException, TokenStreamException {
+		// Base implementation: Just re-throw the exception.
+		throw ex;
+	}
+
+    /**
+     * This method looks ahead and converts . <token> into . IDENT when
+     * appropriate.
+     */
+    protected void handleDotIdent() throws TokenStreamException {
+    }
+
+	/**
+	 * Returns the negated equivalent of the expression.
+	 * @param node The expression to negate.
+	 */
+	protected AST negateNode(AST node) {
+		// Just create a 'not' parent for the default behavior.
+	    return #( [NOT,"not"], node );
+	}
+
+	protected void weakKeywords() throws TokenStreamException {
+	}
+
+    protected void potentialUpdatePersisterAlias() throws TokenStreamException {
+    }
+
+    protected void potentialDeletePersisterAlias() throws TokenStreamException {
+    }
+
+    protected void prepareForPersisterReferenceRoot() throws TokenStreamException {
+    }
+
+    protected void prepareForCrossJoinElements() throws TokenStreamException {
+    }
+
+    protected void prepareForQualifiedJoinElements() throws TokenStreamException {
+    }
+
+    protected void unequivocalKeywordAsIdentifier() throws TokenStreamException {
+    }
+
+    protected void transferTrackingInfo(AST source, AST target) {
+        int type = target.getType();
+        String text = target.getText();
+        target.initialize( source );
+        target.setType( type );
+        target.setText( text );
+    }
+}
+
+// Rules dealing with various IDENT structures ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+identifier :
+    IDENT
+	exception
+	catch [RecognitionException ex] {
+		identifier_AST = handleIdentifierError(LT(1),ex);
+	}
+;
+
+path :
+    identifier { handleDotIdent(); } ( DOT^ identifier )*
+;
+
+/**
+ * Specialied IDENT ( DOT IDENT ) recognition rule for cases where we are fully expecting an entity name.
+ * <p/>
+ * Use the {@link #path} rule here because it is less complex to resolve (and so i assume faster).
+ */
+protected
+entityName :
+    p:path {
+        String name = extractPath( #p );
+        #entityName = #( [ENTITY_NAME,name] );
+        transferTrackingInfo( #p, #entityName );
+    }
+;
+
+protected
+className :
+    p:path {
+		String name = extractPath( #p );
+        #className = #( [CLASS_NAME,name] );
+        transferTrackingInfo( #p, #className );
+    }
+;
+
+
+// alias/correlation recognition rules ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+/**
+ * Creation of an alias or correlation-name.
+ */
+alias :
+    // if the AS is present, it signals that whatever follows is unequivocally an identifier
+    ( AS! { unequivocalKeywordAsIdentifier(); } )? {weakKeywords();} i:identifier {
+        #i.setType( ALIAS );
+    }
+;
+
+/**
+ * Reference to an alias or correlation-name
+ */
+aliasReference :
+    {weakKeywords();} i:identifier {
+        #i.setType( ALIAS_REF );
+    }
+;
+
+
+// Statement rules ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+/**
+ * The main grammar rule
+ */
+statement :
+    updateStatement
+    | deleteStatement
+    | insertStatement
+    | selectStatement
+;
+
+
+
+// filter rules ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+filterStatement :
+    filteredSelectFrom (whereClause)? ( groupByClause ( havingClause )? )? (orderByClause)? {
+	    #filterStatement = #( [QUERY,"query"], #filterStatement );
+    }
+;
+
+filteredSelectFrom :
+    ( s:selectClause )? ( f:fromClause )? {
+		if ( #f != null ) {
+            throw new SemanticException( "collection filters cannot specify explicit FROM clause" );
+        }
+		// Create an artificial token so the 'FROM' can be placed
+		// before the SELECT in the tree to make tree processing
+		// simpler.
+		#filteredSelectFrom = #( [SELECT_FROM,"SELECT_FROM"], #f, #s );
+	}
+;
+
+
+// <tt>UPDATE</tt> statement ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+/**
+ * Recognize an <tt>UPDATE</tt> statement
+ */
+updateStatement :
+    UPDATE^ (VERSIONED)?
+	    (FROM!)? {unequivocalKeywordAsIdentifier();} entityName {potentialUpdatePersisterAlias();} (alias)?
+	    setClause
+	    (whereClause)?
+;
+
+setClause
+	: (SET^ assignment (COMMA! assignment)*)
+	;
+
+assignment :
+    assignmentField eo:EQUALS_OP^ newValue {
+	    #eo.setType( ASSIGNMENT_OP );
+    }
+;
+
+assignmentField :
+    path
+;
+
+newValue :
+    concatenation
+;
+
+
+// <tt>DELETE</tt> statement ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+/**
+ * Recognize an HQL <tt>DELETE</tt> statement
+ */
+deleteStatement :
+    DELETE^
+        ( FROM! )? {unequivocalKeywordAsIdentifier();} entityName {potentialDeletePersisterAlias();} (alias)?
+        ( whereClause )?
+;
+
+
+// <tt>INSERT</tt> statement ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+/**
+ * Recognize an HQL <tt>INSERT</tt> statement
+ */
+insertStatement :
+	INSERT^ intoClause selectStatement
+;
+
+intoClause :
+    INTO^ {unequivocalKeywordAsIdentifier();} entityName insertabilitySpecification
+;
+
+insertabilitySpecification :
+    LEFT_PAREN! insertablePropertySpecification ( COMMA! insertablePropertySpecification )* RIGHT_PAREN! {
+		#insertabilitySpecification = #( [INSERTABILITY_SPEC, "insertability-spec"], #insertabilitySpecification );
+	}
+;
+
+/**
+ * The property being inserted into.
+ */
+insertablePropertySpecification :
+    // todo : ok for this to just be IDENT?
+    //      do we want to allow users to target specific component sub-properties?
+    identifier
+;
+
+
+// <tt>SELECT</tt> statement rules ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+/**
+ * Recognize an HQL <tt>SELECT</tt> statement.
+ * <p/>
+ * This corresponds most closely to the <cursor specification> rule in ISO/ANSI SQL...
+ */
+selectStatement :
+	queryExpression ( orderByClause )? {
+	    #selectStatement = #( [QUERY,"query"], #selectStatement );
+    }
+;
+
+orderByClause :
+    ORDER^ BY! sortSpecification ( COMMA! sortSpecification )*
+;
+
+/**
+ * Reconition rule for what ANSI SQL terms the <tt>sort specification</tt>, which is essentially each thing upon which
+ * the results should be sorted.
+ */
+sortSpecification :
+    sortKey (collationSpecification)? (orderingSpecification)? {
+        #sortSpecification = #( [SORT_SPEC, "{sort specification}"], #sortSpecification );
+    }
+;
+
+/**
+ * Reconition rule for what ANSI SQL terms the <tt>sort key</tt> which is the expression (column, function, etc) upon
+ * which to base the sorting.
+ */
+sortKey :
+    expression
+;
+
+/**
+ * Reconition rule for what ANSI SQL terms the <tt>collation specification</tt> used to allow specifying that sorting for
+ * the given {@link #sortSpecification} be treated within a specific character-set.
+ */
+collationSpecification!  :
+    c:COLLATE cn:collationName {
+        #collationSpecification = #( [COLLATE, extractText( #cn )] );
+    }
+;
+
+/**
+ * The collation name wrt {@link #collationSpecification}.  Namely, the character-set.
+ */
+collationName :
+    identifier
+;
+
+/**
+ * Reconition rule for what ANSI SQL terms the <tt>ordering specification</tt>; <tt>ASCENDING</tt> or
+ * <tt>DESCENDING</tt>.
+ */
+orderingSpecification :
+    // todo : what about "ascending" and "descending" literals?
+    ( ASCENDING | DESCENDING) {
+	    #orderingSpecification = #( [ORDER_SPEC, extractText( #orderingSpecification )] );
+    }
+;
+
+queryExpression :
+  querySpec ( ( UNION | INTERSECT | EXCEPT ) (ALL)? querySpec )*
+;
+
+querySpec :
+    selectFrom
+        ( whereClause )?
+        ( groupByClause ( havingClause )? )?
+;
+
+selectFrom! :
+    ( s:selectClause )? f:fromClause {
+		// Create an artificial token so the 'FROM' can be placed
+		// before the SELECT in the tree to make tree processing
+		// simpler.
+		#selectFrom = #( [SELECT_FROM,"SELECT_FROM"], f, s );
+	}
+;
+
+subQuery :
+    queryExpression {
+        #subQuery = #( [QUERY,"query"], #subQuery );
+    }
+;
+
+
+// table/persister related rules ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+fromClause :
+    FROM^ {unequivocalKeywordAsIdentifier();} persisterSpaces
+;
+
+persisterSpaces :
+    // todo : better name?
+    persisterSpace ( COMMA! persisterSpace )*
+;
+
+persisterSpace :
+    {prepareForPersisterReferenceRoot();} persisterSpaceRoot ( qualifiedJoin | crossJoin )* {
+        #persisterSpace = #( [PERSISTER_SPACE, "persister-space"], #persisterSpace );
+    }
+;
+
+/**
+ * Recognition rule for root persister references.  Forms include:<ol>
+ * <li>[entityName [AS alias]? [FETCH ALL PROPERTIES]?] - which is the standard entity persister reference</li>
+ * <li>[IN (collection-reference) [AS alias]?] - which is the JPA variant of a collection join</li>
+ * <li>[alias IN CLASS entityName] - which is the legacy HQL syntax</li>
+ * <li>[alias IN [ELEMENTS|INDICES]? (collection-reference)] - legacy HQL syntax for a collection join</li>
+ *</ol>
+ * <p/>
+ * NOTE that only options #1 and #3 are valid as the initial root space for a top-level query since
+ * all the other forms require an already existing persister reference in order to reference a collection.
+ */
+persisterSpaceRoot :
+    hibernateLegacySyntax
+    | jpaCollectionReference
+    | mainEntityPersisterReference
+;
+
+hibernateLegacySyntax :
+    a:identifier! IN! (
+        // allow these legacy Hibernate syntaxes, but normalize them and emit a warning...
+        CLASS! {unequivocalKeywordAsIdentifier();} en:entityName! {
+            log.warn( "encountered deprecated, legacy from-clause syntax : [<alias> in class <entity-name>]" );
+            #a.setType( ALIAS );
+            #hibernateLegacySyntax = #( #en, #a );
+        }
+        | ( ELEMENTS! | INDICES! )? LEFT_PAREN! {unequivocalKeywordAsIdentifier();} p:path! RIGHT_PAREN! {
+            log.warn( "encountered deprecated, legacy from-clause syntax : [<alias> in <elements|indices> (<collection-ref>)]" );
+            // todo : properly treat ELEMENTS | INDICES...
+            #a.setType( ALIAS );
+            #hibernateLegacySyntax = #( [JOIN,"join"], [INNER, "inner"], #p, #a );
+        }
+    )
+;
+
+mainEntityPersisterReference :
+    entityName (alias)? (propertyFetch)?
+;
+
+jpaCollectionReference :
+    IN! LEFT_PAREN! {unequivocalKeywordAsIdentifier();} p2:path RIGHT_PAREN! ( a2:alias )? {
+        #jpaCollectionReference = #( [JOIN,"join"], [INNER, "inner"], #p2, #a2 );
+    }
+;
+
+crossJoin :
+    CROSS JOIN^ {prepareForCrossJoinElements();} entityName (alias)? (propertyFetch)?
+;
+
+qualifiedJoin! :
+    (jt:nonCrossJoinType)? j:JOIN {if (#jt==null) #jt=#([INNER]);} (f:FETCH)? {prepareForQualifiedJoinElements();} p:path (a:alias)? (
+        // try to use the ON keyword to disambiguate
+        js:joinSpecification {
+            if ( #f != null ) {
+                throw new org.hibernate.QueryException( "Cannot use fetch keyword in conjunction with an ad hoc join" );
+            }
+            String entityName = extractPath( #p );
+            #qualifiedJoin = #( #j, #jt, [ENTITY_NAME,entityName], #a, #js );
+        }
+        | (pf:propertyFetch)? (w:withClause)? {
+            #qualifiedJoin = #( #j, #jt, #f, #a, #pf, #p, #w );
+        }
+    )
+;
+
+nonCrossJoinType :
+    INNER
+    | outerJoinType ( OUTER )?
+;
+
+outerJoinType :
+    LEFT
+    | RIGHT
+;
+
+joinSpecification :
+    ON^ logicalExpression
+;
+
+withClause :
+    WITH^ logicalExpression
+;
+
+propertyFetch! :
+    FETCH! ALL! PROPERTIES! {
+		#propertyFetch = #( [PROP_FETCH, "property-fetch"] );
+	}
+;
+
+
+// select clause related rules ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+selectClause
+	: SELECT^	// NOTE: The '^' after a token causes the corresponding AST node to be the root of the sub-tree.
+		{ weakKeywords(); }	// Weak keywords can appear immediately after a SELECT token.
+		(DISTINCT)? ( selectedPropertiesList | newExpression | selectObject )
+	;
+
+newExpression
+	: (NEW! path) op:LEFT_PAREN^ {#op.setType(CONSTRUCTOR);} selectedPropertiesList RIGHT_PAREN!
+	;
+
+selectObject
+   : OBJECT^ LEFT_PAREN! identifier RIGHT_PAREN!
+   ;
+
+selectedPropertiesList
+	: aliasedExpression ( COMMA! aliasedExpression )*
+	;
+
+aliasedExpression
+	: expression ( AS^ identifier )?
+	;
+
+
+
+// where clause rules ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+whereClause :
+    WHERE^ logicalExpression
+;
+
+
+
+// group by clause rules ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+groupByClause :
+    GROUP^ BY! groupingSpecification
+;
+
+groupingSpecification :
+    groupingValue ( COMMA groupingValue )*
+;
+
+groupingValue :
+    path ( collationSpecification )?
+;
+
+
+
+// having clause related rules ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+havingClause :
+    HAVING^ logicalExpression
+;
+
+// expressions
+// Note that most of these expressions follow the pattern
+//   thisLevelExpression :
+//       nextHigherPrecedenceExpression
+//           (OPERATOR nextHigherPrecedenceExpression)*
+// which is a standard recursive definition for a parsing an expression.
+//
+// Operator precedence in HQL
+// lowest  --> ( 7)  OR
+//             ( 6)  AND, NOT
+//             ( 5)  equality: ==, <>, !=, is
+//             ( 4)  relational: <, <=, >, >=,
+//                   LIKE, NOT LIKE, BETWEEN, NOT BETWEEN, IN, NOT IN
+//             ( 3)  addition and subtraction: +(binary) -(binary)
+//             ( 2)  multiplication: * / %, concatenate: ||
+// highest --> ( 1)  +(unary) -(unary)
+//                   []   () (method call)  . (dot -- identifier qualification)
+//                   aggregate function
+//                   ()  (explicit parenthesis)
+//
+// Note that the above precedence levels map to the rules below...
+// Once you have a precedence chart, writing the appropriate rules as below
+// is usually very straightfoward
+
+logicalExpression
+	: expression
+	;
+
+// Main expression rule
+expression
+	: logicalOrExpression
+	;
+
+// level 7 - OR
+logicalOrExpression
+	: logicalAndExpression ( OR^ logicalAndExpression )*
+	;
+
+// level 6 - AND, NOT
+logicalAndExpression
+	: negatedExpression ( AND^ negatedExpression )*
+	;
+
+// NOT nodes aren't generated.  Instead, the operator in the sub-tree will be
+// negated, if possible.   Expressions without a NOT parent are passed through.
+negatedExpression!
+{ weakKeywords(); } // Weak keywords can appear in an expression, so look ahead.
+	: NOT^ x:negatedExpression { #negatedExpression = negateNode(#x); }
+	| y:equalityExpression { #negatedExpression = #y; }
+	;
+
+//## OP: EQUALS_OP | LESS_THAN_OP | GREATER_THAN_OP | LESS_THAN_OR_EQUALS_OP | GREATER_THAN_OR_EQUALS_OP | NOT_EQUALS_OP | LIKE;
+
+// level 5 - EQUALS_OP, NOT_EQUALS_OP
+equalityExpression : 
+    x:relationalExpression (
+	    IS! (not:NOT!)? ( nullness:NULL! | emptiness:EMPTY! ) {
+	        if ( #nullness != null ) {
+	            log.debug( "handling <is [not] null> : " + #x.toStringTree() );
+	            #equalityExpression = #( [IS_NULL, "is null"], #x );
+	            if ( #not != null ) {
+	                negateNode( #equalityExpression );
+                }
+            }
+	        else {
+	            #equalityExpression = processIsEmpty( #x, #not );
+            }
+        }
+        | ( EQUALS_OP^ | NOT_EQUALS_OP^ ) relationalExpression
+    )* {
+        // Post process the equality expression to clean up 'is null', etc.
+		#equalityExpression = processEqualityExpression(#equalityExpression);
+    }
+;
+
+// level 4 - LESS_THAN_OP, GREATER_THAN_OP, LESS_THAN_OR_EQUALS_OP, GREATER_THAN_OR_EQUALS_OP, LIKE, NOT LIKE, BETWEEN, NOT BETWEEN
+// NOTE: The NOT prefix for LIKE and BETWEEN will be represented in the
+// token type.  When traversing the AST, use the token type, and not the
+// token text to interpret the semantics of these nodes.
+relationalExpression
+	: concatenation (
+		( ( ( LESS_THAN_OP^ | GREATER_THAN_OP^ | LESS_THAN_OR_EQUALS_OP^ | GREATER_THAN_OR_EQUALS_OP^ ) additiveExpression )* )
+		// Disable node production for the optional 'not'.
+		| (n:NOT!)? (
+			// Represent the optional NOT prefix using the token type by
+			// testing 'n' and setting the token type accordingly.
+			(i:IN^ {
+					#i.setType( (n == null) ? IN : NOT_IN);
+					#i.setText( (n == null) ? "in" : "not in");
+				}
+				inList)
+			| (b:BETWEEN^ {
+					#b.setType( (n == null) ? BETWEEN : NOT_BETWEEN);
+					#b.setText( (n == null) ? "between" : "not between");
+				}
+				betweenList )
+			| (l:LIKE^ {
+					#l.setType( (n == null) ? LIKE : NOT_LIKE);
+					#l.setText( (n == null) ? "like" : "not like");
+				}
+				concatenation likeEscape)
+			| (MEMBER! OF! p:path! {
+				processMemberOf( #p, #n );
+			  } ) )
+		)
+	;
+
+likeEscape
+	: (ESCAPE^ concatenation)?
+	;
+
+inList
+	: x:compoundExpr
+	{ #inList = #([IN_LIST,"inList"], #inList); }
+	;
+
+betweenList
+	: concatenation AND! concatenation
+	;
+
+//level 4 - string concatenation
+concatenation :
+    additiveExpression (
+        co:CONCATENATION_OP^ { #co.setType(ARG_LIST); #co.setText("concat-series"); } additiveExpression ( CONCATENATION_OP!  additiveExpression )* {
+            #concatenation = #( [CONCATENATION_OP, "||"], #co );
+        }
+    )?
+;
+
+    
+// level 3 - binary plus and minus
+additiveExpression
+	: multiplyExpression ( ( PLUS_SIGN^ | MINUS_SIGN^ ) multiplyExpression )*
+	;
+
+// level 2 - binary multiply and divide
+multiplyExpression
+	: unaryExpression ( ( ASTERISK^ | SOLIDUS^ ) unaryExpression )*
+	;
+	
+// level 1 - unary minus, unary plus, not
+unaryExpression
+	: MINUS_SIGN^ {#MINUS_SIGN.setType(UNARY_MINUS);} unaryExpression
+	| PLUS_SIGN^ {#PLUS_SIGN.setType(UNARY_PLUS);} unaryExpression
+	| caseExpression
+	| quantifiedExpression
+	| standardFunction
+	| setFunction
+	| collectionFunction
+	| collectionExpression
+	| atom
+	;
+
+caseExpression :
+    caseAbbreviation
+    | caseSpecification
+;
+
+caseAbbreviation :
+    ( NULLIF LEFT_PAREN unaryExpression COMMA unaryExpression RIGHT_PAREN )
+    | ( COALESCE LEFT_PAREN unaryExpression (COMMA unaryExpression)* RIGHT_PAREN )
+;
+
+caseSpecification :
+    simpleCase
+     | searchedCase
+;
+
+simpleCase :
+    CASE unaryExpression (simpleCaseWhenClause)+ (elseClause)? END
+;
+
+simpleCaseWhenClause :
+    WHEN unaryExpression THEN result
+;
+
+result :
+    unaryExpression
+;
+
+elseClause :
+    ELSE result
+;
+
+searchedCase :
+    CASE (searchedWhenClause)+ (elseClause)? END
+;
+
+searchedWhenClause :
+    WHEN logicalExpression THEN unaryExpression
+;
+
+quantifiedExpression // todo : this should be a function of the predicates (logicalExpression) not of concatenation/additiveExpression: these can come only in very certain circumstances.
+	: ( SOME^ | EXISTS^ | ALL^ | ANY^ ) 
+	( identifier | collectionExpression | (LEFT_PAREN! ( subQuery ) RIGHT_PAREN!) )
+	;
+
+standardFunction :
+    castFunction
+    | concatFunction
+    | substringFunction
+    | trimFunction
+    | upperFunction
+    | lowerFunction
+    | lengthFunction
+    | locateFunction
+    | absFunction
+    | sqrtFunction
+    | modFunction
+    | sizeFunction
+    | indexFunction
+    | currentDateFunction
+    | currentTimeFunction
+    | currentTimestampFunction
+    | extractFunction
+    | positionFunction
+    | charLengthFunction
+    | octetLengthFunction
+    | bitLengthFunction
+//	| USER
+//	| CURRENT_USER
+//	| SESSION_USER
+//	| SYSTEM_USER
+;
+
+castFunction :
+    CAST^ LEFT_PAREN! unaryExpression AS! dataType RIGHT_PAREN!
+;
+
+dataType :
+    // todo : temp...
+    identifier
+;
+
+concatFunction :
+    CONCAT^ LEFT_PAREN! unaryExpression ( COMMA! unaryExpression )+ RIGHT_PAREN!
+;
+
+substringFunction :
+    SUBSTRING^ LEFT_PAREN! unaryExpression COMMA! unaryExpression ( COMMA! unaryExpression)? RIGHT_PAREN!
+;
+
+trimFunction :
+    TRIM^ LEFT_PAREN! trimOperands RIGHT_PAREN!
+;
+
+trimOperands :
+    trimSpecification unaryExpression FROM! unaryExpression
+    | tsp:trimSpecification FROM ts:unaryExpression {
+        #trimOperands = #( #tsp, [CHAR_STRING," "], #ts );
+    }
+    | FROM! ts3:unaryExpression {
+        #trimOperands = #( [BOTH,"both"], [CHAR_STRING," "], #ts3 );
+    }
+    | sve1:unaryExpression ( FROM! sve2:unaryExpression ) {
+        if ( #sve2 != null ) {
+            #trimOperands = #( [BOTH,"both"], #sve1, #sve2 );
+        }
+        else {
+            #trimOperands = #( [BOTH,"both"], [CHAR_STRING," "], #sve1 );
+        }
+    }
+;
+
+trimSpecification :
+    LEADING
+    | TRAILING
+    | BOTH
+;
+
+upperFunction :
+    UPPER^ LEFT_PAREN! concatenation RIGHT_PAREN!
+;
+
+lowerFunction :
+    LOWER^ LEFT_PAREN! concatenation RIGHT_PAREN!
+;
+
+lengthFunction :
+    LENGTH^ LEFT_PAREN! concatenation RIGHT_PAREN!
+;
+
+locateFunction :
+    LOCATE^ LEFT_PAREN! unaryExpression COMMA! unaryExpression ( COMMA! unaryExpression )? RIGHT_PAREN!
+;
+
+absFunction :
+    ABS^ LEFT_PAREN! unaryExpression RIGHT_PAREN!
+;
+
+sqrtFunction :
+    SQRT^ LEFT_PAREN! unaryExpression RIGHT_PAREN!
+;
+
+modFunction :
+    MOD^ LEFT_PAREN! unaryExpression COMMA! unaryExpression RIGHT_PAREN!
+;
+
+sizeFunction :
+    SIZE^ LEFT_PAREN! path RIGHT_PAREN!
+;
+
+indexFunction :
+    INDEX^ LEFT_PAREN! aliasReference RIGHT_PAREN!
+;
+
+currentDateFunction :
+    CURRENT_DATE ( LEFT_PAREN! RIGHT_PAREN! )?
+;
+
+currentTimeFunction :
+    CURRENT_TIME ( LEFT_PAREN! RIGHT_PAREN! )?
+;
+
+currentTimestampFunction :
+    CURRENT_TIMESTAMP ( LEFT_PAREN! RIGHT_PAREN! )?
+;
+
+extractFunction :
+    EXTRACT^ LEFT_PAREN! extractField FROM extractSource RIGHT_PAREN!
+;
+
+extractField :
+    datetimeField
+	| timeZoneField
+;
+
+datetimeField :
+    nonSecondDatetimeField
+	| SECOND
+;
+
+timeZoneField :
+    TIMEZONE_HOUR
+    | TIMEZONE_MINUTE
+;
+
+extractSource :
+    concatenation
+;
+
+positionFunction :
+    POSITION^ LEFT_PAREN! unaryExpression IN! unaryExpression RIGHT_PAREN!
+;
+
+charLengthFunction :
+    ( CHAR_LENGTH^ | CHARACTER_LENGTH^ ) LEFT_PAREN! concatenation RIGHT_PAREN!
+;
+
+octetLengthFunction :
+	OCTET_LENGTH^ LEFT_PAREN! unaryExpression RIGHT_PAREN!
+;
+
+bitLengthFunction :
+	BIT_LENGTH^ LEFT_PAREN! unaryExpression RIGHT_PAREN!
+;
+
+setFunction :
+    ( SUM^ | AVG^ | MAX^ | MIN^ ) LEFT_PAREN! additiveExpression RIGHT_PAREN!
+    | COUNT^ LEFT_PAREN! ( ASTERISK | ( ( DISTINCT | ALL )? ( path | collectionExpression ) ) ) RIGHT_PAREN!
+;
+
+collectionFunction :
+    ( MAXELEMENT^ | MAXINDEX^ | MINELEMENT^ | MININDEX^ ) LEFT_PAREN! identPrimary RIGHT_PAREN!
+;
+
+collectionExpression :
+    ( ELEMENTS^ | INDICES^ ) LEFT_PAREN! path RIGHT_PAREN!
+;
+
+
+// level 0 - expression atom
+// ident qualifier ('.' ident ), array index ( [ expr ] ),
+// method call ( '.' ident '(' exprList ') )
+atom :
+    primaryExpression (
+        DOT^ identifier ( options { greedy=true; } :
+            ( op:LEFT_PAREN^ {#op.setType(GENERIC_FUNCTION);} exprList RIGHT_PAREN! )
+        )?
+		| lb:LEFT_BRACKET^ {#lb.setType(INDEX_OP);} expression RIGHT_BRACKET!
+    )*
+	;
+
+// level 0 - the basic element of an expression
+primaryExpression :
+    identPrimary ( options {greedy=true;} : DOT^ CLASS )?
+	| constant
+	| parameterSpecification
+	| LEFT_PAREN! (expressionOrVector | subQuery) RIGHT_PAREN!
+	;
+
+parameterSpecification! :
+    c:COLON! { weakKeywords(); } name:identifier! {
+        #c.setType( NAMED_PARAM );
+        #c.setText( #name.getText() );
+        #parameterSpecification = #c;
+    }
+    | p:PARAM! ( position:NUM_INT_LITERAL! )? {
+        if ( #position == null ) {
+            #parameterSpecification = #p;
+        }
+        else {
+            #position.setType( JPA_PARAM );
+            #parameterSpecification = #position;
+        }
+    }
+;
+
+// This parses normal expression and a list of expressions separated by commas.  If a comma is encountered
+// a parent VECTOR_EXPR node will be created for the list.
+expressionOrVector!
+	: e:expression ( v:vectorExpr )? {
+		// If this is a vector expression, create a parent node for it.
+		if (#v != null)
+			#expressionOrVector = #([VECTOR_EXPR,"{vector}"], #e, #v);
+		else
+			#expressionOrVector = #e;
+	}
+	;
+
+vectorExpr
+	: COMMA! expression (COMMA! expression)*
+	;
+
+// identifier, followed by member refs (dot ident), or method calls.
+// NOTE: handleDotIdent() is called immediately after the first IDENT is recognized because
+// the method looks a head to find keywords after DOT and turns them into identifiers.
+identPrimary :
+    identifier { handleDotIdent(); }
+        ( options { greedy=true; } : DOT^ ( identifier | ELEMENTS | o:OBJECT { #o.setType(IDENT); } ) )*
+        ( options { greedy=true; } : ( op:LEFT_PAREN^ { #op.setType(GENERIC_FUNCTION);} exprList RIGHT_PAREN! ) )? {
+    			if ( #op == null ) {
+	    		    String path = extractPath( #identPrimary );
+		    	    if ( isJavaConstant( path ) ) {
+			            #identPrimary = #( [JAVA_CONSTANT,path] );
+                    }
+                }
+        }
+;
+
+//aggregate
+//	: ( SUM^ | AVG^ | MAX^ | MIN^ ) LEFT_PAREN! additiveExpression RIGHT_PAREN! { #aggregate.setType(AGGREGATE); }
+//	// Special case for count - It's 'parameters' can be keywords.
+//	|  COUNT^ LEFT_PAREN! ( ASTERISK { #ASTERISK.setType(ROW_STAR); } | ( ( DISTINCT | ALL )? ( path | collectionExpr ) ) ) RIGHT_PAREN!
+//	|  collectionExpr
+//	;
+//
+//collectionExpr
+//	: (ELEMENTS^ | INDICES^) LEFT_PAREN! path RIGHT_PAREN!
+//	;
+                                           
+// NOTE: compoundExpr can be a 'path' where the last token in the path is '.elements' or '.indicies'
+compoundExpr
+	: collectionExpression
+	| path
+	| (LEFT_PAREN! ( (expression (COMMA! expression)*) | subQuery ) RIGHT_PAREN!)
+	;
+
+exprList :
+    ( trimSpec:trimSpecification )? {
+        if(#trimSpec != null) #trimSpec.setType(IDENT);
+    }
+	  (
+	  		expression ( (COMMA! expression)+ | FROM { #FROM.setType(IDENT); } expression | AS! identifier )?
+	  		| FROM { #FROM.setType(IDENT); } expression
+	  )?
+			{ #exprList = #([EXPR_LIST,"exprList"], #exprList); }
+	;
+
+constant :
+    literal
+	| NULL
+	| TRUE
+	| FALSE
+;
+
+literal :
+    numericLiteral
+    | characterLiteral
+    | dateLiteral
+    | timeLiteral
+    | timestampLiteral
+    | intervalLiteral
+;
+
+numericLiteral :
+    UNSIGNED_INTEGER
+    | NUM_INT_LITERAL
+    | NUM_LONG_LITERAL
+    | NUM_DOUBLE_LITERAL
+    | NUM_FLOAT_LITERAL
+;
+
+characterLiteral :
+    CHAR_STRING
+    | NATIONAL_CHAR_STRING_LIT
+	| BIT_STRING_LIT
+	| HEX_STRING_LIT
+;
+
+dateLiteral :
+    DATE^ CHAR_STRING
+;
+
+timeLiteral :
+    TIME^ CHAR_STRING
+;
+
+timestampLiteral :
+    TIMESTAMP^ CHAR_STRING
+;
+
+intervalLiteral :
+    INTERVAL ( PLUS_SIGN | MINUS_SIGN )? CHAR_STRING intervalQualifier
+;
+
+intervalQualifier :
+    intervalStartField ( TO intervalEndField | )
+    | SECOND ( LEFT_PAREN UNSIGNED_INTEGER ( COMMA UNSIGNED_INTEGER )? RIGHT_PAREN )?
+;
+
+intervalStartField :
+    nonSecondDatetimeField ( LEFT_PAREN UNSIGNED_INTEGER RIGHT_PAREN )?
+;
+
+intervalEndField :
+    nonSecondDatetimeField
+	| SECOND ( LEFT_PAREN UNSIGNED_INTEGER RIGHT_PAREN )?
+;
+
+nonSecondDatetimeField :
+    YEAR
+    | MONTH
+    | DAY
+    | HOUR
+    | MINUTE
+;

Added: core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/resolve.g
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/resolve.g	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/antlr/hql/resolve.g	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,844 @@
+header {
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ * Portions of SQL grammar parsing copyright (C) 2003 by Lubos Vnuk.  All rights
+ * reserved.  These portions are distributed under license by Red Hat Middleware
+ * LLC and are covered by the above LGPL notice.  If you redistribute this material,
+ * with or without modification, you must preserve this copyright notice in its
+ * entirety.
+ */
+package org.hibernate.hql.ast.phase.parse;
+import antlr.collections.AST;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+}
+
+/**
+ * An Antlr tree parser for "resolving" or "normalizing" an HQL syntax AST.  This
+ * parser provides the vast majority of the semantic analysis of the HQL AST.
+ * <p/>
+ * Both "resolving" and "normalizing" here seek a single goal of building a
+ * dis-ambiguated, generic query AST.
+ * <p/>
+ * The act of resolving is essentially the process of simplifying complex node
+ * structures into atomic components based on contextual information (aka, the
+ * current parser state).  The main thrust of this process is breaking down
+ * dot-structures (a series of DOT INDET pairs) into <ul>
+ * <li>a series of "implicit" join structures injected into the from clause tree</li>
+ * <li>a simple structure representing the "meaning" of the "leaf" of said dot-structure</li>
+ * </ul>
+ * <p/>
+ * The act of normalizing essentially refers to the process of dis-ambiguating
+ * node structures based on their context and creating a unified AST
+ * representation for different ways to express the same "idea".  An example of this
+ * is normalizing implicit join dot-structures into a structure akin to its explicit
+ * join corollary.
+ *
+ * @author Joshua Davis
+ * @author Steve Ebersole
+ */
+class GeneratedHqlResolver extends TreeParser;
+
+options {
+	importVocab=HqlParse;
+	exportVocab=HqlResolve;
+	buildAST=true;
+}
+
+tokens {
+	PROPERTY_REF;
+	ENTITY_PERSISTER_REF;
+	COLLECTION_PERSISTER_REF;
+	PERSISTER_ALIAS_REF;
+	BOGUS;
+
+//	SELECT_CLAUSE;
+}
+
+
+// -- Declarations --
+{
+    private static Logger log = LoggerFactory.getLogger( GeneratedHqlResolver.class );
+
+	private int ordinalParamCount = 0;
+
+    protected boolean isPersisterReferenceAlias(AST alias) {
+        return false;
+    }
+
+	protected AST resolveAlias(AST alias) {
+		return alias;
+	}
+
+    protected boolean isUnqualifiedPropertyReference(AST property) {
+        return false;
+    }
+
+    protected AST buildUnqualifiedPropertyReference(AST propertyNameNode) {
+        return propertyNameNode;
+    }
+
+    protected AST resolvePropertyPathTerminus(AST source, AST propertyNameNode) {
+        return propertyNameNode;
+    }
+
+    protected AST resolvePropertyPathIntermediary(AST source, AST propertyNameNode) {
+        return propertyNameNode;
+    }
+
+    protected void validateIndexOperationOperands(AST collectionPropertyRef, AST selector) {
+    }
+
+    protected AST resolveQualifiedRoot(AST alias) {
+        return null;
+    }
+
+    protected AST resolveUnqualifiedRoot(AST alias) {
+        return null;
+    }
+
+    protected AST resolveIndexedRoot(AST alias) {
+        return null;
+    }
+
+
+	// Statement node BEGIN/END handling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	protected void pushStatement(AST statementNode) {
+	}
+
+	protected void popStatement() {
+	}
+
+
+	// property-path context pushing/popping ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	protected void pushFromClausePropertyPathContext(AST joinType, AST fetch, AST alias, AST propertyFetch) {
+	}
+
+	protected void popFromClausePropertyPathContext() {
+	}
+
+	protected void pushOnFragmentPropertyPathContext(AST rhsPersisterReference) {
+	}
+
+	protected void popOnFragmentPropertyPathContext() {
+	}
+
+	protected void pushWithFragmentPropertyPathContext(AST rhsPersisterReference) {
+	}
+
+	protected void popWithFragmentPropertyPathContext() {
+	}
+
+    protected void pushSelectClausePropertyPathContext() {
+    }
+
+    protected void popSelectClausePropertyPathContext() {
+    }
+
+
+	// persister reference handling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	protected AST buildEntityPersisterReference(AST entityName, AST alias, AST propertyFetch) {
+		return entityName;
+	}
+
+	protected AST buildAdHocJoinNode(AST persisterReference, AST joinType, AST withFragment) {
+		return persisterReference;
+	}
+
+	protected void applyWithFragment(AST withFragment) {
+	}
+
+
+	// parameter handling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	private AST generateNamedParameter(AST delim, AST name) throws SemanticException {
+		// use the source delim node to properly transfer line/column number information :(
+		AST param = #( delim );
+		param.setType( NAMED_PARAM );
+		param.setText( name.getText() );
+		return param;
+	}
+
+	private AST generateOrdinalParameter(AST source) throws SemanticException {
+		// use the source node to properly transfer line/column number information :(
+		AST param = #( source );
+		param.setType( ORDINAL_PARAM );
+		param.setText( Integer.toString( ordinalParamCount++ ) );
+		return param;
+	}
+
+    protected void injectSelectAlias( AST selectExpression, AST alias) {
+    }
+
+    protected void registerSelectExpression(AST selectExpression) {
+    }
+
+    protected AST handleSelectedPropertyRef(AST propertyRef) {
+        return propertyRef;
+    }
+}
+
+// Statement rules ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+/**
+ * The main grammar rule
+ */
+statement :
+    updateStatement
+    | deleteStatement
+    | insertStatement
+    | selectStatement
+;
+
+
+// <tt>UPDATE</tt> statement ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+/**
+ * Recognize an <tt>UPDATE</tt> statement
+ */
+updateStatement :
+    #(
+        UPDATE { pushStatement( #updateStatement ); }
+	        (VERSIONED)?
+	        ENTITY_NAME (ALIAS)?
+	        setClause
+	        (whereClause)? { popStatement(); }
+    )
+;
+
+setClause :
+    #( SET (assignment)+ )
+;
+
+assignment :
+    #( ASSIGNMENT_OP assignmentField newValue )
+;
+
+assignmentField :
+    propertyReference
+;
+
+newValue :
+    valueExpression
+;
+
+
+
+// <tt>DELETE</tt> statement ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+/**
+ * Recognize an HQL <tt>DELETE</tt> statement
+ */
+deleteStatement :
+    #(
+	    DELETE { pushStatement( #deleteStatement ); }
+	        ENTITY_NAME (ALIAS)?
+	        (whereClause)? { popStatement(); }
+    )
+;
+
+
+// <tt>INSERT</tt> statement ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+/**
+ * Recognize an HQL <tt>INSERT</tt> statement
+ */
+insertStatement :
+    #(
+        INSERT { pushStatement( #insertStatement ); }
+            intoClause
+            queryExpression { popStatement(); }
+    )
+;
+
+intoClause :
+    #( INTO ENTITY_NAME insertabilitySpecification )
+;
+
+insertabilitySpecification :
+    #( INSERTABILITY_SPEC (insertablePropertySpecification)+ )
+;
+
+/**
+ * The property being inserted into.
+ */
+insertablePropertySpecification :
+    IDENT
+;
+
+
+// <tt>SELECT</tt> statement rules ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+/**
+ * Recognize an HQL <tt>SELECT</tt> statement.
+ * <p/>
+ * This corresponds most closely to the <cursor specification> rule in ISO/ANSI SQL...
+ */
+selectStatement :
+    #( QUERY queryExpression orderByClause )
+;
+
+orderByClause :
+    #( ORDER (sortSpecification)+ )
+;
+
+sortSpecification :
+    #( SORT_SPEC sortKey (collationSpecification)? (orderingSpecification)? )
+;
+
+sortKey :
+    // todo : do we want to explicitly limit these?
+    valueExpression
+;
+
+collationSpecification :
+    COLLATE
+;
+
+orderingSpecification :
+    ORDER_SPEC
+;
+
+queryExpression :
+    #(
+        QUERY { pushStatement( #queryExpression ); }
+            querySpec ( ( UNION | INTERSECT | EXCEPT ) (ALL)? querySpec )* { popStatement( #queryExpression ); }
+    )
+;
+
+subquery :
+    queryExpression
+;
+
+querySpec :
+     selectFrom ( whereClause )? ( groupByClause ( havingClause )? )?
+;
+
+
+selectFrom! :
+    #( SELECT_FROM fromClause (selectClause)? )
+;
+
+fromClause :
+    #( FROM (persisterSpace)+ )
+;
+
+persisterSpace :
+    #( PERSISTER_SPACE entityPersisterReference ( qualifiedJoin | crossJoin )* )
+;
+
+entityPersisterReference! :
+    en:ENTITY_NAME (a:ALIAS)? (pf:PROP_FETCH)? {
+		#entityPersisterReference = buildEntityPersisterReference( en, a, pf );
+	}
+;
+
+crossJoin :
+    #( JOIN CROSS entityPersisterReference )
+;
+
+qualifiedJoin :
+    #(
+		j:JOIN (jt:nonCrossJoinType)? (
+            e:entityPersisterReference (on:onFragment[#e])? {
+                buildAdHocJoinNode( #e, #jt, #on );
+                if ( on != null ) {
+                    popOnFragmentPropertyPathContext();
+                }
+            }
+            | (f:FETCH)? (a:ALIAS)? (pf:PROP_FETCH)? { pushFromClausePropertyPathContext( jt, #f, #a, #pf ); } prop:propertyRef (with:withFragment[#prop])? {
+                popFromClausePropertyPathContext();
+            }
+        )
+	)
+;
+
+nonCrossJoinType :
+    ( (LEFT | RIGHT) (OUTER)? )
+	| INNER
+	;
+
+onFragment[ AST rhsPersisterReference ]
+	: #( o:ON { pushOnFragmentPropertyPathContext( rhsPersisterReference ); } le:logicalExpr ) {
+		#onFragment = #( o, le );
+	}
+	;
+
+withFragment[ AST rhsPropertyReference ]
+	: #( w:WITH { pushWithFragmentPropertyPathContext( rhsPropertyReference ); } le:logicalExpr ) {
+		#withFragment = #( w, le );
+		applyWithFragment( #withFragment );
+		popWithFragmentPropertyPathContext();
+	}
+	;
+
+
+
+
+
+
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+// The statement sub-rules
+
+selectStatement :
+    query ( ( m:MINUS | u:UNION ) (a:ALL)? query )*
+;
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+query
+	: #(QUERY { pushStatement( #query ); }
+			// The first phase places the FROM first to make processing the SELECT simpler.
+			#( SELECT_FROM fromClause (selectClause)? )
+			(whereClause)?
+			(groupClause)?
+			(orderClause)? {
+				popStatement();
+			}
+		)
+	;
+
+selectClause
+	: #( SELECT { pushSelectClausePropertyPathContext(); } ( d:DISTINCT )? x:selectExprList ) {
+		#selectClause = #([SELECT_CLAUSE,"{select clause}"], #d, #x);
+		popSelectClausePropertyPathContext();
+	}
+	;
+
+selectExprList
+    : ( selectExprValue )+
+    ;
+
+selectExprValue
+    : ( selectExpr | aliasedSelectExpr ) {
+        registerSelectExpression( #selectExprValue );
+    }
+    ;
+
+aliasedSelectExpr
+	: #( AS se:selectExpr i:identifier! ) {
+	    injectSelectAlias( #se, #i );
+		#aliasedSelectExpr = #se;
+	}
+    ;
+
+// TODO : the old grammar had both literal and constant available as select expressions, but that is probably not valid; it is certainly not valid for non-subqueries
+selectExpr
+    : (persisterReferenceAliasCheck) => persisterRefRef
+    | pr:propertyRef { #selectExpr = handleSelectedPropertyRef( #pr ); }
+    | arithmeticExpr
+    | count
+    | literal
+    | constant
+    ;
+
+persisterRefRef!
+    : alias:IDENT {
+        #persisterRefRef = #( [ PERSISTER_REF_REF, alias.getText() ] ); 
+    }
+    ;
+
+count
+	: #(COUNT ( DISTINCT | ALL )? ( propertyRef | literal | ROW_STAR ) )
+	;
+
+fromClause
+	: #( f:FROM rootFromElement ( explicitJoin | rootFromElement )* )
+	;
+
+rootFromElement!
+	: #( RANGE e:entityPersisterReference ) {
+		#rootFromElement = #e;
+	}
+	;
+
+entityPersisterReference!
+	: en:ENTITY_NAME (a:ALIAS)? (pf:PROP_FETCH)? {
+		#entityPersisterReference = buildEntityPersisterReference( en, a, pf );
+	}
+	;
+
+explicitJoin!
+	: #(
+		j:JOIN (jt:joinType)?
+			(
+				e:entityPersisterReference (on:onFragment[#e])? {
+					buildAdHocJoinNode( #e, #jt, #on );
+					if ( on != null ) {
+						popOnFragmentPropertyPathContext();
+					}
+				}
+				| (f:FETCH)? (a:ALIAS)? (pf:PROP_FETCH)? { pushFromClausePropertyPathContext( jt, #f, #a, #pf ); } prop:propertyRef (with:withFragment[#prop])? {
+					popFromClausePropertyPathContext();
+				}
+			)
+	)
+	;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// propertyRef related rules...
+//
+
+/**
+ * The top level property ref recognition rule.
+ */
+propertyRef
+    : (unqualifiedPropertyRefCheck) => unqualifiedPropertyRef
+    | implicitJoin
+    | indexOperation
+    ;
+
+/**
+ * A rule utilizing a validating semantic predicate to contextually
+ * ensure that we have unqualified property reference.  Generally
+ * used from within syntactic predicates to disambiguate the match path
+ *
+ * see {@link #implicitJoinSource} for example
+ */
+unqualifiedPropertyRefCheck!
+    : prop:IDENT { isUnqualifiedPropertyReference( prop ) }?
+    ;
+
+/**
+ * AST construction rule for building AST relating to *known*
+ * unqualified property references.  Do not call this rule unless
+ * you know for certain (ala, have verified via the unqualifiedPropertyRefCheck
+ * rule or similiar) that the next token is an IDENT representing an
+ * unqualified property reference.
+ */
+unqualifiedPropertyRef!
+    : prop:IDENT {
+        #unqualifiedPropertyRef = buildUnqualifiedPropertyReference( prop );
+    }
+    ;
+
+/**
+ * A rule utilizing a validating semantic predicate to contextually
+ * ensure that we have an alias for a persister reference previously
+ * encountered and processed.  Generally used from within syntactic
+ * predicates to disambiguate the path.
+ */
+persisterReferenceAliasCheck!
+    : alias:IDENT { isPersisterReferenceAlias( alias ) }?
+    ;
+
+/**
+ * AST construction rule for building AST relating to *known*
+ * persister reference aliases.  Do not call this rule unless
+ * you know for certain (ala, have verified via the persisterReferenceAliasCheck
+ * rule or similiar) that the next token is an IDENT representing an
+ * alias for a persister reference
+ */
+persisterReferenceAlias!
+    : alias:IDENT {
+        #persisterReferenceAlias = resolveAlias( alias );
+    }
+    ;
+
+/**
+ * Perhaps better named as 'complex property ref' or 'pathed property ref' i.e.
+ * Anyway, the basic idea is (DOT <source> IDENT)
+ */
+implicitJoin!
+    : #( d:DOT source:implicitJoinSource prop:IDENT) {
+        #implicitJoin = resolvePropertyPathTerminus( #source, #prop );
+    }
+    ;
+
+intermediateImplicitJoin!
+    : #( d:DOT source:implicitJoinSource prop:IDENT) {
+        #intermediateImplicitJoin = resolvePropertyPathIntermediary( #source, #prop );
+    }
+    ;
+
+/**
+ * The output of the implicitJoinSource rule is a {@link org.hibernate.sql.ast.phase.resolve.patg.PropertyPathPart}
+ * reference which is a tokenized and encoded representation of the current path expression
+ * resolution state.
+ */
+implicitJoinSource
+    : (persisterReferenceAliasCheck) => a:IDENT { #implicitJoinSource = resolveQualifiedRoot( #a ); }
+    | (unqualifiedPropertyRefCheck) => pr:IDENT { #implicitJoinSource = resolveUnqualifiedRoot( #pr ); }
+    | intermediateImplicitJoin
+    | i:indexOperation { #implicitJoinSource = resolveIndexedRoot( #i ); }
+    ;
+
+indexOperation
+    : #( i:INDEX_OP coll:propertyRef selector:indexSelector ) {
+        validateIndexOperationOperands( #coll, #selector );
+    }
+    ;
+
+indexSelector
+	: constant
+	| parameter
+	| arithmeticExpr
+	| collectionFunctionCall
+	;
+
+//
+// <end> propertyRef related rules...
+///////////////////////////////////////////////////////////////////////////////
+
+collectionFunctionCall
+	: #( METHOD_CALL pathAsIdent ( #(EXPR_LIST alias ) )? )
+	;
+
+alias!
+	: i:identifier {
+		#alias = resolveAlias( i );
+	}
+	;
+
+joinType
+	: ( (LEFT | RIGHT) (OUTER)? )
+	| FULL
+	| INNER
+	;
+
+onFragment[ AST rhsPersisterReference ]
+	: #( o:ON { pushOnFragmentPropertyPathContext( rhsPersisterReference ); } le:logicalExpr ) {
+		#onFragment = #( o, le );
+	}
+	;
+
+withFragment[ AST rhsPropertyReference ]
+	: #( w:WITH { pushWithFragmentPropertyPathContext( rhsPropertyReference ); } le:logicalExpr ) {
+		#withFragment = #( w, le );
+		applyWithFragment( #withFragment );
+		popWithFragmentPropertyPathContext();
+	}
+	;
+
+
+intoClause
+	: #(i:INTO (subtree)* )
+	;
+
+whereClause
+	: #(WHERE logicalExpr )
+	;
+
+groupClause
+	: #(GROUP (subtree)* )
+	;
+
+orderClause
+	: #(ORDER (subtree)* )
+	;
+
+
+logicalExpr
+	: #(AND logicalExpr logicalExpr)
+	| #(OR logicalExpr logicalExpr)
+	| #(NOT logicalExpr)
+	| comparisonExpr
+	;
+
+comparisonExpr
+	:
+	( #(EQ exprOrSubquery exprOrSubquery)
+	| #(NE exprOrSubquery exprOrSubquery)
+	| #(LT exprOrSubquery exprOrSubquery)
+	| #(GT exprOrSubquery exprOrSubquery)
+	| #(LE exprOrSubquery exprOrSubquery)
+	| #(GE exprOrSubquery exprOrSubquery)
+	| #(LIKE exprOrSubquery expr ( #(ESCAPE expr) )? )
+	| #(NOT_LIKE exprOrSubquery expr ( #(ESCAPE expr) )? )
+	| #(BETWEEN exprOrSubquery exprOrSubquery exprOrSubquery)
+	| #(NOT_BETWEEN exprOrSubquery exprOrSubquery exprOrSubquery)
+	| #(IN exprOrSubquery inRhs )
+	| #(NOT_IN exprOrSubquery inRhs )
+	| #(IS_NULL exprOrSubquery)
+	| #(IS_NOT_NULL exprOrSubquery)
+	| #(EXISTS ( expr | collectionFunctionOrSubselect ) )
+	)
+	;
+
+inRhs
+	: #(IN_LIST ( collectionFunctionOrSubselect | ( (expr)* ) ) )
+	;
+
+exprOrSubquery
+	: expr
+	| query
+	| #(ANY collectionFunctionOrSubselect)
+	| #(ALL collectionFunctionOrSubselect)
+	| #(SOME collectionFunctionOrSubselect)
+	;
+
+collectionFunctionOrSubselect
+	: collectionFunction
+	| query
+	;
+
+collectionFunction
+	: #( ELEMENTS propertyRef )
+	| #( INDICES propertyRef )
+	;
+
+aggregateExpr
+	: expr
+	| collectionFunction
+	;
+
+expr
+	: addrExpr
+	| #( VECTOR_EXPR (expr)* )
+	| constant
+	| arithmeticExpr
+	| functionCall								// Function call, not in the SELECT clause.
+	| parameter
+	| count										// Count, not in the SELECT clause.
+	;
+
+arithmeticExpr
+	: #(PLUS expr expr)
+	| #(MINUS expr expr)
+	| #(DIV expr expr)
+	| #(STAR expr expr)
+	| #(UNARY_MINUS expr)
+	| caseExpr
+	;
+
+caseExpr
+	: #(CASE (#(WHEN logicalExpr expr))+ (#(ELSE expr))?)
+	| #(CASE2 expr (#(WHEN expr expr))+ (#(ELSE expr))?)
+	;
+
+//addrExpr
+//	: propertyRef
+//	| #(INDEX_OP addrExprLhs expr)
+//	;
+
+addrExpr
+	: propertyRef
+	;
+
+addrExprLhs
+	: addrExpr
+	;
+
+constant
+	: NULL
+	| TRUE
+	| FALSE
+	| javaConstant
+	;
+
+javaConstant
+    : JAVA_CONSTANT
+    ;
+
+literal
+	: NUM_INT
+	| NUM_LONG
+	| NUM_FLOAT
+	| NUM_DOUBLE
+	| QUOTED_STRING
+	;
+
+parameter!
+	: #( c:COLON (c2:COLON)? i:identifier ) {
+		if ( c2 != null ) {
+			// allows escaping the colon...
+			String text = ":" + i.getText();
+			#parameter = #( [IDENT, text] );
+		}
+		else {
+			#parameter = generateNamedParameter( c, i );
+		}
+	}
+	| #( p:PARAM (n:NUM_INT)? ) {
+		if ( n != null ) {
+			// An ejb3-style "positional parameter", which we handle internally as a named-parameter
+			#parameter = generateNamedParameter( p, n );
+		}
+		else {
+			#parameter = generateOrdinalParameter( p );
+		}
+	}
+	;
+
+functionCall
+	: #(METHOD_CALL pathAsIdent ( #(EXPR_LIST (expr)* ) )? )
+	| #(AGGREGATE aggregateExpr )
+	;
+
+//propertyRef
+//	: propertyPath
+//	;
+
+propertyName
+	: identifier
+	| CLASS
+	| ELEMENTS
+	| INDICES
+	;
+
+// Matches a path and returns the normalized string for the path (usually
+// fully qualified a class name).
+pathAsString returns [String p] {
+	p = "???";
+	String x = "?x?";
+	}
+	: a:identifier { p = a.getText(); }
+	| #(DOT x=pathAsString y:identifier) {
+			StringBuffer buf = new StringBuffer();
+			buf.append(x).append(".").append(y.getText());
+			p = buf.toString();
+		}
+	;
+
+// Returns a path as a single identifier node.
+pathAsIdent {
+    String text = "?text?";
+    }
+    : text=pathAsString {
+        #pathAsIdent = #([IDENT,text]);
+    }
+    ;
+
+identifier
+	: (IDENT | WEIRD_IDENT)
+	;
+
+// General subtree.  Matches anything, copies the tree verbatim.
+subtree
+	: #(. (subtree)*)
+	;

Added: core/branches/SQL_GEN_REDESIGN/src/main/antlr/sql/common.g
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/antlr/sql/common.g	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/antlr/sql/common.g	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,424 @@
+header
+{
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ * Portions of SQL grammar parsing copyright (C) 2003 by Lubos Vnuk.  All rights
+ * reserved.  These portions are distributed under license by Red Hat Middleware
+ * LLC and are covered by the above LGPL notice.  If you redistribute this material,
+ * with or without modification, you must preserve this copyright notice in its
+ * entirety.
+ */
+package org.hibernate.sql.ast.common;
+
+import antlr.collections.AST;
+import antlr.Token;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+}
+
+/**
+ * A convenience base class for Hibernate parsers.
+ * <p/>
+ * Our parsers are generally dealing with some aspect of SQL, and so this parser provides commonly needed
+ * actions as well as exporting the basic common vocaulary of needed tokens (including all ISO/ANSI SQL-92
+ * key/reserved words).
+ *
+ * @author Lubos Vnuk
+ * @author Joshua Davis
+ * @author Steve Ebersole
+ */
+class CommonHibernateParserSupport extends Parser;
+
+options
+{
+	exportVocab=Sql92;
+	buildAST=true;
+	k=2;
+//    codeGenMakeSwitchThreshold=4; // Code optimization
+//    codeGenBitsetTestThreshold=8; // Code optimization
+}
+
+tokens
+{
+    // SQL key/reserved words
+	ALL = "all";
+	AND = "and";
+	ANY = "any";
+	AS = "as";
+	ASCENDING = "asc";
+    AT = "at";
+	AVG = "avg";
+	BETWEEN = "between";
+    BIT = "bit";
+    BIT_LENGTH = "bit_lenght";
+    BOTH = "both";
+    BY = "by";
+    CASE = "case";
+    CAST = "cast";
+    CHAR = "char";
+    CHARACTER = "character";
+    CHAR_LENGTH = "char_length";
+    CHARACTER_LENGTH = "character_length";
+    COALESCE = "coalesce";
+    COLLATE = "collate";
+    CONVERT = "convert";
+    CORRESPONDING = "corresponding";
+    COUNT = "count";
+    CROSS = "cross";
+    CURRENT = "current";
+    CURRENT_DATE = "current_date";
+    CURRENT_TIME = "current_time";
+    CURRENT_TIMESTAMP = "current_timestamp";
+    DATE = "date";
+    DAY = "day";
+    DEC = "dec";
+    DECIMAL = "decimal";
+    DEFAULT = "default";
+    DELETE = "delete";
+    DESCENDING = "desc";
+	DISTINCT = "distinct";
+	DOUBLE = "double";
+	ELSE = "else";
+	END = "end";
+	ESCAPE = "escape";
+    EXCEPT = "except";
+	EXISTS = "exists";
+	EXTRACT = "extract";
+	FALSE = "false";
+	FLOAT = "float";
+	FOR = "for";
+    FROM = "from";
+    FULL = "full";
+    GLOBAL = "global";
+    GROUP = "group";
+    HAVING = "having";
+    HOUR = "hour";
+    IN = "in";
+    INDICATOR = "indicator";
+    INNER = "inner";
+    INSERT = "insert";
+    INT = "int";
+    INTEGER = "integer";
+    INTERSECT = "intersect";
+    INTERVAL = "interval";
+    INTO = "into";
+	IS = "is";
+    JOIN = "join";
+    LEADING = "leading";
+    LEFT = "left";
+    LIKE = "like";
+    LOCAL = "local";
+    LOWER = "lower";
+    MATCH = "match";
+    MAX = "max";
+    MIN = "min";
+    MINUS = "minus";
+    MINUTE = "minute";
+    MODULE = "module";
+    MONTH = "month";
+    NATIONAL = "national";
+    NATURAL = "natural";
+    NCHAR = "nchar";
+    NOT = "not";
+    NULL = "null";
+    NULLIF = "nullif";
+    NUMERIC = "numeric";
+    OCTET_LENGTH = "octet_length";
+    OF = "of";
+    ON = "on";
+    ONLY = "only";
+    OR = "or";
+    ORDER = "order";
+	OUTER = "outer";
+	OVERLAPS = "overlaps";
+	PARTIAL = "partial";
+	POSITION = "position";
+	PRECISION = "precision";
+    READ = "read";
+    REAL = "real";
+    RIGHT = "right";
+    SECOND = "second";
+    SELECT = "select";
+    SET = "set";
+    SMALLINT = "smallint";
+    SOME = "some";
+    SUBSTRING = "substring";
+    SUM = "sum";
+    TABLE = "table";
+    THEN = "then";
+    TIME = "time";
+    TIMESTAMP = "timestamp";
+    TIMEZONE_HOUR = "timezone_hour";
+    TIMEZONE_MINUTE = "timezone_minute";
+    TO = "to";
+    TRAILING = "trailing";
+    TRANSLATE = "translate";
+    TRIM = "trim";
+    TRUE = "true";
+    UNION = "union";
+    UNIQUE = "unique";
+    UNKNOWN = "unknown";
+    UPDATE = "update";
+    UPPER = "upper";
+    USING = "using";
+    VALUE = "value";
+    VALUES = "values";
+    VARCHAR = "varchar";
+    VARYING = "varying";
+    WHEN = "when";
+    WHERE = "where";
+    WITH = "with";
+    YEAR = "year";
+    ZONE = "zone";
+
+    DOT;
+
+    // synthetic numeric literal types
+    NUM_INT_LITERAL;
+    NUM_LONG_LITERAL;
+    NUM_DOUBLE_LITERAL;
+    NUM_FLOAT_LITERAL;
+
+    NATIONAL_CHAR_STRING_LIT;
+    BIT_STRING_LIT;
+    HEX_STRING_LIT;
+
+    // HQL-specific keywords
+    ABS = "abs";
+	CLASS = "class";
+	CONCAT = "concat";
+	ELEMENTS = "elements";
+	EMPTY = "empty";
+	FETCH = "fetch";
+	INDEX = "index";
+	INDICES = "indices";
+	LENGTH = "length";
+	LOCATE = "locate";
+	MAXELEMENT = "maxelement";
+	MAXINDEX = "maxindex";
+	MEMBER = "member";
+	MINELEMENT = "minelement";
+	MININDEX = "minindex";
+	MOD = "mod";
+	NEW = "new";
+	OBJECT = "object";
+	PROPERTIES = "properties";
+	SIZE = "size";
+	SQRT = "sqrt";
+	VERSIONED = "versioned";
+}
+
+{
+	private static final Logger log = LoggerFactory.getLogger( CommonHibernateParserSupport.class );
+
+    // Grammar actions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	public void showAST(AST ast) {
+	    showAST( ast, "AST" );
+	}
+
+	public void showAST(AST ast, String title) {
+	    if ( log.isDebugEnabled() ) {
+	        log.debug( title + " [tree string] : " + ast.toStringTree() );
+    	}
+	}
+}
+
+noRules :
+;
+
+
+// Lexer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+/**
+ * A Lexer for recognizing ISO/ANSI SQL vocabnulary tokens.
+ *
+ * @author Lubos Vnuk
+ * @author Joshua Davis
+ * @author Steve Ebersole
+ */
+class CommonHibernateLexerSupport extends Lexer;
+
+options {
+	exportVocab = Sql92;
+	testLiterals = false;
+	k = 2;
+	charVocabulary = '\u0000'..'\uFFFE';
+	caseSensitive = false;
+	caseSensitiveLiterals = false;
+}
+
+
+{
+    /**
+     * Lexer action used to hook callbacks from lexer rules whenever we encounter a token
+     * which could conceivable be used as an identifer.  This is used to provide "keyword-as-identifier"
+     * handling (where a keyword is used as an identifier).
+     *
+     * @param possibleIdentifier Whether the token could be an idientifier.
+     */
+	protected void setPossibleIdentifier(boolean possibleIdentifier) {
+	}
+
+    protected void markAsApproximate() {
+    }
+}
+
+EQUALS_OP : '=' ;
+NOT_EQUALS_OP : "!=" | "^=";
+SQL_NOT_EQUALS_OP : "<>" { $setType(NOT_EQUALS_OP); };
+
+LESS_THAN_OP : '<';
+LESS_THAN_OR_EQUALS_OP : "<=";
+
+GREATER_THAN_OP : '>';
+GREATER_THAN_OR_EQUALS_OP : ">=";
+
+CONCATENATION_OP : "||";
+VERTICAL_BAR : '|';
+
+PARAM : '?' ;
+
+COLON : ':';
+SEMICOLON : ';' ;
+
+LEFT_BRACKET : '[' ;
+RIGHT_BRACKET : ']' ;
+
+LEFT_PAREN : '(' ;
+RIGHT_PAREN : ')' ;
+
+PLUS_SIGN : '+'	;
+MINUS_SIGN : '-';
+
+ASTERISK : '*' ;
+SOLIDUS : '/' ;
+
+COMMA : ',' ;
+
+PERCENT : '%' ;
+AMPERSAND : '&' ;
+
+
+CHAR_STRING :
+	  ('\'' (options{greedy=true;}: ~('\'' | '\r' | '\n') | '\'' '\'' | NEWLINE)* '\'' )+
+//	| '\'' {$setType(QUOTE);}
+;
+
+//QUOTED_STRING :
+//    '\'' ( (ESCqs)=> ESCqs | ~'\'' )* '\''
+//;
+//
+//protected
+//ESCqs :
+//    '\'' '\''
+//;
+
+/**
+ * Recognize either double-quote (") or back-tick (`) as delimiting a quoted identifier
+ */
+QUOTED_IDENT :
+	    '"' (~('"' | '\r' | '\n') | '"' '"')+ '"'
+	|   '`' (~('`' | '\r' | '\n') | '`' '`')+ '`'
+;
+
+IDENT options {testLiterals=true;} :
+	( NATIONAL_CHAR_STRING_LIT {$setType(NATIONAL_CHAR_STRING_LIT);}
+	    | BIT_STRING_LIT {$setType(BIT_STRING_LIT);}
+	    | HEX_STRING_LIT {$setType(HEX_STRING_LIT);}
+	)
+	| (SIMPLE_LETTER | '_' | '$') (SIMPLE_LETTER | '_' | '$' | '0'..'9')* {
+        setPossibleIdentifier( true );
+//	    $setType( testLiteralsTable( IDENT ) );
+	}
+;
+
+protected
+NATIONAL_CHAR_STRING_LIT :
+	'n' ('\'' (options{greedy=true;}: ~('\'' | '\r' | '\n' ) | '\'' '\'' | NEWLINE)* '\'' )+
+;
+
+protected
+BIT_STRING_LIT :
+	'b' ('\'' ('0' | '1')* '\'' )+
+;
+
+protected
+HEX_STRING_LIT :
+	'x' ("\'" ('a'..'f' | '0'..'9')* "\'" )+
+;
+
+protected
+SIMPLE_LETTER :
+	'a'..'z'
+    | '\u0080'..'\ufffe'
+;
+
+/**
+ * This rule actually recognizes all numeric literals despite the name...
+ */
+NUM_INT_LITERAL :
+    // IMPL NOTE : 2 basic alt-branches:
+    //      1) starting with unsigned-int
+    //      2) starting with a decimal ('.')
+    UNSIGNED_INTEGER (
+        '.' UNSIGNED_INTEGER {$setType(NUM_DOUBLE_LITERAL);} ( 'e' SIGNED_INTEGER {markAsApproximate();} )? ( 'f' {$setType(NUM_FLOAT_LITERAL);} )?
+        | ( 'e' SIGNED_INTEGER {markAsApproximate();} )? ( ls:'l' {$setType(NUM_LONG_LITERAL);} )?
+    )
+    | '.' UNSIGNED_INTEGER {$setType(NUM_DOUBLE_LITERAL);} ( 'e' SIGNED_INTEGER {markAsApproximate();} )? ( 'f' {$setType(NUM_FLOAT_LITERAL);} )?
+    | '.' {$setType(DOT);}
+;
+
+protected
+SIGNED_INTEGER :
+    ( '+' | '-' )? UNSIGNED_INTEGER
+;
+
+protected
+UNSIGNED_INTEGER :
+	('0'..'9')+
+;
+
+WHITESPACE :
+    ( SPACE | NEWLINE ) {
+        //ignore this token
+        $setType( Token.SKIP );
+    }
+;
+
+protected
+NEWLINE :
+	( '\r' (options{greedy=true;}: '\n')? | '\n' ) {newline();}
+;
+
+protected
+SPACE :
+	  ' ' | '\t'
+;
+
+protected
+ANY_CHAR :
+	.
+;

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/hql/ast/phase/parse/ASTFactoryImpl.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/hql/ast/phase/parse/ASTFactoryImpl.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/hql/ast/phase/parse/ASTFactoryImpl.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,42 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.hql.ast.phase.parse;
+
+import antlr.ASTFactory;
+
+import org.hibernate.sql.ast.common.Node;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class ASTFactoryImpl extends ASTFactory {
+	/**
+	 * {@inheritDoc}
+	 */
+	public Class getASTNodeType(int tokenType) {
+		return Node.class;
+	}
+}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/hql/ast/phase/parse/HqlParser.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/hql/ast/phase/parse/HqlParser.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/hql/ast/phase/parse/HqlParser.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,623 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.hql.ast.phase.parse;
+
+import org.hibernate.sql.ast.util.ASTUtil;
+import org.hibernate.sql.ast.util.ASTPrinter;
+import org.hibernate.sql.ast.util.ErrorCounter;
+import org.hibernate.sql.ast.util.ParseErrorHandler;
+import org.hibernate.QueryException;
+import org.hibernate.MappingException;
+import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.sql.ast.common.CommonHibernateLexer;
+import org.hibernate.sql.ast.common.TokenImpl;
+import org.hibernate.sql.ast.common.Node;
+import org.hibernate.util.ReflectHelper;
+import org.hibernate.util.StringHelper;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.StringReader;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+import antlr.collections.AST;
+import antlr.RecognitionException;
+import antlr.TokenStreamException;
+import antlr.Token;
+import antlr.ASTPair;
+import antlr.MismatchedTokenException;
+import antlr.SemanticException;
+import antlr.ASTFactory;
+
+/**
+ * The parser used by Hibernate to generate an AST given an input
+ * HQL string (a "stream parser").  The produced AST is then used
+ * (and mutated) by later phases/parsers to apply semantic resolution;
+ * this parser, however, is all about syntax resolution.
+ *
+ * @author Steve Ebersole
+ */
+public class HqlParser extends GeneratedHqlParser {
+	private static final Logger log = LoggerFactory.getLogger( HqlParser.class );
+
+	private final Context context;
+	private final ParseErrorHandler parseErrorHandler = new ErrorCounter();
+	private final ASTPrinter printer = new ASTPrinter( HqlParseTokenTypes.class );
+	private int traceDepth = 0;
+
+	public static interface Context {
+		/**
+		 * Does this name represent an entity name?
+		 *
+		 * @param name The name to check
+		 * @return True if the name represents an entioty name; false otherwise.
+		 */
+		public boolean isEntityName(String name);
+
+		/**
+		 * Get the import "replacement" name for the given name (e.g., 'User' -> 'com.acme.User').  <tt>null</tt>
+		 * indicates an unrecognized name.
+		 *
+		 * @param name The name for which to locate the imported name.
+		 * @return The corresponding imported name, or null.
+		 */
+		public String getImportedName(String name);
+
+		/**
+		 * Does the given name represent a registered function name?
+		 *
+		 * @param name The name to check
+		 * @return True if the name matches a registered function name; false otherwise.
+		 */
+		public boolean isRegisteredFunctionName(String name);
+	}
+
+	public HqlParser(String hql, Context context) {
+		super( new CommonHibernateLexer( new StringReader( hql ) ) );
+		this.context = context;
+		super.setASTFactory( new ASTFactoryImpl() );
+	}
+
+	public HqlParser(String hql, final SessionFactoryImplementor sessionFactoryImplementor) {
+		this(
+				hql,
+				new Context() {
+					public boolean isEntityName(String name) {
+						return findEntityPersisterByName( name ) != null;
+					}
+
+					public String getImportedName(String name) {
+						return sessionFactoryImplementor.getImportedClassName( name );
+					}
+
+					public boolean isRegisteredFunctionName(String name) {
+						return sessionFactoryImplementor.getDialect().getFunctions().get( name ) != null;
+					}
+
+					private EntityPersister findEntityPersisterByName(String name) throws MappingException {
+						try {
+							return sessionFactoryImplementor.getEntityPersister( name );
+						}
+						catch ( MappingException ignore ) {
+							// unable to locate it using this name
+						}
+
+						// If that didn't work, try using the 'import' name.
+						String importedClassName = sessionFactoryImplementor.getImportedClassName( name );
+						if ( importedClassName == null ) {
+							return null;
+						}
+						return sessionFactoryImplementor.getEntityPersister( importedClassName );
+					}
+				}
+		);
+	}
+
+
+	// overrides of Antlr infastructure methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	public void reportError(RecognitionException e) {
+		parseErrorHandler.reportError( e );
+	}
+
+	public void reportError(String s) {
+		parseErrorHandler.reportError( s );
+	}
+
+	public void reportWarning(String s) {
+		parseErrorHandler.reportWarning( s );
+	}
+
+	public ParseErrorHandler getParseErrorHandler() {
+		return parseErrorHandler;
+	}
+
+	static public void panic() {
+		//overriden to avoid System.exit
+		throw new QueryException( "Parser: panic" );
+	}
+
+	public void setASTFactory(ASTFactory astFactory) {
+		throw new UnsupportedOperationException( "not allowed!" );
+	}
+
+
+// various AST output methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	public void traceIn(String s) throws TokenStreamException {
+		if ( inputState.guessing > 0 ) {
+			return;
+		}
+		String prefix = StringHelper.repeat( "-", (traceDepth++ * 2) ) + "->";
+		trace( prefix + s );
+	}
+
+	public void traceOut(String s) throws TokenStreamException {
+		if ( inputState.guessing > 0 ) {
+			return;
+		}
+		String prefix = "<-" + StringHelper.repeat( "-", (--traceDepth * 2) );
+		trace( prefix + s );
+	}
+
+    private void trace(String msg) {
+		System.out.println( msg );
+//		log.trace( msg );
+	}
+
+	public void dumpAst(AST ast) {
+		dumpAst( ast, "DUMP" );
+	}
+
+	public void dumpAst(AST ast, String header) {
+		log.info( printer.showAsString( ast, header ) );
+	}
+
+	public void showAst(AST ast, PrintStream out) {
+		showAst( ast, new PrintWriter( out ) );
+	}
+
+	private void showAst(AST ast, PrintWriter pw) {
+		printer.showAst( ast, pw );
+	}
+
+
+	// overrides of grammar semantic actions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	public String extractPath(AST tree) {
+		try {
+			return PathCollector.getPath( tree );
+		}
+		catch ( Throwable t ) {
+			return tree.getText();
+		}
+	}
+
+	public boolean isRegisteredFunction(AST tree) {
+		return context.isRegisteredFunctionName( extractPath( tree ) );
+	}
+
+	public boolean isJavaConstant(String path) {
+		try {
+			log.debug( "Testing path [" + path + "] as potential java constant" );
+			Object value = ReflectHelper.getConstantValueStrictly( path );
+			log.debug( "Resolved path to java constant [" + value + "]" );
+			return true;
+		}
+		catch( Throwable t ) {
+			log.debug( "Path did not resolve to java constant : " + t );
+			return false;
+		}
+	}
+
+	public String resolveEntityName(String name) {
+		return context.getImportedName( name );
+	}
+
+	public String resolveDynamicInstantiationPojoName(AST name) throws SemanticException {
+		String path = extractPath( name );
+		if ( "list".equals( path ) || "map".equals( path ) ) {
+			return path;
+		}
+		else {
+			String importedName = context.getImportedName( path );
+			try {
+				Class importedClass = ReflectHelper.classForName( importedName );
+				return importedClass.getName();
+			}
+			catch ( ClassNotFoundException e ) {
+				throw new SemanticException( "Unable to locate dynamic instantiation class [" + importedName + "]" );
+			}
+		}
+	}
+
+	protected AST processEqualityExpression(AST x) {
+		if ( x == null ) {
+			log.warn( "processEqualityExpression() : No expression to process!" );
+			return null;
+		}
+
+		int type = x.getType();
+		if ( log.isTraceEnabled() ) {
+			log.trace( "processEqualityExpression() -> type : {}, name : {}", Integer.toString( type ), ASTUtil.getTokenTypeName( HqlParseTokenTypes.class, type ) );
+		}
+		if ( type == EQUALS_OP || type == NOT_EQUALS_OP || type == SQL_NOT_EQUALS_OP ) {
+			boolean negated = ( type != EQUALS_OP );
+			if ( x.getNumberOfChildren() == 2 ) {
+				AST a = x.getFirstChild();
+				AST b = a.getNextSibling();
+				// (EQ NULL b) => (IS_NULL b)
+				if ( a.getType() == NULL && b.getType() != NULL ) {
+					return createIsNullParent( b, negated );
+				}
+				// (EQ a NULL) => (IS_NULL a)
+				else if ( b.getType() == NULL && a.getType() != NULL ) {
+					return createIsNullParent( a, negated );
+				}
+				else if ( b.getType() == EMPTY ) {
+					return processIsEmpty( a, negated );
+				}
+				else {
+					return x;
+				}
+			}
+			else {
+				return x;
+			}
+		}
+		else {
+			return x;
+		}
+	}
+
+	private AST createIsNullParent(AST node, boolean negated) {
+		node.setNextSibling( null );
+		int type = negated ? IS_NOT_NULL : IS_NULL;
+		String text = negated ? "is not null" : "is null";
+		return ASTUtil.createParent( astFactory, type, text, node );
+	}
+
+	protected AST processMemberOf(AST path, AST notNode) {
+		AST inNode = notNode == null ? astFactory.create( IN, "in" ) : astFactory.create( NOT_IN, "not in" );
+		AST subqueryNode = createSubquery( path );
+		AST inListNode = ASTUtil.createParent( astFactory, IN_LIST, "in-list", subqueryNode );
+		inNode.addChild( inListNode );
+		return inNode;
+	}
+
+	private AST createSubquery(AST subquerySource) {
+//		AST ast = ASTUtil.createParent( astFactory, RANGE, "RANGE", node );
+// todo : what is the type of 'node'?
+		log.debug(
+				"Generating subquery; incoming node type = {}; incoming node = [{}]",
+				printer.getTokenTypeName( subquerySource.getType() ),
+				subquerySource
+		);
+		AST fromNode = ASTUtil.createParent( astFactory, FROM, "from", subquerySource );
+		AST selectFromNode = ASTUtil.createParent( astFactory, SELECT_FROM, "SELECT_FROM", fromNode );
+		return ASTUtil.createParent( astFactory, QUERY, "QUERY", selectFromNode );
+	}
+
+	protected AST processIsEmpty(AST collection, AST notToken) {
+		return processIsEmpty( collection, notToken != null );
+	}
+
+	private AST processIsEmpty(AST node, boolean negated) {
+		node.setNextSibling( null );
+		AST ast = createSubquery( node );
+		ast = ASTUtil.createParent( astFactory, EXISTS, "exists", ast );
+		// Add NOT if it's negated.
+		if ( negated ) {
+			ast = ASTUtil.createParent( astFactory, NOT, "not", ast );
+		}
+		return ast;
+	}
+	public AST negateNode(AST x) {
+		//TODO: switch statements are always evil! We already had bugs because
+		//      of forgotten token types. Use polymorphism for this!
+		switch ( x.getType() ) {
+			case OR:
+				x.setType(AND);
+				x.setText("{and}");
+				negateNode( x.getFirstChild() );
+				negateNode( x.getFirstChild().getNextSibling() );
+				return x;
+			case AND:
+				x.setType(OR);
+				x.setText("{or}");
+				negateNode( x.getFirstChild() );
+				negateNode( x.getFirstChild().getNextSibling() );
+				return x;
+			case EQUALS_OP:
+				x.setType( NOT_EQUALS_OP );
+				x.setText( "{not}" + x.getText() );
+				return x;	// (NOT (EQ a b) ) => (NE a b)
+			case NOT_EQUALS_OP:
+				x.setType( EQUALS_OP );
+				x.setText( "{not}" + x.getText() );
+				return x;	// (NOT (NE a b) ) => (EQ a b)
+			case GREATER_THAN_OP:
+				x.setType( LESS_THAN_OR_EQUALS_OP );
+				x.setText( "{not}" + x.getText() );
+				return x;	// (NOT (GT a b) ) => (LE a b)
+			case LESS_THAN_OP:
+				x.setType( GREATER_THAN_OR_EQUALS_OP );
+				x.setText( "{not}" + x.getText() );
+				return x;	// (NOT (LT a b) ) => (GE a b)
+			case GREATER_THAN_OR_EQUALS_OP:
+				x.setType( LESS_THAN_OP );
+				x.setText( "{not}" + x.getText() );
+				return x;	// (NOT (GE a b) ) => (LT a b)
+			case LESS_THAN_OR_EQUALS_OP:
+				x.setType( GREATER_THAN_OP );
+				x.setText( "{not}" + x.getText() );
+				return x;	// (NOT (LE a b) ) => (GT a b)
+			case LIKE:
+				x.setType( NOT_LIKE );
+				x.setText( "{not}" + x.getText() );
+				return x;	// (NOT (LIKE a b) ) => (NOT_LIKE a b)
+			case NOT_LIKE:
+				x.setType( LIKE );
+				x.setText( "{not}" + x.getText() );
+				return x;	// (NOT (NOT_LIKE a b) ) => (LIKE a b)
+			case IN:
+				x.setType( NOT_IN );
+				x.setText( "{not}" + x.getText() );
+				return x;
+			case NOT_IN:
+				x.setType( IN );
+				x.setText( "{not}" + x.getText() );
+				return x;
+			case IS_NULL:
+				x.setType( IS_NOT_NULL );
+				x.setText( "{not}" + x.getText() );
+				return x;	// (NOT (IS_NULL a b) ) => (IS_NOT_NULL a b)
+			case IS_NOT_NULL:
+				x.setType( IS_NULL );
+				x.setText( "{not}" + x.getText() );
+				return x;	// (NOT (IS_NOT_NULL a b) ) => (IS_NULL a b)
+			case BETWEEN:
+				x.setType( NOT_BETWEEN );
+				x.setText( "{not}" + x.getText() );
+				return x;	// (NOT (BETWEEN a b) ) => (NOT_BETWEEN a b)
+			case NOT_BETWEEN:
+				x.setType( BETWEEN );
+				x.setText( "{not}" + x.getText() );
+				return x;	// (NOT (NOT_BETWEEN a b) ) => (BETWEEN a b)
+			case NOT:
+				return x.getFirstChild();			// (NOT (NOT x) ) => (x)
+			default:
+				return super.negateNode( x );		// Just add a 'not' parent.
+		}
+	}
+
+	protected void transferTrackingInfo(AST source, AST target) {
+		if ( target instanceof Node ) {
+			( ( Node ) target ).transferTrackingInfo( source );
+		}
+		else {
+			super.transferTrackingInfo( source, target );
+		}
+	}
+
+	/**
+	 * Overrides the base behavior to retry keywords as identifiers.
+	 *
+	 * @param token The token.
+	 * @param ex    The recognition exception.
+	 * @return AST - The new AST.
+	 * @throws antlr.RecognitionException if the substitution was not possible.
+	 * @throws antlr.TokenStreamException if the substitution was not possible.
+	 */
+	public AST handleIdentifierError(Token token, RecognitionException ex) throws RecognitionException, TokenStreamException {
+		// If the token can tell us if it could be an identifier...
+		if ( token instanceof TokenImpl ) {
+			TokenImpl hqlToken = ( TokenImpl ) token;
+			// ... and the token could be an identifer and the error is
+			// a mismatched token error ...
+			if ( hqlToken.isPossibleIdentifier() && ex instanceof MismatchedTokenException ) {
+				MismatchedTokenException mte = ( MismatchedTokenException ) ex;
+				// ... and the expected token type was an identifier, then:
+				if ( mte.expecting == IDENT ) {
+					// Use the token as an identifier.
+					reportWarning(
+							"Keyword  '"+ token.getText()
+							+ "' is being interpreted as an identifier due to: "
+							+ mte.getMessage()
+					);
+					// Add the token to the AST.
+					ASTPair currentAST = new ASTPair();
+//					token.setType( WEIRD_IDENT );
+					token.setType( IDENT );
+					astFactory.addASTChild( currentAST, astFactory.create( token ) );
+					consume();
+					return currentAST.root;
+				}
+			}
+		}
+		return super.handleIdentifierError( token, ex );
+	}
+
+    public void handleDotIdent() throws TokenStreamException {
+        // This handles HHH-354, where there is a strange property name in a where clause.
+        // If the lookahead contains a DOT then something that isn't an IDENT...
+		handleDotIdent( 1 );
+    }
+
+	protected int handleDotIdent(int offset) throws TokenStreamException {
+		while ( LA( offset ) == DOT ) {
+			switch ( LA( offset+1 ) ) {
+				case IDENT:
+				case CLASS:
+					break; // break the case statement, not the loop...
+				default:
+					convertPossibleIdentifier( ( TokenImpl ) LT( offset+1 ) );
+			}
+			offset += 2;
+		}
+		return offset;
+	}
+
+	protected void weakKeywords() throws TokenStreamException {
+		switch ( LA( 1 ) ) {
+			case ORDER:
+			case GROUP:
+                // Case 1: Multi token keywords GROUP BY and ORDER BY
+				// The next token ( LT(2) ) should be 'by'... otherwise, this is just an ident.
+				if ( LA( 2 ) != BY ) {
+					convertPossibleIdentifier( ( TokenImpl ) LT(1) );
+				}
+				break;
+			case IDENT:
+				break;
+			default :
+				if ( LA(0) == FROM && LA(2) == DOT ) {
+					convertPossibleIdentifier( ( TokenImpl ) LT(1) );
+				}
+		}
+	}
+
+	protected void unequivocalKeywordAsIdentifier() throws TokenStreamException {
+		if ( LA(1) == IDENT ) {
+			return;
+		}
+		convertPossibleIdentifier( ( TokenImpl ) LT(1) );
+	}
+
+    protected void potentialUpdatePersisterAlias() throws TokenStreamException {
+		switch( LA(1) ) {
+			case AS:
+				// alias rule will handle this...
+			case SET:
+				// SET marks the beginning of the UPDATE's SET-clause
+				break;
+			default:
+				convertPossibleIdentifier( ( TokenImpl ) LT(1) );
+		}
+	}
+
+    protected void potentialDeletePersisterAlias() throws TokenStreamException {
+		switch( LA(1) ) {
+			case AS:
+				// alias rule will handle this...
+			case WHERE:
+				break;
+			default:
+				convertPossibleIdentifier( ( TokenImpl ) LT(1) );
+		}
+    }
+
+    protected void prepareForPersisterReferenceRoot() throws TokenStreamException {
+		if ( LA(1) == IN ) {
+			return;
+		}
+
+		unequivocalKeywordAsIdentifier();
+
+		if ( LA(1) == IDENT && LA(2) == IN ) {
+			return;
+		}
+
+		prepareForBasicEntityPersisterReference();
+	}
+
+    protected void prepareForCrossJoinElements() throws TokenStreamException {
+		unequivocalKeywordAsIdentifier();
+		prepareForBasicEntityPersisterReference();
+    }
+
+	protected void prepareForBasicEntityPersisterReference() throws TokenStreamException {
+		int offset = handleDotIdent( 2 );
+		int next = LA(offset);
+		switch ( next ) {
+			case AS: {
+				// the next token would need to be the persister alias
+				convertPossibleIdentifier( (TokenImpl) LT(offset+1) );
+				break;
+			}
+			case IDENT : {
+				// nothing to do
+				break;
+			}
+			case WHERE:
+			case COMMA:
+			case ON:
+			case WITH:
+			case JOIN:
+			case RIGHT:
+			case LEFT:
+			case CROSS: {
+				// single token structural elements indicating that the next thing could not be an alias
+				break;
+			}
+			case UNION:
+			case INTERSECT:
+			case EXCEPT: {
+				int nextNext = LA(offset+1);
+				if ( nextNext == SELECT || nextNext == FROM ) {
+					break;
+				}
+				else if ( nextNext == ALL ) {
+					int nextNextNext = LA(offset+2);
+					if ( nextNextNext == SELECT || nextNextNext == FROM ) {
+						break;
+					}
+				}
+				convertPossibleIdentifier( ( TokenImpl ) LT(offset) );
+				break;
+			}
+			case GROUP:
+			case ORDER:
+				if ( LA(offset+1) != BY ) {
+					convertPossibleIdentifier( ( TokenImpl ) LT(offset) );
+				}
+				break;
+			case FETCH:
+				if ( ! ( LA(offset+1) == ALL && LA(offset+2) == PROPERTIES ) ) {
+					// not sure sure I like allowing 'fetch' as an indentifier
+					log.warn( "interpretting [fetch] keyword as alias; consider using differen alias" );
+					convertPossibleIdentifier( ( TokenImpl ) LT(offset) );
+				}
+				break;
+			default:
+				convertPossibleIdentifier( ( TokenImpl ) LT(offset) );
+				break;
+		}
+	}
+
+	protected void prepareForQualifiedJoinElements() throws TokenStreamException {
+		unequivocalKeywordAsIdentifier();
+		prepareForBasicEntityPersisterReference();
+    }
+
+	protected void convertPossibleIdentifier(TokenImpl token) {
+		if ( token.isPossibleIdentifier() ) {
+			token.setType( IDENT );
+			log.debug( "Converting keyword-to-identifier [{}]; [id={}]", token, new Integer(System.identityHashCode( token ) ) );
+		}
+	}
+}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/hql/ast/phase/parse/PathCollector.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/hql/ast/phase/parse/PathCollector.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/hql/ast/phase/parse/PathCollector.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,74 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.hql.ast.phase.parse;
+
+import org.hibernate.sql.ast.util.NodeTraverser;
+
+import antlr.collections.AST;
+
+/**
+ * Utilizes a NodeTraverser in order to collect a path from
+ * a (expecting dot-structure) an AST.
+ *
+ * @author Steve Ebersole
+ */
+public class PathCollector implements NodeTraverser.VisitationStrategy, HqlParseTokenTypes {
+	private String path = "";
+
+	private PathCollector() {
+	}
+
+	public void visit(AST node) {
+		if ( node.getType() == DOT ) {
+			path += '.';
+		}
+		else if ( "$".equals( node.getText() ) ) {
+			// allowable for treating java constants
+			path += '$';
+		}
+		else {
+			path += node.getText();
+		}
+	}
+
+	public static String getPath(AST dotStructure) {
+		if ( dotStructure.getType() == IDENT ) {
+			return dotStructure.getText();
+		}
+
+		return extractText( dotStructure );
+	}
+
+	private static String extractText(AST node) {
+		AST lhs = node.getFirstChild();
+		AST rhs = lhs.getNextSibling();
+
+		if ( lhs.getType() == IDENT ) {
+			return lhs.getText() + node.getText() + rhs.getText();
+		}
+		else {
+			return extractText( lhs ) + node.getText() + rhs.getText();
+		}
+	}
+}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/DetailedSemanticException.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/DetailedSemanticException.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/DetailedSemanticException.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,77 @@
+// $Id: DetailedSemanticException.java 5690 2005-02-12 20:27:50Z pgmjsd $
+package org.hibernate.sql.ast;
+
+import antlr.SemanticException;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * Thrown when a call to the underlying Hibernate engine fails, indicating
+ * some form of semantic exception (e.g. a class name was not found in the
+ * current mappings, etc.).
+ */
+public class DetailedSemanticException extends SemanticException {
+	private Throwable cause;
+	private boolean showCauseMessage = true;
+
+	public DetailedSemanticException(String message) {
+		super( message );
+	}
+
+	public DetailedSemanticException(String s, Throwable e) {
+		super( s );
+		cause = e;
+	}
+
+	/**
+	 * Converts everything to a string.
+	 *
+	 * @return a string.
+	 */
+	public String toString() {
+		if ( cause == null || ( !showCauseMessage ) ) {
+			return super.toString();
+		}
+		else {
+			return super.toString() + "\n[cause=" + cause.toString() + "]";
+		}
+	}
+
+	/**
+	 * Prints a stack trace.
+	 */
+	public void printStackTrace() {
+		super.printStackTrace();
+		if ( cause != null ) {
+			cause.printStackTrace();
+		}
+	}
+
+	/**
+	 * Prints a stack trace to the specified print stream.
+	 *
+	 * @param s the print stream.
+	 */
+	public void printStackTrace(PrintStream s) {
+		super.printStackTrace( s );
+		if ( cause != null ) {
+			s.println( "Cause:" );
+			cause.printStackTrace( s );
+		}
+	}
+
+	/**
+	 * Prints this throwable and its backtrace to the specified print writer.
+	 *
+	 * @param w the print writer.s
+	 */
+	public void printStackTrace(PrintWriter w) {
+		super.printStackTrace( w );
+		if ( cause != null ) {
+			w.println( "Cause:" );
+			cause.printStackTrace( w );
+		}
+	}
+
+}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/QuerySyntaxException.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/QuerySyntaxException.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/QuerySyntaxException.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,55 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ast;
+
+import antlr.RecognitionException;
+import org.hibernate.QueryException;
+
+/**
+ * Exception thrown when there is a syntax error in the HQL.
+ *
+ * @author josh
+ */
+public class QuerySyntaxException extends QueryException {
+	public QuerySyntaxException(String message) {
+		super( message );
+	}
+
+	public QuerySyntaxException(String message, String hql) {
+		this( message );
+		setQueryString( hql );
+	}
+
+	public static QuerySyntaxException convert(RecognitionException e) {
+		return convert( e, null );
+	}
+
+	public static QuerySyntaxException convert(RecognitionException e, String hql) {
+		String positionInfo = e.getLine() > 0 && e.getColumn() > 0
+				? " near line " + e.getLine() + ", column " + e.getColumn()
+				: "";
+		return new QuerySyntaxException( e.getMessage() + positionInfo, hql );
+	}
+
+}
\ No newline at end of file

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/AbstractToken.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/AbstractToken.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/AbstractToken.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,77 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ast.common;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public abstract class AbstractToken extends antlr.CommonToken {
+	private int previousTokenType;
+
+	/**
+	 * Getter for property 'previousTokenType'.
+	 *
+	 * @return Value for property 'previousTokenType'.
+	 */
+	public int getPreviousTokenType() {
+		return previousTokenType;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void setType(int type) {
+		this.previousTokenType = getType();
+		super.setType( type );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String toDisplayString() {
+		StringBuffer text = new StringBuffer( super.toString() );
+		text.append( "['" )
+				.append( getText() )
+				.append( "', <" )
+				.append( getType() )
+				.append( "> previously: <" )
+				.append( getPreviousTokenType() )
+				.append( ">, line=" )
+				.append( line )
+				.append( ", col=" )
+				.append( col );
+		appendTextualInfo( text );
+		text.append( "]" );
+		return text.toString();
+	}
+
+	protected void appendTextualInfo(StringBuffer text) {
+	}
+
+	public String getLocation() {
+		return getLine() + ":" + getColumn();
+	}
+}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/CommonHibernateLexer.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/CommonHibernateLexer.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/CommonHibernateLexer.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,70 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ast.common;
+
+import java.io.InputStream;
+import java.io.Reader;
+
+/**
+ * The common lexer for Hibernate stream parsers.
+ *
+ * @author Steve Ebersole
+ */
+public class CommonHibernateLexer extends CommonHibernateLexerSupport {
+	private boolean possibleIdentifier = false;
+
+	public CommonHibernateLexer(InputStream in) {
+		super( in );
+		super.setTokenObjectClass( TokenImpl.class.getName() );
+	}
+
+	public CommonHibernateLexer(Reader in) {
+		super( in );
+		super.setTokenObjectClass( TokenImpl.class.getName() );
+	}
+
+	public void setTokenObjectClass(String s) {
+		// no-op, we've already set ours in the constructor
+	}
+
+	protected void setPossibleIdentifier(boolean possibleIdentifier) {
+		this.possibleIdentifier = possibleIdentifier;
+	}
+
+	protected antlr.Token makeToken(int i) {
+		TokenImpl token = ( TokenImpl ) super.makeToken( i );
+		token.setPossibleIdentifier( possibleIdentifier );
+		possibleIdentifier = false;
+		return token;
+	}
+
+	public void panic() {
+		panic("CharScanner: panic");
+	}
+
+	public void panic(String s) {
+		// todo : better exception type?
+		throw new PanicException( s );
+	}
+}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/JoinType.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/JoinType.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/JoinType.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,62 @@
+package org.hibernate.sql.ast.common;
+
+import java.io.Serializable;
+import java.util.HashMap;
+
+/**
+ * Represents a canonical join type.
+ * <p/>
+ * Note that currently HQL really only supports inner and left outer joins
+ * (though cross joins can also be achieved).  This is because joins in HQL
+ * are always defined in relation to a mapped association.  However, when we
+ * start allowing users to specify ad-hoc joins this may need to change to
+ * allow the full spectrum of join types.  Thus the others are provided here
+ * currently just for completeness and for future expansion.
+ *
+ * @author Steve Ebersole
+ */
+public class JoinType implements Serializable {
+	/**
+	 * Represents an inner join.
+	 */
+	public static final JoinType INNER = new JoinType( "inner" );
+	/**
+	 * Represents a left outer join.
+	 */
+	public static final JoinType LEFT = new JoinType( "left outer" );
+	/**
+	 * Represents a right outer join.
+	 */
+	public static final JoinType RIGHT = new JoinType( "right outer" );
+	/**
+	 * Represents a cross join (aka a cartesian product).
+	 */
+	public static final JoinType CROSS = new JoinType( "cross" );
+	/**
+	 * Represents a full join.
+	 */
+	public static final JoinType FULL = new JoinType( "full" );
+
+	private static final HashMap INSTANCES = new HashMap();
+	static {
+		INSTANCES.put( INNER.name, INNER );
+		INSTANCES.put( LEFT.name, LEFT );
+		INSTANCES.put( RIGHT.name, RIGHT );
+		INSTANCES.put( CROSS.name, CROSS );
+		INSTANCES.put( FULL.name, FULL );
+	}
+
+	private final String name;
+
+	private JoinType(String name) {
+		this.name = name;
+	}
+
+	public String toString() {
+		return name;
+	}
+
+	private Object readResolve() {
+		return INSTANCES.get( name );
+	}
+}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/Node.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/Node.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/Node.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,92 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ast.common;
+
+import antlr.Token;
+import antlr.collections.AST;
+
+/**
+ * Basic AST node
+ *
+ * @author Joshua Davis
+ * @author Steve Ebersole
+ */
+public class Node extends antlr.CommonAST {
+	private String filename;
+	private int line;
+	private int column;
+
+	public Node() {
+		super();
+	}
+
+	public Node(Token tok) {
+		super( tok );  // NOTE: This will call initialize(tok)!
+	}
+
+	public void initialize(Token token) {
+		super.initialize( token );
+		// Propagate line/column information from the lexer during
+		// stream parsing.
+		filename = token.getFilename();
+		line = token.getLine();
+		column = token.getColumn();
+	}
+
+	public void initialize(AST ast) {
+		super.initialize( ast );
+		if ( ast instanceof Node ) {
+			// Propagate line/column information from the source AST during tree walking.
+			transferTrackingInfo( ( Node ) ast );
+		}
+	}
+
+	public void transferTrackingInfo(AST ast) {
+		if ( ast instanceof Node ) {
+			transferTrackingInfo( ( Node ) ast );
+		}
+		else {
+			line = ast.getLine();
+			column = ast.getColumn();
+		}
+	}
+
+	public void transferTrackingInfo(Node node) {
+		filename = node.filename;
+		line = node.line;
+		column = node.column;
+	}
+
+	public String getFilename() {
+		return filename;
+	}
+
+	public int getLine() {
+		return line;
+	}
+
+	public int getColumn() {
+		return column;
+	}
+}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/NumericLiteralToken.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/NumericLiteralToken.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/NumericLiteralToken.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,50 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ast.common;
+
+/**
+ * A custom token class for representing numeric literals.  The reasoning is that there are 2 classifications
+ * by which we need to identify numeric literals:<ol>
+ * <li>The SQL notions of <tt>exact</tt> and <tt>approximate</tt></li>
+ * <li>The java language types (i.e. <tt>int</tt>, <tt>long</tt>, etc)</li>
+ * </ol>
+ * <p/>
+ * Explicitly handling the intersection of these two classification sets is unwieldy (EXACT_INTEGER_LITERAL, etc) so
+ * we instead track one classification by the token-types, and the other is tracked by state on the token.  Since we
+ * generally need to treat with the java types, we use this custom token to track whether the literal is  <tt>exact</tt>
+ * or <tt>approximate</tt>.
+ *
+ * @author Steve Ebersole
+ */
+public class NumericLiteralToken extends AbstractToken {
+	private boolean isApproximate = false; // assume exact
+
+	public boolean isApproximate() {
+		return isApproximate;
+	}
+
+	public void setApproximate(boolean approximate) {
+		isApproximate = approximate;
+	}
+}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/PanicException.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/PanicException.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/PanicException.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,41 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ast.common;
+
+import org.hibernate.HibernateException;
+
+/**
+ * Thrown to indicate a panic situation ossuring in a lexer.
+ *
+ * @author Steve Ebersole
+ */
+public class PanicException extends HibernateException {
+	public PanicException(String s) {
+		super( s );
+	}
+
+	public PanicException(String string, Throwable root) {
+		super( string, root );
+	}
+}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/TokenImpl.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/TokenImpl.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/common/TokenImpl.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,58 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ast.common;
+
+/**
+ * A custom token class for various Hibernate lexers; specifically we are adding the
+ * {@link #isPossibleIdentifier() keyword-as-identifier} capability and tracking of any changes in  token types
+ * via {@link #getPreviousTokenType()}.
+ *
+ * @author Steve Ebersole
+ */
+public class TokenImpl extends AbstractToken {
+	private boolean possibleIdentifier;
+
+	/**
+	 * Getter for property 'possibleIdentifier'.
+	 *
+	 * @return Value for property 'possibleIdentifier'.
+	 */
+	public boolean isPossibleIdentifier() {
+		return possibleIdentifier;
+	}
+
+	/**
+	 * Setter for property 'possibleIdentifier'.
+	 *
+	 * @param possibleIdentifier Value to set for property 'possibleIdentifier'.
+	 */
+	public void setPossibleIdentifier(boolean possibleIdentifier) {
+		this.possibleIdentifier = possibleIdentifier;
+	}
+
+	protected void appendTextualInfo(StringBuffer text) {
+		text.append( ",possibleIdentifier?=" ).append( possibleIdentifier );
+	}
+
+}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTAppender.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTAppender.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTAppender.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,68 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ast.util;
+
+import antlr.ASTFactory;
+import antlr.collections.AST;
+
+/**
+ * Appends child nodes to a parent efficiently.
+ *
+ * @author Joshua Davis
+ */
+public class ASTAppender {
+	private AST parent;
+	private AST last;
+	private ASTFactory factory;
+
+	public ASTAppender(ASTFactory factory, AST parent) {
+		this( parent );
+		this.factory = factory;
+	}
+
+	public ASTAppender(AST parent) {
+		this.parent = parent;
+		this.last = ASTUtil.getLastChild( parent );
+	}
+
+	public AST append(int type, String text, boolean appendIfEmpty) {
+		if ( text != null && ( appendIfEmpty || text.length() > 0 ) ) {
+			return append( factory.create( type, text ) );
+		}
+		else {
+			return null;
+		}
+	}
+
+	public AST append(AST child) {
+		if ( last == null ) {
+			parent.setFirstChild( child );
+		}
+		else {
+			last.setNextSibling( child );
+		}
+		last = child;
+		return last;
+	}
+}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTIterator.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTIterator.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTIterator.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,92 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ast.util;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import antlr.collections.AST;
+
+/**
+ * Depth first iteration of an ANTLR AST.
+ *
+ * @author Joshua Davis
+ */
+public class ASTIterator implements Iterator {
+	private AST next;
+	private LinkedList parents = new LinkedList();
+
+	public void remove() {
+		throw new UnsupportedOperationException( "remove() is not supported" );
+	}
+
+	public boolean hasNext() {
+		return next != null;
+	}
+
+	public Object next() {
+		return nextNode();
+	}
+
+	public ASTIterator(AST tree) {
+		next = tree;
+		down();
+	}
+
+	public AST nextNode() {
+		AST current = next;
+		if ( next != null ) {
+			AST nextSibling = next.getNextSibling();
+			if ( nextSibling == null ) {
+				next = pop();
+			}
+			else {
+				next = nextSibling;
+				down();
+			}
+		}
+		return current;
+	}
+
+	private void down() {
+		while ( next != null && next.getFirstChild() != null ) {
+			push( next );
+			next = next.getFirstChild();
+		}
+	}
+
+	private void push(AST parent) {
+		parents.addFirst( parent );
+	}
+
+	private AST pop() {
+		if ( parents.size() == 0 ) {
+			return null;
+		}
+		else {
+			return ( AST ) parents.removeFirst();
+		}
+	}
+
+}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTParentsFirstIterator.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTParentsFirstIterator.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTParentsFirstIterator.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,96 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ast.util;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+
+import antlr.collections.AST;
+
+/**
+ * Depth first iteration of an ANTLR AST.
+ *
+ * @author Joshua Davis
+ */
+public class ASTParentsFirstIterator implements Iterator {
+	private AST next;
+	private AST tree;
+	private LinkedList parents = new LinkedList();
+
+	public void remove() {
+		throw new UnsupportedOperationException( "remove() is not supported" );
+	}
+
+	public boolean hasNext() {
+		return next != null;
+	}
+
+	public Object next() {
+		return nextNode();
+	}
+
+	public ASTParentsFirstIterator(AST tree) {
+		this.tree = next = tree;
+	}
+
+	public AST nextNode() {
+		AST current = next;
+		if ( next != null ) {
+			AST child = next.getFirstChild();
+			if ( child == null ) {
+				AST sibling = next.getNextSibling();
+				if ( sibling == null ) {
+					AST parent = pop();
+					while ( parent != null && parent.getNextSibling() == null )
+						parent = pop();
+					next = ( parent != null ) ? parent.getNextSibling() : null;
+				}
+				else {
+					next = sibling;
+				}
+			}
+			else {
+				if ( next != tree ) {
+					push( next );
+				}
+				next = child;
+			}
+		}
+		return current;
+	}
+
+	private void push(AST parent) {
+		parents.addFirst( parent );
+	}
+
+	private AST pop() {
+		if ( parents.size() == 0 ) {
+			return null;
+		}
+		else {
+			return ( AST ) parents.removeFirst();
+		}
+	}
+
+}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTPrinter.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTPrinter.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTPrinter.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,224 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ast.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Map;
+
+import org.hibernate.util.StringHelper;
+
+import antlr.collections.AST;
+
+/**
+ * Utility for generating pretty "ASCII art" representations of syntax trees.
+ *
+ * @author Joshua Davis
+ * @author Steve Ebersole
+ */
+public class ASTPrinter {
+	private final Map tokenTypeNameCache;
+	private final boolean showClassNames;
+
+	/**
+	 * Constructs a printer.
+	 * <p/>
+	 * Delegates to {@link #ASTPrinter(Class, boolean)} with {@link #isShowClassNames showClassNames} as <tt>true</tt>
+	 *
+	 * @param tokenTypeConstants The token types to use during printing; typically the {vocabulary}TokenTypes.java
+	 * interface generated by ANTLR.
+	 */
+	public ASTPrinter(Class tokenTypeConstants) {
+		this( ASTUtil.generateTokenNameCache( tokenTypeConstants ), true );
+	}
+
+	public ASTPrinter(boolean showClassNames) {
+		this( ( Map ) null, showClassNames );
+	}
+
+	/**
+	 * Constructs a printer.
+	 *
+	 * @param tokenTypeConstants The token types to use during printing; typically the {vocabulary}TokenTypes.java
+	 * interface generated by ANTLR.
+	 * @param showClassNames Should the class names of the {@link org.hibernate.sql.ast.common.Node} impls be displayed.
+	 */
+	public ASTPrinter(Class tokenTypeConstants, boolean showClassNames) {
+		this( ASTUtil.generateTokenNameCache( tokenTypeConstants ), showClassNames );
+	}
+
+	private ASTPrinter(Map tokenTypeNameCache, boolean showClassNames) {
+		this.tokenTypeNameCache = tokenTypeNameCache;
+		this.showClassNames = showClassNames;
+	}
+
+	/**
+	 * Getter for property 'showClassNames'.
+	 *
+	 * @return Value for property 'showClassNames'.
+	 */
+	public boolean isShowClassNames() {
+		return showClassNames;
+	}
+
+	/**
+	 * Renders the AST into 'ASCII art' form and returns that string representation.
+	 *
+	 * @param ast The AST to display.
+	 * @param header The header for the display.
+	 *
+	 * @return The AST in 'ASCII art' form, as a string.
+	 */
+	public String showAsString(AST ast, String header) {
+		ByteArrayOutputStream baos = new ByteArrayOutputStream();
+		PrintStream ps = new PrintStream( baos );
+		ps.println( header );
+		showAst( ast, ps );
+		ps.flush();
+		return new String( baos.toByteArray() );
+	}
+
+	/**
+	 * Prints the AST in 'ASCII art' form to the specified print stream.
+	 *
+	 * @param ast The AST to print.
+	 * @param out The print stream to which the AST should be printed.
+	 */
+	public void showAst(AST ast, PrintStream out) {
+		showAst( ast, new PrintWriter( out ) );
+	}
+
+	/**
+	 * Prints the AST in 'ASCII art' tree form to the specified print writer.
+	 *
+	 * @param ast The AST to print.
+	 * @param pw The print writer to which the AST should be written.
+	 */
+	public void showAst(AST ast, PrintWriter pw) {
+		ArrayList parents = new ArrayList();
+		showAst( parents, pw, ast );
+		pw.flush();
+	}
+
+	/**
+	 * Returns the token type name for the given token type.
+	 *
+	 * @param type The token type.
+	 * @return String - The token type name from the token type constant class,
+	 *         or just the integer as a string if none exists.
+	 */
+	public String getTokenTypeName(int type) {
+		if ( tokenTypeNameCache == null ) {
+			return Integer.toString( type );
+		}
+		return ( String ) tokenTypeNameCache.get( new Integer( type ) );
+	}
+
+	private void showAst(ArrayList parents, PrintWriter pw, AST ast) {
+		if ( ast == null ) {
+			pw.println( "AST is null!" );
+			return;
+		}
+
+		for ( int i = 0; i < parents.size(); i++ ) {
+			AST parent = ( AST ) parents.get( i );
+			if ( parent.getNextSibling() == null ) {
+
+				pw.print( "   " );
+			}
+			else {
+				pw.print( " | " );
+			}
+		}
+
+		if ( ast.getNextSibling() == null ) {
+			pw.print( " \\-" );
+		}
+		else {
+			pw.print( " +-" );
+		}
+
+		showNode( pw, ast );
+
+		ArrayList newParents = new ArrayList( parents );
+		newParents.add( ast );
+		for ( AST child = ast.getFirstChild(); child != null; child = child.getNextSibling() ) {
+			showAst( newParents, pw, child );
+		}
+		newParents.clear();
+	}
+
+	private void showNode(PrintWriter pw, AST ast) {
+		String s = nodeToString( ast, isShowClassNames() );
+		pw.println( s );
+	}
+
+	public String nodeToString(AST ast, boolean showClassName) {
+		if ( ast == null ) {
+			return "{node:null}";
+		}
+		StringBuffer buf = new StringBuffer();
+		buf.append( "[" ).append( getTokenTypeName( ast.getType() ) ).append( "] " );
+		if ( showClassName ) {
+			buf.append( StringHelper.unqualify( ast.getClass().getName() ) ).append( ": " );
+		}
+
+        buf.append( "'" );
+        String text = ast.getText();
+		if ( text == null ) {
+			text = "{text:null}";
+		}
+		appendEscapedMultibyteChars(text, buf);
+        buf.append( "'" );
+		if ( ast instanceof DisplayableNode ) {
+			DisplayableNode displayableNode = ( DisplayableNode ) ast;
+			// Add a space before the display text.
+			buf.append( " " ).append( displayableNode.getDisplayText() );
+		}
+		return buf.toString();
+	}
+
+    public static void appendEscapedMultibyteChars(String text, StringBuffer buf) {
+        char[] chars = text.toCharArray();
+        for (int i = 0; i < chars.length; i++) {
+            char aChar = chars[i];
+            if (aChar > 256) {
+                buf.append("\\u");
+                buf.append(Integer.toHexString(aChar));
+            }
+            else
+                buf.append(aChar);
+        }
+    }
+
+    public static String escapeMultibyteChars(String text)
+    {
+        StringBuffer buf = new StringBuffer();
+        appendEscapedMultibyteChars(text,buf);
+        return buf.toString();
+    }
+}
\ No newline at end of file

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTUtil.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTUtil.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTUtil.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,435 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ast.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+import antlr.ASTFactory;
+import antlr.collections.AST;
+import antlr.collections.impl.ASTArray;
+
+/**
+ * Provides utility methods for AST traversal and manipulation.
+ *
+ * @author Joshua Davis
+ * @author Steve Ebersole
+ */
+public final class ASTUtil {
+	/**
+	 * Disallow instantiation.
+	 *
+	 * @deprecated (tellclovertoignorethis)
+	 */
+	private ASTUtil() {
+	}
+
+	/**
+	 * Creates a single node AST.
+	 * <p/>
+	 * TODO : remove this; this is silly...
+	 *
+	 * @param astFactory The factory.
+	 * @param type The node type.
+	 * @param text The node text.
+	 *
+	 * @return AST - A single node tree.
+	 */
+	public static AST create(ASTFactory astFactory, int type, String text) {
+		return astFactory.create( type, text );
+	}
+
+	/**
+	 * Creates a single node AST as a sibling of the passed prevSibling,
+	 * taking care to reorganize the tree correctly to account for this
+	 * newly created node.
+	 *
+	 * @param astFactory The factory.
+	 * @param type The node type.
+	 * @param text The node text.
+	 * @param prevSibling The previous sibling.
+	 *
+	 * @return The created AST node.
+	 */
+	public static AST createSibling(ASTFactory astFactory, int type, String text, AST prevSibling) {
+		AST node = astFactory.create( type, text );
+		return insertSibling( node, prevSibling );
+	}
+
+	/**
+	 * Inserts a node into a child subtree as a particularly positioned
+	 * sibling taking care to properly reorganize the tree to account for this
+	 * new addition.
+	 *
+	 * @param node The node to insert
+	 * @param prevSibling The previous node at the sibling position
+	 * where we want this node inserted.
+	 *
+	 * @return The return is the same as the node parameter passed in.
+	 */
+	public static AST insertSibling(AST node, AST prevSibling) {
+		node.setNextSibling( prevSibling.getNextSibling() );
+		prevSibling.setNextSibling( node );
+		return node;
+	}
+
+	/**
+	 * Creates a 'binary operator' subtree, given the information about the
+	 * parent and the two child nodex.
+	 *
+	 * @param factory The AST factory.
+	 * @param parentType The type of the parent node.
+	 * @param parentText The text of the parent node.
+	 * @param child1 The first child.
+	 * @param child2 The second child.
+	 *
+	 * @return AST - A new sub-tree of the form "(parent child1 child2)"
+	 */
+	public static AST createBinarySubtree(ASTFactory factory, int parentType, String parentText, AST child1, AST child2) {
+		ASTArray array = createAstArray( factory, 3, parentType, parentText, child1 );
+		array.add( child2 );
+		return factory.make( array );
+	}
+
+	/**
+	 * Creates a single parent of the specified child (i.e. a 'unary operator'
+	 * subtree).
+	 *
+	 * @param factory The AST factory.
+	 * @param parentType The type of the parent node.
+	 * @param parentText The text of the parent node.
+	 * @param child The child.
+	 *
+	 * @return AST - A new sub-tree of the form "(parent child)"
+	 */
+	public static AST createParent(ASTFactory factory, int parentType, String parentText, AST child) {
+		ASTArray array = createAstArray( factory, 2, parentType, parentText, child );
+		return factory.make( array );
+	}
+
+	public static AST createTree(ASTFactory factory, AST[] nestedChildren) {
+		AST[] array = new AST[2];
+		int limit = nestedChildren.length - 1;
+		for ( int i = limit; i >= 0; i-- ) {
+			if ( i != limit ) {
+				array[1] = nestedChildren[i + 1];
+				array[0] = nestedChildren[i];
+				factory.make( array );
+			}
+		}
+		return array[0];
+	}
+
+	/**
+	 * Finds the first node of the specified type in the chain of children.
+	 *
+	 * @param parent The parent
+	 * @param type The type to find.
+	 *
+	 * @return The first node of the specified type, or null if not found.
+	 */
+	public static AST findTypeInChildren(AST parent, int type) {
+		AST n = parent.getFirstChild();
+		while ( n != null && n.getType() != type ) {
+			n = n.getNextSibling();
+		}
+		return n;
+	}
+
+	/**
+	 * Returns the last direct child of 'n'.
+	 *
+	 * @param n The parent
+	 *
+	 * @return The last direct child of 'n'.
+	 */
+	public static AST getLastChild(AST n) {
+		return getLastSibling( n.getFirstChild() );
+	}
+
+	/**
+	 * Returns the last sibling of 'a'.
+	 *
+	 * @param a The sibling.
+	 *
+	 * @return The last sibling of 'a'.
+	 */
+	private static AST getLastSibling(AST a) {
+		AST last = null;
+		while ( a != null ) {
+			last = a;
+			a = a.getNextSibling();
+		}
+		return last;
+	}
+
+	/**
+	 * Returns the 'list' representation with some brackets around it for debugging.
+	 *
+	 * @param n The tree.
+	 *
+	 * @return The list representation of the tree.
+	 */
+	public static String getDebugString(AST n) {
+		StringBuffer buf = new StringBuffer();
+		buf.append( "[ " );
+		buf.append( ( n == null ) ? "{null}" : n.toStringTree() );
+		buf.append( " ]" );
+		return buf.toString();
+	}
+
+	/**
+	 * Find the previous sibling in the parent for the given child.
+	 *
+	 * @param parent the parent node
+	 * @param child the child to find the previous sibling of
+	 *
+	 * @return the previous sibling of the child
+	 */
+	public static AST findPreviousSibling(AST parent, AST child) {
+		AST prev = null;
+		AST n = parent.getFirstChild();
+		while ( n != null ) {
+			if ( n == child ) {
+				return prev;
+			}
+			prev = n;
+			n = n.getNextSibling();
+		}
+		throw new IllegalArgumentException( "Child not found in parent!" );
+	}
+
+	/**
+	 * Makes the child node a sibling of the parent, reconnecting all siblings.
+	 *
+	 * @param parent the parent
+	 * @param child the child
+	 */
+	public static void makeSiblingOfParent(AST parent, AST child) {
+		AST prev = findPreviousSibling( parent, child );
+		if ( prev != null ) {
+			prev.setNextSibling( child.getNextSibling() );
+		}
+		else { // child == parent.getFirstChild()
+			parent.setFirstChild( child.getNextSibling() );
+		}
+		child.setNextSibling( parent.getNextSibling() );
+		parent.setNextSibling( child );
+	}
+
+	public static String getPathText(AST n) {
+		StringBuffer buf = new StringBuffer();
+		getPathText( buf, n );
+		return buf.toString();
+	}
+
+	private static void getPathText(StringBuffer buf, AST n) {
+		AST firstChild = n.getFirstChild();
+		// If the node has a first child, recurse into the first child.
+		if ( firstChild != null ) {
+			getPathText( buf, firstChild );
+		}
+		// Append the text of the current node.
+		buf.append( n.getText() );
+		// If there is a second child (RHS), recurse into that child.
+		if ( firstChild != null && firstChild.getNextSibling() != null ) {
+			getPathText( buf, firstChild.getNextSibling() );
+		}
+	}
+
+	public static boolean hasExactlyOneChild(AST n) {
+		return n != null && n.getFirstChild() != null && n.getFirstChild().getNextSibling() == null;
+	}
+
+	public static void appendSibling(AST n, AST s) {
+		while ( n.getNextSibling() != null ) {
+			n = n.getNextSibling();
+		}
+		n.setNextSibling( s );
+	}
+
+	/**
+	 * Inserts the child as the first child of the parent, all other children are shifted over to the 'right'.
+	 *
+	 * @param parent the parent
+	 * @param child the new first child
+	 */
+	public static void insertChild(AST parent, AST child) {
+		if ( parent.getFirstChild() == null ) {
+			parent.setFirstChild( child );
+		}
+		else {
+			AST n = parent.getFirstChild();
+			parent.setFirstChild( child );
+			child.setNextSibling( n );
+		}
+	}
+
+	private static ASTArray createAstArray(ASTFactory factory, int size, int parentType, String parentText, AST child1) {
+		ASTArray array = new ASTArray( size );
+		array.add( factory.create( parentType, parentText ) );
+		array.add( child1 );
+		return array;
+	}
+
+	/**
+	 * Filters nodes out of a tree.
+	 */
+	public static interface FilterPredicate {
+		/**
+		 * Returns true if the node should be filtered out.
+		 *
+		 * @param n The node.
+		 *
+		 * @return true if the node should be filtered out, false to keep the node.
+		 */
+		boolean exclude(AST n);
+	}
+
+	/**
+	 * A predicate that uses inclusion, rather than exclusion semantics.
+	 */
+	public abstract static class IncludePredicate implements FilterPredicate {
+		public final boolean exclude(AST node) {
+			return !include( node );
+		}
+
+		public abstract boolean include(AST node);
+	}
+
+	public static List collectChildren(AST root, FilterPredicate predicate) {
+		return new CollectingNodeVisitor( predicate ).collect( root );
+	}
+
+	private static class CollectingNodeVisitor implements NodeTraverser.VisitationStrategy {
+		private final FilterPredicate predicate;
+		private final List collectedNodes = new ArrayList();
+
+		public CollectingNodeVisitor(FilterPredicate predicate) {
+			this.predicate = predicate;
+		}
+
+		public void visit(AST node) {
+			if ( predicate == null || !predicate.exclude( node ) ) {
+				collectedNodes.add( node );
+			}
+		}
+
+		public List getCollectedNodes() {
+			return collectedNodes;
+		}
+
+		public List collect(AST root) {
+			NodeTraverser traverser = new NodeTraverser( this );
+			traverser.traverseDepthFirst( root );
+			return collectedNodes;
+		}
+	}
+
+	/**
+	 * Method to generate a map of token type names, keyed by their token type values.
+	 *
+	 * @param tokenTypeInterface The *TokenTypes interface (or implementor of said interface).
+	 * @return The generated map.
+	 */
+	public static Map generateTokenNameCache(Class tokenTypeInterface) {
+		final Field[] fields = tokenTypeInterface.getFields();
+		Map cache = new HashMap( (int)( fields.length * .75 ) + 1 );
+		for ( int i = 0; i < fields.length; i++ ) {
+			final Field field = fields[i];
+			if ( Modifier.isStatic( field.getModifiers() ) ) {
+				try {
+					cache.put( field.get( null ), field.getName() );
+				}
+				catch ( Throwable ignore ) {
+				}
+			}
+		}
+		return cache;
+	}
+
+	/**
+	 * Get the name of a constant defined on the given class which has the given value.
+	 * <p/>
+	 * Note, if multiple constants have this value, the first will be returned which is known to be different
+	 * on different JVM implementations.
+	 *
+	 * @param owner The class which defines the constant
+	 * @param value The value of the constant.
+	 *
+	 * @return The token type name, *or* the integer value if the name could not be found.
+	 */
+	public static String getConstantName(Class owner, int value) {
+		String tokenTypeName = Integer.toString( value );
+		if ( owner != null ) {
+			Field[] fields = owner.getFields();
+			for ( int i = 0; i < fields.length; i++ ) {
+				final Integer fieldValue = extractIntegerValue( fields[i] );
+				if ( fieldValue != null && fieldValue.intValue() == value ) {
+					tokenTypeName = fields[i].getName();
+					break;
+				}
+			}
+		}
+		return tokenTypeName;
+	}
+
+	private static Integer extractIntegerValue(Field field) {
+		Integer rtn = null;
+		try {
+			Object value = field.get( null );
+			if ( value instanceof Integer ) {
+				rtn = ( Integer ) value;
+			}
+			else if ( value instanceof Short ) {
+				rtn = new Integer( ( ( Short ) value ).intValue() );
+			}
+			else if ( value instanceof Long ) {
+				if ( ( ( Long ) value ).longValue() <= Integer.MAX_VALUE ) {
+					rtn = new Integer( ( ( Long ) value ).intValue() );
+				}
+			}
+		}
+		catch ( IllegalAccessException ignore ) {
+		}
+		return rtn;
+	}
+
+	/**
+	 * Just a friendly renaming of {@link #getConstantName}; in fact this method just simply delegates to that one.
+	 *
+	 * @param tokenTypeInterface The *TokenTypes interface (or one of its implementors).
+	 * @param tokenType The token type value.
+	 * @return The corresponding name.
+	 *
+	 * @see #getConstantName
+	 */
+	public static String getTokenTypeName(Class tokenTypeInterface, int tokenType) {
+		return getConstantName( tokenTypeInterface, tokenType );
+	}
+}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/DisplayableNode.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/DisplayableNode.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/DisplayableNode.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,40 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ast.util;
+
+/**
+ * Contract for {@link org.hibernate.sql.ast.common.Node} implementations which wish to return customized display information
+ * about themselves.
+ *
+ * @author Steve Ebersole
+ * @author Joshua Davis
+ */
+public interface DisplayableNode {
+	/**
+	 * Returns additional display text for the AST node.
+	 *
+	 * @return String - The additional display text.
+	 */
+	public String getDisplayText();
+}
\ No newline at end of file

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ErrorCounter.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ErrorCounter.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ErrorCounter.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,95 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ast.util;
+
+import antlr.RecognitionException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.QueryException;
+import org.hibernate.sql.ast.QuerySyntaxException;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * An error handler that counts parsing errors and warnings.
+ */
+public class ErrorCounter implements ParseErrorHandler {
+	private Log log = LogFactory.getLog( ErrorCounter.class );
+
+	private List errorList = new ArrayList();
+	private List warningList = new ArrayList();
+	private List recognitionExceptions = new ArrayList();
+
+	public void reportError(RecognitionException e) {
+		String msg = e.toString();
+		reportError( msg );
+		recognitionExceptions.add( e );
+		if ( log.isTraceEnabled() ) {
+			log.trace( msg, e );
+		}
+	}
+
+	public void reportError(String message) {
+		log.error( message );
+		errorList.add( message );
+	}
+
+	public void reportWarning(String message) {
+		log.debug( message );
+		warningList.add( message );
+	}
+
+	public int getErrorCount() {
+		return errorList.size();
+	}
+
+	private String getErrorString() {
+		StringBuffer buf = new StringBuffer();
+		for ( Iterator iterator = errorList.iterator(); iterator.hasNext(); ) {
+			buf.append( ( String ) iterator.next() );
+			if ( iterator.hasNext() ) buf.append( "\n" );
+
+		}
+		return buf.toString();
+	}
+
+	public void throwQueryException() throws QueryException {
+		if ( getErrorCount() > 0 ) {
+			if ( recognitionExceptions.size() > 0 ) {
+				throw QuerySyntaxException.convert( ( RecognitionException ) recognitionExceptions.get( 0 ) );
+			}
+			else {
+				throw new QueryException( getErrorString() );
+			}
+		}
+		else {
+			// all clear
+			if ( log.isDebugEnabled() ) {
+				log.debug( "throwQueryException() : no errors" );
+			}
+		}
+	}
+}
\ No newline at end of file

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ErrorReporter.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ErrorReporter.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ErrorReporter.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,39 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ast.util;
+
+import antlr.RecognitionException;
+
+/**
+ * Implementations will report or handle errors invoked by an ANTLR base parser.
+ *
+ * @author Joshua Davis
+ */
+public interface ErrorReporter {
+	void reportError(RecognitionException e);
+
+	void reportError(String s);
+
+	void reportWarning(String s);
+}
\ No newline at end of file

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/NodeTraverser.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/NodeTraverser.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/NodeTraverser.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,67 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ast.util;
+
+import antlr.collections.AST;
+
+/**
+ * A visitor for traversing an AST tree.
+ *
+ * @author Steve Ebersole
+ */
+public class NodeTraverser {
+	public static interface VisitationStrategy {
+		public void visit(AST node);
+	}
+
+	private final VisitationStrategy strategy;
+
+	public NodeTraverser(VisitationStrategy strategy) {
+		this.strategy = strategy;
+	}
+
+	/**
+	 * Traverse the AST tree depth first.
+	 * <p/>
+	 * Note that the AST passed in is not visited itself.  Visitation starts
+	 * with its children.
+	 *
+	 * @param ast
+	 */
+	public void traverseDepthFirst(AST ast) {
+		if ( ast == null ) {
+			throw new IllegalArgumentException( "node to traverse cannot be null!" );
+		}
+		visitDepthFirst( ast.getFirstChild() );
+	}
+
+	private void visitDepthFirst(AST ast) {
+		if ( ast == null ) {
+			return;
+		}
+		strategy.visit( ast );
+		visitDepthFirst( ast.getFirstChild() );
+		visitDepthFirst( ast.getNextSibling() );
+	}
+}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ParseErrorHandler.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ParseErrorHandler.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ParseErrorHandler.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,39 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ast.util;
+
+import org.hibernate.QueryException;
+
+
+/**
+ * Defines the behavior of an error handler for the Hibernate parsers.
+ *
+ * @author Joshua Davis
+ */
+public interface ParseErrorHandler extends ErrorReporter {
+
+	int getErrorCount();
+
+	void throwQueryException() throws QueryException;
+}
\ No newline at end of file

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/PathHelper.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/PathHelper.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/PathHelper.java	2008-12-13 16:25:05 UTC (rev 15693)
@@ -0,0 +1,112 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ast.util;
+
+import org.hibernate.util.StringHelper;
+import org.hibernate.sql.ast.common.Sql92TokenTypes;
+
+import antlr.ASTFactory;
+import antlr.collections.AST;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Provides utility methods for dealing with path expressions.
+ * <p/>
+ * Note that these utilities do not properly account for index operations.
+ *
+ * @author Joshua Davis
+ * @author Steve Ebersole
+ */
+public final class PathHelper implements Sql92TokenTypes {
+	private static final Log log = LogFactory.getLog( PathHelper.class );
+
+	/**
+	 * Direct instantiation of PathHelper disallowed.
+	 */
+	private PathHelper() {
+	}
+
+	/**
+	 * Turns a path into an AST.
+	 *
+	 * @param path    The path.
+	 * @param factory The AST factory to use.
+	 * @return An HQL AST representing the path.
+	 */
+	public static AST parsePath(String path, ASTFactory factory) {
+		String[] identifiers = StringHelper.split( ".", path );
+		AST lhs = null;
+		for ( int i = 0; i < identifiers.length; i++ ) {
+			String identifier = identifiers[i];
+			AST child = ASTUtil.create( factory, IDENT, identifier );
+			if ( i == 0 ) {
+				lhs = child;
+			}
+			else {
+				lhs = ASTUtil.createBinarySubtree( factory, DOT, ".", lhs, child );
+			}
+		}
+		if ( log.isDebugEnabled() ) {
+			log.debug( "parsePath() : " + path + " -> " + ASTUtil.getDebugString( lhs ) );
+		}
+		return lhs;
+	}
+
+	/**
+	 * Provides the inverse functionality of {@link #parsePath}.  In other words, for any path
+	 * 'p' not involving index operations, p == reconstitutePathString( parsePath( p, someASTFactory ) ).
+	 *
+	 * @param pathAST The path AST structure.
+	 * @return The corresponding path string.
+	 */
+	public static String rebuildPathExpression(AST pathAST) {
+		final StringBuffer buffer = new StringBuffer();
+		visitExpression( pathAST, buffer );
+		return buffer.toString();
+	}
+
+	private static void visitExpression(AST expression, StringBuffer buffer) {
+		if ( DOT == expression.getType() ) {
+			visitDot( expression.getFirstChild(), expression.getFirstChild().getNextSibling(), buffer );
+		}
+		else if ( IDENT == expression.getType() ) {
+			visitIdent( expression, buffer );
+		}
+	}
+
+	private static void visitDot(AST lhs, AST rhs, StringBuffer buffer) {
+		visitExpression( lhs, buffer );
+		buffer.append( '.' ).append( rhs.getText() );
+	}
+
+	private static void visitIdent(AST ident, StringBuffer buffer) {
+		buffer.append( ident.getText() );
+	}
+
+	public static String getAlias(String path) {
+		return StringHelper.root( path );
+	}
+}




More information about the hibernate-commits mailing list