2012-04-16 92 views
1

我試圖根據它的上下文修改規則,儘可能少地複製/粘貼。我會用最好的我想要實現的僞變種開始:根據解析器規則的可選部分重寫規則ANTLR3

module[boolean isParam]: 'module' id=identity? 
     declaration+ 
     update+ 
     'endmodule' -> ^(MODULE ({if (isParam)} IS_PARAMETER {else} $id) declaration+ update+); 

如果isParam設爲我希望模塊不匹配identity規則,但創造它的地方IS_PARAMETER令牌。我敢肯定,我可以用兩個單獨的module規則來做到這一點,但是是否有更簡潔的方式,減少代碼重複或者不將規則拆分成許多更小的規則?

回答

1

我相信是這樣的工作:

module[boolean isParam]: 'module' id=identity? 
     declaration+ 
     update+ 
     'endmodule' -> {isParam}? ^(MODULE IS_PARAMETER declaration+ update+) 
        ->   ^(MODULE $id declaration+ update+); 
+1

是的,但是,因爲'identity'是可選的,所以應當在其標籤'$ id'在重寫規則。 – 2012-04-16 15:15:54

+0

這是我正在尋找的解決方案,謝謝。看起來'$ id'不需要是可選的。如果它不是可選的並且變量還沒有被設置,它會插入一個'nil'節點嗎? – Lichtblitz 2012-04-16 15:55:07

+0

@Lichtblitz,不,如果它在解析器規則中是可選的,而在重寫規則中不是可選的,則當節點不存在時引發異常(我相信當在樹語法中遍歷樹時,但可能在AST創建期間,I我不是100%確定的:試着找出答案!)。 – 2012-04-16 16:59:29

1

前面已經提出,這會工作:

module[boolean isParam] 
: 'module' id=identity? declaration+ update+ 'endmodule' 
    -> {isParam}? ^(MODULE IS_PARAMETER declaration+ update+) 
    ->   ^(MODULE $id? declaration+ update+) 
; 

(注意可選$id但是!)

但通過觀察根據你的規定,我得到的印象是,只要identity而不是目前,您希望AST中有一個IS_PARAMETER節點。如果是這樣的話,你可以處理這個不帶參數和謂詞,這是IMO首選:

module 
: 'module' (identity declaration+ update+ 'endmodule' -> ^(MODULE identity declaration+ update+) 
      | declaration+ update+ 'endmodule'   -> ^(MODULE IS_PARAMETER declaration+ update+) 
      ) 
; 
+0

感謝您的建議,這是我個人的備用解決方案。由於我只想在某些情況下允許缺少「身份」,因此此解決方案會接受太多。無論如何感謝:-) – Lichtblitz 2012-04-16 15:55:30

+0

好吧,這只是我的一個猜測。很高興知道您找到了解決方案。 – 2012-04-16 16:56:23