2010-02-01 39 views
4

我正在嘗試編寫一個ANTLR解析器規則,該規則匹配事物列表,並且我想要編寫一個可以獨立處理列表中每個項目的解析器操作。如何爲可匹配多個項目的規則中的每個項目執行ANTLR解析器操作?

這些規則的一些輸入的例子是:

$(A1 A2 A3) 

我想這導致包含三個MyIdentEvaluator對象的列表的評估 - 每個A1,A2和A3的。

這裏是我的語法的一個片段:

my_list returns [IEvaluator e] 
    : { $e = new MyListEvaluator(); } 
     '$' 
     LPAREN 
     op=my_ident+ { 
        /* want to do something here for each 'my_ident'. */ 
        /* the following seems to see only the 'A3' my_ident */ 
        $e.Add($op.e); 
        } 
     RPAREN 
    ; 

my_ident returns [IEvaluator e] 
    : IDENT { $e = new MyIdentEvaluator($IDENT.text); } 
    ; 

我覺得my_ident定義正確的,因爲我可以看到三個MyIdentEvaluators得到預期爲我的輸入字符串創建的,但只有最後my_ident不斷被添加到列表(在我的示例輸入中爲A3)。

如何通過語法更改或解析器操作更改獨立地對待每個元素?

我還想到,我對這些概念的詞彙量並不是它應該是的,所以如果看起來我濫用了一個詞,我可能是。


編輯迴應韋恩的評論:

我試圖用op+=my_ident+。在這種情況下,我的動作中的$op變爲IList(在C#中),其中包含Antlr.Runtime.Tree.CommonTree實例。它在$op中爲每個匹配的令牌提供了一個條目,所以我看到了我的三個匹配項,但我沒有我真正想要的實例。我希望能夠在ANTLR文檔中找到一個可能有助於此的規則屬性,但似乎沒有任何東西可以幫助我擺脫這種IList


結果...

基於chollida的答案,我結束了這個效果很好:

my_list returns [IEvaluator e] 
    : { $e = new MyListEvaluator(); } 
     '$' 
     LPAREN 
     (op=my_ident { $e.Add($op.e); })+ 
     RPAREN 
    ; 

Add方法被調用的my_ident的每場比賽。這裏

my_list returns [IEvaluator e] 
: { $e = new MyListEvaluator(); } 
    '$' 
    LPAREN 
    op=my_ident { $e.Add($op.e); } 
    (opNext=my_ident { $e.Add($opNext.e); })* 
    RPAREN 
; 


my_ident returns [IEvaluator e] 
: IDENT { $e = new MyIdentEvaluator($IDENT.text); } 
; 

而不是使用ANTLR的內置的+我們迭代自己的:

+0

對於我來說,回答你的問題還不夠,是否$ op不包含所有三個標記?還是其他的東西,比如你想爲每個標記做一些特定的事情?爲了將所有三個令牌放入$ op中,我認爲您需要op + = my_ident +(等號前面的另一個加號)。我需要更多信息來回答另一個問題。 – WayneH 2010-02-02 00:06:35

+0

我的問題是我真的不知道「$ op」究竟是什麼。我到了那裏,部分歸功於你對這個和其他問題的幫助!我訂購了Terence Parr書。 :)是的,我只是想能夠對每個令牌做同樣的事情 - 在這種情況下,將令牌添加到列表中。我將編輯我的問題以反映您提出的「op +」建議的結果。 – 2010-02-02 05:45:36

+0

好吧,所以來自該規則的my_ident和返回值加上$ op都按預期工作(此時通緝)。現在獲取my_list中的$ e以返回正確的對象。它應該只返回$ op的列表嗎?我想一個你想修改my_list規則在開始時是 - my_list返回[IEvaluator e] @init {$ e = new MyListEvaluator(); } :'$'... 另外,您可能希望更改my_ident或my_list中的返回標籤/變量;他們兩個都可能會有點混亂。 接下來是MyListEvaluator vs MyIdentEvaluator(我不知道C#)。 – WayneH 2010-02-02 13:34:04

回答

1

如果我在寫這個我會分裂出單獨匹配到一個列表模式。我們匹配第一個項目並將其添加到列表中,然後匹配連續的項目並存儲它們。

0
my_list returns [IEvaluator e] 
    : '$' LPAREN ops+=my_ident+ RPAREN { e = new MyListEvaluator(list_ops); } 
    ; 

我做在Java中類似的事情,不得不檢查生成的代碼,發現ANTLR3生成一個變量稱爲「LIST_NAME」(其中在這種情況下,NAME = OPS),這是所有的子列表 - 語言規則返回值。我想在C#中它是一樣的,雖然我可能是錯的。你會希望這個變量被稱爲「ops」,但該變量將只包含最後匹配的規則值(至少在Java中)。

相關問題