乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      ANTLR學(xué)習(xí)心得——表達(dá)式 (轉(zhuǎn)與JavaEye技術(shù)社區(qū))

       快樂學(xué)習(xí) 2006-12-30
       
      先說說我們打算干什么,表達(dá)式是幾乎所有高級(jí)編程語言中,都會(huì)出現(xiàn)的重要組成部分。因此,如何準(zhǔn)確的理解一個(gè)表達(dá)式,可以說是各種不同的語言所共同面臨的問題。表達(dá)式千變?nèi)f化,真正要想正確解釋C/C++那樣的復(fù)雜表達(dá)式,是非常困難的,我們這里只從最簡(jiǎn)單的表達(dá)式做起。
       
      假設(shè)一個(gè)表達(dá)式中,只有常量,沒有變量。所有的運(yùn)算只有:“+”、“-”、“*”、“/”、“^”、“%”六種,而且沒有括號(hào),只有整數(shù),沒有小數(shù)。就這么簡(jiǎn)單,要解釋這樣的表達(dá)式,我們?nèi)绻胱约簩憘€(gè)程序來解釋,只怕也是非常麻煩的吧。當(dāng)年我就自己搞過一次,我的本專業(yè)不是計(jì)算機(jī)系,所有也沒有學(xué)過任何編譯原理的東西,Lex呀、Yacc呀、Antlr呀,一概沒有聽說過,就一股子勁自己去搞。我的辦法現(xiàn)在想想也挺簡(jiǎn)單的,一個(gè)表達(dá)式,要么是數(shù)字,要么是運(yùn)算符,我就規(guī)定死了,中間一律用一個(gè)空格分割開來,這樣就不需要詞法分析了然后再自己編程序,硬寫遞歸計(jì)算(當(dāng)時(shí)連前綴表達(dá)式都沒聽說過),那個(gè)苦啊。
       
      現(xiàn)在有了ANTLR,我們只需要將定義寫清楚,程序就會(huì)自動(dòng)幫我們生成了??梢韵认螺d一個(gè)人家現(xiàn)成的文件來看看:expression.g,然后再antlr expression.g生成一堆java文件。
       
      接下來的步驟和前面的也差不多,建一個(gè)Main.java,
      import java.io.*;
      import antlr.CommonAST;
      import antlr.collections.AST;
      import antlr.debug.misc.ASTFrame;
      public class Main {
        public static void main(String args[]) {
          try {
            DataInputStream input = new DataInputStream(System.in);

            ExpressionLexer lexer = new ExpressionLexer(input);

            ExpressionParser parser = new ExpressionParser(lexer);
            parser.expr();

            CommonAST parseTree = (CommonAST)parser.getAST();
            System.out.println(parseTree.toStringList());
            ASTFrame frame = new ASTFrame("The tree", parseTree);
            frame.setVisible(true);

            ExpressionTreeWalker walker = new ExpressionTreeWalker();
            double r = walker.expr(parseTree);
            System.out.println("Value: "+r);
          } catch(Exception e) { System.err.println("Exception: "+e); }
        }
      }

      執(zhí)行這個(gè)Main.class,輸入個(gè)表達(dá)式給它試一試,比如: 1+2-3*4/5^6;系統(tǒng)應(yīng)該就能給出正確的答案了:

      ( - ( + 1 2 ) ( / ( * 3 4 ) ( ^ 5 6 ) ) ) ;

      Value: 2.999232
       
      咱們來一句一句的解釋一下這個(gè)expression.g文件。還是從最簡(jiǎn)單的幾行開始:
       
      class ExpressionLexer extends Lexer; //這是用來聲明一個(gè)詞法分析器,名字叫
                                                         //ExpressionLexer

      PLUS  : ‘+‘ ;                                   //加號(hào)
      MINUS : ‘-‘ ;                                   //減號(hào)
      MUL   : ‘*‘ ;                                   //乘號(hào)
      DIV   : ‘/‘ ;                                    //除號(hào)
      MOD   : ‘%‘ ;                                 //求余
      POW   : ‘^‘ ;                                 //開方
      SEMI  : ‘;‘ ;                                    //結(jié)束號(hào)
                                                         //上面這些都太簡(jiǎn)單了,簡(jiǎn)直就不需要說明

      protected DIGIT : ‘0‘..‘9‘ ;               //數(shù)字,這是一個(gè)受保護(hù)的單詞,只能被
                                                         //詞法分析器內(nèi)部使用
      INT   : (DIGIT)+ ;                           //出現(xiàn)了一次以上的數(shù)字的詞,就是整數(shù),
                                                         //它通過受保護(hù)的單詞:“數(shù)字”來定義自己。
                                                         //如果DIGIT不是被保護(hù)的單詞,則詞法分析器就會(huì)
                                                         //無法分辨究竟是數(shù)字還是整數(shù)了
       
      接下來看語法分析器的代碼:
       
      class ExpressionParser extends Parser;   //定義一個(gè)語法分析器,名字叫ExpressionParser
      options { buildAST=true; }                  //告訴ANTLR,要幫我生成一個(gè)抽象語法樹,
                                                             //留著以后有用
       
      //接下來的部分就非常復(fù)雜了,主要是多出來了兩個(gè)特殊的符號(hào)“!”、“^”
      //這兩個(gè)符號(hào),不是EBNF原有的,而是ANTLR為了生成AST而增加的符號(hào)
      //“!”,是告訴AST生成程序,不要把自己算進(jìn)去
      //“^”,是告訴AST生成程序,把這個(gè)符號(hào),放在一顆樹的根部,或者一顆子樹的根部
      //另外,“*”表示出現(xiàn)0次以上,“+”表示出現(xiàn)一次以上,“?”表示出現(xiàn)0或1次

      expr     : sumExpr SEMI!;                                           //“;”作為結(jié)束符,不放入AST
      sumExpr  : prodExpr ((PLUS^|MINUS^) prodExpr)* ;     //“+”“-”作為計(jì)算符號(hào)
                                                                                    //放在樹的頂部
      prodExpr : powExpr ((MUL^|DIV^|MOD^) powExpr)* ; //剩下的就不解釋了,都能明白的
      powExpr  : atom (POW^ atom)? ;
      atom     : INT ;
       
      再來看AST計(jì)算器的代碼。這“AST計(jì)算器”是我起的名字,也就是通過對(duì)一個(gè)生成的抽象語法樹,遞歸求值,得到最后的結(jié)果。
       
      {import java.lang.Math;}                                     //ExpressionTreeWalker要用到的
      class ExpressionTreeWalker extends TreeParser;    //聲明一個(gè)樹計(jì)算器

      expr returns [double r]                                      //有一個(gè)方法叫expr
                                                                            //它的返回值是double類型
        {double a,b; r=0; }                                         //嵌入的代碼,后面要用到

        : #(PLUS a=expr b=expr)  { r=a+b; }               //以下就是計(jì)算各種算符,不用多說了
        | #(MINUS a=expr b=expr) { r=a-b; }
        | #(MUL  a=expr b=expr)  { r=a*b; }
        | #(DIV  a=expr b=expr)  { r=a/b; }
        | #(MOD  a=expr b=expr)  { r=a%b; }
        | #(POW  a=expr b=expr)  { r=Math.pow(a,b); }
        | i:INT { r=(double)Integer.parseInt(i.getText()); }
        ;

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多