如何使用JFlex、JavaCUP(詳細代碼模版)

openkk 12年前發布 | 72K 次閱讀 JFlex 語法/詞法分析器

編譯原理的實驗要求我們用JFlex和JavaCUP來對語言進行分析處理,JavaCUP有一個User's Manual教你怎樣做,上面還有一個簡單的計算器作為例子,但一試之下,卻發現那個例子有不少錯誤,結果改了我n久才完成~當然馬上就決定寫一篇博客告訴大家怎樣做才是正確的,以免像我那樣白走許多彎路。我也不知是不是我找的那份不好,如果你有更好的manual,記得告訴我。

撰寫本文的目的
給出使用JFlex、JavaCUP來為一個計算器建立分析器的示例的完整代碼,使讀者能充分領會JavaCUP的使用方法。雖然本文僅僅給出了計算器的代碼,但只要你會寫你的語言的翻譯模式,則只要照抄這個模版,并改改相應動作就可以了。

引用到的資料

  • 《CUP User's Manual》,作者:Scott E. Hudson地址為李老師那里下載下來的JavaCUP-11a.rar\CUP-develop.tar.gz\develop\manual.html,有詳細的英文說明和示例代碼,但有很多錯。本文中簡稱為《手冊》。
  • 《使用CUP進行語法分析》,摘自Apollo的博客,貎似是轉載的(竟然不注明[轉]和真實出處?!,BS之~),作者待考。有詳盡的解釋,但缺乏示例代碼。本文中簡稱為《語法分析》。

詳細步驟
1、準備工作。
JavaCUP和JFlex一樣,壓縮包里邊有許多的文件夾和文件,我不知道正統的做法是否要求使用javaCUP也像Jflex一樣要設置一堆path啊、classpath啊、jflex_home 之類的環境變量,但如果你像我一樣只打算用它幾次,你只要執行下述的兩個簡單步驟就可以了,它并不需要你設置任何的環境變量(以下假設你的工作目錄是 work\):
1)   將JavaCUP壓縮包里的java-cup-11a.jar解壓到work\下。
2)   將JavaCUP壓縮包里的CUP-develop.tar.gz\develop\src下的java_cup文件夾整個解壓到work\下。
現在你可以使用JavaCUP了。

2、為這個計算器寫一個詞法分析器。或者用JFlex生成一個詞法分析器

兩種方法都可以生成詞法分析器,其中,直接寫分析器的代碼如下:
// Simple Example Scanner Class 
// scanner.java
import java_cup.runtime.;
import java.io.;
//import sym;

public class scanner implements java_cup.runtime.Scanner { / single lookahead character / protected static int next_char; // since cup v11 we use SymbolFactories rather than Symbols private SymbolFactory sf = new DefaultSymbolFactory(); private static FileReader fileReader; public scanner(FileReader fr){ this.fileReader=fr; } / advance input by one character / protected static void advance() throws java.io.IOException { next_char = fileReader.read(); }

/ initialize the scanner / public static void init() throws java.io.IOException { advance(); }

/ recognize and return the next complete token / public Symbol next_token() throws java.io.IOException { for (;;) switch (next_char) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': / parse a decimal integer / int i_val = 0; do { i_val = i_val * 10 + (next_char - '0'); advance(); } while (next_char >= '0' && next_char <= '9'); return sf.newSymbol("NUMBER",sym.NUMBER, new Integer(i_val));

    case ';': advance(); return sf.newSymbol("SEMI",sym.SEMI);
    case '+': advance(); return sf.newSymbol("PLUS",sym.PLUS);
    case '-': advance(); return sf.newSymbol("MINUS",sym.MINUS);
    case '*': advance(); return sf.newSymbol("TIMES",sym.TIMES);
    case '/': advance(); return sf.newSymbol("DIVIDE",sym.DIVIDE);
    case '%': advance(); return sf.newSymbol("MOD",sym.MOD);
    case '(': advance(); return sf.newSymbol("LPAREN",sym.LPAREN);
    case ')': advance(); return sf.newSymbol("RPAREN",sym.RPAREN);

    case -1: return sf.newSymbol("EOF",sym.EOF);

    default: 
      /* in this simple scanner we just ignore everything else */
      advance();
    break;
  }
}

};</pre>

 本文由用戶 openkk 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!