2012-06-25 43 views
3

ANTLR分析器產生以下生成的代碼:強制ANTLR使用個性化的TreeAdaptor在解析器

protected TreeAdaptor adaptor = new CommonTreeAdaptor(); 

我實現我自己的TreeAdaptor,我想解析器總是用我的,從來沒有使用CommonTreeAdaptor( )。我發現的唯一方法是每次我創建一個新的解析器時間設置調用代碼裏面:

Parser parser = new MyParser(); 
parser.setTreeAdaptor(new MyAdaptor()); 

有一些方法我可以設置默認TreeAdaptor或一些初始化代碼附加到生成的構造函數?

回答

0

我認爲我找到了比Bart的命名構造方法更好的解決方案。

我無法直接修改生成的構造函數(包括使其成爲私有的,這就是爲什麼我不喜歡命名構造函數解決方案)。不過,我可以介紹一個初始化塊:

grammar T; 

options { 
    output=AST; 
    ASTLabelType=CommonTree; 
} 

@parser::members { 
    { 
     this.adaptor = new MyAdaptor(); 
    } 
} 

按照Java documentation,「Java編譯器副本初始化語句塊到每一個構造函數因此,這種方法可以用來分享的多個構造函數之間的代碼塊。」

所以this.adaptor將首先被設置爲new CommonTreeAdaptor()由生成的代碼,但將被設置爲new MyAdaptor()我的初始化塊。測試證實這是實際發生的事情。

這個解決方案的優點是我的解析器的調用者不需要知道它使用自定義的TreeAdaptor或者做任何不尋常的事情(我的適配器是CommonTreeAdaptor的一個子類,所以任何代碼依賴於很好)。

2

有什麼辦法可以設置默認TreeAdaptor或將一些初始化代碼附加到生成的構造函數?要做到這一點

一種方法是添加設置自定義樹適配器一個靜態方法:

grammar T; 

options { 
    output=AST; 
    ASTLabelType=CommonTree; 
} 

@parser::members { 

    public static TParser newTParser(TreeNodeStream input) { 
    TParser parser = new TParser(input); 
    parser.setTreeAdaptor(new MyAdaptor()); 
    return parser; 
    } 
} 

parse 
: Any* EOF 
; 

Any 
: . 
; 

然後你就可以更換:

TParser parser = new TParser(input); 

TParser parser = TParser.newTParser(input); 
+0

這不適合我。 '@parser :: members'代碼被添加進來,並且默認的構造函數保留,所以生成的文件具有重複的構造函數。 –

+0

@NathanielWaisbrot,啊,是的,我調整了我的答案。 –

+0

我希望能夠在不必追捕每一個(一大組)解析器的構造的情況下就能夠進行更改。哦,那麼,命名構造函數就是這樣。 –