【问题标题】:Transcompiling to another language [closed]转换为另一种语言 [关闭]
【发布时间】:2015-03-13 23:35:15
【问题描述】:

可以对代码进行反编译的典型方法是什么?目前,我正在编写一种简单的编程语言,它的处理方式是递归的。循环遍历一个节点列表,并且说当前节点是一个变量节点,它会调用一个emit_variable_node 函数,它会在字面上附加一些代码到一个字符串,例如:

以下代码是伪代码,我正在用 C 编写我的项目,并编译为 C。

char *file_contents;

void emit_variable_node(VariableNode *var) {
    // I know += doesn't work on strings, just pretend it does.
    file_contents += var.getType();
    file_contents += " "; // a space
    file_contents += var.getName();
    // etc
}

我还假设我们给出的代码已经过语义分析,并且是正确的。然后将 file_contents 字符串存储到一个临时文件中,该文件在被 C 编译器编译后被删除。

这是一种不好的做法,还是有更好、更清洁的方法来做到这一点?

【问题讨论】:

  • 对我来说似乎很好。试一试,看看完成后的效果:) 根据转换的复杂性,您可能会发现某种模板库很有用。
  • 啊,已经部分实现了!我只是想在进一步研究它之前检查它是否是一个好的实现:)
  • 嗯,遗憾的是,我以前从未做过这样的事情,但对于字符串解析,我会使用 perl 或 python 之类的语言......但如果 C++ 有效,为什么不呢。有一些工具可能会有所帮助,例如 Bison、Flex 或 LLVM
  • @feliks:由于 C 缺乏方便的字符串处理函数,而且我习惯使用 printf 格式,我倾向于使用自己编写的一个小库。恕我直言,其中大部分是concatf,如果需要,您可以从this little bison example 中提取。
  • 相关链接:en.wikipedia.org/wiki/Source-to-source_compiler(对于那些不确定“转编译”是什么意思的人)。

标签: c compiler-construction


【解决方案1】:

您可以通过任何您喜欢的方式编写解析器,并在解析时生成代码,无需 AST 节点(“语法定向翻译”)。这通常会产生非常糟糕的代码,因为代码生成器没有机会考虑上下文来生成更好的代码。

您可以构建一个解析器,该解析器首先构建抽象语法树 (AST),然后作为第二遍遍历树生成代码,而不查看任何相邻节点。这只是前面带有 AST 的答案。 这是一个 stunningly bad example of unoptimized transpiler output 做这样的事情。

更好的是从 AST 生成代码,其中每个 AST 节点本地代码生成器检查其邻居,以决定做什么。这将为您提供更好的代码。

更好的解决方案是效仿传统编译器,为您的语言构建良好的前端,包括符号表以及控制和数据流分析。然后,您可以使用它来生成更好的代码。

关于实际代码生成:是的,您可以打印文本字符串。字符串模板更方便一些,但它们只是打印文本字符串的一种奇特方式,因此它们不会增加任何功能或提高生成的代码质量。

更好的解决方案是将源语言中的 AST 转换为目标语言中的 AST,包括所有本地检查以及使用来自符号表和流分析的信息。这样做的好处是,通过在目标语言中生成 AST,您现在可以在目标语言中应用源语言中无法实现的优化。 [真正的编译器会做这样的事情,但是他们使用的术语是“将 AST 转换为 IR(内部表示)”并且他们对 IR 进行优化。] 在目标 AST 上的所有优化都完成之后,你必须漂亮地打印最终的 AST... 使用类似字符串模板的东西。

大多数人没有精力从头开始构建一个好的转换器。所以他们做了一些 hacky 的事情,比如第一个建议(只是说)。但是,如果您想为将代码从一种语言转换为另一种语言打下非常好的基础,请查看我们的DMS Software Reengineering Toolkit。 DMS 具有多种语言的解析器,可以实现自定义语言的解析器,自动构建 AST,为Life After Parsing 提供大量支持,例如构建符号表和流分析,进行 AST 到 AST 的转换,并拥有漂亮的打印机。 DMS is designed to be a platform to support this kind of task。这意味着您可以专注于构建任务的高质量翻译部分,而不是尝试构建所有有用的基础架构。

【讨论】:

  • 这太完美了,谢谢!有点无关紧要,Nim 编译为 C,他们使用什么方法来做到这一点?
  • @feliks:……好吧,现在我知道了。 GIYF。请参阅有关 Nim 编译器的文档:nim-lang.org/intern.html 似乎它们解析为 AST。因为 Nim 是“全局”编译的,他们首先为整个程序构建树,在读取所有内容之后对程序进行名称解析,然后显然进行大量树重写.从字里行间看,似乎有一些非常复杂的算法涉及分析和代码生成(当然与我在“LifeAfterParsing”中的评论一致)。特别是,Nim 似乎没有一个简单的代码生成器。
  • @feliks: ... 知道开发它的人似乎已经为此工作了 ~~ 10 年,而且 Github 足迹表明他有 100 多个帮助开发人员,这很有帮助。这不是一个“hacky”解决方案。
  • 哦,哇,为我研究这个而欢呼。我将对他们的编译器进行一些研究,我相信我可以从中学到很多东西。再次感谢:0
  • 好吧,谢谢你激起了我的好奇心。即使是老屁仍然“想知道”。我怀疑它是一个“小”研究,它是一个相当大的程序。(大多数 [trans] 编译器都是)。我出于兴趣而研究它,但仍然花了一两个小时得出我所做的结论,我查看了零源代码:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-27
  • 1970-01-01
  • 2015-10-31
相关资源
最近更新 更多