【问题标题】:How to Write a Source to Source Compiler API如何编写源代码到源代码编译器 API
【发布时间】:2015-04-27 00:11:06
【问题描述】:

我正在对源到源编译进行一些研究,但现在我对源到源编译有所了解。我想知道这些源到源编译器是否有任何 API 示例。

我的意思是将一种编程语言的源代码传递给另一种编译器进行编译的接口描述符?如果是的话,请你给我指出这些例子,或者你能给我一些提示(只是纯粹的解释),让我写一篇仍在研究中的文章。

哦,我应该注意我已经研究了几天,我遇到了诸如 ROSE、DMS 和 LLVM 之类的东西。如前所述,它纯粹是研究,所以我不知道我知道我不会使用 ROSE 的最佳方法是什么,因为它仅适用于 C/C++。 LLVMs 似乎很有希望,但我是 LLVM 的新手。哦,我的目标是为 4 种语言支持创建一个转译器(这可行吗)。这就是为什么我只需要专家建议:)

【问题讨论】:

  • 听起来您需要先学习编译器构造 101。你肯定找不到它的 API。您首先需要的是源语言和目标语言的语法。这方面有商业产品。不是一件容易的事。
  • 所以真的我要使用一些在线课程谢谢@EJP
  • 如果您对转换由GCC 编译的代码(例如,C、C++、Fortran、Ada 等)感兴趣,您可以使用MELT 来实现此目的。但是您需要了解 GCC 的内部表示。
  • LLVM 不会进行源到源的翻译;它旨在编译为二进制指令集。 Clang 似乎已从一些源代码更改中使用,尽管不是跨语言 AFAIK。如果您将自己限制在构建 AST、遍历 AST 和吐出代码(纯语法定向翻译),尽管您必须编写自己的解析器,但您也许可以使用 Clang。但是你不需要 Clang 来做这个;您所需要的只是来自解析器的 AST。
  • @EJP:是的,实际上,您可以找到这样的 API。 DMS 提供其中之一作为其众多方面之一。

标签: api compiler-construction code-translation


【解决方案1】:

是的,您可以使用程序 API 进行源到源的翻译。这些在抽象上非常简单:定义一个核心数据结构来表示 AST 节点,然后定义 API 来“将文件解析为 AST”、“访问树节点”、“检查树节点”、“修改树节点”、“吐出”文本”。它们在具体方面变得混乱,特别是如果 API 特定于被翻译的语言;该语言的太多细节被卷入 API。虽然传统,但这确实是定义源到源翻译器的一种相当笨拙的方法,因为您必须编写大量程序代码来调用 API 来进行翻译。

您可以改为使用program transformation system (PTS) 来定义它们,使用基于表面语法的源到源转换;这些是使用您的待编译语言和目标语言的符号编写的模式,形式为“如果您看到 this,则将其替换为 that",对语法树而不是文本字符串进行操作。这意味着您只需盯着它们就可以检查变换。你的程序员同事也可以。

这样的翻译规则可能如下所示:

 rule tranlate_add_to(t: access_path, u: access_path):COBOL -> Java
      " add \t to \u "
 ->   "  \object_for\(\u\).\u += \object_for\(\t\).\t; ";

左侧“将 \t 添加到 \u”,指定 COBOL 片段 (this) 将替换为右侧“\object_for...”,表示对应的 Java代码(那个)。此规则使用辅助函数“object_for”来决定将在目标 Java 程序中的何处放置源 COBOL 程序中的全局变量。 (如果您要将 Java 转换为 COBOL,则无法避免编写这样的函数。您可以争论它的复杂程度)。在实践中,这种规则的工作方式是构造每一方的模式 AST,然后将模式与解析的 AST 进行匹配;匹配导致相应的子树被拼接到找到匹配的位置。 (所有这些低级别的树匹配和拼接都必须在程序上完成……但其他人已经在 PTS 中实现了)。

根据我们的经验,您需要one to two thousand such rules to translate one language to another。过多的规则来自源语言的语言语法结构的组合(以及它们可能根据类型的不同解释;当 a 是 int 与 a 是字符串时,“a+b”意味着不同的东西)和目标语言机会。这种重写的一个好处是可以构建一个更简单的基础翻译,并将目标语言的额外重写应用到自身,以清理和优化翻译结果。

许多 PTS 纯粹基于源到源表面语法重写。我们发现,将 PTS 和过程 API 结合起来,并使其可以在它们之间进行分离是非常好的工具:您可以在方便的地方使用重写,而在它们不能很好工作的地方使用过程 API(“object_for”上面建议的函数更容易编码为过程)。

查看更多详细信息,了解我们的DMS Software Reengineering Toolkit 如何以与语言无关(嗯,参数化)的方式编码此类转换规则(上面是 DMS 样式的代码)。 DMS 根据 OP 的要求提供了一个“纯”过程 API,具有大约 400 个函数,但 DMS 鼓励其用户大量依赖于重写,并且只编写尽可能少的代码,而不是过程 API。以这种方式构建您的“4 种语言支持”将是“直截了当”(至少与实际一样直截了当)。

即使有很多优秀的技术机器作为基础,也不要低估构建此类翻译器的工作量。语言往往是复杂的野兽,它们的翻译更是如此。而且你必须决定是要truly crummy translation还是好的。

【讨论】:

  • 好的,感谢您的动力,我有一个 5 人的团队,所以我只需要转发此消息并开始行动,再次感谢
  • @Redcode:你最终做了什么/使用了什么?
【解决方案2】:

我一直在使用 ROSE 编译器框架来编写源代码到源代码的翻译器。 ROSE 可以解析它支持的语言并从中创建 AST。它提供了不同的 API(在 SageInterface 中找到)来对 AST 执行转换和分析。转换后,您可以对转换后的 AST 进行反解析以生成目标源代码。

如果 ROSE 不支持解析您的输入语言,您可以编写自己的解析器,同时利用 ROSE 的 SageBuilder API 构建 AST。如果您的目标语言是 ROSE 支持的语言之一,那么您可以依靠 ROSE 的 unparser 来获取目标代码。但是如果 ROSE 不支持你的目标语言,那么你也可以使用 ROSE 提供的不同的 AST 遍历机制编写自己的 unparser。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-26
    • 2021-02-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多