Author: pgmjsd
Date: 2006-04-01 09:08:20 -0500 (Sat, 01 Apr 2006)
New Revision: 9726
Added:
branches/HQL_ANTLR_2/Hibernate3/grammar/hql-resolve.g
branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/HqlResolver.java
branches/HQL_ANTLR_2/Hibernate3/test/org/hibernate/test/hql/HqlResolverTest.java
Modified:
branches/HQL_ANTLR_2/Hibernate3/build.xml
branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/HqlASTFactory.java
branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/tree/Node.java
branches/HQL_ANTLR_2/Hibernate3/test/org/hibernate/test/hql/HqlParserTest.java
Log:
First cut at a new query translator phase that will pre-process the HQL AST.
Modified: branches/HQL_ANTLR_2/Hibernate3/build.xml
===================================================================
--- branches/HQL_ANTLR_2/Hibernate3/build.xml 2006-04-01 00:02:15 UTC (rev 9725)
+++ branches/HQL_ANTLR_2/Hibernate3/build.xml 2006-04-01 14:08:20 UTC (rev 9726)
@@ -179,6 +179,11 @@
target="${grammar.dir}/hql.g"
outputdirectory="${parser.src}"
/>
+ <!-- The HQL resolver tree transform grammar -->
+ <antlrtask
+ target="${grammar.dir}/hql-resolve.g"
+ outputdirectory="${parser.src}"
+ />
<!-- The HQL-SQL tree transform grammar -->
<antlrtask
target="${grammar.dir}/hql-sql.g"
Added: branches/HQL_ANTLR_2/Hibernate3/grammar/hql-resolve.g
===================================================================
--- branches/HQL_ANTLR_2/Hibernate3/grammar/hql-resolve.g 2006-04-01 00:02:15 UTC (rev 9725)
+++ branches/HQL_ANTLR_2/Hibernate3/grammar/hql-resolve.g 2006-04-01 14:08:20 UTC (rev 9726)
@@ -0,0 +1,112 @@
+header
+{
+// $Id:$
+package org.hibernate.hql.antlr;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+}
+
+/**
+ * Hibernate Query Language resolver phase.<br>
+ * This is a tree grammar that transforms an HQL AST into another HQL AST, resolving and normalizing
+ * sub-trees along the way.
+ * <br>
+ * <i>NOTE:</i> The java class is generated from hql-resolver.g by ANTLR.
+ * <i>DO NOT EDIT THE GENERATED JAVA SOURCE CODE.</i>
+ * @author Joshua Davis (jo...@hi...)
+ */
+class HqlBaseResolver extends TreeParser;
+
+options
+{
+ // Note: importVocab and exportVocab cause ANTLR to share the token type numbers between the
+ // two grammars. This means that the token type constants from the source tree are the same
+ // as those in the target tree. If this is not the case, tree translation can result in
+ // token types from the *source* tree being present in the target tree.
+ importVocab=Hql; // import definitions from "Hql"
+ exportVocab=HqlR; // The result is "HqlR", for "HQL, Resolved"
+ buildAST=true;
+}
+
+tokens
+{
+ BOGUS;
+}
+
+
+// -- Declarations --
+{
+ private static Log log = LogFactory.getLog( HqlBaseResolver.class );
+}
+
+// The main statement rule.
+statement
+ : selectStatement | updateStatement | deleteStatement | insertStatement
+ ;
+
+// --- HQL statements ---
+
+selectStatement
+ : query
+ ;
+
+updateStatement
+ : #(UPDATE (VERSIONED)? fromClause setClause (whereClause)? )
+ ;
+
+deleteStatement
+ : #(DELETE fromClause (whereClause)? )
+ ;
+
+insertStatement
+ : #(INSERT intoClause query )
+ ;
+
+query
+ : #(QUERY
+ // The first phase places the FROM first to make processing the SELECT simpler.
+ #(SELECT_FROM
+ fromClause
+ (selectClause)?
+ )
+ (whereClause)?
+ (groupClause)?
+ (orderClause)?
+ )
+ ;
+
+selectClause
+ : #(SELECT (DISTINCT)? (~DISTINCT)* )
+ ;
+
+// -- Language sub-elements --
+
+fromClause
+ : #(FROM (subtree)* )
+ ;
+
+intoClause
+ : #(INTO (subtree)* )
+ ;
+
+whereClause
+ : #(WHERE (subtree)* )
+ ;
+
+groupClause
+ : #(GROUP (subtree)* )
+ ;
+
+orderClause
+ : #(ORDER (subtree)* )
+ ;
+
+setClause
+ : #(SET (subtree)* )
+ ;
+
+// General subtree. Matches anything, copies the tree verbatim.
+subtree
+ : #(. (subtree)*)
+ ;
\ No newline at end of file
Modified: branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/HqlASTFactory.java
===================================================================
--- branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/HqlASTFactory.java 2006-04-01 00:02:15 UTC (rev 9725)
+++ branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/HqlASTFactory.java 2006-04-01 14:08:20 UTC (rev 9726)
@@ -4,17 +4,20 @@
import org.hibernate.hql.ast.tree.Node;
/**
- * User: Joshua Davis<br>
- * Date: Sep 23, 2005<br>
- * Time: 12:30:01 PM<br>
+ * Use this AST factory to enable line/column tracking.
+ * <br>User: Joshua Davis
+ * Date: Sep 23, 2005
+ * Time: 12:30:01 PM
+ * @see antlr.TreeParser#setASTFactory(antlr.ASTFactory)
+ * @see antlr.Parser#setASTFactory(antlr.ASTFactory)
*/
public class HqlASTFactory extends ASTFactory {
/**
- * Returns the class for a given token type (a.k.a. AST node type).
- *
+ * Returns a node class that tracks line/column information.
* @param tokenType The token type.
* @return Class - The AST node class to instantiate.
+ * @see Node
*/
public Class getASTNodeType(int tokenType) {
return Node.class;
Added: branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/HqlResolver.java
===================================================================
--- branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/HqlResolver.java 2006-04-01 00:02:15 UTC (rev 9725)
+++ branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/HqlResolver.java 2006-04-01 14:08:20 UTC (rev 9726)
@@ -0,0 +1,16 @@
+package org.hibernate.hql.ast;
+
+import org.hibernate.hql.antlr.HqlBaseResolver;
+
+/**
+ * Implements the methods for the HqlBaseResolver.
+ * <br>User: Joshua Davis
+ * Date: Apr 1, 2006
+ * Time: 7:40:42 AM
+ */
+public class HqlResolver extends HqlBaseResolver {
+ public HqlResolver() {
+ super();
+ setASTFactory(new HqlASTFactory()); // Create nodes that track line and column number.
+ }
+}
Modified: branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/tree/Node.java
===================================================================
--- branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/tree/Node.java 2006-04-01 00:02:15 UTC (rev 9725)
+++ branches/HQL_ANTLR_2/Hibernate3/src/org/hibernate/hql/ast/tree/Node.java 2006-04-01 14:08:20 UTC (rev 9726)
@@ -5,10 +5,14 @@
import org.hibernate.util.StringHelper;
/**
- * Generic AST Node.
- * User: Joshua Davis<br>
- * Date: Sep 23, 2005<br>
- * Time: 12:20:53 PM<br>
+ * Generic AST Node. Propagates line/column information during stream/string
+ * parsing (stream to AST) and during tree walking (AST to AST).
+ * To use this, make an ASTFactory that returns this class, or some sub-class
+ * from getASTNodeType().
+ * <br>User: Joshua Davis
+ * Date: Sep 23, 2005
+ * Time: 12:20:53 PM
+ * @see antlr.ASTFactory#getASTNodeType(int)
*/
public class Node extends antlr.CommonAST {
private String filename;
@@ -26,6 +30,8 @@
public void initialize(Token tok) {
super.initialize(tok);
+ // Propagate line/column information from the lexer during
+ // stream parsing.
filename = tok.getFilename();
line = tok.getLine();
column = tok.getColumn();
@@ -35,6 +41,8 @@
public void initialize(AST t) {
super.initialize(t);
+ // Propagate line/column information from the source AST
+ // during tree walking.
if (t instanceof Node)
{
Node n = (Node)t;
Modified: branches/HQL_ANTLR_2/Hibernate3/test/org/hibernate/test/hql/HqlParserTest.java
===================================================================
--- branches/HQL_ANTLR_2/Hibernate3/test/org/hibernate/test/hql/HqlParserTest.java 2006-04-01 00:02:15 UTC (rev 9725)
+++ branches/HQL_ANTLR_2/Hibernate3/test/org/hibernate/test/hql/HqlParserTest.java 2006-04-01 14:08:20 UTC (rev 9726)
@@ -1059,7 +1059,7 @@
doParse( input, false );
}
- private AST doParse(String input, boolean filter) throws RecognitionException, TokenStreamException {
+ public static AST doParse(String input, boolean filter) throws RecognitionException, TokenStreamException {
System.out.println( "input: ->" + ASTPrinter.escapeMultibyteChars(input) + "<-" );
HqlParser parser = HqlParser.getInstance( input );
parser.setFilter( filter );
Added: branches/HQL_ANTLR_2/Hibernate3/test/org/hibernate/test/hql/HqlResolverTest.java
===================================================================
--- branches/HQL_ANTLR_2/Hibernate3/test/org/hibernate/test/hql/HqlResolverTest.java 2006-04-01 00:02:15 UTC (rev 9725)
+++ branches/HQL_ANTLR_2/Hibernate3/test/org/hibernate/test/hql/HqlResolverTest.java 2006-04-01 14:08:20 UTC (rev 9726)
@@ -0,0 +1,45 @@
+package org.hibernate.test.hql;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.framework.Test;
+import antlr.collections.AST;
+import antlr.RecognitionException;
+import antlr.TokenStreamException;
+import org.hibernate.hql.ast.util.ASTPrinter;
+import org.hibernate.hql.ast.HqlParser;
+import org.hibernate.hql.ast.HqlResolver;
+import org.hibernate.hql.antlr.HqlRTokenTypes;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+
+/**
+ * Tests the new HQL resolver phase.
+ * <br>User: Joshua Davis
+ * Date: Apr 1, 2006
+ * Time: 7:25:37 AM
+ */
+public class HqlResolverTest extends TestCase {
+ private ASTPrinter hqlrPrinter = new ASTPrinter(HqlRTokenTypes.class);
+
+ public HqlResolverTest(String n) {
+ super(n);
+ }
+
+
+ public void testSimpleHql() throws Exception {
+ // First, get an AST by parsing some HQL text.
+ AST hqlAst = HqlParserTest.doParse("from Foo f, Bar b where f.x.id = b.id",false);
+ // Now, pass it though the resolver phase, which yeilds
+ // a processed HQL AST.
+ HqlResolver resolver = new HqlResolver();
+ resolver.statement(hqlAst);
+ AST resolvedHql = resolver.getAST();
+ System.out.println(hqlrPrinter.showAsString(resolvedHql,"Resolved AST : " + resolvedHql.toStringTree() + "" ));
+ }
+
+ public static Test suite() {
+ return new TestSuite(HqlResolverTest.class);
+ }
+}
|