【问题标题】:Generate C struct constructors automatically?自动生成 C 结构构造函数?
【发布时间】:2012-03-08 00:54:02
【问题描述】:

我想实现一门新语言,我想用 C 语言来实现,使用著名的 flex+yacc 组合。好吧,问题是,编写整个 AST 代码非常耗时。有没有工具可以自动生成结构体的构造函数?

我想要具有以下行为的东西:

输入:

enum AgentKind {A_KIND1, A_KIND2};
typedef struct Agent_st
{
    enum AgentKind kind;
    union {
        struct {int a, b, c} k1;
        struct {int a, GList* rest} k2;
    } u;
} Agent;

输出:

Agent*    agent_A_KIND1_new(int a, b, c)
{
    Agent* a = (Agent*)malloc(sizeof(Agent));
    a->kind = A_KIND1;
    a->k1.a = a;
    ...
    ...
    return a;
}

Agent*    agent_A_KIND2_new(int a, GList* rest)
{ ... }

谢谢!

【问题讨论】:

  • 很多(很多很多)年前,我尝试了一个使用类似于 lex/yacc 的文件格式的工具,并且应该与这些工具一起使用,其目的是帮助创建和遍历AST。不幸的是我不记得这个名字了,我怀疑它是否会很容易再次找到。但至少存在(或已经存在)这样的工具。
  • 如果你使用 emacs 或 Visual Studio 可以依靠 sn-ps 帮助你获得大量时间

标签: c compiler-construction constructor code-generation abstract-syntax-tree


【解决方案1】:

您也许可以通过巧妙地使用预处理器宏来获得一些工作。

首先是头文件:

#ifndef AST_NODE
# define AST_NODE(token) \
    struct AST_ ## token \
    {                    \
        int kind;        \
    };
#endif

AST_NODE(TokenType1)
AST_NODE(TokenType2)

然后是源文件:

#define AST_NODE(token)                                        \
struct AST_ ## token *AST_ ## token ## _new()                  \
{                                                              \
    struct AST_ ## token *node = malloc(sizeof(AST_ ## token); \
    node->kind = token;                                        \
    return node;                                               \
}

#include "ast.h"

如果您在任何其他文件中包含“ast.h”文件,您将有两个结构:AST_TokenType1AST_TokenType2

上述源文件创建了两个函数:AST_TokenType1_new()AST_TokenType2_new(),它们分配正确的结构并设置结构成员 kind

【讨论】:

  • 感谢您的代码,我尝试使用宏,但它们无法为我提供所需的所有“力量”。我刚刚用我今天编写的代码回答了我的问题。
【解决方案2】:

好吧,由于没有工具,我决定今天下午编写一些代码。 我开始了一个看起来不错的项目,我想继续它。

我在 Haskell 中编写了一个有点简单(只是 IO monad 中的一堆嵌套折叠)的代码生成器,它基于内置的 haskell 类型。

AST 类型声明:

http://pastebin.com/gF9xF1vf

C 代码生成器,基于 AST 声明:

http://pastebin.com/83Z4GH38

以及生成的结果:

http://pastebin.com/jJPgm5PE

怎么会有人不喜欢 Haskell? :)

ps:我编写这个代码是因为我目前正在从事的项目在不久的将来会发生大量变化,这些变化会使 AST 失效,从而迫使我编写另一个 AST 模块...... 现在我可以很快做到了!

谢谢你的回答。

【讨论】:

  • 我从来没有真正有时间学习 Haskell(或类似语言),但在我看来,函数式语言通常非常适合制作编译器。
  • @JoachimPileborg,不太正确。一些非常简单的任务,例如全局累加器,在函数式编程中可能会让人头疼,但对于简单的或遍历复杂数据结构的任何事情来说,它是相当不错的!
猜你喜欢
  • 2016-12-07
  • 1970-01-01
  • 2016-12-16
  • 2013-01-23
  • 2011-08-21
  • 2019-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多