2010-08-20 41 views
1

我有一個樹狀結構的抽象類和表示小語言抽象語法樹的案例類。只有部分匹配的結構上的映射

對於頂級抽象類我實現的方法map

abstract class AST { 
... 
    def map(f: (AST => AST)): AST = { 
    val b1 = this match { 
     case s: STRUCTURAL => s.smap(f) // structural node for example IF(expr,truebranch,falsebranch) 
     case _ => this // leaf, // leaf, like ASSIGN(x,2) 
    } 
    f(b1) 
    } 
... 

的smap的定義如下:

override def smap(f: AST => AST) = { 
    this.copy(trueb = trueb.map(f), falseb = falseb.map(f)) 
    } 

現在我寫不同的「轉變」插入,刪除和更改AST中的節點。

例如,從塊中刪除相鄰NOP節點:

def handle_list(l:List[AST]) = l match { 
    case (NOP::NOP::tl) => handle_list(tl) 
    case h::tl => h::handle_list(tl) 
    case Nil => Nil 
} 

ast.map { 
    case BLOCK(listofstatements) => handle_list(listofstatements) 
} 

如果我寫這樣的,我最終MatchError和由上述地圖改變到I可以「修復」:

ast.map { 
    case BLOCK(listofstatements) => handle_list(listofstatements) 
    case a => a 
} 

我應該和所有那些人一起生活嗎?或者我可以用某種方式改進我的map方法(或其他部分)嗎?

回答

4

充分利用參數map一個PartialFunction

def map(f: PartialFunction[AST, AST]): AST = { 
    val idAST: PartialFunction[AST, AST] = {case a => a} 
    val g = f.orElse(idAST) 

    val b1 = this match { 
    case s: STRUCTURAL => s.smap(g) 
    case _ => this 
    } 
    g(b1) 
} 
+0

哇!我繼續在斯卡拉看到奇妙的事物。這正是我所尋找的 – svrist 2010-08-21 06:18:46

+0

這段代碼可能有點不對,因爲我沒有注意到'f'被用作'smap'的參數。固定。 – 2010-08-21 07:22:08

+0

是不是'orElse'而不是'和Then'? – svrist 2010-08-23 09:54:35

4

如果樹轉換不僅僅是項目的一個小方面,我強烈建議您使用Kiama的重寫器模塊來實現它們。它實施了像Stratego一樣的策略驅動的轉換。它有一組非常豐富的策略和策略組合器,它們允許將遍歷邏輯完全分離(對於絕大多數情況,可以從所提供的策略和組合器中「下架」)從(局部)變換(它們是特定於你的AST,當然你會提供)。

+0

非常有趣。將研究它! – svrist 2010-08-21 06:19:28