Index: src/Parser/DeclarationNode.cc
===================================================================
--- src/Parser/DeclarationNode.cc	(revision b110bcc1f3711112c2fbc182403e08383e1f4be0)
+++ src/Parser/DeclarationNode.cc	(revision 28f8f154b94c0b9fd3ef74a8d0de01187a5522c6)
@@ -279,4 +279,12 @@
 } // DeclarationNode::newEnum
 
+DeclarationNode * DeclarationNode::newADT( const string * name, DeclarationNode * constructors ) {
+	DeclarationNode * newnode = newEnum( name, nullptr, true, false );
+	newnode->type->enumeration.isData = true;
+	newnode->type->enumeration.data_constructors = constructors;
+	return newnode;
+}
+
+
 DeclarationNode * DeclarationNode::newName( const string * name ) {
 	DeclarationNode * newnode = new DeclarationNode;
@@ -305,4 +313,9 @@
 	} // if
 } // DeclarationNode::newEnumValueGeneric
+
+DeclarationNode * DeclarationNode::newDataConstructor( const string * name ) {
+	DeclarationNode * newnode = newName(name);
+	return newnode;
+}
 
 DeclarationNode * DeclarationNode::newEnumInLine( const string name ) {
@@ -1083,4 +1096,92 @@
 	}
 	return nullptr;
+}
+
+void buildDataConstructors( DeclarationNode * firstNode, std::vector<ast::ptr<ast::StructDecl>> & outputList ) {
+	std::back_insert_iterator<std::vector<ast::ptr<ast::StructDecl>>> out( outputList );
+	for ( const DeclarationNode * cur = firstNode; cur; cur = strict_next( cur ) ) {
+		// td->kind == TypeData::Symbolic
+		assert( cur->type->kind == TypeData::Symbolic );
+		const std::string * name = cur->name;
+		auto ctor = new ast::StructDecl( cur->location,
+			std::string(*name),
+			ast::AggregateDecl::Aggregate::Struct
+		);
+		ctor->set_body(true);
+		TypeData * td = cur->type;
+		TypeData::Symbolic_t st = td->symbolic;
+		DeclarationNode * params = st.params;
+		
+		if ( params ) {
+			buildList( params, ctor->members );
+		}
+
+		for ( std::size_t i = 0; i < ctor->members.size(); ++i ) {
+			assert(ctor->members[i]->name == "");
+			ast::Decl * member = ctor->members[i].get_and_mutate();
+			member->name = "field_" + std::to_string(i);
+		}
+		*out++ = ctor;		
+	}
+}
+
+ast::UnionDecl * buildDataUnion( ast::EnumDecl * data, const std::vector<ast::ptr<ast::StructDecl>> & typeList ) {
+	ast::UnionDecl * out = new ast::UnionDecl( data->location, "temp_data_union" );
+	// size_t index = 0;
+	if ( typeList.size() > 0 ) out->set_body( true );
+	size_t i = 0;
+	for (const ast::ptr<ast::StructDecl> structDecl : typeList ) {
+		ast::StructInstType * inst = new ast::StructInstType(structDecl);
+		ast::ObjectDecl * instObj = new ast::ObjectDecl(
+			structDecl->location,
+			"option_" + std::to_string(i),
+			inst
+		);
+		i++;
+		out->members.push_back( instObj );
+
+	}
+	return out;
+}
+
+ast::EnumDecl * buildTag( ast::EnumDecl * data, const std::vector<ast::ptr<ast::StructDecl>> & typeList ) {
+	ast::EnumDecl * out = new ast::EnumDecl( data->location, "temp_data_tag" );
+	if ( typeList.size() > 0 ) out->set_body( true );
+	for ( const ast::ptr<ast::StructDecl> structDecl : typeList ) {
+		ast::EnumInstType * inst = new ast::EnumInstType( out );
+		assert( inst->base != nullptr );
+		ast::ObjectDecl * instObj = new ast::ObjectDecl(
+			structDecl->location,
+			structDecl->name,
+			inst
+		);
+		out->members.push_back( instObj );
+	}
+	return out;
+}
+
+ast::StructDecl * buildTaggedUnions( const ast::EnumDecl * data, const ast::EnumDecl * tags, const ast::UnionDecl * data_union ) {
+	assert( tags->members.size() == data_union->members.size() );
+	ast::StructDecl * out = new ast::StructDecl( data->location, data->name );
+	out->kind = ast::AggregateDecl::ADT;
+
+	out->set_body( true );
+
+	ast::EnumInstType * tag = new ast::EnumInstType( tags );
+	ast::ObjectDecl * tag_obj = new ast::ObjectDecl(
+		data->location,
+		"tag",
+		tag
+	);
+	ast::UnionInstType * value = new ast::UnionInstType( data_union );
+	ast::ObjectDecl * value_obj = new ast::ObjectDecl(
+		data->location,
+		"value",
+		value
+	);
+
+	out->members.push_back( value_obj );
+	out->members.push_back( tag_obj );
+	return out;
 }
 
