Index: src/Parser/DeclarationNode.cc
===================================================================
--- src/Parser/DeclarationNode.cc	(revision 3982384b9c4ea1f8724897508e84041d2ab66cf1)
+++ src/Parser/DeclarationNode.cc	(revision 044ae62f3758370207e9bd48aa003fbc826b3d4d)
@@ -279,4 +279,14 @@
 } // DeclarationNode::newEnum
 
+DeclarationNode * DeclarationNode::newAdt( const string * name, DeclarationNode * constructors ) {
+	assert( name );
+	DeclarationNode * newnode = new DeclarationNode;
+	newnode->type = new TypeData( TypeData::Adt );
+	newnode->type->adt.name = name;
+	newnode->type->adt.data_constructors = constructors;
+	return newnode;
+} // DeclarationNode::newAdt
+
+
 DeclarationNode * DeclarationNode::newName( const string * name ) {
 	DeclarationNode * newnode = new DeclarationNode;
@@ -305,4 +315,9 @@
 	} // if
 } // DeclarationNode::newEnumValueGeneric
+
+DeclarationNode * DeclarationNode::newDataConstructor( const string * name ) {
+	DeclarationNode * newnode = newName(name);
+	return newnode;
+}
 
 DeclarationNode * DeclarationNode::newEnumInLine( const string name ) {
@@ -1083,4 +1098,94 @@
 	}
 	return nullptr;
+}
+
+std::vector<ast::ptr<ast::StructDecl>> 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;		
+	}
+	return outputList;
+}
+
+ast::UnionDecl * buildDataUnion( const CodeLocation & loc, const std::vector<ast::ptr<ast::StructDecl>> & typeList ) {
+	ast::UnionDecl * out = new ast::UnionDecl( loc, "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( const CodeLocation & loc, std::vector<ast::ptr<ast::StructDecl>> & typeList ) {
+	ast::EnumDecl * out = new ast::EnumDecl( loc, "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 TypeData * 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->adt.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 3982384b9c4ea1f8724897508e84041d2ab66cf1)
+++ src/Parser/DeclarationNode.h	(revision 044ae62f3758370207e9bd48aa003fbc826b3d4d)
@@ -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;
@@ -211,4 +217,9 @@
 void buildTypeList( const DeclarationNode * firstNode, std::vector<ast::ptr<ast::Type>> & outputList );
 
+std::vector<ast::ptr<ast::StructDecl>> buildDataConstructors( DeclarationNode * firstNode );
+ast::UnionDecl * buildDataUnion( const CodeLocation & loc, const std::vector<ast::ptr<ast::StructDecl>> & typeList );
+ast::EnumDecl * buildTag( const CodeLocation & loc, std::vector<ast::ptr<ast::StructDecl>> & typeList );
+ast::StructDecl * buildTaggedUnions( const TypeData * data, const ast::EnumDecl * tag, const ast::UnionDecl * data_union );
+
 template<typename AstType, typename NodeType,
 		template<typename, typename...> class Container, typename... Args>
Index: src/Parser/TypeData.cc
===================================================================
--- src/Parser/TypeData.cc	(revision 3982384b9c4ea1f8724897508e84041d2ab66cf1)
+++ src/Parser/TypeData.cc	(revision 044ae62f3758370207e9bd48aa003fbc826b3d4d)
@@ -59,4 +59,8 @@
 		enumeration.anon = false;
 		break;
+	case Adt:
+		adt.name = nullptr;
+		adt.data_constructors = nullptr;
+		break;
 	case Aggregate:
 		aggregate.kind = ast::AggregateDecl::NoAggregate;
@@ -160,4 +164,8 @@
 		delete qualified.child;
 		break;
+	case Adt:
+		delete adt.data_constructors;
+		delete adt.name;
+		break;
 	} // switch
 } // TypeData::~TypeData
@@ -217,4 +225,9 @@
 		newtype->enumeration.body = enumeration.body;
 		newtype->enumeration.anon = enumeration.anon;
+		newtype->enumeration.data_constructors = maybeClone( enumeration.data_constructors );
+		break;
+	case Adt:
+		newtype->adt.data_constructors = maybeClone( enumeration.data_constructors );
+		newtype->adt.name = new string ( *adt.name );
 		break;
 	case Symbolic:
@@ -459,4 +472,6 @@
 	case Enum:
 		return enumeration.name;
+	case Adt:
+		return adt.name;
 	case Symbolic:
 	case SymbolicInst:
@@ -822,4 +837,5 @@
 	case TypeData::Symbolic:
 	case TypeData::Enum:
+	case TypeData::Adt:
 	case TypeData::Aggregate:
 		assert( false );
@@ -1260,4 +1276,13 @@
 	);
 	buildList( td->enumeration.constants, ret->members );
+	if ( td->enumeration.data_constructors != nullptr ) {
+		assert( false );
+		// ret->data_constructors = buildDataConstructors( td->enumeration.data_constructors );
+		// ret->data_union = buildDataUnion( td->location, ret->data_constructors );
+		// ret->tag = buildTag( td->location, ret->data_constructors );
+		// ret->tag_union = buildTaggedUnions( td, 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;
@@ -1286,4 +1311,16 @@
 	return ret;
 } // buildEnum
+
+ast::AdtDecl * buildAdt(const TypeData * td,
+	std::vector<ast::ptr<ast::Attribute>> && attributes,
+	ast::Linkage::Spec linkage ) {
+	assert( td->kind == TypeData::Adt );
+	ast::AdtDecl * ret = new ast::AdtDecl( td->location, *(td->adt.name) );
+	ret->data_constructors = buildDataConstructors( td->adt.data_constructors );
+	ret->data_union = buildDataUnion( td->location, ret->data_constructors );
+	ret->tag = buildTag( td->location, ret->data_constructors );
+	ret->tag_union = buildTaggedUnions( td, ret->tag.get(), ret->data_union.get() );
+	return ret;
+}
 
 
@@ -1429,4 +1466,6 @@
 	} else if ( td->kind == TypeData::Enum ) {
 		return buildEnum( td, std::move( attributes ), linkage );
+	} else if ( td->kind == TypeData::Adt) {
+		return buildAdt( td, std::move( attributes), linkage );
 	} else if ( td->kind == TypeData::Symbolic ) {
 		return buildSymbolic( td, std::move( attributes ), name, scs, linkage );
Index: src/Parser/TypeData.h
===================================================================
--- src/Parser/TypeData.h	(revision 3982384b9c4ea1f8724897508e84041d2ab66cf1)
+++ src/Parser/TypeData.h	(revision 044ae62f3758370207e9bd48aa003fbc826b3d4d)
@@ -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,12 @@
 		bool typed;
 		EnumHiding hiding;
+		bool isData = false;
+
+		DeclarationNode * data_constructors = nullptr;
+	};
+
+	struct ADT_t {
+		const std::string * name = nullptr;
+		DeclarationNode * data_constructors;
 	};
 
@@ -98,4 +106,6 @@
 	Array_t array;
 	Enumeration_t enumeration;
+	ADT_t adt;
+
 	Function_t function;
 	Symbolic_t symbolic;
@@ -124,4 +134,5 @@
 ast::TypeDecl * buildVariable( const TypeData * );
 ast::EnumDecl * buildEnum( const TypeData *, std::vector<ast::ptr<ast::Attribute>> &&, ast::Linkage::Spec );
+ast::EnumDecl * buildAst( const TypeData *, std::vector<ast::ptr<ast::Attribute>> &&, ast::Linkage::Spec );
 ast::TypeInstType * buildSymbolicInst( const TypeData * );
 ast::TupleType * buildTuple( const TypeData * );
Index: src/Parser/lex.ll
===================================================================
--- src/Parser/lex.ll	(revision 3982384b9c4ea1f8724897508e84041d2ab66cf1)
+++ src/Parser/lex.ll	(revision 044ae62f3758370207e9bd48aa003fbc826b3d4d)
@@ -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 3982384b9c4ea1f8724897508e84041d2ab66cf1)
+++ src/Parser/parser.yy	(revision 044ae62f3758370207e9bd48aa003fbc826b3d4d)
@@ -340,5 +340,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
@@ -455,4 +455,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
@@ -2449,4 +2452,5 @@
 		}
 	| enum_type
+	/* | algebric_data_type */
 	;
 
@@ -2702,5 +2706,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:
