?? hql.g
字號:
header{// $Id: hql.g 10163 2006-07-26 15:07:50Z steve.ebersole@jboss.com $package org.hibernate.hql.antlr;import org.hibernate.hql.ast.*;import org.hibernate.hql.ast.util.*;}/** * Hibernate Query Language Grammar * <br> * This grammar parses the query language for Hibernate (an Open Source, Object-Relational * mapping library). A partial BNF grammar description is available for reference here: * http://www.hibernate.org/Documentation/HQLBNF * * Text from the original reference BNF is prefixed with '//##'. * @author Joshua Davis (pgmjsd@sourceforge.net) */class HqlBaseParser extends Parser;options{ exportVocab=Hql; buildAST=true; k=3; // For 'not like', 'not in', etc.}tokens{ // -- HQL Keyword tokens -- ALL="all"; ANY="any"; AND="and"; AS="as"; ASCENDING="asc"; AVG="avg"; BETWEEN="between"; CLASS="class"; COUNT="count"; DELETE="delete"; DESCENDING="desc"; DOT; DISTINCT="distinct"; ELEMENTS="elements"; ESCAPE="escape"; EXISTS="exists"; FALSE="false"; FETCH="fetch"; FROM="from"; FULL="full"; GROUP="group"; HAVING="having"; IN="in"; INDICES="indices"; INNER="inner"; INSERT="insert"; INTO="into"; IS="is"; JOIN="join"; LEFT="left"; LIKE="like"; MAX="max"; MIN="min"; NEW="new"; NOT="not"; NULL="null"; OR="or"; ORDER="order"; OUTER="outer"; PROPERTIES="properties"; RIGHT="right"; SELECT="select"; SET="set"; SOME="some"; SUM="sum"; TRUE="true"; UNION="union"; UPDATE="update"; VERSIONED="versioned"; WHERE="where"; // -- SQL tokens -- // These aren't part of HQL, but the SQL fragment parser uses the HQL lexer, so they need to be declared here. CASE="case"; END="end"; ELSE="else"; THEN="then"; WHEN="when"; ON="on"; WITH="with"; // -- EJBQL tokens -- BOTH="both"; EMPTY="empty"; LEADING="leading"; MEMBER="member"; OBJECT="object"; OF="of"; TRAILING="trailing"; // -- Synthetic token types -- AGGREGATE; // One of the aggregate functions (e.g. min, max, avg) ALIAS; CONSTRUCTOR; CASE2; EXPR_LIST; FILTER_ENTITY; // FROM element injected because of a filter expression (happens during compilation phase 2) IN_LIST; INDEX_OP; IS_NOT_NULL; IS_NULL; // Unary 'is null' operator. METHOD_CALL; NOT_BETWEEN; NOT_IN; NOT_LIKE; ORDER_ELEMENT; QUERY; RANGE; ROW_STAR; SELECT_FROM; UNARY_MINUS; UNARY_PLUS; VECTOR_EXPR; // ( x, y, z ) WEIRD_IDENT; // Identifiers that were keywords when they came in. // Literal tokens. CONSTANT; NUM_DOUBLE; NUM_FLOAT; NUM_LONG; JAVA_CONSTANT;}{ /** True if this is a filter query (allow no FROM clause). **/ private boolean filter = false; /** * Sets the filter flag. * @param f True for a filter query, false for a normal query. */ public void setFilter(boolean f) { filter = f; } /** * Returns true if this is a filter query, false if not. * @return true if this is a filter query, false if not. */ public boolean isFilter() { return filter; } /** * 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. */ public 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. */ public void handleDotIdent() throws TokenStreamException { } /** * Returns the negated equivalent of the expression. * @param x The expression to negate. */ public AST negateNode(AST x) { // Just create a 'not' parent for the default behavior. return ASTUtil.createParent(astFactory, NOT, "not", x); } /** * Returns the 'cleaned up' version of a comparison operator sub-tree. * @param x The comparison operator to clean up. */ public AST processEqualityExpression(AST x) throws RecognitionException { return x; } public void weakKeywords() throws TokenStreamException { } public void processMemberOf(Token n,AST p,ASTPair currentAST) { }}statement : ( updateStatement | deleteStatement | selectStatement | insertStatement ) ;updateStatement : UPDATE^ (VERSIONED)? optionalFromTokenFromClause setClause (whereClause)? ;setClause : (SET^ assignment (COMMA! assignment)*) ;assignment : stateField EQ^ newValue ;// "state_field" is the term used in the EJB3 sample grammar; used here for easy reference.// it is basically a property refstateField : path ;// this still needs to be defined in the ejb3 spec; additiveExpression is currently just a best guess,// although it is highly likely I would think that the spec may limit this even more tightly.newValue : concatenation ;deleteStatement : DELETE^ (optionalFromTokenFromClause) (whereClause)? ;optionalFromTokenFromClause! : (FROM!)? f:path (a:asAlias)? { AST #range = #([RANGE, "RANGE"], #f, #a); #optionalFromTokenFromClause = #([FROM, "FROM"], #range); } ;selectStatement : queryRule { #selectStatement = #([QUERY,"query"], #selectStatement); } ;insertStatement // Would be nice if we could abstract the FromClause/FromElement logic // out such that it could be reused here; something analogous to // a "table" rule in sql-grammars : INSERT^ intoClause selectStatement ;intoClause : INTO^ path { weakKeywords(); } insertablePropertySpec ;insertablePropertySpec : OPEN! primaryExpression ( COMMA! primaryExpression )* CLOSE! { // Just need *something* to distinguish this on the hql-sql.g side #insertablePropertySpec = #([RANGE, "column-spec"], #insertablePropertySpec); } ;union : queryRule (UNION queryRule)* ;//## query://## [selectClause] fromClause [whereClause] [groupByClause] [havingClause] [orderByClause];queryRule : selectFrom (whereClause)? (groupByClause)? (orderByClause)? ;selectFrom! : (s:selectClause)? (f:fromClause)? { // If there was no FROM clause and this is a filter query, create a from clause. Otherwise, throw // an exception because non-filter queries must have a FROM clause. if (#f == null) { if (filter) { #f = #([FROM,"{filter-implied FROM}"]); } else throw new SemanticException("FROM expected (non-filter queries must contain a FROM clause)"); } // 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); } ;//## selectClause://## SELECT DISTINCT? selectedPropertiesList | ( NEW className OPEN selectedPropertiesList CLOSE );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:OPEN^ {#op.setType(CONSTRUCTOR);} selectedPropertiesList CLOSE! ;selectObject : OBJECT^ OPEN! identifier CLOSE! ;//## fromClause://## FROM className AS? identifier ( ( COMMA className AS? identifier ) | ( joinType path AS? identifier ) )*;// NOTE: This *must* begin with the "FROM" token, otherwise the sub-query rule will be ambiguous// with the expression rule.// Also note: after a comma weak keywords are allowed and should be treated as identifiers.fromClause : FROM^ { weakKeywords(); } fromRange ( fromJoin | COMMA! { weakKeywords(); } fromRange )* ;//## joinType://## ( ( 'left'|'right' 'outer'? ) | 'full' | 'inner' )? JOIN FETCH?;fromJoin : ( ( ( LEFT | RIGHT ) (OUTER)? ) | FULL | INNER )? JOIN^ (FETCH)? path (asAlias)? (propertyFetch)? (withClause)? ;withClause : WITH^ logicalExpression ;fromRange : fromClassOrOuterQueryPath | inClassDeclaration | inCollectionDeclaration | inCollectionElementsDeclaration ; fromClassOrOuterQueryPath! : c:path { weakKeywords(); } (a:asAlias)? (p:propertyFetch)? { #fromClassOrOuterQueryPath = #([RANGE, "RANGE"], #c, #a, #p); } ;inClassDeclaration! : a:alias IN! CLASS! c:path { #inClassDeclaration = #([RANGE, "RANGE"], #c, #a); } ;inCollectionDeclaration! : IN! OPEN! p:path CLOSE! a:alias { #inCollectionDeclaration = #([JOIN, "join"], [INNER, "inner"], #p, #a); } ;inCollectionElementsDeclaration! : a:alias IN! ELEMENTS! OPEN! p:path CLOSE! { #inCollectionElementsDeclaration = #([JOIN, "join"], [INNER, "inner"], #p, #a); } ;// Alias rule - Parses the optional 'as' token and forces an AST identifier node.asAlias : (AS!)? alias ;alias : a:identifier { #a.setType(ALIAS); } ; propertyFetch : FETCH ALL! PROPERTIES! ;//## groupByClause://## GROUP_BY path ( COMMA path )*;groupByClause : GROUP^ "by"! expression ( COMMA! expression )* (havingClause)? ;//## orderByClause://## ORDER_BY selectedPropertiesList;orderByClause : ORDER^ "by"! orderElement ( COMMA! orderElement )* ;orderElement : expression ( ascendingOrDescending )? ;ascendingOrDescending : ( "asc" | "ascending" ) { #ascendingOrDescending.setType(ASCENDING); } | ( "desc" | "descending") { #ascendingOrDescending.setType(DESCENDING); } ;//## havingClause://## HAVING logicalExpression;havingClause : HAVING^ logicalExpression ;//## whereClause://## WHERE logicalExpression;whereClause : WHERE^ logicalExpression ;//## selectedPropertiesList://## ( path | aggregate ) ( COMMA path | aggregate )*;selectedPropertiesList : aliasedExpression ( COMMA! aliasedExpression )* ; aliasedExpression : expression ( AS^ identifier )? ;// 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
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -