隨筆-26  評論-4  文章-0  trackbacks-0
          1、概念:
                antlr是 another tool for language recongnition,用于 詞法、語法和語義分析。如果大家仔細看一些開源項目的lib包,會經常看到其包含有antlr.jar文件。

          2、使用場景:
                  設想一個運算的場景,“1+3”為多少,如果通過程序解析這個字符串,可以嘗試使用拆解字符串的方法,識別其中的運算符“+”,然后將結果輸出,感覺很簡單。但是,如果場景變化呢?“1+3-6/2”這個樣子的呢,也得改程序?是不是有些頭大呢?那么antlr就可以幫助你來解決這個頭大的問題。

          3、主要內容:
                    antlr重要包含三個重要的內容,分別是 詞法分析、語法分析、語義分析,其各個部分的用途主要如下所示:
                    詞法分析:  (識別出 “1”,“+”,“3”)

                         (1)逐個字符讀取公式源文件

                         (2)識別公式源文件中的詞法單元(Token)

                          (3)將詞法單元傳遞給語法分析器

                         (4)詞法分析器又叫掃描器(Scanner)  
                  語法分析:(識別1+3)

                          (1)從詞法分析器獲得詞法單元

                          (2)利用文法定義驗證詞法單元組合

                         (3)構造語法分析樹

                          (4)將語法分析樹傳遞給下一階段

                         (5)語法分析器又叫解析器(Parser)
                   語義分析:(計算結果)
                        (1)完成語義動作定義

                        (2)一般在語法分析器中完成語義分析

                 大致各部分的含義就是,首先 識別出 輸入的字符是否正確,其次檢驗字符之間的運算關系,然后計算得出相關的結果。

          4、主要工作:
                   需要寫兩個.g的文件,分別是 Expr.g和Eval.g文件,前者生成詞法、語法分析相關的java文件,通過編譯生成ExprLexer.java、ExprParser.java 和 Expr.tokens文件,后者生成語義分析文件,分別為Eval.java和Eval.tokens文件。
                   相關的編譯方法為:java org.antlr.Tool Expr.g

          5、開發環境搭建:
                    1、配置java環境變量
                    2、將antlr的相關jar包添加到環境變量中
                    3、運行 java org.antlr.Tool 進行驗證

          6、簡單代碼展示,用于計算簡答的加減運算
                    1)、expr.g
          grammar Expr;
          options {
           language=Java;
           output=AST;
           ASTLabelType=CommonTree; // type of $stat.tree ref etc...
          }
          @header {
           package test.tool;
          }

           prog: ( stat {/* System.out.println($stat.tree.toStringTree()); */})+ ;

          stat
           : expr  NEWLINE -> expr
           | NEWLINE    ->
           ;
          expr: multExpr (('+' ^|'-' ^) multExpr)* ;
          multExpr
           : atom (('/' ^|'*' ^) atom)*
           ;
           
          atom
           : INT
           | DOUBLE
           | ID
           | '(' ! expr ')' !
           ; 

          ID  :   ('N'|'R'|'A'|'C'|'I'|'D')'B'('S'|'H');
          INT :   '0'..'9'+ ;
          WS  :   (' '|'\t')+ {skip();} ;
          NEWLINE:'\r'? '\n' ;
          DOUBLE : (('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9') ('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9')*) '.' (('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9') ('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9')*); 

                  2)Eval.g
                     

          tree grammar Eval;     
          options {
           tokenVocab=Expr;    // read token types from Expr.tokens file
           ASTLabelType=CommonTree;  // what is Java type of nodes?
          }
          @header {
           package fanxiqian.tool;(可在此處添加 package和import等相關信息)
          }
          @members {
                 …………(可在此處添加java方法) 
          }

          prog: stat+ ;
          stat: expr+;

          expr returns [double value]
           : ^('+' a=expr b=expr) {$value = a+b;}  //此處定義了 相關運算符的含義
           | ^('-' a=expr b=expr) {$value = a-b;}
           | ^('*' a=expr b=expr) {$value = a*b;}
           | ^('/' a=expr b=expr) {$value=a/b;}
           | INT {$value = Integer.parseInt($INT.text);}
           | DOUBLE {$value = Double.parseDouble($DOUBLE.text);}
           ; 

                   3)通過編譯命令,生成相關的java文件
                                 java org.antlr.Tool Expr.g
                                 java org.antlr.Tool Eval.g  

                    4)編寫相關的測試類
          public class Test
          {
              public static void main(String[] args) throws Exception
              {
               ANTLRStringStream input;
               ExprLexer lexer;
               CommonTokenStream tokens;
               ExprParser parser;
                String formula="1+3";
             //開始解析
             formula += "\n";
             input = new ANTLRStringStream(formula);
             lexer = new ExprLexer(input);
             tokens = new CommonTokenStream(lexer);
             parser = new ExprParser(tokens);
             ExprParser.prog_return r = parser.prog();
             // walk resulting tree
                   CommonTree t = (CommonTree)r.getTree();
                   CommonTreeNodeStream nodes = new CommonTreeNodeStream(t);
                   Eval walker = new Eval(nodes);
                   System.out.println(walker.expr());
          //  }   

          即可得到輸出結果為4。

          7,總結
                 antlr是個強大的公式解析工具,本文只是簡單的一個小結,以后遇到相關的使用繼續補充吧,歡迎大家補充添加吧。
          posted on 2011-05-16 20:12 mingsen 閱讀(4526) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 舟曲县| 淳化县| 定结县| 荣昌县| 呼图壁县| 凌海市| 栾城县| 东光县| 华池县| 兰西县| 武夷山市| 博乐市| 万载县| 龙州县| 婺源县| 安阳市| 景德镇市| 承德县| 安顺市| 黄冈市| 连城县| 濮阳县| 香港 | 克山县| 安阳市| 寿光市| 托克托县| 武穴市| 临武县| 凉城县| 沽源县| 湖口县| 彭州市| 江都市| 化隆| 嵊州市| 开远市| 盐山县| 淳安县| 建水县| 大姚县|