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); + } +} |