diff --git a/src/main/grammar/Grammar.bnf b/src/main/grammar/Grammar.bnf
index d5165bdf1842a9de8abb50ca3056f4d508e986c4..ca92e0fd3bf99f0f98add4a662748cb893ac6a6e 100644
--- a/src/main/grammar/Grammar.bnf
+++ b/src/main/grammar/Grammar.bnf
@@ -19,7 +19,7 @@ GrammarFile ::= comment* ((type_decl | relation) comment*)*
 
 comment ::= (WHITESPACE | MULTILINECOMMENT | DOCCOMMENT | SINGLELINECOMMENT)
 
-type_decl ::= ABSTRACT? declared_name (COL type_reference)? (ASSIGN (component | nta_component)*)? SCOL
+type_decl ::= ABSTRACT? type_name (COL type_reference)? (ASSIGN (component | nta_component)*)? SCOL
 {
   extends="org.jastadd.tooling.grammar.psi.impl.GrammarTypeDeclImplExtension"
   implements="org.jastadd.tooling.grammar.psi.GrammarNamedElement"
@@ -27,7 +27,7 @@ type_decl ::= ABSTRACT? declared_name (COL type_reference)? (ASSIGN (component |
 
 nta_component ::= SLASH component SLASH
 
-component ::= (declared_name COL type_reference STAR?) | (type_reference STAR?) | (LBRACKET declared_name COL type_reference RBRACKET) | (LBRACKET type_reference RBRACKET) | (LT declared_name (COL (java_type_use))? GT)
+component ::= (component_name COL type_reference STAR?) | (type_reference STAR?) | (LBRACKET component_name COL type_reference RBRACKET) | (LBRACKET type_reference RBRACKET) | (LT component_name (COL (java_type_use))? GT)
 
 java_type_use ::=  parameterized_java_type_use | simple_java_type_use
 
@@ -39,14 +39,22 @@ relation ::=  REL ((unnamed_role LEFT navigable_role) | (navigable_role RIGHT un
 
 unnamed_role ::= type_reference | navigable_role
 
-navigable_role ::= type_reference DOT declared_name (STAR | QUESTION_MARK)?
+navigable_role ::= type_reference DOT component_name (STAR | QUESTION_MARK)?
 
 // for auto-completion, it is helpful if we can distinguish the different IDs
-declared_name ::= ID
+type_name ::= ID
+
 type_reference ::= ID
 {
   extends="org.jastadd.tooling.grammar.psi.impl.GrammarTypeReferenceImplExtension"
   implements="org.jastadd.tooling.grammar.psi.GrammarNamedElement"
 }
 
+component_name ::= ID
+{
+  extends="org.jastadd.tooling.grammar.psi.impl.GrammarComponentNameImplExtension"
+  implements="org.jastadd.tooling.grammar.psi.GrammarNamedElement"
+}
+
+
 java_name ::= ID
diff --git a/src/main/java/org/jastadd/tooling/grammar/GrammarAnnotator.java b/src/main/java/org/jastadd/tooling/grammar/GrammarAnnotator.java
index 67973459c048ce172a6698f080e7c46ecb1678f5..7e501556e65c64b1f6df50315432d252f2384c21 100644
--- a/src/main/java/org/jastadd/tooling/grammar/GrammarAnnotator.java
+++ b/src/main/java/org/jastadd/tooling/grammar/GrammarAnnotator.java
@@ -18,11 +18,11 @@ public class GrammarAnnotator implements Annotator {
 
     if (element instanceof GrammarComponent) {
       GrammarComponent component = (GrammarComponent) element;
-      if (component.getTypeReference() != null && component.getDeclaredName() != null) {
-        String name = component.getDeclaredName().getText();
+      if (component.getTypeReference() != null && component.getComponentName() != null) {
+        String name = component.getComponentName().getText();
         if (name != null && !name.equals("") && name.equals(component.getTypeReference().getName())) {
           holder.newAnnotation(HighlightSeverity.WEAK_WARNING, "Redundant name")
-            .range(component.getDeclaredName().getTextRange())
+            .range(component.getComponentName().getTextRange())
             .highlightType(ProblemHighlightType.WEAK_WARNING)
             .textAttributes(DefaultLanguageHighlighterColors.HIGHLIGHTED_REFERENCE)
             .tooltip("When the name of a component is the same as its type, it can be omitted.")
diff --git a/src/main/java/org/jastadd/tooling/grammar/GrammarChooseByNameContributor.java b/src/main/java/org/jastadd/tooling/grammar/GrammarChooseByNameContributor.java
index f1d88f5bdd920cd0494edf557d463572f4c8f215..615f51e2e80274d44e432b3752e79c422f929325 100644
--- a/src/main/java/org/jastadd/tooling/grammar/GrammarChooseByNameContributor.java
+++ b/src/main/java/org/jastadd/tooling/grammar/GrammarChooseByNameContributor.java
@@ -18,7 +18,7 @@ public class GrammarChooseByNameContributor implements ChooseByNameContributor {
     List<GrammarTypeDecl> typeDecls = GrammarUtil.findTypeDecl(project);
     List<String> names = new ArrayList<>(typeDecls.size());
     for (GrammarTypeDecl typeDecl : typeDecls) {
-      if (typeDecl.getName() != null && typeDecl.getName().length() > 0) {
+      if (typeDecl.getName() != null && !typeDecl.getName().isEmpty()) {
         names.add(typeDecl.getName());
       }
     }
diff --git a/src/main/java/org/jastadd/tooling/grammar/GrammarRefactoringSupportProvider.java b/src/main/java/org/jastadd/tooling/grammar/GrammarRefactoringSupportProvider.java
index 1e70ce549ffe5b03a1befa41a162fb785ad77224..c726f7971618b49ff00c934ebd3b7cd79704faf0 100644
--- a/src/main/java/org/jastadd/tooling/grammar/GrammarRefactoringSupportProvider.java
+++ b/src/main/java/org/jastadd/tooling/grammar/GrammarRefactoringSupportProvider.java
@@ -3,7 +3,7 @@ package org.jastadd.tooling.grammar;
 
 import com.intellij.lang.refactoring.RefactoringSupportProvider;
 import com.intellij.psi.PsiElement;
-import org.jastadd.tooling.grammar.psi.GrammarDeclaredName;
+import org.jastadd.tooling.grammar.psi.GrammarTypeName;
 import org.jastadd.tooling.grammar.psi.GrammarTypeReference;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -14,7 +14,7 @@ public class GrammarRefactoringSupportProvider extends RefactoringSupportProvide
   public boolean isMemberInplaceRenameAvailable(@NotNull PsiElement elementToRename, @Nullable PsiElement context) {
     // in-place rename is still not available since not all requirements are met
     // see https://intellij-support.jetbrains.com/hc/en-us/community/posts/360006918740-How-do-I-enable-in-place-rename-Renaming-via-dialog-works-fine-
-    return (elementToRename instanceof GrammarDeclaredName) || (elementToRename instanceof GrammarTypeReference);
+    return (elementToRename instanceof GrammarTypeName) || (elementToRename instanceof GrammarTypeReference);
   }
 
 }
diff --git a/src/main/java/org/jastadd/tooling/grammar/GrammarReference.java b/src/main/java/org/jastadd/tooling/grammar/GrammarReference.java
index 3c6fc4b3afa6eb1eebe986362d90a88234f2f571..2825e6631cca7531cf229a040f95820a1d79a3c4 100644
--- a/src/main/java/org/jastadd/tooling/grammar/GrammarReference.java
+++ b/src/main/java/org/jastadd/tooling/grammar/GrammarReference.java
@@ -48,7 +48,7 @@ public class GrammarReference extends PsiReferenceBase<PsiElement> implements Ps
     List<GrammarTypeDecl> typeDecls = GrammarUtil.findTypeDecl(project);
     List<LookupElement> variants = new ArrayList<>();
     for (final GrammarTypeDecl typeDecl : typeDecls) {
-      if (typeDecl.getName() != null && typeDecl.getName().length() > 0) {
+      if (typeDecl.getName() != null && !typeDecl.getName().isEmpty()) {
         variants.add(LookupElementBuilder
           .create(typeDecl).withIcon(JastAddIcons.FILE)
           .withPresentableText(typeDecl.getName())
diff --git a/src/main/java/org/jastadd/tooling/grammar/GrammarRemoveRedundantComponentNameFix.java b/src/main/java/org/jastadd/tooling/grammar/GrammarRemoveRedundantComponentNameFix.java
index b906a768ff0caa222424459a692b38577c53e7e5..a95cb2a727795e8cbf9942dcc7ba6e216ea0e426 100644
--- a/src/main/java/org/jastadd/tooling/grammar/GrammarRemoveRedundantComponentNameFix.java
+++ b/src/main/java/org/jastadd/tooling/grammar/GrammarRemoveRedundantComponentNameFix.java
@@ -38,8 +38,8 @@ public class GrammarRemoveRedundantComponentNameFix extends BaseIntentionAction
   @Override
   public void invoke(@NotNull final Project project, final Editor editor, PsiFile file) throws
     IncorrectOperationException {
-    PsiElement first = component.getDeclaredName();
-    PsiElement last = component.getDeclaredName();
+    PsiElement first = component.getComponentName();
+    PsiElement last = component.getComponentName();
     while (last != null && last.getNode().getElementType() != GrammarTypes.COL) {
       last = last.getNextSibling();
     }
diff --git a/src/main/java/org/jastadd/tooling/grammar/psi/GrammarElementFactory.java b/src/main/java/org/jastadd/tooling/grammar/psi/GrammarElementFactory.java
index 05a33fa932d60b0c1651b986c91e9c163a95430a..aaacf268a10a5b7d47b9db1d479e5a34d93b3394 100644
--- a/src/main/java/org/jastadd/tooling/grammar/psi/GrammarElementFactory.java
+++ b/src/main/java/org/jastadd/tooling/grammar/psi/GrammarElementFactory.java
@@ -13,9 +13,9 @@ public class GrammarElementFactory {
     throw new IllegalStateException("Utility class");
   }
 
-  public static GrammarDeclaredName createDeclaredName(Project project, String name) {
+  public static GrammarTypeName createTypeName(Project project, String name) {
     final GrammarFile file = createFile(project, name + ";");
-    return (GrammarDeclaredName) file.getFirstChild().getFirstChild();
+    return (GrammarTypeName) file.getFirstChild().getFirstChild();
   }
 
   public static GrammarTypeReference createTypeReference(Project project, String name) {
@@ -23,6 +23,11 @@ public class GrammarElementFactory {
     return (GrammarTypeReference) (Objects.requireNonNull(file.getFirstChild().getNode().findChildByType(GrammarTypes.TYPE_REFERENCE)).getPsi());
   }
 
+  public static GrammarComponentName createComponentName(Project project, String name) {
+    final GrammarFile file = createFile(project, "X ::= " + name + ":X ;");
+    return (GrammarComponentName) file.getFirstChild().getFirstChild();
+  }
+
   public static GrammarFile createFile(Project project, String text) {
     String name = "dummy.relast";
     return (GrammarFile) PsiFileFactory.getInstance(project).
diff --git a/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarComponentNameImplExtension.java b/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarComponentNameImplExtension.java
new file mode 100644
index 0000000000000000000000000000000000000000..84e04ad5b5368a181d9a23abf6f4e5dc2b72de5e
--- /dev/null
+++ b/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarComponentNameImplExtension.java
@@ -0,0 +1,37 @@
+package org.jastadd.tooling.grammar.psi.impl;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.PsiElement;
+import org.jastadd.tooling.grammar.psi.GrammarComponentName;
+import org.jastadd.tooling.grammar.psi.GrammarElementFactory;
+import org.jastadd.tooling.grammar.psi.GrammarNamedElement;
+import org.jastadd.tooling.grammar.psi.GrammarTypeReference;
+import org.jetbrains.annotations.NotNull;
+
+public class GrammarComponentNameImplExtension extends GrammarNamedElementImpl implements GrammarNamedElement {
+
+  public GrammarComponentNameImplExtension(@NotNull ASTNode node) {
+    super(node);
+  }
+
+  public String getName() {
+    // this finds the *first* ID, which is what we want
+    return getNode().getText();
+  }
+
+  public PsiElement setName(@NotNull String newName) {
+    // FIXME this can break the grammar when the type is used in an unnamed component (and in many other cases probably)
+    ASTNode keyNode = getNode().getFirstChildNode();
+    if (keyNode != null) {
+      GrammarComponentName name = GrammarElementFactory.createComponentName(getProject(), newName);
+      ASTNode newKeyNode = name.getNode().getFirstChildNode();
+      getNode().replaceChild(keyNode, newKeyNode);
+    }
+    return this;
+  }
+
+  public PsiElement getNameIdentifier() {
+    return getNode().getPsi();
+  }
+
+}
diff --git a/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeDeclImplExtension.java b/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeDeclImplExtension.java
index 8634701910da77b6fe07964d9cf25f9d3556e141..39bd24dbfd95d0f4f9989ec860c9de58a9e2b38a 100644
--- a/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeDeclImplExtension.java
+++ b/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeDeclImplExtension.java
@@ -3,9 +3,9 @@ package org.jastadd.tooling.grammar.psi.impl;
 import com.intellij.lang.ASTNode;
 import com.intellij.psi.PsiElement;
 import org.jastadd.tooling.grammar.parser.GrammarTypes;
-import org.jastadd.tooling.grammar.psi.GrammarDeclaredName;
 import org.jastadd.tooling.grammar.psi.GrammarElementFactory;
 import org.jastadd.tooling.grammar.psi.GrammarNamedElement;
+import org.jastadd.tooling.grammar.psi.GrammarTypeName;
 import org.jetbrains.annotations.NotNull;
 
 public class GrammarTypeDeclImplExtension extends GrammarNamedElementImpl implements GrammarNamedElement {
@@ -16,7 +16,7 @@ public class GrammarTypeDeclImplExtension extends GrammarNamedElementImpl implem
 
   public String getName() {
     // this finds the *first* ID, which is what we want
-    ASTNode keyNode = getNode().findChildByType(GrammarTypes.DECLARED_NAME);
+    ASTNode keyNode = getNode().findChildByType(GrammarTypes.TYPE_NAME);
     if (keyNode != null) {
       return keyNode.getText();
     } else {
@@ -25,9 +25,9 @@ public class GrammarTypeDeclImplExtension extends GrammarNamedElementImpl implem
   }
 
   public PsiElement setName(@NotNull String newName) {
-    ASTNode keyNode = getNode().findChildByType(GrammarTypes.DECLARED_NAME);
+    ASTNode keyNode = getNode().findChildByType(GrammarTypes.TYPE_NAME);
     if (keyNode != null) {
-      GrammarDeclaredName name = GrammarElementFactory.createDeclaredName(getProject(), newName);
+      GrammarTypeName name = GrammarElementFactory.createTypeName(getProject(), newName);
       ASTNode newKeyNode = name.getNode();
       getNode().replaceChild(keyNode, newKeyNode);
     }
@@ -35,7 +35,7 @@ public class GrammarTypeDeclImplExtension extends GrammarNamedElementImpl implem
   }
 
   public PsiElement getNameIdentifier() {
-    ASTNode keyNode = getNode().findChildByType(GrammarTypes.DECLARED_NAME);
+    ASTNode keyNode = getNode().findChildByType(GrammarTypes.TYPE_NAME);
     if (keyNode != null) {
       return keyNode.getPsi();
     } else {
diff --git a/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeNameImplExtension.java b/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeNameImplExtension.java
new file mode 100644
index 0000000000000000000000000000000000000000..753e63cc14ca327f4e521221916b9e293e854641
--- /dev/null
+++ b/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeNameImplExtension.java
@@ -0,0 +1,36 @@
+package org.jastadd.tooling.grammar.psi.impl;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.psi.PsiElement;
+import org.jastadd.tooling.grammar.psi.GrammarElementFactory;
+import org.jastadd.tooling.grammar.psi.GrammarNamedElement;
+import org.jastadd.tooling.grammar.psi.GrammarTypeName;
+import org.jetbrains.annotations.NotNull;
+
+public class GrammarTypeNameImplExtension extends GrammarNamedElementImpl implements GrammarNamedElement {
+
+  public GrammarTypeNameImplExtension(@NotNull ASTNode node) {
+    super(node);
+  }
+
+  public String getName() {
+    // this finds the *first* ID, which is what we want
+    return getNode().getText();
+  }
+
+  public PsiElement setName(@NotNull String newName) {
+    // FIXME this can break the grammar when the type is used in an unnamed component (and in many other cases probably)
+    ASTNode keyNode = getNode().getFirstChildNode();
+    if (keyNode != null) {
+      GrammarTypeName name = GrammarElementFactory.createTypeName(getProject(), newName);
+      ASTNode newKeyNode = name.getNode().getFirstChildNode();
+      getNode().replaceChild(keyNode, newKeyNode);
+    }
+    return this;
+  }
+
+  public PsiElement getNameIdentifier() {
+    return getNode().getPsi();
+  }
+
+}