diff --git a/.gitmodules b/.gitmodules
index 3c84ce173620beb96fe04cfbf8f12dc315eabe80..a8b57b043c81bc4bd581b4c0dc3abe7e3ecc6ffe 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
 [submodule "relast.preprocessor"]
 	path = relast.preprocessor
 	url = ../relast-preprocessor.git
+[submodule "dumpAst/src/main/jastadd/mustache"]
+	path = dumpAst/src/main/jastadd/mustache
+	url = ../mustache
diff --git a/dumpAst/build.gradle b/dumpAst/build.gradle
index 9580ac1001708897e38908ec6e44c087f4d1db8a..84b5e8972a6d7da3df94099b54d50b259ee4b412 100644
--- a/dumpAst/build.gradle
+++ b/dumpAst/build.gradle
@@ -61,6 +61,7 @@ test {
 }
 
 File dumpAstGrammar = file('./src/main/jastadd/DumpAst.relast')
+File mustacheGrammar = file('./src/main/jastadd/mustache/Mustache.relast')
 
 task relast(type: JavaExec) {
     group = 'Build'
@@ -77,7 +78,7 @@ task relast(type: JavaExec) {
     args = [
             "../libs/relast.jar",
             dumpAstGrammar,
-//            "./src/main/jastadd/MustacheNodes.relast",
+            mustacheGrammar,
             "--listClass=java.util.ArrayList",
             "--jastAddList=JastAddList",
             "--useJastAddNames",
@@ -87,7 +88,8 @@ task relast(type: JavaExec) {
     ]
 
     inputs.files(file("../libs/relast.jar"),
-            dumpAstGrammar)
+            dumpAstGrammar,
+            mustacheGrammar)
     outputs.files(file("./src/gen/jastadd/DumpAst.ast"),
             file("./src/gen/jastadd/DumpAst.jadd"),
             file("./src/gen/jastadd/DumpAstRefResolver.jadd"),
diff --git a/dumpAst/src/main/jastadd/DumpAst.relast b/dumpAst/src/main/jastadd/DumpAst.relast
index c1b1ed92c553bcdf7950bec1f328e4e6fac9777b..e1ca0cd437443c3035b156a31d3baa77b3daba5b 100644
--- a/dumpAst/src/main/jastadd/DumpAst.relast
+++ b/dumpAst/src/main/jastadd/DumpAst.relast
@@ -1,4 +1,6 @@
 DumpAst ::= DumpNode* <PackageName> BuildConfig PrintConfig ;
+rel DumpAst.RootNode -> DumpNode ;
+
 BuildConfig ::= <TypeIgnore> <TokenIgnore> <ChildIgnore> <AttributeInclude> <NonterminalAttributeInclude> <RelationIgnore> <IncludeEmptyString:boolean> <Debug:boolean> ;
 PrintConfig ::= <Scale:double> <Version> Header* ;
 Header ::= <Value> ;
diff --git a/dumpAst/src/main/jastadd/Generation.jadd b/dumpAst/src/main/jastadd/Generation.jadd
index 111d76778ddf21b28c35fedcd0de03deed3698c0..f0e7dc5735e5768b07fb111b41cc82995d8d028c 100644
--- a/dumpAst/src/main/jastadd/Generation.jadd
+++ b/dumpAst/src/main/jastadd/Generation.jadd
@@ -180,8 +180,8 @@ import java.lang.String;aspect GenerationFrontend {
       return this;
     }
 
-    public DumpBuilder dumpAsYaml(java.nio.file.Path destination) throws java.io.IOException {
-      String content = build().toYaml();
+    public DumpBuilder dumpAsYaml(java.nio.file.Path destination, boolean prependCreationComment) throws java.io.IOException {
+      String content = build().toYaml(prependCreationComment);
       try (java.io.Writer writer = java.nio.file.Files.newBufferedWriter(destination)) {
         writer.write(content);
       }
@@ -201,6 +201,7 @@ aspect GenerationBackend {
   protected DumpNode DumpAst.transform(TransformationTransferInformation tti, Object obj)
       throws java.lang.reflect.InvocationTargetException, IllegalAccessException, NoSuchMethodException {
     DumpNode result = transform(tti, obj, Source.ROOT);
+    setRootNode(result);
     // post-process relationTargetsUnprocessed
     boolean someAreUnprocessed = true;
     while (someAreUnprocessed) {
@@ -538,8 +539,62 @@ aspect GenerationBackend {
     return sb.toString();
   }
 
-  syn String DumpAst.toYaml() {
-    return "TODO :)";
+  syn String DumpAst.toYaml(boolean prependCreationComment) {
+    Document doc = new Document();
+    doc.setRootElement(getRootNode().toYaml());
+    return doc.prettyPrint(prependCreationComment);
+  }
+
+  syn MappingElement DumpNode.toYaml() {
+    MappingElement result = new MappingElement();
+    // tokens are key-value-pairs
+    for (DumpToken token : getDumpTokenList()) {
+      if (token.isDumpValueToken()) {
+        result.put(cleanLabel(token.label()), makeValueElement(token.asDumpValueToken().getValue()));
+      } else {
+        result.put(cleanLabel(token.label()), token.asDumpReferenceToken().getValue().toYaml());
+      }
+    }
+    // children
+    for (DumpChildNode child : getDumpChildNodeList()) {
+      ListElement list = new ListElement();
+      for (DumpNode inner : child.innerNodes(true)) {
+        list.add(inner.toYaml());
+      }
+      if (child.isList()) {
+        result.put(cleanLabel(child.label()), list);
+      } else if (list.getNumElement() == 1) {
+        result.put(cleanLabel(child.label()), list.getElement(0));
+      }
+    }
+    // relations
+    for (DumpRelation relation : getDumpRelationList()) {
+      ListElement list = new ListElement();
+      for (DumpNode inner : relation.innerNodes(true)) {
+        list.add(inner.toYaml());
+      }
+      if (relation.isList()) {
+        result.put(cleanLabel(relation.label()), list);
+      } else if (list.getNumElement() == 1) {
+        result.put(cleanLabel(relation.label()), list.getElement(0));
+      }
+    }
+    return result;
+  }
+
+  private static ComplexElement ASTNode.HELPER_COMPLEX_ELEMENT = new MappingElement();
+  protected static Element ASTNode.makeValueElement(Object obj) {
+    if (obj instanceof Integer) {
+      return ValueElement.of((int) obj);
+    } else if (obj instanceof Boolean) {
+      return ValueElement.of((boolean) obj);
+    } else {
+      return HELPER_COMPLEX_ELEMENT.makeStringElement(obj.toString());
+    }
+  }
+
+  private String DumpNode.cleanLabel(String originalLabel) {
+    return originalLabel.replace("()", "");
   }
 
   public class AppendableWriter extends java.io.Writer {
diff --git a/dumpAst/src/main/jastadd/Navigation.jrag b/dumpAst/src/main/jastadd/Navigation.jrag
index e03dbf37a0d9c7a615de6f7641fb730460b4199b..0f4687dbcb5af2c3f222ef43c9b957d79d3cf780 100644
--- a/dumpAst/src/main/jastadd/Navigation.jrag
+++ b/dumpAst/src/main/jastadd/Navigation.jrag
@@ -13,6 +13,10 @@ aspect Navigation {
   syn DumpValueToken DumpToken.asDumpValueToken() = null;
   eq DumpValueToken.asDumpValueToken() = this;
 
+  // --- asDumpReferenceToken ---
+  syn DumpReferenceToken DumpToken.asDumpReferenceToken() = null;
+  eq DumpReferenceToken.asDumpReferenceToken() = this;
+
   // --- buildConfig ---
   inh BuildConfig DumpNode.buildConfig();
   eq DumpAst.getChild().buildConfig() = getBuildConfig();
diff --git a/dumpAst/src/main/jastadd/mustache b/dumpAst/src/main/jastadd/mustache
new file mode 160000
index 0000000000000000000000000000000000000000..c10bed0d03e3fa18b8133ce1de48de7646899615
--- /dev/null
+++ b/dumpAst/src/main/jastadd/mustache
@@ -0,0 +1 @@
+Subproject commit c10bed0d03e3fa18b8133ce1de48de7646899615
diff --git a/testDumper/build.gradle b/testDumper/build.gradle
index 9980fef2d08a4422fc26a598b495b1dc16d18ce1..d17865230d96006e899e1b4f85373887debe8dcb 100644
--- a/testDumper/build.gradle
+++ b/testDumper/build.gradle
@@ -13,7 +13,7 @@ buildscript {
 }
 
 dependencies {
-    runtime group: 'org.jastadd', name: 'jastadd', version: '2.3.4'
+//    runtime group: 'org.jastadd', name: 'jastadd', version: '2.3.4'
 
     testImplementation project(':dumpAst')
     testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.4.0'
diff --git a/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestDumperMain.java b/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestDumperMain.java
new file mode 100644
index 0000000000000000000000000000000000000000..fc3d4c80558d64cf5dc882522e8afd11db04258a
--- /dev/null
+++ b/testDumper/src/test/java/de/tudresden/inf/st/jastadd/testDumper/TestDumperMain.java
@@ -0,0 +1,41 @@
+package de.tudresden.inf.st.jastadd.testDumper;
+
+import org.jastadd.testDumper.ast.A;
+import org.jastadd.testDumper.ast.B;
+import org.jastadd.testDumper.ast.C;
+import org.jastadd.testDumper.ast.Root;
+
+public class TestDumperMain {
+  public static void main(String[] args) {
+    Root root = new Root();
+    root.setName("Root1");
+    A a = new A();
+    a.setName("A2");
+    B b1 = new B();
+    b1.setName("B3");
+    C c = new C();
+    c.setName("C4");
+    c.setRawReference(a);
+    b1.setOneA(a);
+    B b2 = new B();
+    b2.setName("B5");
+    C myC = new C();
+    myC.setName("C6");
+    a.setMyC(myC);
+    root.setA(a);
+    root.addB(b1);
+    root.addB(b2);
+    root.setC(c);
+
+    TestUtils.ExposingDumpBuilder builder = new TestUtils.ExposingDumpBuilder(root);
+    builder.includeAttributes("simpleAttr")
+        .includeNonterminalAttributes("getCalculated");
+
+    System.out.println(">> PlantUml");
+    System.out.println(builder.build().toPlantUml());
+
+    System.out.println(">> YAML begin");
+    System.out.println(builder.build().toYaml(true));
+    System.out.println(">> YAML end");
+  }
+}