Wednesday, December 31, 2008

ANTLR (2) - Lexer和Parser的文件格式

有了上一篇的基本概念,接下來看ANTLR Lexer和Parser的文件格式。

*ANTLR的lib可以在ANTLR的官方網站下載。
*以下資料參考:ANTLR by Ashley J.S Mills

一份ANTLR的文件,是由幾個部份所組成的,有些是必要,有些則是選擇性寫或不寫。一份基本的ANTLR文件(*.g)大概如下圖所示。如果能馬上理解下面的格式,想必閣下是神人等級的人物,就直接祝你新年快樂了,哈。反正大概有個印象就好,下面會慢慢解釋。



(1) 最上面藍色的區塊,是針對整份文件所做的宣告。
header {
    // stuff that is placed at the top of generated files
}
在這個header裡宣告的東西,會被逐字的複製到ANTLR產出文件中的最開頭。所以import package之類的指令會被放在這塊。因為ANTLR這份文件只是一個中介的檔案,最終會轉成我們指定的語言(ex. Java, C/C++ ...)

(2)
{ optional class preamble - output to generated classfile
immediately before the definition of the class }
class YourLexerClass extends Lexer;
// definition extends from here to next class definition
// (or EOF if no more class defs)
options { YourOptions }
tokens...
lexer rules...
第二部份的紫色區塊以optional class preamble為開頭,若你有一些在定義class之前必需宣告的東西就放在這裡(非必要)。通常以大括號圍起來的部份,會原封不動的被複製到由ANTLR轉出來的程式碼當中。這裡的options是只針對這個class所做的設定 (i.e., YourLexerClass),options可能會長這樣:
options {
    k = 2;// Set token lookahead to two
    tokenVocabulary = Befunge; // Call it's vocabulary "Befunge"
    defaultErrorHandler = false; // Don't generate parser error handlers
}
options裡還有很多可以設定的項目,可以參考ANTLR的文件。接下來tokens的部份可以讓你明確的定義literals和imaginary tokens,例如:
tokens {
    EXPR; // Imaginary token
    THIS="that"; // Literal definition
    INT="int"; // Literal definition
}
下一個部份是定義lexer rule,也就是定義文件元件的地方,通常一條lexer rule的格式大概如下:
rulename [args] returns [retval]
options { defaultErrorHandler=false; }
{ optional initiation code }
: alternative_1
| alternative_2
...
| alternative_n
;
一個辨視整數的簡單rule可以只寫這樣:
INT: ('0'..'9')+; // Matches an integer
rule name後面的冒號和最後的分號是一定要的啦。這條rule的意思是指在文章裡看到一個或多個0~9的字元,他就代表一個INT;例如一個字串「ABC123」,123就會被視為是一個INT;字串「我是1,你是23」,這裡會被辨視出兩個INT,分別是1和23。

其餘兩個部份的Parser和TreeParser格式也和上面的Lexer相同。每份*.g檔案裡,這三大部份(Lexer, Parser, TreeParser)可以任意順序出現多次或不出現。每個class的有效範圍(scope)是從其宣告開始,至另一個class宣告之前為結尾,等同於上圖顏色的區隔,如紫色、粉紅和灰色區塊。

ANTLR Notation
最後,簡單介紹ANTLR的標示符號和意義。基本上,Lexer和Parser是使用同一套符號來表示一些特殊的意義。定義一條規則(rule)最主要的目的是讓ANTLR能根據這一連串的rule,一步一步分析文章的組成結構 (i.e., 在文件中辨視符合規則定義的pattern)。
  • (expression)*
    ANTLR用'*'表示括號中裡的敘述出現0次或多次。

  • (expression)+
    ANTLR用'+'表示括號中裡的敘述至少出現1次或多次。

  • (expression)?
    ANTLR用'?'表示括號中裡的敘述出現0次或1次,即可有可無。
延用上面Lexer的例子:INT : ('0'..'9')+;
即表示0~9之間的數字字元,只要出現一次或是出現多次,就可視為INT。因此連續的幾個數字一起出現,依然只會被視為一個INT,如:"5678"。若有被其他非0~9的字元隔開,就會被視為多個INT元件,如"AB9C12D234",會被辨識出三個INT,分別是9,12和234。

上一篇:ANTLR (1) - 概念介紹
下一篇:ANTLR (3) - Simple Lexer Example

2 comments: