2010-03-22 102 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