Конвертер языков письма в 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
                                }
    ;

person Stefan    schedule 22.03.2010    source источник


Ответы (2)


После того, как у вас есть AST, вам нужно будет написать обходчик дерева, который будет генерировать вашу программу как преобразованный исходный код. У вас может даже быть промежуточный обходчик деревьев, выполняющий преобразования дерева в зависимости от сложности ваших изменений.

Тем не менее, выполнение шага AST может быть не лучшим подходом.

Возможно, вы захотите взглянуть на «Шаблоны языкового проектирования» Терренса Парра (программисты-прагматики). В главе 11 рассматривается ваш тип программы.

Он упоминает инструмент ANTLRMorph, который может лучше подойти для вашей проблемы.

person Mike Cargal    schedule 22.03.2010

Самый простой способ - создать рерайтер. Настройте грамматику на переписывание, используйте шаблоны и создайте шаблон на месте. Затем используйте 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());
person Stefan    schedule 24.03.2010