本文介紹了返回不同數據類型的ANTLR AST訪問器的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!
問題描述
我完成了ANTLR CST到AST的轉換,并創建了一個特定的Visitor<T>
接口,該接口允許我訪問所有的AST節點,但我遇到的主要問題是,一些訪問應該返回不同的數據類型,我不確定如何處理這一問題。
例如,對于簡單的算術運算,我希望從它們各自的訪問方法返回一個雙精度值;但其他字符串操作需要它們各自的節點返回一個字符串。
因為我的訪問方法都需要泛型類型T
,所以我嘗試創建了一個名為Result
的類和兩個子類DoubleResult
和StringResult
,以便我的訪問者可以在訪問期間返回字符串或雙精度類型,但它似乎很糟糕,并且充滿了強制轉換和類型檢查。
有沒有更好的方法來做這樣的事情?
以下是示例代碼:
public class ExpressionVisitor implements Visitor<Result> {
...
public Result visit(BinaryExpression node) {
// here the node's left or right can be StringResults
// So i'd have to do instance and type checks
}
public Result visit(StringExpression node) {
// here i'd return a StringResult specifically
}
}
編輯:
目標是能夠進行字符串算術,例如,像在Python中2*"hello"
但是,二進制表達式訪問方法必須檢查哪個操作數是字符串(左或右),然后大多數其他訪問方法將需要相應地檢查和處理DoubleResult或StringResult類型。有沒有更干凈的方法來實現同樣的目標?
推薦答案
正如您已經毫無疑問地發現的那樣,ANTLR為您生成的Visitor類是一個泛型類,您需要在其中標識預期的返回類型,并且必須返回該類型:
有幾種方法可以解決您的問題。(它肯定是在動態類型語言中出現的)。
對于我為教程拼湊的一種簡單語言,我只是定義了一個Value
類,它可以包含我允許的任何動態類型。我為每種類型使用了getters/setters,并為每種類型使用了is*()
方法。我的表達式訪問器剛剛返回此動態類型。
注意:在執行之前,我使用了語義驗證偵聽器,該偵聽器使用了一種基于堆棧的方法,在退出表達式時從堆棧中彈出表達式類型(在我訪問子級時已推送到堆棧上),驗證這些值的類型兼容性,然后將結果類型推送到堆棧上(文字和變量只是將它們的類型推送到堆棧上)。我遇到的任何問題都會在執行之前推送一條錯誤消息。這樣,我知道,在執行類型中,我總是擁有正確的類型。(同樣可以在運行時完成;這正是我選擇的解決方案。)
實現這一點的另一種可能很方便的方法是,因為您在使用訪問者時控制了樹導航,所以不必說必須有一個用于整個樹的訪問者。您可以有多個訪問者(每個訪問者都有自己的類型),并選擇要使用哪個訪問者來訪問您的子節點。例如,我使用返回NULL
類型的Visator訪問語句節點,但使用返回我的動態Value
類型的Visator訪問所有表達式節點。
沒有真正的理由不能擁有你想要的訪問者,每個訪問者都是不同類型的。訪問者是無國籍的,這并不少見,所以您可以重復使用它們,在訪問每個孩子的適當類型之間來回跳躍。(當然,這假設您可以從父節點確定應該使用哪種訪問者類型來訪問每個子節點。)
小錯誤…ANTLR4生成分析樹(不是AST)
這篇關于返回不同數據類型的ANTLR AST訪問器的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,