3

我想在两种语言 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 生成编译器

4

1 回答 1

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

于 2012-12-29T11:26:39.500 回答