IDL compiler front-end library
Printer.cpp

This is an example of how to use CodeGen class.

// Printer.h Demonstrates the back-end code generator class.
#ifndef NIDLFE_EXAMPLE_PRINTER_H_
#define NIDLFE_EXAMPLE_PRINTER_H_
#include <AST/CodeGen.h>
#include <BE/IndentedOut.h>
class Printer : public AST::CodeGen
{
public:
Printer (const std::filesystem::path& filename) :
out_ (filename)
{}
protected:
virtual void end (const AST::Root& ast);
virtual void leaf (const AST::Include& item);
virtual void leaf (const AST::Native& item);
virtual void leaf (const AST::TypeDef& item);
virtual void leaf (const AST::Constant& item);
virtual void begin (const AST::ModuleItems& item);
virtual void end (const AST::ModuleItems& item);
virtual void leaf (const AST::InterfaceDecl& item);
virtual void begin (const AST::Interface& item);
virtual void end (const AST::Interface& item);
virtual void leaf (const AST::Operation& item);
virtual void leaf (const AST::Attribute& item);
virtual void leaf (const AST::Exception& item);
virtual void leaf (const AST::StructDecl& item);
virtual void leaf (const AST::Struct& item);
virtual void leaf (const AST::UnionDecl& item);
virtual void leaf (const AST::Union& item);
virtual void leaf (const AST::Enum& item);
virtual void leaf (const AST::ValueTypeDecl& item);
virtual void begin (const AST::ValueType& item);
virtual void end (const AST::ValueType& item);
virtual void leaf (const AST::StateMember& item);
virtual void leaf (const AST::ValueFactory& item);
virtual void leaf (const AST::ValueBox& item);
private:
void print_type (const AST::Type& t);
void print_interface_kind (const AST::InterfaceKind ik);
void print_op_base (const AST::OperationBase& item);
void print (const AST::Parameter& p);
void constructed_begin (const char* type, const AST::NamedItem& item);
void constructed (const AST::StructBase& item);
void complex_end ();
void print (const AST::Raises& raises);
private:
};
#endif
The attribute specification.
Definition: Attribute.h:39
Base for code generators. Abstract class.
Definition: CodeGen.h:75
virtual void leaf(const Include &)=0
#include
virtual void end(const Root &)
Definition: CodeGen.h:85
virtual void begin(const Root &)
Definition: CodeGen.h:80
const definition.
Definition: Constant.h:45
The enum declaration.
Definition: Enum.h:71
The exception declaration.
Definition: Exception.h:41
#include file.
Definition: Include.h:44
Interface forward declaration.
Definition: Interface.h:138
Interface definition.
Definition: Interface.h:95
The kind of interface.
Definition: Interface.h:40
The seqence of items in a module.
Definition: Module.h:73
A named AST item.
Definition: NamedItem.h:45
A 'native` type.
Definition: Native.h:41
An operation base.
Definition: OperationBase.h:40
An operation.
Definition: Operation.h:42
A parameter of an operation.
Definition: Parameter.h:41
Abstract Syntax Tree root.
Definition: Root.h:62
State member.
Definition: StateMember.h:40
The common base for Struct and Exception.
Definition: StructBase.h:41
The struct forward declaration.
Definition: Struct.h:44
The struct definition.
Definition: Struct.h:73
Type alias.
Definition: TypeDef.h:43
An IDL type.
Definition: Type.h:47
union forward declaration.
Definition: Union.h:45
union definition.
Definition: Union.h:75
Boxed value type.
Definition: ValueBox.h:43
Value type factory operation.
Definition: ValueFactory.h:41
Value type forward declaration.
Definition: ValueType.h:132
Value type definition.
Definition: ValueType.h:61
Output file stream with indentation.
Definition: IndentedOut.h:40
std::vector< const ItemWithId * > Raises
Definition: Exception.h:55
// Printer.cpp Demonstrates the back-end code generator class.
#include "Printer.h"
using namespace std;
using namespace AST;
#if defined (__GNUG__) || defined (__clang__)
#pragma GCC diagnostic ignored "-Wswitch"
#endif
void Printer::end (const Root& ast)
{
out_.close ();
}
void Printer::print_type (const Type& t)
{
static const char* const basic_types [(size_t)BasicType::ANY + 1] = {
"boolean",
"octet",
"char",
"wchar",
"unsigned short",
"unsigned long",
"unsigned longlong",
"short",
"long",
"long long",
"float",
"double",
"long double",
"Object",
"ValueBase",
"any"
};
switch (t.tkind ()) {
case Type::Kind::BASIC_TYPE:
out_ << basic_types [(size_t)t.basic_type ()];
break;
case Type::Kind::NAMED_TYPE:
out_ << t.named_type ().qualified_name ();
break;
case Type::Kind::STRING:
case Type::Kind::WSTRING:
out_ << (t.tkind () == Type::Kind::STRING ? "string" : "wstring");
if (t.string_bound ())
out_ << " <" << t.string_bound () << '>';
break;
case Type::Kind::FIXED:
out_ << "fixed";
if (t.fixed_digits ())
out_ << " <" << t.fixed_digits () << ", " << t.fixed_scale () << '>';
break;
case Type::Kind::SEQUENCE: {
const Sequence& seq = t.sequence ();
out_ << "sequence <";
print_type (seq);
if (seq.bound ())
out_ << ", " << seq.bound ();
out_ << '>';
} break;
case Type::Kind::ARRAY: {
const Array& arr = t.array ();
print_type (arr);
for (auto dim : arr.dimensions ()) {
out_ << '[' << dim << ']';
}
} break;
default:
assert (false);
}
}
void Printer::leaf (const Include& item)
{
if (item.system ())
out_ << "#include <" << item.file ().string () << ">\n";
else
out_ << "#include \"" << item.file ().string () << "\"\n";
}
void Printer::leaf (const Native& item)
{
out_ << "native " << item.name () << ";\n";
}
void Printer::leaf (const TypeDef& item)
{
out_ << "typedef ";
print_type (item);
out_ << ' ' << item.name () << ";\n";
}
void Printer::leaf (const Constant& item)
{
out_ << "const ";
print_type (item);
out_ << ' ' << item.name ();
if (item.vtype () != Variant::VT::EMPTY) {
out_ << " = ";
if (item.vtype () == Variant::VT::WSTRING)
out_ << 'L';
out_ << item.to_string ();
if (item.vtype () == Variant::VT::FIXED)
out_ << 'D';
}
out_ <<";\n";
}
void Printer::begin (const ModuleItems& item)
{
out_.empty_line ();
out_ << "module " << item.name () << " {\n\n";
}
void Printer::end (const ModuleItems& item)
{
out_ << "};\n\n";
}
void Printer::print_interface_kind (const InterfaceKind ik)
{
switch (ik.interface_kind ()) {
case InterfaceKind::ABSTRACT:
out_ << "abstract ";
break;
case InterfaceKind::LOCAL:
out_ << "local ";
break;
case InterfaceKind::PSEUDO:
out_ << "pseudo ";
break;
}
}
void Printer::leaf (const InterfaceDecl& item)
{
print_interface_kind (item);
out_ << "interface " << item.name () << ";\n";
}
void Printer::begin (const Interface& item)
{
out_.empty_line ();
print_interface_kind (item);
out_ << "interface " << item.name ();
if (!item.bases ().empty ()) {
out_ << " :\n";
out_.indent ();
auto base = item.bases ().begin ();
out_ << (*base)->name ();
++base;
for (; base != item.bases ().end (); ++base) {
out_ << ",\n";
out_ << (*base)->name ();
}
out_.unindent ();
}
out_ << '\n';
out_ << "{\n";
out_.indent ();
}
void Printer::end (const Interface& item)
{
complex_end ();
}
void Printer::constructed_begin (const char* type, const NamedItem& item)
{
out_.empty_line ();
out_ << type << item.name () << " {\n";
out_.indent ();
}
void Printer::complex_end ()
{
out_.unindent ();
out_ << "};\n\n";
}
void Printer::leaf (const Operation& item)
{
if (item.oneway ())
out_ << "oneway void";
else if (item.tkind () == Type::Kind::VOID)
out_ << "void";
else
print_type (item);
print_op_base (item);
if (!item.context ().empty ()) {
out_ << " context (\"";
auto s = item.context ().begin ();
out_ << *s;
for (++s; s != item.context ().end (); ++s) {
out_ << "\", \"" << *s;
}
out_ << "\")";
}
out_ << ";\n";
}
void Printer::print_op_base (const OperationBase& item)
{
out_ << ' ' << item.name () << " (";
if (!item.empty ()) {
auto param = item.begin ();
print (**param);
for (++param; param != item.end (); ++param) {
out_ << ", ";
print (**param);
}
}
out_ << ')';
if (!item.raises ().empty ()) {
out_ << " raises ";
print (item.raises ());
}
}
void Printer::print (const Raises& raises)
{
auto ex = raises.begin ();
out_ << '(' << (*ex)->name ();
for (++ex; ex != raises.end (); ++ex) {
out_ << ", " << (*ex)->name ();
}
out_ << ')';
}
void Printer::print (const Parameter& p)
{
const char* att = "in";
switch (p.attribute ()) {
case Parameter::Attribute::OUT:
att = "out";
break;
case Parameter::Attribute::INOUT:
att = "inout";
break;
}
out_ << att << ' ';
print_type (p);
out_ << ' ' << p.name ();
}
void Printer::leaf (const Attribute& item)
{
if (item.readonly ()) {
out_ << "readonly attribute ";
print_type (item);
out_ << ' ' << item.name ();
if (!item.getraises ().empty ()) {
out_ << " raises ";
print (item.getraises ());
}
} else {
out_ << "attribute ";
print_type (item);
out_ << ' ' << item.name ();
if (!item.getraises ().empty ()) {
out_ << " getraises ";
print (item.getraises ());
}
if (!item.setraises ().empty ()) {
out_ << " setraises ";
print (item.setraises ());
}
}
out_ << ";\n";
}
void Printer::constructed (const AST::StructBase& item)
{
constructed_begin (item.kind () == Item::Kind::EXCEPTION ? "exception " : "struct ", item);
for (auto m : item) {
print_type (*m);
out_ << ' ' << m->name () << ";\n";
}
complex_end ();
}
void Printer::leaf (const Exception& item)
{
constructed (item);
}
void Printer::leaf (const StructDecl& item)
{
out_ << "struct " << item.name () << ";\n";
}
void Printer::leaf (const Struct& item)
{
constructed (item);
}
void Printer::leaf (const UnionDecl& item)
{
out_ << "union " << item.name () << ";\n";
}
void Printer::leaf (const Union& item)
{
out_ << "union " << item.name () << " switch (";
print_type (item.discriminator_type ());
out_ << ") {\n";
out_.indent ();
for (auto el : item) {
if (!el->is_default ()) {
for (const auto& label : el->labels ()) {
out_ << "case " << label.to_string () << ":\n";
}
} else
out_ << "default:\n";
out_.indent ();
print_type (*el);
out_ << ' ' << el->name () << ";\n";
out_.unindent ();
}
complex_end ();
}
void Printer::leaf (const Enum& item)
{
constructed_begin ("enum ", item);
auto it = item.begin ();
out_ << (*it)->name ();
for (++it; it != item.end (); ++it) {
out_ << ",\n";
out_ << (*it)->name ();
}
out_ << endl;
complex_end ();
}
void Printer::leaf (const ValueTypeDecl& item)
{
if (item.is_abstract ())
out_ << "abstract ";
out_ << "valuetype " << item.name () << ";\n";
}
void Printer::begin (const ValueType& item)
{
switch (item.modifier ()) {
case ValueType::Modifier::ABSTRACT:
out_ << "abstract ";
break;
case ValueType::Modifier::CUSTOM:
out_ << "custom ";
break;
}
out_ << "valuetype " << item.name ();
if (!item.bases ().empty ()) {
out_ << ":\n";
out_.indent ();
auto base = item.bases ().begin ();
out_ << (*base)->name ();
++base;
for (; base != item.bases ().end (); ++base) {
out_ << ",\n";
out_ << (*base)->name ();
}
out_.unindent ();
}
if (!item.supports ().empty ()) {
out_ << "supports\n";
out_.indent ();
auto base = item.supports ().begin ();
if (item.modifier () == ValueType::Modifier::TRUNCATABLE)
out_ << "truncatable ";
out_ << (*base)->name ();
++base;
for (; base != item.supports ().end (); ++base) {
out_ << ",\n";
out_ << (*base)->name ();
}
out_.unindent ();
}
out_ << '\n';
out_ << "{\n";
out_.indent ();
}
void Printer::end (const ValueType& item)
{
complex_end ();
}
void Printer::leaf (const StateMember& item)
{
if (item.is_public ())
out_ << "public ";
else
out_ << "private ";
print_type (item);
out_ << ' ' << item.name () << ";\n";
}
void Printer::leaf (const ValueFactory& item)
{
out_ << "factory ";
print_op_base (item);
out_ << ";\n";
}
void Printer::leaf (const ValueBox& item)
{
out_ << "valuetype " << item.name () << ' ';
print_type (item);
out_ << ";\n";
}
Abstract Syntax Tree namespace.
Definition: Array.h:34