1 package org.hibernate.hql.ast; 3 4 import java.io.PrintStream ; 5 import java.io.PrintWriter ; 6 import java.io.StringReader ; 7 8 import antlr.ASTPair; 9 import antlr.MismatchedTokenException; 10 import antlr.RecognitionException; 11 import antlr.Token; 12 import antlr.TokenStream; 13 import antlr.TokenStreamException; 14 import antlr.collections.AST; 15 import org.apache.commons.logging.Log; 16 import org.apache.commons.logging.LogFactory; 17 import org.hibernate.hql.antlr.HqlBaseParser; 18 import org.hibernate.hql.antlr.HqlTokenTypes; 19 import org.hibernate.hql.ast.util.ASTPrinter; 20 import org.hibernate.hql.ast.util.ASTUtil; 21 import org.hibernate.QueryException; 22 23 29 public final class HqlParser extends HqlBaseParser { 30 33 private static final Log log = LogFactory.getLog( HqlParser.class ); 34 35 private ParseErrorHandler parseErrorHandler; 36 private ASTPrinter printer = getASTPrinter(); 37 38 private static ASTPrinter getASTPrinter() { 39 return new ASTPrinter( org.hibernate.hql.antlr.HqlTokenTypes.class ); 40 } 41 42 public static HqlParser getInstance(String hql) { 43 HqlLexer lexer = new HqlLexer( new StringReader ( hql ) ); 46 HqlParser parser = new HqlParser( lexer ); 47 return parser; 48 } 49 50 private HqlParser(TokenStream lexer) { 51 super( lexer ); 52 initialize(); 53 } 54 55 public void reportError(RecognitionException e) { 56 parseErrorHandler.reportError( e ); } 58 59 public void reportError(String s) { 60 parseErrorHandler.reportError( s ); } 62 63 public void reportWarning(String s) { 64 parseErrorHandler.reportWarning( s ); 65 } 66 67 public ParseErrorHandler getParseErrorHandler() { 68 return parseErrorHandler; 69 } 70 71 80 public AST handleIdentifierError(Token token, RecognitionException ex) throws RecognitionException, TokenStreamException { 81 if ( token instanceof HqlToken ) { 83 HqlToken hqlToken = ( HqlToken ) token; 84 if ( hqlToken.isPossibleID() && ( ex instanceof MismatchedTokenException ) ) { 87 MismatchedTokenException mte = ( MismatchedTokenException ) ex; 88 if ( mte.expecting == HqlTokenTypes.IDENT ) { 90 reportWarning( "Keyword '" 92 + token.getText() 93 + "' is being interpreted as an identifier due to: " + mte.getMessage() ); 94 ASTPair currentAST = new ASTPair(); 96 token.setType( HqlTokenTypes.WEIRD_IDENT ); 97 astFactory.addASTChild( currentAST, astFactory.create( token ) ); 98 consume(); 99 AST identifierAST = currentAST.root; 100 return identifierAST; 101 } 102 } } return super.handleIdentifierError( token, ex ); 106 } 107 108 116 public AST negateNode(AST x) { 117 switch ( x.getType() ) { 120 case OR: 121 x.setType(AND); 122 x.setText("{and}"); 123 negateNode( x.getFirstChild() ); 124 negateNode( x.getFirstChild().getNextSibling() ); 125 return x; 126 case AND: 127 x.setType(OR); 128 x.setText("{or}"); 129 negateNode( x.getFirstChild() ); 130 negateNode( x.getFirstChild().getNextSibling() ); 131 return x; 132 case EQ: 133 x.setType( NE ); 134 x.setText( "{not}" + x.getText() ); 135 return x; case NE: 137 x.setType( EQ ); 138 x.setText( "{not}" + x.getText() ); 139 return x; case GT: 141 x.setType( LE ); 142 x.setText( "{not}" + x.getText() ); 143 return x; case LT: 145 x.setType( GE ); 146 x.setText( "{not}" + x.getText() ); 147 return x; case GE: 149 x.setType( LT ); 150 x.setText( "{not}" + x.getText() ); 151 return x; case LE: 153 x.setType( GT ); 154 x.setText( "{not}" + x.getText() ); 155 return x; case LIKE: 157 x.setType( NOT_LIKE ); 158 x.setText( "{not}" + x.getText() ); 159 return x; case NOT_LIKE: 161 x.setType( LIKE ); 162 x.setText( "{not}" + x.getText() ); 163 return x; case IS_NULL: 165 x.setType( IS_NOT_NULL ); 166 x.setText( "{not}" + x.getText() ); 167 return x; case IS_NOT_NULL: 169 x.setType( IS_NULL ); 170 x.setText( "{not}" + x.getText() ); 171 return x; case BETWEEN: 173 x.setType( NOT_BETWEEN ); 174 x.setText( "{not}" + x.getText() ); 175 return x; case NOT_BETWEEN: 177 x.setType( BETWEEN ); 178 x.setText( "{not}" + x.getText() ); 179 return x; 184 default: 185 return super.negateNode( x ); } 187 } 188 189 195 public AST processEqualityExpression(AST x) { 196 if ( x == null ) { 197 log.warn( "processEqualityExpression() : No expression to process!" ); 198 return null; 199 } 200 201 int type = x.getType(); 202 if ( type == EQ || type == NE ) { 203 boolean negated = type == NE; 204 if ( x.getNumberOfChildren() == 2 ) { 205 AST a = x.getFirstChild(); 206 AST b = a.getNextSibling(); 207 if ( a.getType() == NULL && b.getType() != NULL ) { 209 return createIsNullParent( b, negated ); 210 } 211 else if ( b.getType() == NULL && a.getType() != NULL ) { 213 return createIsNullParent( a, negated ); 214 } 215 else if ( b.getType() == EMPTY ) { 216 return processIsEmpty( a, negated ); 217 } 218 else { 219 return x; 220 } 221 } 222 else { 223 return x; 224 } 225 } 226 else { 227 return x; 228 } 229 } 230 231 private AST createIsNullParent(AST node, boolean negated) { 232 node.setNextSibling( null ); 233 int type = negated ? IS_NOT_NULL : IS_NULL; 234 String text = negated ? "is not null" : "is null"; 235 return ASTUtil.createParent( astFactory, type, text, node ); 236 } 237 238 private AST processIsEmpty(AST node, boolean negated) { 239 node.setNextSibling( null ); 240 AST ast = createSubquery( node ); 243 ast = ASTUtil.createParent( astFactory, EXISTS, "exists", ast ); 244 if ( !negated ) { 246 ast = ASTUtil.createParent( astFactory, NOT, "not", ast ); 247 } 248 return ast; 249 } 250 251 private AST createSubquery(AST node) { 252 AST ast = ASTUtil.createParent( astFactory, RANGE, "RANGE", node ); 253 ast = ASTUtil.createParent( astFactory, FROM, "from", ast ); 254 ast = ASTUtil.createParent( astFactory, SELECT_FROM, "SELECT_FROM", ast ); 255 ast = ASTUtil.createParent( astFactory, QUERY, "QUERY", ast ); 256 return ast; 257 } 258 259 public void showAst(AST ast, PrintStream out) { 260 showAst( ast, new PrintWriter ( out ) ); 261 } 262 263 private void showAst(AST ast, PrintWriter pw) { 264 printer.showAst( ast, pw ); 265 } 266 267 private void initialize() { 268 parseErrorHandler = new ErrorCounter(); 270 } 271 272 public void weakKeywords() throws TokenStreamException { 273 274 int t = LA( 1 ); 275 switch ( t ) { 276 case ORDER: 277 case GROUP: 278 if ( LA( 2 ) != LITERAL_by ) { 281 LT( 1 ).setType( IDENT ); 282 if ( log.isDebugEnabled() ) { 283 log.debug( "weakKeywords() : new LT(1) token - " + LT( 1 ) ); 284 } 285 } 286 break; 287 default: 288 if (LA(0) == FROM && t != IDENT && LA(2) == DOT) { 290 HqlToken hqlToken = (HqlToken)LT(1); 291 if (hqlToken.isPossibleID()) { 292 hqlToken.setType(IDENT); 293 if ( log.isDebugEnabled() ) { 294 log.debug( "weakKeywords() : new LT(1) token - " + LT( 1 ) ); 295 } 296 } 297 } 298 break; 299 } 300 } 301 302 public void handleDotIdent() throws TokenStreamException { 303 if (LA(1) == DOT && LA(2) != IDENT) { 306 HqlToken t = (HqlToken)LT(2); 308 if (t.isPossibleID()) 309 { 310 LT( 2 ).setType( IDENT ); 312 if ( log.isDebugEnabled() ) { 313 log.debug( "handleDotIdent() : new LT(2) token - " + LT( 1 ) ); 314 } 315 } 316 } 317 } 318 319 public void processMemberOf(Token n, AST p, ASTPair currentAST) { 320 AST inAst = n == null ? astFactory.create( IN, "in" ) : astFactory.create( NOT_IN, "not in" ); 321 astFactory.makeASTRoot( currentAST, inAst ); 322 AST ast = createSubquery( p ); 323 ast = ASTUtil.createParent( astFactory, IN_LIST, "inList", ast ); 324 inAst.addChild( ast ); 325 } 326 327 static public void panic() { 328 throw new QueryException("Parser: panic"); 330 } 331 } 332 | Popular Tags |