我想在两种语言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++生成的解析器。

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

最佳答案

在最一般的情况下,您必须将语法的每个可能部分从LANG1转换为适合LANG2的内容,或者必须深入研究两种语言的最简单可能的原语,例如汇编语言或组合语言。这是浪费时间,并且不是很有趣。

但是,如果语法相同或具有很多共同点,则可能只需要解析两个语法的同一个树,并拥有可以将标准化树转换为LANG1或LANG1的输出函数即可。 LANG2来源(与一般情况基本相同,但捷径更多)。

编辑:由于我刚刚重读了您的问题,意识到您只想翻译一种方式,所以您只需要担心制作树形套装LANG1的形式,而只需为LANG2提供翻译功能即可。但是我希望我的例子仍然有帮助。

树结构示例:

这是两种产生相同的极其简单的AST的不同ANTLR语法:

语法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转换回您选择的语言。

10-08 09:08