我想在两种语言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转换回您选择的语言。