--- /dev/null
+#include "enum.h"
+#include <msp/io/print.h>
+
+using namespace std;
+using namespace Msp;
+
+Enum::Enum(const string &n):
+ name(n)
+{ }
+
+void Enum::define_type(IO::Base &out) const
+{
+ IO::print(out, "enum class %s\n{\n", name);
+ for(auto i=values.begin();; )
+ {
+ IO::print(out, "\t%s", i->name);
+ if(i->value)
+ IO::print(out, " = %d", i->value.value());
+ ++i;
+ if(i==values.end())
+ break;
+ IO::print(out, ",\n");
+ }
+ IO::print(out, "\n};\n");
+}
+
+void Enum::declare_conversions(IO::Base &out) const
+{
+ IO::print(out, "void operator>>(const Msp::LexicalConverter &, %s &);\n", name);
+ IO::print(out, "void operator<<(Msp::LexicalConverter &, %s);\n", name);
+}
+
+void Enum::define_conversions(IO::Base &out) const
+{
+ IO::print(out, "void operator>>(const Msp::LexicalConverter &conv, %s &_e)\n{\n", name);
+ IO::print(out, "\tconst std::string &str = conv.get();\n\t");
+ for(auto i=values.begin(); i!=values.end(); ++i)
+ {
+ if(i!=values.begin())
+ IO::print(out, "else ");
+ IO::print(out, "if(str==\"%s\")\n\t\t_e = %s::%s;\n\t", i->name, name, i->name);
+ }
+ IO::print(out, "else\n\t\tthrow Msp::lexical_error(Msp::format(\"conversion of '%%s' to %s\", str));\n", name);
+ IO::print(out, "}\n");
+
+ IO::print(out, "\nvoid operator<<(Msp::LexicalConverter &conv, %s _e)\n{\n", name);
+ IO::print(out, "\tswitch(_e)\n\t{\n");
+ for(const Value &v: values)
+ IO::print(out, "\tcase %s::%s: conv.result(\"%s\"); break;\n", name, v.name, v.name);
+ IO::print(out, "\tdefault: conv.result(Msp::format(\"%s(%%#x)\", static_cast<int>(_e)));\n", name);
+ IO::print(out, "\t}\n}\n");
+}
+
+
+Enum::Loader::Loader(Enum &e):
+ ObjectLoader<Enum>(e)
+{
+ static ActionMap shared_actions;
+ set_actions(shared_actions);
+}
+
+void Enum::Loader::init_actions()
+{
+ add("value", &Loader::value);
+ add("value", &Loader::value_auto);
+}
+
+void Enum::Loader::value(const DataFile::Symbol &n, int v)
+{
+ obj.values.emplace_back(n.name, v);
+}
+
+void Enum::Loader::value_auto(const DataFile::Symbol &n)
+{
+ obj.values.emplace_back(n.name);
+}