2010-03-22 101 views
3

我在同一種編程語言的一些方言之間編寫了一個轉換器。我在網上發現了一個語法 - 它很複雜,可以處理所有的情況。現在我正在嘗試寫出適當的操作。ANTLR中的寫入語言轉換器

大部分輸入只是要重寫輸出。我需要做的是解析函數調用,執行我的魔術(重命名函數,重新排序參數等)並寫入它。

我使用AST作爲輸出。當我遇到一個函數調用時,我構建了一個自定義對象結構(從我的目標語言中定義的類),調用相應的函數,並且我有一個字符串表示我想要獲得的轉換後的函數。

問題是,我應該用這個字符串做什麼?我想替換封閉規則的.text屬性,但setText()僅適用於詞法分析器規則,規則的.text屬性是隻讀的。如何解決這個問題呢?

program 
    : statement_list   { output = $statement_list.text; } 
    ; 

//... 

statement 
    : expression_statement 
    // ... 
    ; 

expression_statement 
    : function_call 
    // ... 
    ; 

function_call 
    : ID '('     { /* build the object, assign name */ 
            Function function = new Function(); 
            //... 
           } 
     (
     arg1 = expression   { /* add first parameter */ } 
     (',' arg2 = expression { /* add the rest of parameters */ } 
    )* 
    )? 
     ')'      { /* convert the function call */ 
            string converted = Tools.Convert(function); 
            // $setText(converted);    // doesn't work 
            // $functionCall.text = converted; // doesn't work 
           } 
    ; 

回答

1

最簡單的方法是創建一個重寫器。將語法設置爲重寫,使用模板並就地創建模板。然後使用TokenRewriteStream和它的ToString()方法。

grammar Test; 

options { 
    language = CSharp2; 
    output = template; 
    rewrite = true; 
} 

program 
    : statement_list 
    ; 

//... 

statement 
    : expression_statement 
    // ... 
    ; 

expression_statement 
    : function_call 
    // ... 
    ; 

function_call 
    : ID '('     { /* build the object, assign name */ 
            Function function = new Function(); 
            //... 
           } 
     (
     arg1 = expression   { /* add first parameter */ } 
     (',' arg2 = expression { /* add the rest of parameters */ } 
    )* 
    )? 
     ')' -> { new StringTemplate(Tools.Convert(function)) } 
    ; 

和司機:

string input = "...."; 

    var stream = new ANTLRStringStream(input); 
    var lexer = new TestLexer(stream); 

    // need to use TokenRewriteStream 
    var tokenStream = new TokenRewriteStream(lexer); 
    var parser = new TestParser(tokenStream); 

    parser.program(); 

    // original text 
    Console.WriteLine(tokenStream.ToOriginalString()); 
    // rewritten text 
    Console.WriteLine(tokenStream.ToString()); 
4

一旦你有一個AST,你需要編寫一個樹狀漫步者,它發出你的程序作爲轉換源。根據變化的複雜程度,您甚至可能會有一位中間樹型漫遊者進行樹型轉換。

這就是說,通過AST步驟,可能不是最好的方法。

您可能想看看Terrence Parr(Pragmatic Programmers)的「語言設計模式」。第11章討論你的程序類型。

他提到了一個工具ANTLRMorph,它可能更適合您的問題。

+1

的ANTLRMorph項目是在http://www.antlr.org/wiki/display/Morph/Home;jsessionid=1EE0150D66C1B50451B202AD44D74134 我們的目標是能夠prople以ASF-SDF的精神編寫具有具體語法重寫規則的翻譯員。 順便說一下,ASF-SDF(http://www.meta-environment.org/)確實應該考慮寫這樣的翻譯。 – tonio 2010-03-24 14:38:07