使用antlr生成另一种语言的源代码

时间:2016-04-01 13:57:20

标签: antlr

可以ANTLR用于解析一种语言的源代码并为另一种语言创建源代码吗?

因为到目前为止,看着所有听众,我看不到分离不同设施的方法 - 比如不同的statement块等 - 以便创建另一种语言设施

(program (programHeading program (identifier HelloWorld) ;) 
(block (procedureAndFunctionDeclarationPart (procedureOrFunctionDeclaration 
(procedureDeclaration procedure (identifier myprocedure) (formalParameterList ( 
(formalParameterSection (parameterGroup (identifierList (identifier x) , (identifier y)) : (typeIdentifier integer))) )) ; 
(block (compoundStatement begin (statements (statement (unlabelledStatement (simpleStatement (procedureStatement (identifier writeln) ( 
(parameterList (actualParameter (expression (simpleExpression (term (signedFactor (factor (variable (identifier x))))) + (term (signedFactor 
(factor (unsignedConstant (string ' : '))))) + (term (signedFactor (factor (variable (identifier y))))))))) ))))) ; 
(statement (unlabelledStatement (simpleStatement emptyStatement)))) end)))) ;) (compoundStatement begin (statements 
(statement (unlabelledStatement (simpleStatement (procedureStatement (identifier from))))) i := 1 to 10 do begin writeln ( i ) ;) end)) ; writeln ( 'Hello, World!' ) ; end .)

例如,我找不到一种方法来定义一个begin语句的开始位置和另一个end结束的语句。

我可以使用stack帮助程序做一些事情,但在这种情况下我可以逐行解析文件......

这是此代码的解析结果

program HelloWorld;

procedure myprocedure(x, y: integer);
begin
    writeln(x + ' : ' + y);
end;

begin
    from i := 1 to 10 do
    begin
        writeln(i);
    end;
    writeln('Hello, World!');
end.

也许我只是从错误的一面看或者不理解某事?

1 个答案:

答案 0 :(得分:2)

是的,ANTLR可用于将语言L1翻译为语言L2。但这并不像人们说的那么容易。

方法1:为L1构建解析器。遍历树以获取L1实例。在每个节点,使用ANTLR的字符串模板为L2翻译翻译的文本。

您会发现很难准确确定要生成什么,因为您在每个位置生成的内容取决于上下文(周围的声明,代码以及您决定翻译其他语言结构的方式)。考虑翻译:

 a+b

如果" a"你想要产生的东西可能会有很大差异。是一个数字,而不是" a"是一个字符串。你不能通过查看" a"来了解这一点。在那个表达中;你必须找到并解释" a" (例如,构建并查阅符号表)。

您会发现很难生成良好的代码,因为(字符串模板)输出是原始文本,您无法轻松解释该文本以优化它。 例如,想象一下你想翻译:

x = y + "abc"
x = x + "def"

一个简单的翻译者(语句陈述)可能会产生(作为纯文本):

set(x,concat(y,"abc"))
set(x,concat(x,"def"))

但理想情况下,优化翻译会产生:

set(x,concat(y,"abcdef"))

它只能通过检查输出并实现输出可以优化来实现。 (好的,在这个例子中,您可能首先优化输入,但语言差异可能会阻止这种情况。)

这个问题激发了......

方法2:为L1构建解析器。为L2构建解析器。走过L1树。在每个节点,使用ANTLR生成的L2节点构造器构建L2树。出于同样的原因,您将有同样的困难决定生成什么,但是现在您已经拥有了L2树,您至少可以考虑编写代码来遍历L2树并对其进行优化,例如,实现L2 -to-L2树转换,实现上述操作。

完成后,prettyprint the L2 tree。您可以使用ANTLR的字符串模板为L2节点提供帮助。

纯解析器翻译器的其他问题

两种方法都遇到像ANTLR这样的纯解析器生成器存在的一般问题:它们没有(简单)方法collect context information needed to implement a good translator。 [对于您选择的任何纯解析器生成器]都是如此。

您通常也需要其他支持,例如,漂亮的机器。如果你可以直接写下转换,例如,

,生活也会更方便
 rule translate_square(t: term): product -> product
      "  \t**2 " =>   " \t * \t "

而不是编写代码来在树上走来走去,以确定根是" power"运算符和正确的子节点是常数2.如果L1是一种非平凡的语言,你需要编写数百位代码来翻译L1中的所有结构,并且在程序上这样做很快就会很烦人。

因此,您可以使用任何解析器生成器来构建从一种语言到另一种语言的翻译器。这肯定比在没有解析器生成器的情况下构建转换器更好,你也可以这样做(许多真正的编译器是以这种方式构建的)。但是,虽然解析器生成器帮助了一些,但它几乎不会影响问题。你需要更多的机器,并且应该花费更多的精力而不仅仅是让解析器工作(很多真正的编译器付出这个代价来实现它们的结果)。