Antlr–看Hibernate3如何解釋HQL語言

來源:互聯網
上載者:User

    作者:江南白衣 

     ANTLR(ANother Tool for Language Recognition)風頭正盛,經常可以看到用它做文法解譯器的項目,比如Hibernate就在3.0換上它來解釋HQL,加強了HQL的文法。
     因為Antlr是EBNF-AST文法解釋系的代表,而自己總是心思思想搞一下DSL(領域語言),所以從Hibernate來學習一下Antlr的應用。

     Hibernate HQL translator作者Joshua Davis的兩個Blog
     Hibernate3 Query Translator Design - Part One : The Basics
     Hibernate3 Query Translator Design - Part Two : Parsing HQL

     Antlr最好的介紹文章是那篇,在《程式員》2004年3月有中文的版本。  不過,那個計算機的例子太簡單了。深刻一點的有
     另外,SlickEdit 支援Antlr的文法,是一定要用的編輯器,在 ttdown.com上有破解。

  一,Antlr引擎的工作過程大概是這樣的:
  1.Lexer類--詞法分析器。 
        定義語言中的各種Token(單詞),如 From 、Where、=、<>.......
        Lexer負責把讀入的普通文字資料流識別成Token串。

  2.Parser類--文法分析器。
        使用BNF文法,遞迴定義句子的Pattern,如whereStatement、FromStatement、SelectStatement。
     Parser負責把讀入的Token串匹配成句子,翻譯出AST(抽象文法樹)。
     有些簡單的應用,也可以在本層現炒現賣,完成所有動作,屬於Single Pass Builder。

  3.TreeParser類--抽象文法樹遍曆器。
        根據Parser類分析出來的AST(抽象文法樹)進行動作。
           
        用Parser把AST抽取出來,再用TreeParser進行動作的Double Pass Builder模式,解耦了Parser和Generation,再配合Template 產生代碼,是Antlr推薦的最佳模式。

  二,開發人員的實際步驟

  1.按照Antlr的簡單文法定義前面講的3個類,檔案的尾碼名為g。

  2.使用java antlr.Tool xxx.g 命令,把grammar檔案編譯成java檔案。

  3.編寫應用程式,如:


     看過Antlr對HQL的解釋,覺得EBNF系的方法要解釋Java這樣的程式設計語言還好些,如果要解釋類自然語言的DSL就比較痛苦,所以情緒不是很高漲,挑一條最容易的"Delete from goods where ....." 匆匆走過場

   Joel的一句話對我的影響比較大:"如果為了證明一個微不足道的問題需要花三個小時寫下幾黑板的證明步驟,那麼這種機制不可能用來證明任何有趣的東西" 。對於我這個層次的程式員,antlr在我手中造不出有趣的DSL來。

import antlr.*; 
import antlr.collections.*; 
public class Main 

  public static void main(String[] args) throws Exception 
  {
     ExprLexer lexer = new ExprLexer(System.in); 
     ExprParser parser = new ExprParser(lexer);
     parser.expr(); AST ast = parser.getAST();
     ExprTreeParser treeParser = new ExprTreeParser();
     int x = treeParser.expr(ast); 
  } 

    三,Hibernate對Antlr的應用

   Hibernate的HQL Grammar檔案一共有三個,在/grammar目錄下:
   1.hql.g   定義Token類和Parser類,將HQL解釋成hql的抽象文法樹(AST)
   2.hql-sql.g  定義Tree Walker ,將HQL AST轉化為SQL AST,將產生模組與Hibernate解耦。
   3.sql-gen.g 定義Tree Walker,從SQL AST產生sql

   下面看 DELETE FROM GOODS的翻譯過程

   1.HqlBaseLexer extends Lexer
     
定義EQ: '=';  LT: '<';  GT: '>';PLUS: '+';等符號
      及IDENT: ( 'a' .. 'z' | '_' ) ( 'a' .. 'z' | '0' .. '9' | '_' | '$' )*

   2.HqlBaseParser extends Parser
      先定義DELETE="delete"; FROM="from"; MIN="min"; 等字串
      再定義:

statement
          : ( updateStatement | deleteStatement | selectStatement )
          ; 三種Statement之一

      deleteStatement
         : DELETE^
           (optionalFromTokenFromClause)
           (whereClause)?
         ;DELETE為葉子,(whereClause)可選

      optionalFromTokenFromClause!
        : (FROM!)? f:path {
           AST #range = #([RANGE, "RANGE"], #f);
           #optionalFromTokenFromClause = #([FROM, "FROM"], #range);
          }
         ;不是很好懂對吧,我也這樣覺得,whereClause就更加不要看了。 

     

     3. HqlSqlBaseWalker extends TreeParser  
         hql與sql的delete語句基本上是一樣的,沒什麼轉換。

     4.SqlGeneratorBase extends TreeParser
          
         根據SQL AST, 產生SQL語句         

 private StringBuffer buf = new StringBuffer();
          protected void out(String s) 
          {
                buf.append(s);
          }

          statement
          : selectStatement | updateStatement | deleteStatement
          ; 
         deleteStatement
         : #(DELETE { out("delete"); }
               from
              (whereClause)?
             )
         ;輸出"delete"          from
          : #(f:FROM { out(" from "); }
           (fromTable)* )
                    fromTable
         : #( a:FROM_FRAGMENT  { out(a); } (tableJoin [ a ])* { fromFragmentSeparator(a); } )
         | #( b:JOIN_FRAGMENT  { out(b); } (tableJoin [ b ])* { fromFragmentSeparator(b); } )
         ;         tableJoin [ AST parent ]
          : #( c:JOIN_FRAGMENT { out(" "); out(c); } (tableJoin [ c ] )* )
          | #( d:FROM_FRAGMENT { nestedFromFragment(d,parent); } (tableJoin [ d ] )* )
         ;

         .暈了吧 ~~~~~
         whereClause
          : #(WHERE { out(" where "); } ( conditionList | booleanExpr[ false ] ) )
          ;

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.