在ANTLR中编写语言转换器

3
我正在编写一个转换器,用于一些相同编程语言的方言之间的翻译。我在网络上找到了一个复杂的语法可以处理所有的情况。现在,我正在尝试编写适当的操作。
大部分输入只需要重写为输出。我需要做的是解析函数调用,进行必要的更改(例如,重命名函数、重新排序参数等),并将其写入。
我使用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
                                }
    ;
2个回答

5
一旦您拥有了AST,您需要编写一个树遍历器,将您的程序作为转换后的源代码发出。根据您所做更改的复杂性,您甚至可能会有一个中间的树遍历器进行树形变换。
话虽如此,通过AST步骤可能不是最佳方法。
您可能想看一下Terrence Parr(Pragmatic Programmers)的“语言设计模式”。第11章涉及您的程序类型。
他提到了一个工具ANTLRMorph,可能更适合您的问题。

1
ANTLRMorph项目位于 http://www.antlr.org/wiki/display/Morph/Home;jsessionid=1EE0150D66C1B50451B202AD44D74134 。该项目的目标是让人们能够编写具有具体语法重写规则的翻译器,以ASF-SDF的精神为指导。 顺便提一下,ASF-SDF (http://www.meta-environment.org/) 真的可以考虑用来编写这样的翻译器。 - tonio

2
最简单的方法是创建一个重写器。将语法设置为重写,使用模板并在原地创建一个模板。然后使用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());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接