在 ANTLR 中编写语言转换器 [英] Writing language converter in ANTLR

查看:22
本文介绍了在 ANTLR 中编写语言转换器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm writing a converter between some dialects of the same programming language. I've found a grammar on the net - it's complex and handles all the cases. Now I'm trying to write the appropriate actions.

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

Most of the input is just going to be rewritten to output. What I need to do is parse function calls, do my magic (rename function, reorder arguments, etc) and write it.

我使用 AST 作为输出.当我遇到函数调用时,我构建了一个自定义对象结构(从在我的目标语言中定义的类),调用适当的函数,然后我有一个字符串来表示我想要获得的转换后的函数.

I'm using AST as output. When I come across a function call, I build a custom object structure (from classes defined in my target language), call the appropriate function and I have a string that represents the transformed function that I want to get.

问题是,我应该用那个字符串做什么?我想替换封闭规则的 .text 属性,但 setText() 仅适用于词法分析器规则,并且规则的 .text 属性是只读的.如何解决这个问题?

The problem is, what I'm supposed to do with that string? I'd like to replace the .text attribute of the enclosing rule, but setText() is only available on lexer rules and the rule's .text attribute is read-only. How to solve this problem?

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
                                }
    ;

推荐答案

最简单的方法是创建重写器.将语法设置为重写、使用模板并就地创建模板.然后使用 TokenRewriteStream 和它的 ToString() 方法.

The easiest way is to create a rewriter. Set grammar to rewrite, use templates and create a template in-place. Then use TokenRewriteStream and it's ToString() method.

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());

这篇关于在 ANTLR 中编写语言转换器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