如何使用两个单独的语法实现计算机语言翻译器

时间:2012-12-29 10:41:38

标签: c++ compiler-construction antlr antlr3 translate

我想在两种语言LANG1和LANG2之间创建一个计算机语言翻译器。更具体地说,我想将用LANG1编写的代码翻译成LANG2中的源代码。

我有LANG1和LANG2的BNF语法。

LANG1是我自己写的一个小型DSL,基本上是一个“更容易”的LANG2版本。

我希望能够使用LANG1编写的输入语句在LANG2中生成语句。

我正在为LANG1编译编译器,但我不知道下一步该做什么(为了将LANG1语句翻译成LANG2语句)。

我对所涉及步骤的理解如下:

1. BNF for my DSL (LANG1)                                  DONE
2. Reverse engineered the BNF for LANG2                    DONE
3. Learning how to generate a compiler for LANG1           TODO
4. Translate LANG1 statements to LANG2 statements          ???

从LANG1语句生成LANG2语句涉及哪些步骤?

我的代码库是用C ++编写的,所以我可以使用C或C ++生成的Parser。

PS:我将使用ANTLR3为LANG1生成编译器

1 个答案:

答案 0 :(得分:4)

在最常见的情况下,您必须将语法的每个可能部分从LANG1翻译成适合LANG2的部分,或者您必须愚蠢地使用两种语言的最简单的原语,如汇编或组合器。这有点费时而且不是很有趣。

但是,如果语法是等价的或共享很多共同点,那么你可能只需要解析两个语法的同一个树并具有可以获取标准化树并将其转换回来的输出函数。进入LANG1或LANG2源(这与一般情况大致相同,但需要更多的捷径)。

编辑:因为我刚刚重读了你的问题意识到你只想翻译一种方式,你只需要担心树的形式适合LANG1并且只有LANG2的翻译功能。但我希望我的例子无论如何都有用。

示例树构造:

这是两个不同的ANTLR语法,它们产生同样极其简单的AST:

语法1

第一个是表达加法的标准方式:

grammar simpleAdd;

options {output=AST;}

tokens {
    PLUS = '+';
}

expression : addition EOF!;
addition   : NUMBER (PLUS NUMBER)+ -> ^(PLUS NUMBER*);

NUMBER     :'0'..'9'+;
WHITESPACE : ( '\t' | ' ' | '\r' | '\n')+    { $channel = HIDDEN; } ;

这将接受两个或更多整数,并生成一个带有PLUS节点的树,并将列表中的所有数字加在一起。如,

1 + 1 + 2 + 3 + 5

语法2

第二种语法形式不太优雅:

grammar horribleAdd;

options {output=AST;}

tokens {
    PLUS = '+';
    PLUS_FUNC = 'plus';
    COMMA = ',';
    LEFT_PARENS ='(';
    RIGHT_PARENS=')';
} 

expression : addition EOF!;
addition   : PLUS_FUNC LEFT_PARENS NUMBER (COMMA NUMBER)+ RIGHT_PARENS -> ^(PLUS NUMBER*);

NUMBER     :'0'..'9'+;
WHITESPACE : ( '\t' | ' ' | '\r' | '\n')+    { $channel = HIDDEN; } ;

这个语法期望给一个函数赋予数字(是的,我知道函数不是真的像这样工作,我只是想尽可能清楚地保持这个例子)。如,

plus(1, 1, 2, 3, 5)

它生成与第一个语法完全相同的树(一个PLUS节点,数字为子节点)。

现在您不必担心您的指令来自哪种语言,您可以以您喜欢的任何形式输出它。您需要做的就是编写一个可以将此AST转换回您选择的语言的函数。