diff --git a/spec/jastadd/Analysis.jrag b/spec/jastadd/Analysis.jrag
index 646474700f49de5cc97bbff6ecdcb4920894756b..79439576fcb4bbe0a40dc8f97fe9396629c9676d 100644
--- a/spec/jastadd/Analysis.jrag
+++ b/spec/jastadd/Analysis.jrag
@@ -18,29 +18,14 @@ aspect TypeAnalysis {
 }
 
 aspect ComponentAnalysis {
-	syn boolean Component.isDeclaringName() = true;
-	eq RelationComponent.isDeclaringName() = !isTargetOfRightDirection();
+	syn boolean Component.isTargetOfDirectedRelation() = false;
+	eq RelationComponent.isTargetOfDirectedRelation() = isTargetOfRightDirection();
 	inh boolean RelationComponent.isTargetOfRightDirection();
 	eq Relation.getRight().isTargetOfRightDirection()
 		= getDirection() instanceof RightDirection;
 	eq Program.getChild().isTargetOfRightDirection() = false;
 
-	syn String Component.name() {
-		if (!isDeclaringName()) {
-			return "";
-		}
-		if (!getID().isEmpty()) {
-			return getID();
-		}
-		return otherRelationSideName();
-	}
-	inh String Component.otherRelationSideName();
-	eq Relation.getLeft().otherRelationSideName()
-		= getRight().getTypeUse().getID();
-	eq Relation.getRight().otherRelationSideName()
-		= getLeft().getTypeUse().getID();
-	eq Program.getChild().otherRelationSideName()
-		= "";
+	syn String Component.name() = getID();
 
 	syn TypeDecl Component.toTypeDecl() = enclosingTypeDecl();
 	eq RelationComponent.toTypeDecl() = getTypeUse().decl();
@@ -53,7 +38,8 @@ aspect ComponentAnalysis {
 	eq Program.getChild().ofTypeDecl() = null;
 
 	syn boolean Component.isAlreadyDeclared()
-		= isDeclaringName() && lookupComponent(toTypeDecl(), name()) != this;
+		= !isTargetOfDirectedRelation()
+			&& lookupComponent(toTypeDecl(), name()) != this;
 	inh Component Component.lookupComponent(TypeDecl td, String name);
 	eq Program.getChild().lookupComponent(TypeDecl td, String name) {
 		if (td != null) {
@@ -73,7 +59,7 @@ aspect ComponentAnalysis {
 	}
 
 	syn RelationComponent RelationComponent.lookup(TypeDecl td, String name)
-		= isDeclaringName() && toTypeDecl() == td && name().equals(name)
+		= !isTargetOfDirectedRelation() && toTypeDecl() == td && name().equals(name)
 		? this
 		: null;
 
@@ -82,7 +68,7 @@ aspect ComponentAnalysis {
 		[new HashSet<RelationComponent>()]
 		root Program;
 	RelationComponent contributes this
-		when isDeclaringName() && toTypeDecl() != null
+		when !isTargetOfDirectedRelation() && toTypeDecl() != null
 		to TypeDecl.relationComponents()
 		for toTypeDecl();
 }
diff --git a/spec/jastadd/Backend.jadd b/spec/jastadd/Backend.jadd
index e12ba7fc394edf078904aca8f12b40c688f22c3d..b7a4b101064bb652fcaf77bfeacecb9b777588fe 100644
--- a/spec/jastadd/Backend.jadd
+++ b/spec/jastadd/Backend.jadd
@@ -128,7 +128,7 @@ aspect PrettyPrint {
 		}
 	}
 	public String OptionalRelationComponent.prettyPrint() {
-		return "[" + super.prettyPrint() + "]";
+		return super.prettyPrint() + "?";
 	}
 	public String ManyRelationComponent.prettyPrint() {
 		return super.prettyPrint() + "*";
diff --git a/spec/jastadd/DumpTree.jrag b/spec/jastadd/DumpTree.jrag
index 897b8d2bc68534469d6b5f18c947296d13d245bf..f49741e6fe607365f323846828b6735e4034d913 100644
--- a/spec/jastadd/DumpTree.jrag
+++ b/spec/jastadd/DumpTree.jrag
@@ -21,7 +21,12 @@ aspect DumpTree {
 
 	public void ASTNode.dumpTree(PrintStream out, String indent) {
 		out.print(indent + getClass().getSimpleName());
-		out.println(getTokens());
+		out.print(getTokens());
+		String extra = extraDumpInfo();
+		if (!extra.isEmpty()) {
+			out.print(" " + extra);
+		}
+		out.println();
 		String childIndent = indent + DUMP_TREE_INDENT;
 		for (ASTNode child : astChildren()) {
 			if (child == null) {
@@ -32,6 +37,8 @@ aspect DumpTree {
 		}
 	}
 
+	public String ASTNode.extraDumpInfo() { return ""; }
+
 	public String ASTNode.getTokens() {
 		java.util.TreeSet<java.lang.reflect.Method> methods = new java.util.TreeSet<>(
 				new java.util.Comparator<java.lang.reflect.Method>() {
diff --git a/spec/jastadd/Errors.jrag b/spec/jastadd/Errors.jrag
index 3aa6ff27a17bd45fd367ee44925005347b165e14..b97c8252e95eb2f7bca97c863c5c544cef859c71 100644
--- a/spec/jastadd/Errors.jrag
+++ b/spec/jastadd/Errors.jrag
@@ -19,6 +19,21 @@ aspect Errors {
 			+ "' is already declared for type '" + toTypeDecl() + "'")
 		when isAlreadyDeclared()
 		to Program.errors();
+
+	RelationComponent contributes
+		error("Role name missing for type '" + toTypeDecl() + "'")
+		when !isTargetOfDirectedRelation() && name().isEmpty()
+		to Program.errors();
+
+	RelationComponent contributes
+		error("The target of a directed relation cannot have a role name")
+		when isTargetOfDirectedRelation() && !getID().isEmpty()
+		to Program.errors();
+
+	RelationComponent contributes
+		error("The target of a directed relation may only have multiplicity 1")
+		when isTargetOfDirectedRelation() && !hasMultiplicityOne()
+		to Program.errors();
 }
 
 aspect HelpAttributes {
@@ -28,6 +43,9 @@ aspect HelpAttributes {
 	inh boolean TypeUse.isToken();
 	eq Program.getChild().isToken() = false;
 	eq TokenComponent.getTypeUse().isToken() = true;
+
+	syn boolean RelationComponent.hasMultiplicityOne() = false;
+	eq OneRelationComponent.hasMultiplicityOne() = true;
 }
 
 aspect ErrorMessage {
diff --git a/src/java/org/jastadd/relast/compiler/Compiler.java b/src/java/org/jastadd/relast/compiler/Compiler.java
index eeaeacfbde606bbbe41f3b0476be7d639797188b..0a0cf2a9f3280612b8b76f7b0ba62ec53b6e0b6b 100644
--- a/src/java/org/jastadd/relast/compiler/Compiler.java
+++ b/src/java/org/jastadd/relast/compiler/Compiler.java
@@ -34,6 +34,7 @@ public class Compiler {
 		Program p = parseProgram(commandLine.getArguments().get(0));
 
 		if (!p.errors().isEmpty()) {
+			System.out.println(p.dumpTree());
 			System.err.println("Errors:");
 			for (ErrorMessage e: p.errors()) {
 				System.err.println(e);