【问题标题】:Writing language converter in ANTLR在 ANTLR 中编写语言转换器
【发布时间】:2010-03-24 22:33:32
【问题描述】:

我正在编写相同编程语言的一些方言之间的转换器。我在网上找到了一个语法 - 它很复杂并且可以处理所有情况。现在我正在尝试编写适当的操作。

大部分输入将被重写为输出。我需要做的是解析函数调用,发挥我的作用(重命名函数、重新排序参数等)并编写它。

我使用 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
                                }
    ;

【问题讨论】:

    标签: antlr rewrite


    【解决方案1】:

    拥有 AST 后,您需要编写一个 tree walker,将您的程序作为转换后的源代码发出。根据更改的复杂性,您甚至可能有一个中间树遍历器进行树转换。

    也就是说,通过 AST 步骤可能不是最好的方法。

    您可能想看看 Terrence Parr(实用程序员)的“语言设计模式”。第 11 章介绍了您的程序类型。

    他提到了一个工具 ANTLRMorph,它可能更适合您的问题。

    【讨论】:

    【解决方案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());
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多