Capella -- AST generation utility

capella is a utility program that reads a definition file and generates data structure in C++ source that defines the AST.

It was made on the assumption that it will be used with caper, but it doesn't depend on caper. It depends on STL (and boost on specific option).

Please remember that it's a extra stuff of caper (but bug reports are welcome).

The Input File

The input file is in the following form:

atom = Identifier;

class-header = {
}

class-footer = {
    template < class Visitor >
    void accept( Visitor& visitor )
    {
        visitor.visit( *this );
    }
}

type Module = Declarations(declarations);
type Declarations = Declaration*(elements);
type Declaration = AtomDef | TypeDef;
type AtomDef = Atoms(atoms);
type Atoms = Identifier*(elements);
type TypeDef = Identifier(name), TypeDefRight(right);
type TypeDefRight = Scalor | List | Variant;
type Scalor = Identifier(stype);
type List = Identifier(etype);
type Variant = Identifier*(choises);

Let me explain step by step.


atom = Identifier;

Defines atom (an undivideable item). That is data etc. from scanner.


class-header = {
	...
}

class-footer = {
	...
}

Defines a text inserted at every heads/tails of all the AST definition structures to be outputted. You can include comments etc. in it.


type Module = Declarations(declarations);
type Declarations = Declaration*(elements);
type Declaration = AtomDef | TypeDef;
type AtomDef = Atoms(atoms);
type Atoms = Identifier*(elements);
type TypeDef = Identifier(name), TypeDefRight(right);
type TypeDefRight = Scalor | List | Variant;
type Scalor = Identifier(stype);
type List = Identifier(etype);
type Variant = Identifier*(choises);

Defines data that represents a tree structure of AST. See the next section.

AST definition

You can define an AST definition by a "type" declaration. There are two kinds of type declaration.

Field declaration

By declaration of [ type structure_name = field_type(field_name) ] the field of target structure will be defined.


For example:

type Module = Declarations(declarations);

This declaration outputs the following output (details are omitted).

struct Module {
    Declarations* declarations;
};

If it have multiple fields, then describe code as follows:

type TypeDef = Identifier(name), TypeDefRight(right);

The output is:

struct TypeDef {
    Identifier* name;
    TypeDefRight* right;
};

If you want each field to become a container (contains type fields of same type), then please append "*" after type name. It'll be a container.

type Atoms = Identifier*(elements);

The output is:

struct Atoms {
    std::vector < Identifier* > elements;
};

Polymorphous Declarations

By declaration of [ type base_struct_name = derived_struct_name_1 1 | derived_struct_name_2; ] , the derived hierarchy of structures will be generated.


For example, if there are declarations like:

type AtomDef = Atoms(atoms);
type TypeDef = Identifier(name), TypeDefRight(right);

and if you convert it, then it outputs:

struct AtomDef {
    Atoms* atoms;
};
struct TypeDef {
    Identifier* name;
    TypeDefRight* right;
};

If you add the following code in addition:

type Declaration = AtomDef | TypeDef;

Then common base class "Declaration" of AtomDef/TypeDef will be added and it outputs:

struct Declaration {};
struct AtomDef : public Declaration {
    Atoms* atoms;
};
struct TypeDef : public Declaration {
    Identifier* name;
    TypeDefRight* right;
};

Options

We didn't debug capella enough. Don't trust it except default.

-c++
Generates normal C++ source (default).
-c++-shared
Generates source using boost::shared_ptr.
-c++-variant
Generates source using boost::variant.
-c++-stub
-c++-shared-stub
-c++-variant-stub
dot
Outputs derived graph in the dot format of graphviz.

How To Port

If you want to port capella into other languages, the porting might become very troublesome because it uses topological sort of boost.graph.

Conclusion

In the end, it is not necessarily true that good source will be generated for all the user on default. So, you might rewrite the generater code (arround capella_generate_cpp). I don't think it is so difficult to rewrite it.