Index: src/Parser/DeclarationNode.h
===================================================================
--- src/Parser/DeclarationNode.h	(revision b110bcc1f3711112c2fbc182403e08383e1f4be0)
+++ src/Parser/DeclarationNode.h	(revision 28f8f154b94c0b9fd3ef74a8d0de01187a5522c6)
@@ -76,4 +76,9 @@
 	static DeclarationNode * newStaticAssert( ExpressionNode * condition, ast::Expr * message );
 
+	// Experimental algebric data type
+	static DeclarationNode * newADT( const std::string * name, DeclarationNode * constructors );
+	static DeclarationNode * newDataConstructor( const std::string * name );
+	// static DeclarationNode * newDataConstructor( const std::string * name, DeclarationNode * typeSpecifiers );
+
 	DeclarationNode();
 	~DeclarationNode();
@@ -156,4 +161,5 @@
 	ExpressionNode * bitfieldWidth = nullptr;
 	std::unique_ptr<ExpressionNode> enumeratorValue;
+
 	bool hasEllipsis = false;
 	ast::Linkage::Spec linkage;
@@ -210,4 +216,8 @@
 void buildList( DeclarationNode * firstNode, std::vector<ast::ptr<ast::DeclWithType>> & outputList );
 void buildTypeList( const DeclarationNode * firstNode, std::vector<ast::ptr<ast::Type>> & outputList );
+void buildDataConstructors( DeclarationNode * firstNode, std::vector<ast::ptr<ast::StructDecl>> & outputList );
+ast::UnionDecl * buildDataUnion( ast::EnumDecl * data, const std::vector<ast::ptr<ast::StructDecl>> & typeList );
+ast::EnumDecl * buildTag( ast::EnumDecl * data, const std::vector<ast::ptr<ast::StructDecl>> & typeList );
+ast::StructDecl * buildTaggedUnions( const ast::EnumDecl * data, const ast::EnumDecl * tags, const ast::UnionDecl * data_union );
 
 template<typename AstType, typename NodeType,
Index: src/Parser/TypeData.cc
===================================================================
--- src/Parser/TypeData.cc	(revision b110bcc1f3711112c2fbc182403e08383e1f4be0)
+++ src/Parser/TypeData.cc	(revision 28f8f154b94c0b9fd3ef74a8d0de01187a5522c6)
@@ -1260,4 +1260,12 @@
 	);
 	buildList( td->enumeration.constants, ret->members );
+	if ( td->enumeration.data_constructors != nullptr ) {
+		buildDataConstructors( td->enumeration.data_constructors, ret->data_constructors );
+		ret->data_union = buildDataUnion( ret, ret->data_constructors );
+		ret->tag = buildTag( ret, ret->data_constructors );
+		ret->tag_union = buildTaggedUnions( ret, ret->tag.get(), ret->data_union.get() );
+	}
+
+	if ( ret->data_constructors.size() > 0 ) ret->isData = true;
 	auto members = ret->members.begin();
 	ret->hide = td->enumeration.hiding == EnumHiding::Hide ? ast::EnumDecl::EnumHiding::Hide : ast::EnumDecl::EnumHiding::Visible;
