0

I want to implement a new language, and I would like to do it in C, with the famous flex+yacc combination. Well, the thing is, writing the whole AST code is very time consuming. Is there a tool that automatically generate the constructors for the structs?

I would like something with the following behavior:

input:

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;

output:

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)
{ ... }

Thank you!

2
  • Many (many many) years ago I tried a tool that used a fileformat similar to lex/yacc, and was supposed to be used together with those tools, whose purpose it was to help create and traverse an AST. Unfortunately I can't remember the name, and I doubt that it will be easy to find again. But at least the exists (or has existed) such tools. Commented Feb 16, 2012 at 15:59
  • If you use emacs or visual studio you can rely on snippets to help you gain a lot of time
    – Eregrith
    Commented Feb 16, 2012 at 16:02

2 Answers 2

2

You might be able to get something working with clever use of pre-processor macros.

First the header file:

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

AST_NODE(TokenType1)
AST_NODE(TokenType2)

Then the source file:

#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"

If you include the "ast.h" file in any other file, you will have two structures: AST_TokenType1 and AST_TokenType2.

The source file described above creates two functions: AST_TokenType1_new() and AST_TokenType2_new() which allocate the correct structure and sets the structure member kind.

1
  • Thanks for the code, I tried to use macros, but they won't give me all the "power" I need. I have just answered my question with something I coded today.
    – Victor
    Commented Feb 17, 2012 at 2:30
1

Well, since there was no tool I decided to code something this afternoon. I started something that looks like a nice project, and I would like to continue it.

I coded a somewhat simple (just a bunch of nested folds inside the IO monad) code generator in Haskell, based in builtin haskell types.

The AST type declaration:

http://pastebin.com/gF9xF1vf

The C code generator, based on the AST declaration:

http://pastebin.com/83Z4GH38

And the generated result:

http://pastebin.com/jJPgm5PE

How can somebody not love Haskell? :)

ps: I coded this because the project I'm currently working on is going to suffer a huge amount of changes in the near future, and those changes will invalidade the AST, thus forcing me to code another AST module... Now I can do it quite fast!

Thanks for the answer though.

2
  • I never really had time to learn Haskell (or similar languages) but it seems to me that functional languages in general are very good for making compilers. Commented Feb 17, 2012 at 6:19
  • @JoachimPileborg, not quite true. Some very simple tasks such as global accumulators can present a major headache in functional programming, but for simple or anything that traverses through complex data structures it is quite good!
    – Victor
    Commented Feb 17, 2012 at 10:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.