Atitit.antlr實現詞法分析 1.1. antlrworks-1.4.3.jar wizard1 1.2. 詞法的類型 id,int,float ,comment,str,char,white space2 1.3. 3.1詞法文件的規定3 1.4. 3.2字元編碼定義4 1.5. 最後需要 ...
Atitit.antlr實現詞法分析
1.1. antlrworks-1.4.3.jar wizard1
1.2. 詞法的類型 id,int,float ,comment,str,char,white space2
1.6. 或者使用antlrworks生成需要的詞法分析器6
1.11. contains grammar SimpleCalc; names must be identical。 13
1.12. org.antlr.runtime.tree.CommonTree cannot be cast to org.antlr.tool.GrammarAST13
1.13. no viable alternative at character '='14
1.14. Antlr 支持多種目標語言,可以把生成的分析器生成為 Java,C#,C,Python,JavaScript 等多種語言 14
1.1. antlrworks-1.4.3.jar wizard
1.2. 詞法的類型 id,int,float ,comment,str,char,white space
Zai antlr裡面兒的keyword是所有的大寫
public static final int CHAR=4;
public static final int COMMENT=5;
public static final int ESC_SEQ=6;
public static final int EXPONENT=7;
public static final int FLOAT=8;
public static final int HEX_DIGIT=9;
public static final int ID=10;
public static final int INT=11;
public static final int OCTAL_ESC=12;
public static final int STRING=13;
public static final int UNICODE_ESC=14;
public static final int WS=15;
讀者可能對"單詞"感到有點疑惑,不明白到底什麼才是詞法分析中所說的"單詞"。試圖回答這個問題就必須瞭解幾個基本概念。這裡,引入幾個程式設計語言相關的名詞。
(1)標識符:用戶自定義的變數名、函數名等字元串。
(2)關鍵字:具有特殊含義的標識符。
(3)運算符:例如+、-、*、/ 等。
(4)常量:例如3.24、92等。
(5)界符:具有特殊含義的符號,如分號、括弧等。
作者:: ★(attilax)>>> 綽號:老哇的爪子 ( 全名::Attilax Akbar Al Rapanui 阿提拉克斯 阿克巴 阿爾 拉帕努伊 ) 漢字名:艾龍, EMAIL:[email protected]
轉載請註明來源: http://www.cnblogs.com/attilax/
這裡面的ID INT FLOAT什麼的並不是關鍵字,可以自定義的..
1.3. 3.1詞法文件的規定
與第二章中的例子不同,在ANTLR中詞法分析定義的規則名必須以大寫字母開頭如“LETTER”,“NewLine”。我們在第一章示例中的詞法分析部分與語法分析部分合寫到一個E.g文件中,ANTLR允許把詞法分析部分和語法分析寫分別寫到兩個文件中。
T.g文件存放語法定義:
grammar T;
Options {tokenVocab = T2;}
a : B*;
T2.g文件存放詞法定義:
lexer grammar T2;
B : ‘b’;
將詞法分析放到單獨的文件中時文法的名稱也要和文件的名稱相同,在grammar關鍵字之前要加入lexer關鍵字。上例中的T.g文件生成語法分析類TParser,T2.g文件生成詞法分析類T2Lexer。在T.g中要加入一個設置項tokenVocab來指定語法文件所需的詞法單詞是來自T2.g。這樣就可以按照第一章示例中的方法編譯運行分析器了。
1.4. 3.2字元編碼定義
詞法分析與源代碼直接接觸,因為源代碼是由字元串組成的,所以我們需要定義字元的方法。ANTLR有兩種方法定義字元,第一種方法是:ANTLR可以直接使用字元本身很簡單直觀的定義基本符號。
CHAR : ‘a’ | ‘b’ | ‘c’;
但這種定義只限於ASCII碼的字元,下麵的定義是不合法的。
CHAR : ‘代碼’;
定義漢字這樣除ASCII碼以外的字元只能用第二種方法十六進位編碼定義法。使用“\u”開頭加四位十六進位數定義來定義一個字元。
CHAR : ‘\u0040’;
C#中使用String.Format("{0:x} {1:x}", Convert.ToInt32('代'), Convert.ToInt32('碼'));可以獲得漢字的編碼。如上面的CHAR : ‘代碼’;我們可以定義為:
CHAR : '\u4ee3' '\u7801';
編碼有很多種GB2312的編碼範圍是A1A1 ~ FEFE,去掉未定義的區域之後可以理解為實際編碼範圍是A1A1 ~ F7FE。GBK的整體編碼範圍是為8140 ~ FEFE。 BIG5字元編碼範圍是A140 ~ F97E。
字元集 |
編碼範圍 |
GB2312 |
A1A1 ~ 7E7E |
GBK |
8140 ~ FEFE |
BIG5 |
A140 ~ F97E |
Unicode |
000000 ~ 10FFFF |
UTF-8 |
000000 ~ 10FFFF |
其中漢字在GB2312中的編碼範圍為:‘\uB0A1' .. '\uF7FE',漢字在Unicode編碼範圍為:’\u4E00’ .. ‘\u9FA5’ | ‘\uF900’ .. ‘\uFA2D’。
1.5. 最後需要考慮的詞法的定義
,在 Antlr 中語法定義和詞法定義通過規則的第一個字元來區別, 規定語法定義符號的第一個字母小寫,而詞法定義符號的第一個字母大寫。算術表達式中用到了 4 類記號 ( 在 Antlr 中被稱為 Token),分別是標識符 ID,表示一個變數;常量 INT,表示一個常數;換行符 NEWLINE 和空格 WS,空格字元在語言處理時將被跳過,skip() 是詞法分析器類的一個方法。如清單 3 所示:
1.5.1.1.1. 清單 3. 記號定義
ID : ('a'..'z' |'A'..'Z')+ ;
INT : '0'..'9' + ;
NEWLINE:'\r' ? '\n' ;
WS : (' ' |'\t' |'\n' |'\r' )+ {skip();} ;
1.5.1. 文法可視化
使用 Antlrworks 打開 Expr.g,Antlrworks 對每一個文法定義都做了可視化顯示。整體的文法定義如圖 3:
1.5.1.1.1. 圖 3. 文法定義的可視化
其中語法規則和詞法記號的定義都有對應的圖形表示方式。比如語法規則 atom 的圖示形式如圖 4 所示:
1.5.1.1.2. 圖 4. 語法規則 atom 的可視化
詞法記號 ID 的圖示形式如圖 5 所示:
1.5.1.1.3. 圖 5. 詞法記號 ID 的可視化
使用 Antlrworks 還可以對語法分析樹可視化,在 Antlrworks 的 GUI 視窗中,點擊 Run ->Debug, 在 Input Text 視窗中輸入 a+(2 + b),Start Rule 選擇 prog, 然後完成調試,可以看到 a+(2 + b) 時的語法分析樹,如圖 6 所示:
1.6. 或者使用antlrworks生成需要的詞法分析器
>>menubar >gene 。。 到個g文件../output目錄下麵
Or use antlr tool..
運行 Antlr 生成需要的詞法分析器
完成文法定義之後,即可以運行 Antlr,為我們生成需要的詞法分析器和語法分析器。在命令行運行以下下命令,如清單 4 所示:
1.6.0.1.1. 清單 4. 運行 Antlr
java org.antlr.Tool c:/
antlr_intro\src\expr\Expr.g
成功運行Antlr之後,將為我們生成 3 個文件,Expr.tokens、ExprLexer.java和ExprParser.java。其中Expr.tokens為文法中用到的各種符號做了數字化編號,我們可以不關註這個文件。ExprLexer是Antlr生成的詞法分析器,ExprParser是Antlr 生成的語法分析器,如圖 1 所示。
1.6.0.1.2. 圖 1. Antlr 生成結果
1.6.1. 查看每一個標識符的代碼
Antlrwork hto select left menu symb..then menubar >gene>show rule coe
Then show the code form lexelParser...java..
1.6.2. 表達式驗證
基於 Antlr 生成的詞法分析器和語法分析器後,可以基於它們來驗證我們的輸入的表達式是否合法。我們需要調用 Antlr 的 API 完成以下 Java 程式,如清單 5 所示:
1.6.2.1.1. 清單 5. 調用分析器
public static void run(String expr) throws Exception {
ANTLRStringStream in = new ANTLRStringStream(expr);
ExprLexer lexer = new ExprLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
ExprParser parser = new ExprParser(tokens);
parser.prog();
}
對每一個輸入的字元串,我們構造一個 ANTLRStringStream 流 in,用 in 構造詞法分析器 lexer,詞法分析的作用是產生記號,用詞法分析器 lexer 構造一個記號流 tokens,然後再使用 tokens 構造語法分析器 parser,至此已經完成詞法分析和語法分析的準備工作。最終調用語法分析器的規則 prog,完成對錶達式的驗證。詳細的 Java 程式參考樣例代碼中的 Test.java。
當輸入合法的的表達式時,分析器沒有任何輸出,表示語言被分析器接受;當輸入的表達式違反文法規則時,比如“a + (b * 3”,分析器輸出 line 0:-1 mismatched input '<EOF>' expecting ')';提示期待一個右括弧卻遇到了結束符號。如圖 2 所示:
1.6.2.1.2. 圖 2. 表達式驗證結果
1.7. 獲取tokens
public static void main(String[] args) {
run(" where=\"atiq422\" ");
System.out.println("--f");
}
public static void run(String