Index: src/Parser/TypeData.h
===================================================================
--- src/Parser/TypeData.h	(revision b110bcc1f3711112c2fbc182403e08383e1f4be0)
+++ src/Parser/TypeData.h	(revision 28f8f154b94c0b9fd3ef74a8d0de01187a5522c6)
@@ -25,5 +25,5 @@
 struct TypeData {
 	enum Kind { Basic, Pointer, Reference, Array, Function, Aggregate, AggregateInst, Enum, EnumConstant, Symbolic,
-				SymbolicInst, Tuple, Basetypeof, Typeof, Vtable, Builtin, GlobalScope, Qualified, Unknown };
+				SymbolicInst, Tuple, Basetypeof, Typeof, Vtable, Builtin, GlobalScope, Qualified, ADT, Ctor, Unknown };
 
 	struct Aggregate_t {
@@ -58,4 +58,17 @@
 		bool typed;
 		EnumHiding hiding;
+		bool isData = false;
+
+		DeclarationNode * data_constructors = nullptr;
+	};
+
+	struct ADT_t {
+		const std::string * name = nullptr;
+		DeclarationNode * constructors;
+	};
+
+	struct Constructor_t {
+		const std::string * name;
+		DeclarationNode * type; // types?
 	};
 
@@ -98,4 +111,7 @@
 	Array_t array;
 	Enumeration_t enumeration;
+	ADT_t adt;
+	Constructor_t data_constructor;
+
 	Function_t function;
 	Symbolic_t symbolic;
Index: src/Parser/lex.ll
===================================================================
--- src/Parser/lex.ll	(revision b110bcc1f3711112c2fbc182403e08383e1f4be0)
+++ src/Parser/lex.ll	(revision 28f8f154b94c0b9fd3ef74a8d0de01187a5522c6)
@@ -353,4 +353,5 @@
 with			{ KEYWORD_RETURN(WITH); }				// CFA
 zero_t			{ NUMERIC_RETURN(ZERO_T); }				// CFA
+_DATA_            { KEYWORD_RETURN(DATA); }				// Experimental
 
 				/* identifier */
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision b110bcc1f3711112c2fbc182403e08383e1f4be0)
+++ src/Parser/parser.yy	(revision 28f8f154b94c0b9fd3ef74a8d0de01187a5522c6)
@@ -339,5 +339,5 @@
 %token SIZEOF TYPEOF VA_LIST VA_ARG AUTO_TYPE			// GCC
 %token OFFSETOF BASETYPEOF TYPEID						// CFA
-%token ENUM STRUCT UNION
+%token ENUM STRUCT UNION DATA
 %token EXCEPTION										// CFA
 %token GENERATOR COROUTINE MONITOR THREAD				// CFA
@@ -453,4 +453,7 @@
 %type<decl> enumerator_list enum_type enum_type_nobody
 %type<init> enumerator_value_opt
+
+%type<decl> value_list
+%type<decl> data_constructor type_specifier_list
 
 %type<decl> external_definition external_definition_list external_definition_list_opt
@@ -2441,4 +2444,5 @@
 		}
 	| enum_type
+	/* | algebric_data_type */
 	;
 
@@ -2694,5 +2698,49 @@
 		}
 	| enum_type_nobody
-	;
+	| DATA identifier
+	{ typedefTable.makeTypedef( *$2 ); }
+	 '{' value_list '}'
+	 {
+		$$ = DeclarationNode::newADT( $2, $5 );
+	 }
+	;
+
+value_list:
+	data_constructor 
+	{
+		$$ = $1;
+	}
+	/* | identifier_or_type_name '(' type_specifier ')'
+	{
+		$$ = DeclarationNode::newEnumValueGeneric( $1, nullptr );
+	} */
+	/* | data_constructor '|' value_list   */
+	| value_list '|' data_constructor
+	{
+		 { $$ = $1->appendList( $3 ); }
+	}
+	;
+
+data_constructor:
+	identifier_or_type_name 
+	{
+		typedefTable.makeTypedef( *$1 );
+		$$ =  DeclarationNode::newTypeDecl( $1, nullptr );;
+	}
+	| identifier_or_type_name '(' type_specifier_list ')'
+	{
+		typedefTable.makeTypedef( *$1 );
+		$$ = DeclarationNode::newTypeDecl( $1, $3 );
+	}
+
+type_specifier_list:
+	type_specifier
+	/* | type_specifier ',' type_specifier_list  */
+	| type_specifier_list ',' type_specifier
+	{
+		$$ = $1->appendList($3);
+	}
+	;
+
 
 hide_opt:
