2009-12-22 17 views
0

我正在研究玩具語言的解釋器,以瞭解有關構建解釋器的信息。我已經爲生成解析樹的語法實現了一個簡單的解析器。現在,評估分析樹的常用方法是使用解析樹的節點上的多態性,用代碼,看起來像下面(在Python):在編碼表達式分析樹/評估器時使用多態性存在疑問

class Node: 
    def __init__(self,left,right): 
     self.left=left 
     self.right=right 

    def evaluate(self): 
     print "throw an exception" 

class AddNode(Node): 
    def evaluate(self): 
     return evaluate(self.left)+evaluate(self.right) 

class SubNode(Node): 
    def evaluate(self): 
     return evaluate(self.left)-evaluate(self.right) 

的方法評估在每個後代覆蓋的節點,並捍衛行爲的需要。只需在根上調用evaluate()即可找到表達式的值。

另一種方法是在節點中沒有任何評估函數,而是生成一個簡單地將類型分配給節點的分析樹。評估代碼在一個單獨的函數中完成,遞歸檢查每個節點並決定如何評估它。這將導致帶有大量「if else」結構,開關或跳轉表的函數。

幾乎在我看的每一個地方,以及我在大學教過的東西,似乎都表明第一種方法總是更好。我不完全理解的是爲什麼第一種方法應該優於第二種方法。爲什麼在這種情況下多態必然更好?帶有大「if else」表的函數不存在,但基本上相同的代碼仍然存在,但移動到不同的地方並散佈在許多不同的類中。

這引起了我的注意,因爲我想我以後可能需要更改某些操作符的含義,甚至允許運算符在運行時重新定義。我也將函數調用和運算符一樣對待,所以像運行一個跳轉表一樣可以在運行時添加的東西會很好。

第一種方法可能有一些顯着的優點,我現在沒有看到。有人可以指出嗎?

回答

1

這是一個有趣的問題。在我看來,多態仍然是一個很好的途徑,即使你有運算符重載。

您使用多態類定義的是在該語言中支持的基本操作。運算符重載不會爲語言添加更多原始功能。重載操作符實際上等同於函數調用,應該以類似的方式實現。

在我看來,保持操作員類中本地化操作符的語義將使您的設計更加清潔。這是因爲要實現一個新的基本操作,您只需要定義該類,然後在解析過程中創建一個實例。替代方案需要更改解析器和評估器。我只是覺得評估者可以成爲一個if語句的龐大嵌套來處理操作員的各種特殊情況,這些特殊情況可能會很好地隱藏在操作員類中。

我很難相信我在這裏說什麼,因爲我過去使用過兩種技術,而且他們都運行良好。 ;-)

+0

謝謝。每當我需要爲該語言添加一個新操作符時,必須更改解析器和評估器的好處。 – MAK 2009-12-22 16:46:27