2010-01-13 31 views
4

我試圖學習語言解析的樂趣...如何在ANTLR3中製作TreeParser?

我創建了一個ANTLR語法,我相信會匹配一個簡單的語言,我希望實現。這將有以下語法:

<FunctionName> (<OptionalArguments>+) { 
    <OptionalChildFunctions>+ 
} 

實際的例子:

ForEach(in:[1,2,3,4,5] as:"nextNumber") { 
    Print(message:{nextNumber}) 
} 

我相信我有語法正確的工作,以配合這個結構,現在我attemping建立一個抽象語法樹爲語言。

首先,我必須承認我不完全確定這棵樹應該如何看。其次,我完全喪失瞭如何在Antlr語法中做到這一點......我幾個小時一直在努力嘗試。

這是我現在的想法 - 請和我一起裸照! :)

    FunctionName 
       /  \ 
      Attributes   \ 
      /\  /\ 
      ID /\ ChildFunctions 
     /\ ID etc 
     / \ 
    Attribute AttributeValue 
     Type 

這是我目前ANTLR的語法文件:

grammar Test; 

options {output=AST;ASTLabelType=CommonTree;} 

program : function ; 
function : ID (OPEN_BRACKET (attribute (COMMA? attribute)*)? CLOSE_BRACKET)? (OPEN_BRACE function* CLOSE_BRACE)?; 

attribute : ID COLON datatype; 

datatype : NUMBER | STRING | BOOLEAN | array | lookup ; 
array : OPEN_BOX (datatype (COMMA datatype)*)? CLOSE_BOX ; 
lookup : OPEN_BRACE (ID (PERIOD ID)*) CLOSE_BRACE; 

NUMBER 
: ('+' | '-')? (INTEGER | FLOAT) 
; 

STRING 
    : '"' (ESC_SEQ | ~('\\'|'"'))* '"' 
    ; 

BOOLEAN 
: 'true' | 'TRUE' | 'false' | 'FALSE' 
; 

ID : (LETTER|'_') (LETTER | INTEGER |'_')* 
    ; 

COMMENT 
    : '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;} 
    | '/*' (options {greedy=false;} : .)* '*/' {$channel=HIDDEN;} 
    ; 

WHITESPACE : (' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;} ; 

COLON : ':' ; 
COMMA : ',' ; 
PERIOD : '.' ; 

OPEN_BRACKET : '(' ; 
CLOSE_BRACKET : ')' ; 

OPEN_BRACE : '{' ; 
CLOSE_BRACE : '}' ; 

OPEN_BOX : '[' ; 
CLOSE_BOX : ']' ; 

fragment 
LETTER 
: 'a'..'z' | 'A'..'Z' 
; 

fragment 
INTEGER 
: '0'..'9'+ 
; 

fragment 
FLOAT 
: INTEGER+ '.' INTEGER* 
; 

fragment 
ESC_SEQ 
    : '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\') 
    ; 

任何幫助/建議將是巨大的。我嘗試閱讀幾十個教程,但沒有任何關於AST一代似乎堅持:(

回答

9

第1步是使樹看起來像你張貼的小圖。現在,你沒有任何樹的建設運營商,所以你要與一個平面列表來結束。

tree construction的antlr.org網站上。

您可以使用ANTLRWorks看看你得到什麼的解析樹和AST。開始加入樹建設運營商,看事情如何變化。

編輯/附加信息:

這裏你可以按照給你如何去做一個粗略的想法的過程:

  1. 下載ANTLRWorks和使用它的繪圖設備。在進行更改之前和之後,您一定會希望看到分析樹和AST。一旦你瞭解了一切如何工作,那麼你可以使用任何你想要的IDE或編輯器。
  2. 有兩個樹構造的基本操作符 - 感嘆號!它告訴編譯器不要將節點放在AST內,並告訴ANTLR將某個節點作爲根節點。首先檢查每個非終端規則並確定哪些元素不需要在AST中。例如,你不需要逗號或括號。一旦獲得了所有信息,您就可以填充提供所有信息的結構(或創建自己的AST結構)。逗號不再有幫助,所以給他們添加一個!。例如:

    function: ID (OPEN_BRACKET! (attribute (COMMA!? attribute)*)? CLOSE_BRACKET!)? (OPEN_BRACE! function* CLOSE_BRACE!)?;

  3. 看看前後ANTLRWorks的AST。比較。

  4. 現在決定哪個元素應該是根節點。它看起來像你想ID是根節點,所以ID後添加^和ANTLRWorks比較。

下面是使其更接近我想你想的幾個變化:

program : function ; 
function : ID^ (OPEN_BRACKET! attributeList? CLOSE_BRACKET!)? (OPEN_BRACE! function* CLOSE_BRACE!)?; 
attributeList: (attribute (COMMA!? attribute)*); 
attribute : ID COLON! datatype; 
datatype : NUMBER | STRING | BOOLEAN | array | lookup ; 
array : OPEN_BOX! (datatype^ (COMMA! datatype)*)? CLOSE_BOX!; 
lookup : OPEN_BRACE! (ID (PERIOD! ID)*) CLOSE_BRACE!; 

隨着你的腰帶,現在就去看看一些tutorials的。

+0

這是我害怕的部分,我害怕。我讀過樹構建頁面,並沒有真正理解它:( – 2010-01-14 00:28:30

+0

感謝您的編輯,這增加了很多有用的信息。 – 2010-01-24 16:03:52

+0

真正偉大的解釋。我也用ANTLR一個初學者,我認爲該網站是在某種程度上以某種方式告訴您買的書感謝 – INS 2010-02-10 12:29:42