Synopsis 0.5 - User Manual

New output format

Making a new output formatter for Synopsis is easy. There are two structural approaches: create a new formatter and put it in the Formatter directory (for now, you cannot specify a path with the formatter), or create a stand-alone formatter that reads an AST file. The former is more integrated, but the latter doesn't require you to put the file in the Synopsis/Formatter directory.

Most formatters follow the pattern of taking the AST, and visiting its nodes in turn while writing output. This is done via the Visitor pattern, which basically means that you create an object with one method for each type of AST node, such as classes, modules, operations (methods), typedefs, etc. You may find it easiest to take an existing formatter with similar output structure to what you want, and modify the output to fit your particular format.

One point to note is the way that Type objects are formatted. Type objects (defined in Synopsis/Core/Type.py) are used to store things like function parameters, return types, variable types, typedef types, and class parents. (A Type is used for class parents since the base class might be a parameterized instance of a class template). Types have their own class and node hierarchy, though it is simpler than the AST hierarchy. Consider the type "const char*" - this is represented as a "Modifier" Type containing the "const" and "*", which points to a "Base" Type for the "char". The Base type could instead be a Declared type, if the complete type was "const string*", for example.

The best way to figure out how a program is represented as an AST is to use the DUMP formatter. I've had to use it so many times myself that I lost count years ago! The DUMP formatter will show both the AST heirarchy, and also how any types you are using are represented.

The existing formatters generally format types by implementing a Visitor for the Type hierarchy. Each Type object has an "accept(self, visitor)" method which simply calls the appropriate method of the visitor object. For example, the Modifier Type's accept method calls "visitor.visitModifier(self)".

The formatters have a series of "visit" methods, one for each Type class, each of which helps build a label string. In the above Modifier example, the visitModifier method recursively formats the aliased type (e.g: a Base Type if it was a char or a Declared Type if it was a string), then sticks a "const" on the front and a "*" on the end of the label string.

The Synopsis Reference Manual contains graphs and class details for the AST and Type hierarchies.