diff --git a/build.gradle b/build.gradle
index f9795a4d764e618fb537cd37a57bf6a412d8267c..f9afaaf64eb1bc07821b85b8888dd4f183918f7b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,5 +1,8 @@
+
+apply plugin: 'java'
 apply plugin: 'jastadd'
 apply plugin: 'application'
+apply plugin: "idea"
 
 sourceCompatibility = 1.8
 
@@ -20,13 +23,11 @@ dependencies {
     testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.0'
     testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.0'
     testCompile 'org.assertj:assertj-core:3.12.1'
-    compile "com.fasterxml.jackson.core:jackson-core:${jackson_version}"
-    compile "com.fasterxml.jackson.core:jackson-databind:${jackson_version}"
+    compile 'com.fasterxml.jackson.core:jackson-core:2.9.8'
+    compile 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
     compile 'org.jastadd:jastadd:2.3.4'
     runtime 'org.jastadd:jastadd:2.3.4'
     compile group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
-    compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.10.0'
-    compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.10.0'
 }
 
 sourceSets {
@@ -52,6 +53,39 @@ jar {
     }
 }
 
+task relast(type: JavaExec) {
+    group = 'Build'
+    main = "-jar"
+
+    doFirst {
+        delete "src/gen/jastadd/*.ast"
+        delete "src/gen/jastadd/Ros2Rag.jadd"
+        delete "src/gen/jastadd/Ros2RagRefResolver.jadd"
+        delete "src/gen/jastadd/Ros2RagResolverStubs.jrag"
+        mkdir  "src/gen/jastadd/"
+    }
+
+    args = [
+            "../libs/relast.jar",
+            "./src/main/jastadd/RelAst.relast",
+            "./src/main/jastadd/Ros2Rag.relast",
+            "--listClass=java.util.ArrayList",
+            "--jastAddList=JastAddList",
+            "--useJastAddNames",
+            "--file",
+            "--resolverHelper",
+            "--grammarName=./src/gen/jastadd/RelAST"
+    ]
+
+    inputs.files file("../libs/relast.jar"),
+            file("src/main/jastadd/RelAST.relast"),
+            file("src/main/jastadd/Ros2Rag.relast")
+    outputs.files file("./src/gen/jastadd/RelAst.ast"),
+            file("src/gen/jastadd/RelAst.jadd"),
+            file("src/gen/jastadd/RelAstRefResolver.jadd"),
+            file('src/gen/jastadd/RelAstResolverStubs.jrag')
+}
+
 jastadd {
     configureModuleBuild()
     modules {
@@ -65,10 +99,13 @@ jastadd {
             }
 
             jastadd {
-                basedir "src/main/jastadd/"
-                include "**/*.ast"
-                include "**/*.jadd"
-                include "**/*.jrag"
+                basedir "."
+                include "src/main/jastadd/**/*.ast"
+                include "src/main/jastadd/**/*.jadd"
+                include "src/main/jastadd/**/*.jrag"
+                include "src/gen/jastadd/**/*.ast"
+                include "src/gen/jastadd/**/*.jadd"
+                include "src/gen/jastadd/**/*.jrag"
             }
 
             scanner {
@@ -106,6 +143,7 @@ jastadd {
     scanner.genDir = "src/gen/java/org/jastadd/ros2rag/scanner"
     parser.genDir = "src/gen/java/org/jastadd/ros2rag/parser"
 
-    jastaddOptions = ["--lineColumnNumbers", "--safeLazy", "--visitCheck=true", "--rewrite=cnta", "--cache=all"]
+    jastaddOptions = ["--lineColumnNumbers", "--List=JastAddList", "--safeLazy", "--visitCheck=true", "--rewrite=cnta", "--cache=all"]
 }
 
+generateAst.dependsOn relast
diff --git a/src/main/jastadd/Analysis.jrag b/src/main/jastadd/Analysis.jrag
index 21456331346ac897ee8f597c52e93c1ac8edb498..118dd2373e1fb883c829cb8867cb3d898f574e07 100644
--- a/src/main/jastadd/Analysis.jrag
+++ b/src/main/jastadd/Analysis.jrag
@@ -1,277 +1,3 @@
-import java.util.*;
+aspect Analysis {
 
-
-aspect TypeAnalysis {
-  public abstract TypeUse Component.getTypeUse();
-
-  //--- lookupType ---
-  syn TypeDecl TypeUse.decl() = lookupType(getID());
-  inh TypeDecl TypeUse.lookupType(String name);
-  inh TypeDecl TypeDecl.lookupType(String name);
-  eq Program.getChild().lookupType(String name) {
-    for (TypeDecl td : getTypeDecls()) {
-      if (td.getID().equals(name)) {
-        return td;
-      }
-    }
-    return null;
-  }
-
-  //--- isAlreadyDeclared ---
-  syn boolean TypeDecl.isAlreadyDeclared() = lookupType(getID()) != this;
-}
-
-aspect ComponentAnalysis {
-  //--- isTargetOfDirectedRelation ---
-  inh boolean Component.isTargetOfDirectedRelation();
-  eq Relation.getRight().isTargetOfDirectedRelation() = getDirection() instanceof RightDirection;
-  eq Program.getChild().isTargetOfDirectedRelation() = false;
-
-  //--- name ---
-  syn String Component.name() = getID();
-
-  //--- enclosingTypeDecl ---
-  inh TypeDecl Component.enclosingTypeDecl();
-  eq TypeDecl.getChild().enclosingTypeDecl() = this;
-  eq Program.getChild().enclosingTypeDecl() = null;
-
-  //--- otherSide ---
-  inh RelationComponent RelationComponent.opposite();
-  eq Relation.getLeft().opposite() = getRight();
-  eq Relation.getRight().opposite() = getLeft();
-  eq Program.getChild().opposite() = null;
-
-  //--- ofTypeDecl ---
-  syn TypeDecl RelationComponent.ofTypeDecl() = opposite().getTypeUse().decl();
-
-  //--- isAlreadyDeclared ---
-  /**
-   * Check, if role with the same name is already declared on the same nonterminal
-   */
-  syn boolean RelationComponent.isAlreadyDeclared()
-    = !isTargetOfDirectedRelation()                     /* if unnamed in relation, there is no role name, so no error */
-      && getTypeUse().decl() != null                           /* nonterminal type of role is defined */
-      && findComponent(getTypeUse().decl(), name()) != this;   /* there is another role defined previously with the same name */
-
-  //--- findComponent ---
-  /** Search for either a component on the RHS of the given type with the given name,
-   *   or a relation part for the given type and a role with the given name */
-  inh Component Component.findComponent(TypeDecl td, String name);
-  eq Program.getChild().findComponent(TypeDecl td, String name)
-    = findComponentSyn(td, name);
-  syn Component Program.findComponentSyn(TypeDecl td, String name) {
-    for (Component c: td.getComponents()) {
-      if (c.name().equals(name)) {
-        return c;
-      }
-    }
-
-    for (Relation r : getRelations()) {
-      if (r.getLeft().matches(td, name))
-        return r.getLeft();
-      if (r.getRight().matches(td, name))
-        return r.getRight();
-    }
-
-    return null;
-  }
-
-  //--- isInvalidRedefinition ---
-  /**
-   * Check, if a component with the same name is already declared in some supertype
-   */
-  syn boolean Component.isInvalidRedefinition() = invalidRedefinition() != null;
-
-  /**
-   * Check, if a component with the same name is already declared in some supertype, and return it, if any
-   */
-  syn Component Component.invalidRedefinition() = null;
-  eq TokenComponent.invalidRedefinition() = invalidRedefinitionOn(enclosingTypeDecl());
-  eq RelationComponent.invalidRedefinition() = invalidRedefinitionOn(getTypeUse().decl());
-
-  syn Component Component.invalidRedefinitionOn(TypeDecl td) {
-    if (td == null) return null;
-
-    while (td.hasSuper() && td.getSuper().decl() != null) {
-      td = td.getSuper().decl();
-      // find a matching component on the RHS of the (current) super type
-      Component c = findComponent(td, getID());
-
-      if (c != null && !this.isEqual(c)) return c;
-    }
-    return null;
-  }
-
-  //--- isEqual ---
-  syn boolean Component.isEqual(Component c) = this.getClass() == c.getClass() && getTypeUse().isEqual(c.getTypeUse());
-
-  /**
-   * TokenComponents may be specialized by NTATokenComponents and vice versa
-   */
-  eq TokenComponent.isEqual(Component c) = (c instanceof TokenComponent) && getTypeUse().isEqual(c.getTypeUse());
-
-  syn boolean TypeUse.isEqual(TypeUse u);
-  eq SimpleTypeUse.isEqual(TypeUse u) = u instanceof SimpleTypeUse && getID().equals(u.getID());
-  eq ParameterizedTypeUse.isEqual(TypeUse u) {
-    if (!getID().equals(u.getID())) return false;
-    if (!(u instanceof ParameterizedTypeUse)) return false;
-    ParameterizedTypeUse pu = (ParameterizedTypeUse) u;
-    if (getNumTypeUse() != pu.getNumTypeUse()) return false;
-    for (int i = 0; i < getNumTypeUse(); i++) {
-      if (!getTypeUse(i).isEqual(pu.getTypeUse(i))) return false;
-    }
-    return true;
-  }
-
-  //--- matches ---
-  /**
-   * @return true, if the component has both type and role, its type matches the given typeDecl and its name matches the given name
-   */
-  syn boolean RelationComponent.matches(TypeDecl td, String name)
-    = !isTargetOfDirectedRelation() && getTypeUse().decl() == td && name().equals(name);
-
-  //--- relationComponents ---
-  coll Set<RelationComponent> TypeDecl.relationComponents()
-    [new HashSet<RelationComponent>()]
-    root Program;
-  RelationComponent contributes this
-    when !isTargetOfDirectedRelation() && getTypeUse().decl() != null
-    to TypeDecl.relationComponents()
-    for getTypeUse().decl();
-
-  //--- relationComponentsTransitive ---
-  syn Collection<RelationComponent> TypeDecl.relationComponentsTransitive() {
-    Collection<RelationComponent> list = new ArrayList<>();
-    if (hasSuper() && getSuper().decl() != null) {
-      list.addAll(getSuper().decl().relationComponentsTransitive());
-    }
-    list.addAll(relationComponents());
-    return list;
-  }
-
-  //--- oneRelationComponents ---
-  syn Set<OneRelationComponent> TypeDecl.oneRelationComponents() {
-    Set<OneRelationComponent> set = new HashSet<>();
-    for (RelationComponent rc: relationComponents()) {
-      if (rc instanceof OneRelationComponent) {
-        set.add((OneRelationComponent) rc);
-      }
-    }
-    return set;
-  }
-
-  //--- needUnresolvedClass ---
-  syn boolean TypeDecl.needUnresolvedClass() {
-    // a TypeDecl needs an unresolved class, if it can appear in a relation
-    // TODO
-    return true;
-  }
-
-  //--- isList ---
-  syn boolean Component.isList() = false;
-  eq ListComponent.isList() = true;
-  eq NTAListComponent.isList() = true;
-  eq ManyRelationComponent.isList() = true;
-
-  //--- isOpt ---
-  syn boolean Component.isOpt() = false;
-  eq OptComponent.isOpt() = true;
-  eq NTAOptComponent.isOpt() = true;
-  eq OptionalRelationComponent.isOpt() = true;
-
-  //--- isNullable ---
-  syn boolean Component.isNullable() = false;
-  eq TokenComponent.isNullable() = !"float double int short long char byte boolean".contains(getTypeUse().getID());
-}
-
-aspect InstanceSupplier {
-
-  //--- program ---
-  inh Program TypeDecl.program();
-  eq Program.getTypeDecl(int i).program() = this;
-
-  //--- subTypeDecls ---
-  syn Collection<TypeDecl> TypeDecl.subTypeDecls() {
-    Collection<TypeDecl> subDecls = new ArrayList();
-    for (TypeDecl decl : program().getTypeDeclList()) {
-      if (decl.hasSuper() && decl.getSuper().getID().equals(getID())) {
-        subDecls.add(decl);
-      }
-    }
-    return subDecls;
-  }
-
-  //--- instantiableSubType ---
-  syn TypeDecl TypeDecl.instantiableSubType() {
-    if (getAbstract() == false) {
-      return this;
-    } else {
-      for (TypeDecl sub : subTypeDecls()) {
-        if (sub.getAbstract() == false) {
-          return sub;
-        } else {
-          TypeDecl subInstance = sub.instantiableSubType();
-          if (subInstance != null) {
-            return subInstance;
-          }
-        }
-      }
-    }
-    return null;
-  }
-}
-
-aspect Constructors {
-  //--- componentsTransitive ---
-  syn Collection<Component> TypeDecl.componentsTransitive() {
-    ArrayList<Component> list = new ArrayList<>();
-    if (hasSuper() && getSuper().decl() != null) {
-      list.addAll(getSuper().decl().componentsTransitive());
-    }
-    for (Component c: getComponents()) {
-      if (c.inConstructor()) {
-        list.add(c);
-      }
-    }
-    return list;
-  }
-
-  //--- needsConstructor ---
-  syn boolean TypeDecl.needsConstructor() = !componentsTransitive().isEmpty() && !relationComponentsTransitive().isEmpty();
-
-  //--- inConstructor ---
-  /**
-   * @return true, if the component should be added to the constructor (i.e., is not an NTA)
-   */
-  syn boolean Component.inConstructor() = true;
-  eq NTAComponent.inConstructor() = false;
-  eq NTAOptComponent.inConstructor() = false;
-  eq NTAListComponent.inConstructor() = false;
-  eq NTATokenComponent.inConstructor() = false;
-}
-
-aspect Utils {
-
-  //--- toString ---
-  public String SimpleTypeUse.toString() {
-    return getID();
-  }
-  public String ParameterizedTypeUse.toString() {
-    StringBuilder sb = new StringBuilder();
-    sb.append(getID()).append("<");
-    boolean first = true;
-    for (TypeUse u: getTypeUses()) {
-      if (first) {
-        first = false;
-      } else {
-        sb.append(", ");
-      }
-      sb.append(u.toString());
-    }
-    sb.append(">");
-    return sb.toString();
-  }
-  public String TypeDecl.toString() {
-    return getID();
-  }
 }
diff --git a/src/main/jastadd/DumpTree.jrag b/src/main/jastadd/DumpTree.jrag
index 2d2f3403c7c03738cd6ff6e4351d22dadc440988..0c119fd24a42983e26c16b9056611571a6e61f8a 100644
--- a/src/main/jastadd/DumpTree.jrag
+++ b/src/main/jastadd/DumpTree.jrag
@@ -33,7 +33,7 @@ aspect DumpTree {
   public String ASTNode.extraDumpInfo() { return ""; }
 
   public String ASTNode.getTokens() {
-    java.util.TreeSet<java.lang.reflect.Method> methods = new java.util.TreeSet<>(Comparator.comparing(java.lang.reflect.Method::getName));
+    java.util.TreeSet<java.lang.reflect.Method> methods = new java.util.TreeSet<>(java.util.Comparator.comparing(java.lang.reflect.Method::getName));
 
     methods.addAll(java.util.Arrays.asList(getClass().getMethods()));
 
diff --git a/src/main/jastadd/Errors.jrag b/src/main/jastadd/Errors.jrag
index b1ec073575e4ea6c15e924c1f6c6b95eeaba2cba..60bdf24708ed6b26bd1094bff8185ff07de62fe3 100644
--- a/src/main/jastadd/Errors.jrag
+++ b/src/main/jastadd/Errors.jrag
@@ -1,138 +1,65 @@
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.LinkedList;
-
-aspect Errors {
-  coll Set<ErrorMessage> Program.errors()
-    [new TreeSet<ErrorMessage>()]
-    root Program;
-
-  TypeUse contributes error("Type '" + getID() + "' not found")
-    when decl() == null && !isToken()
-    to Program.errors();
-
-  TypeDecl contributes error("Type '" + getID() + "' is already declared")
-    when isAlreadyDeclared()
-    to Program.errors();
-
-  RelationComponent contributes error("Role '" + name()
-      + "' is already declared for type '" + getTypeUse().decl() + "'")
-    when isAlreadyDeclared()
-    to Program.errors();
-
-  RelationComponent contributes error("Role '" + name()
-    + "' is an invalid redefinition for type '" + getTypeUse().decl() + "', conflicts with supertype '"
-    + invalidRedefinition().enclosingTypeDecl() + "'")
-    when isInvalidRedefinition()
-    to Program.errors();
-
-  TokenComponent contributes error("Token '" + name()
-    + "' is an invalid redefinition for type '" + enclosingTypeDecl() + "', conflicts with supertype '"
-    + invalidRedefinition().enclosingTypeDecl() + "'")
-    when isInvalidRedefinition()
-    to Program.errors();
-
-  RelationComponent contributes
-    error("Role name missing for type '" + getTypeUse().decl() + "'")
-    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() && !multiplicityOne()
-    to Program.errors();
-}
-
-aspect HelpAttributes {
-  inh Program ASTNode.program();
-  eq Program.getChild().program() = this;
-
-  inh boolean TypeUse.isToken();
-  eq Program.getChild().isToken() = false;
-  eq TokenComponent.getTypeUse().isToken() = true;
-
-  syn boolean RelationComponent.multiplicityOne() = false;
-  eq OneRelationComponent.multiplicityOne() = true;
-  syn boolean RelationComponent.multiplicityOpt() = false;
-  eq OptionalRelationComponent.multiplicityOpt() = true;
-  syn boolean RelationComponent.multiplicityMany() = false;
-  eq ManyRelationComponent.multiplicityMany() = true;
-
-  inh ContainedInFile Component.enclosingFileContainer();
-  eq TypeDecl.getComponent().enclosingFileContainer() = this;
-  eq Relation.getChild().enclosingFileContainer() = this;
-  inh ContainedInFile TypeUse.enclosingFileContainer();
-  eq SimpleTypeComponent.getTypeUse().enclosingFileContainer() = enclosingFileContainer();
-  eq TokenComponent.getTypeUse().enclosingFileContainer() = enclosingFileContainer();
-  eq TypeDecl.getSuper().enclosingFileContainer() = this;
-
-  syn String ASTNode.containedFile() = "Unknown";
-  eq Component.containedFile() = enclosingFileContainer() == null ? "Unknown2" : enclosingFileContainer().containedFile();
-  eq TypeUse.containedFile() = enclosingFileContainer() == null ? "Unknown3" : enclosingFileContainer().containedFile();
-  eq TypeDecl.containedFile() = getFileName();
-  eq Relation.containedFile() = getFileName();
-}
-
-aspect ErrorMessage {
-  public class ErrorMessage implements Comparable<ErrorMessage> {
-    private final ASTNode node;
-    private final String filename;
-    private final int line;
-    private final int col;
-    private final String message;
-
-    public ErrorMessage(ASTNode node, String message) {
-      this.node = node;
-      this.filename = node.containedFile();
-      this.line = node.getStartLine();
-      this.col = node.getStartColumn();
-      this.message = message;
-    }
-
-    public ASTNode getNode() {
-      return node;
-    }
-    public int getLine() {
-      return line;
-    }
-    public int getCol() {
-      return col;
-    }
-    public String getMessage() {
-      return message;
-    }
-
-    public String toString() {
-      return filename + " Line " + line + ", column " + col + ": " + message;
-    }
-
-    @Override
-    public int compareTo(ErrorMessage err) {
-      int n = filename.compareTo(err.filename);
-      if (n != 0) {
-        return n;
-      }
-
-      n = line - err.line;
-      if (n != 0) {
-        return n;
-      }
-
-      n = col-err.col;
-      if (n != 0) {
-        return n;
-      }
-
-      return message.compareTo(err.message);
-    }
-  }
-
-  protected ErrorMessage ASTNode.error(String message) {
-    return new ErrorMessage(this, message);
-  }
-}
+//import java.util.Set;
+//import java.util.TreeSet;
+//import java.util.LinkedList;
+//
+//
+//
+//
+//aspect ErrorMessage {
+//  public class ErrorMessage implements Comparable<ErrorMessage> {
+//    private final ASTNode node;
+//    private final String filename;
+//    private final int line;
+//    private final int col;
+//    private final String message;
+//
+//    public ErrorMessage(ASTNode node, String message) {
+//      this.node = node;
+//      this.filename = node.containedFile().getFileName();
+//      this.line = node.getStartLine();
+//      this.col = node.getStartColumn();
+//      this.message = message;
+//    }
+//
+//    public ASTNode getNode() {
+//      return node;
+//    }
+//    public int getLine() {
+//      return line;
+//    }
+//    public int getCol() {
+//      return col;
+//    }
+//    public String getMessage() {
+//      return message;
+//    }
+//
+//    public String toString() {
+//      return filename + " Line " + line + ", column " + col + ": " + message;
+//    }
+//
+//    @Override
+//    public int compareTo(ErrorMessage err) {
+//      int n = filename.compareTo(err.filename);
+//      if (n != 0) {
+//        return n;
+//      }
+//
+//      n = line - err.line;
+//      if (n != 0) {
+//        return n;
+//      }
+//
+//      n = col-err.col;
+//      if (n != 0) {
+//        return n;
+//      }
+//
+//      return message.compareTo(err.message);
+//    }
+//  }
+//
+//  protected ErrorMessage ASTNode.error(String message) {
+//    return new ErrorMessage(this, message);
+//  }
+//}
diff --git a/src/main/jastadd/NameResolution.jrag b/src/main/jastadd/NameResolution.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..ed0cbd6035364a52319986269807db5bcbbf6eb5
--- /dev/null
+++ b/src/main/jastadd/NameResolution.jrag
@@ -0,0 +1,15 @@
+aspect NameResolution {
+
+  refine RefResolverStubs eq ASTNode.globallyResolveTypeDeclByToken(String id) = program().resolveTypeDecl(id);
+
+  syn TypeDecl Program.resolveTypeDecl(String name) {
+    for (TypeDecl decl : typeDecls()) {
+      if (decl.getName().equals(name)) {
+        return decl;
+      }
+    }
+    throw new RuntimeException("TypeDecl " + name + " could not be resolved.");
+  }
+
+
+}
diff --git a/src/main/jastadd/Navigation.jrag b/src/main/jastadd/Navigation.jrag
new file mode 100644
index 0000000000000000000000000000000000000000..b6028726b4406353f1acb0711d69ff66c509d661
--- /dev/null
+++ b/src/main/jastadd/Navigation.jrag
@@ -0,0 +1,28 @@
+aspect Navigation {
+
+  inh Program ASTNode.program();
+  eq Program.getChild().program() = this;
+
+  coll java.util.Set<TypeDecl> Program.typeDecls() [new java.util.HashSet<>()] root Program;
+  TypeDecl contributes this
+    to Program.typeDecls()
+    for program();
+
+  coll java.util.Set<Relation> Program.relations() [new java.util.HashSet<>()] root Program;
+  Relation contributes this
+    to Program.relations()
+    for program();
+
+  inh TypeDecl Component.containingTypeDecl();
+  eq TypeDecl.getChild().containingTypeDecl() = this;
+
+//  syn boolean RelationComponent.multiplicityOne() = false;
+//  eq OneRelationComponent.multiplicityOne() = true;
+//  syn boolean RelationComponent.multiplicityOpt() = false;
+//  eq OptionalRelationComponent.multiplicityOpt() = true;
+//  syn boolean RelationComponent.multiplicityMany() = false;
+//  eq ManyRelationComponent.multiplicityMany() = true;
+
+  inh GrammarFile ASTNode.containedFile();
+  eq GrammarFile.getChild().containedFile() = this;
+}
diff --git a/src/main/jastadd/RelAst.ast b/src/main/jastadd/RelAst.ast
deleted file mode 100644
index 31083b99eda970809f5f61e6e44a8e4fb23d1a68..0000000000000000000000000000000000000000
--- a/src/main/jastadd/RelAst.ast
+++ /dev/null
@@ -1,28 +0,0 @@
-Program ::= TypeDecl* Relation*;
-abstract ContainedInFile ::= <FileName> ;
-TypeDecl : ContainedInFile ::= <ID> <Abstract:boolean> [Super:TypeUse] Component*;
-
-abstract Component ::= <ID>;
-abstract SimpleTypeComponent : Component ::= TypeUse:SimpleTypeUse;
-NormalComponent : SimpleTypeComponent;
-ListComponent : SimpleTypeComponent;
-OptComponent : SimpleTypeComponent;
-NTAComponent : SimpleTypeComponent;
-NTAOptComponent : SimpleTypeComponent;
-NTAListComponent : SimpleTypeComponent;
-TokenComponent : Component ::= TypeUse;
-NTATokenComponent : TokenComponent ::= TypeUse;
-
-abstract TypeUse ::= <ID>;
-SimpleTypeUse : TypeUse;
-ParameterizedTypeUse : TypeUse ::= TypeUse*;
-
-Relation : ContainedInFile ::= Left:RelationComponent Direction Right:RelationComponent;
-abstract RelationComponent : SimpleTypeComponent;
-OneRelationComponent : RelationComponent;
-OptionalRelationComponent : RelationComponent;
-ManyRelationComponent : RelationComponent;
-abstract Direction;
-RightDirection : Direction;
-LeftDirection : Direction;
-Bidirectional : Direction;
diff --git a/src/main/jastadd/RelAst.flex b/src/main/jastadd/RelAst.flex
index 4fc2773b90da327133afbeead5533ceac9fc0184..b0a3fd2e5ad19d90580960340bd7b99b35a1897a 100644
--- a/src/main/jastadd/RelAst.flex
+++ b/src/main/jastadd/RelAst.flex
@@ -44,7 +44,7 @@ ID = [a-zA-Z$_][a-zA-Z0-9$_]*
 
 %%
 {WhiteSpace} { /* ignore */ }
-{Comment}    { /* ignore */ }
+{Comment}    { return sym(Terminals.COMMENT); }
 
 "abstract"   { return sym(Terminals.ABSTRACT); }
 "rel"        { return sym(Terminals.RELATION); }
diff --git a/src/main/jastadd/RelAst.parser b/src/main/jastadd/RelAst.parser
index 12a7044e722f07ebce04c83fb4f37dc0a3f15c13..f94fbef474825bbd669f89ce070b2ce8fc406c72 100644
--- a/src/main/jastadd/RelAst.parser
+++ b/src/main/jastadd/RelAst.parser
@@ -1,123 +1,218 @@
-Program goal =
-  /* empty */              {: return new Program(); :}
-  | type_decl.t goal.p     {: p.getTypeDeclList().insertChild(t, 0); return p; :}
-  | relation.r goal.p      {: p.getRelationList().insertChild(r, 0); return p; :}
-  ;
+GrammarFile goal
+  = declaration.d goal.p     {: p.getDeclarationList().insertChild(d, 0); return p; :}
+  |                          {: return new GrammarFile(); :}
+;
 
-TypeDecl type_decl =
-  ID type_decl_super.s components_opt.c SCOL
+Declaration declaration
+  = type_decl
+  | relation
+  | comment
+;
+
+Comment comment
+  = COMMENT  {: return new Comment(COMMENT); :};
+
+TypeDecl type_decl
+  = ID components_opt.c SCOL
     {:
       TypeDecl result = new TypeDecl();
-      result.setID(ID);
+      result.setName(ID);
       result.setAbstract(false);
-      result.setSuperOpt(s);
       result.setComponentList(c);
       return result;
     :}
-  | ABSTRACT ID type_decl_super.s components_opt.c SCOL
-      {:
-        TypeDecl result = new TypeDecl();
-        result.setID(ID);
-        result.setAbstract(true);
-        result.setSuperOpt(s);
-        result.setComponentList(c);
-        return result;
-      :}
-  ;
-
-Opt type_decl_super =
-  /* empty */ {: return new Opt(); :}
-  | COL s_type_use.u {: return new Opt(u); :}
-  ;
-
-SimpleTypeUse s_type_use =
-  ID {: return new SimpleTypeUse(ID); :}
-  ;
-
-ArrayList inner_type_use
-    = ID
-    | inner_type_use DOT ID
-    ;
-
-TypeUse type_use =
-  parameterized_type_use.p    {: return p; :}
-  | inner_type_use.p            {: return new SimpleTypeUse((String)p.stream().map( x -> ((Symbol)x).value.toString()).collect(java.util.stream.Collectors.joining("."))); :}
-  ;
-ParameterizedTypeUse parameterized_type_use =
-  inner_type_use.i LT type_use_list.l GT      {: return new ParameterizedTypeUse((String)i.stream().map( x -> ((Symbol)x).value.toString()).collect(java.util.stream.Collectors.joining(".")), l); :}
-  ;
-List type_use_list =
-  type_use.u                              {: return new List().add(u); :}
-  | type_use_list.l COMMA type_use.u      {: return l.add(u); :}
-  ;
-
-List components_opt =
-  /* empty */               {: return new List(); :}
+  | ID COL ID.s components_opt.c SCOL
+    {:
+      TypeDecl result = new TypeDecl();
+      result.setName(ID);
+      result.setAbstract(false);
+      result.setSuperType(TypeDecl.createRef(s));
+      result.setComponentList(c);
+      return result;
+    :}
+  | ABSTRACT ID components_opt.c SCOL
+    {:
+      TypeDecl result = new TypeDecl();
+      result.setName(ID);
+      result.setAbstract(true);
+      result.setComponentList(c);
+      return result;
+    :}
+  | ABSTRACT ID COL ID.s components_opt.c SCOL
+    {:
+      TypeDecl result = new TypeDecl();
+      result.setName(ID);
+      result.setAbstract(true);
+      result.setSuperType(TypeDecl.createRef(s));
+      result.setComponentList(c);
+      return result;
+    :}
+;
+
+JastAddList components_opt
+  = /* empty */             {: return new JastAddList(); :}
   | ASSIGN components.l     {: return l; :}
-  ;
+;
 
-List components =
-  /* empty */                   {: return new List(); :}
+JastAddList components
+  = /* empty */                 {: return new JastAddList(); :}
   | components.l component.c    {: return l.add(c); :}
-  ;
-
-Component component =
-    ID COL s_type_use.u                       {: return new NormalComponent(ID, u); :}
-  | s_type_use.u                              {: return new NormalComponent(u.getID(), u); :}
-  // List
-  | ID COL s_type_use.u STAR                  {: return new ListComponent(ID, u); :}
-  | s_type_use.u STAR                         {: return new ListComponent(u.getID(), u); :}
-  // Opt
-  | LBRACKET ID COL s_type_use.u RBRACKET     {: return new OptComponent(ID, u); :}
-  | LBRACKET s_type_use.u RBRACKET            {: return new OptComponent(u.getID(), u); :}
-  // NTA list
-  | SLASH ID COL s_type_use.u STAR SLASH      {: return new NTAListComponent(ID, u); :}
-  | SLASH s_type_use.u STAR SLASH             {: return new NTAListComponent(u.getID(), u); :}
-  // NTA opt
-  | SLASH LBRACKET ID COL s_type_use.u RBRACKET SLASH {: return new NTAOptComponent(ID, u); :}
-  | SLASH LBRACKET s_type_use.u RBRACKET SLASH {: return new NTAOptComponent(u.getID(), u); :}
-  // NTA
-  | SLASH ID COL s_type_use.u SLASH           {: return new NTAComponent(ID, u); :}
-  | SLASH s_type_use.u SLASH                  {: return new NTAComponent(u.getID(), u); :}
-  // NTA Token (same as NTA)
-  | SLASH LT ID COL s_type_use.u GT SLASH     {: return new NTATokenComponent(ID, u); :}
-  | SLASH LT ID GT SLASH                      {: return new NTATokenComponent(ID, new SimpleTypeUse("String")); :}
-  // Token
-  | LT ID COL type_use.u GT                   {: return new TokenComponent(ID, u); :}
-  | LT ID GT                                  {: return new TokenComponent(ID, new SimpleTypeUse("String")); :}
-  ;
-
-Relation relation =
-  RELATION relation_comp.l direction relation_comp.r SCOL
-   {:
-      Relation result = new Relation();
-      if (direction instanceof LeftDirection) {
-        result.setLeft(r);
-        result.setDirection(new RightDirection());
-        result.setRight(l);
-      } else {
-        result.setLeft(l);
-        result.setDirection(direction);
-        result.setRight(r);
-      }
-      return result;
-   :}
-  ;
-
-RelationComponent relation_comp =
-  // One
-  s_type_use.u DOT ID                       {: return new OneRelationComponent(ID, u); :}
-  | s_type_use.u                            {: return new OneRelationComponent("", u); :}
-  // Optional
-  | s_type_use.u DOT ID QUESTION_MARK       {: return new OptionalRelationComponent(ID, u); :}
-  | s_type_use.u QUESTION_MARK              {: return new OptionalRelationComponent("", u); :}
-  // Many
-  | s_type_use.u DOT ID STAR                {: return new ManyRelationComponent(ID, u); :}
-  | s_type_use.u STAR                       {: return new ManyRelationComponent("", u); :}
-  ;
-
-Direction direction =
-  RIGHT {: return new RightDirection(); :}
-  | LEFT {: return new LeftDirection(); :}
-  | BIDIRECTIONAL {: return new Bidirectional(); :}
-  ;
+;
+
+Component component
+  = SLASH actual_component.c SLASH
+      {:
+        c.setNTA(true);
+        return c;
+      :}
+  | actual_component
+;
+
+Component actual_component
+  = ID.name COL ID.type STAR
+    {:
+      ListComponent result = new ListComponent();
+      result.setName(name);
+      result.setTypeDecl(TypeDecl.createRef(type));
+      return result;
+    :}
+  | ID.name COL ID.type
+    {:
+      NormalComponent result = new NormalComponent();
+      result.setName(name);
+      result.setTypeDecl(TypeDecl.createRef(type));
+      return result;
+    :}
+  | ID.type STAR
+    {:
+      ListComponent result = new ListComponent();
+      result.setName(type);
+      result.setTypeDecl(TypeDecl.createRef(type));
+      return result;
+    :}
+  | ID.type
+    {:
+      NormalComponent result = new NormalComponent();
+      result.setName(type);
+      result.setTypeDecl(TypeDecl.createRef(type));
+      return result;
+    :}
+  | LBRACKET ID.name COL ID.type RBRACKET
+    {:
+      OptComponent result = new OptComponent();
+      result.setName(name);
+      result.setTypeDecl(TypeDecl.createRef(type));
+      return result;
+    :}
+  | LBRACKET ID.type RBRACKET
+    {:
+      OptComponent result = new OptComponent();
+      result.setName(type);
+      result.setTypeDecl(TypeDecl.createRef(type));
+      return result;
+    :}
+  | LT ID.name COL java_type_use.type GT
+    {:
+      TokenComponent result = new TokenComponent();
+      result.setName(name);
+      result.setJavaTypeUse(type);
+      return result;
+    :}
+  | LT ID.type GT
+    {:
+      TokenComponent result = new TokenComponent();
+      result.setName(type);
+      result.setJavaTypeUse(new SimpleJavaTypeUse(type));
+      return result;
+    :}
+;
+
+
+JavaTypeUse java_type_use
+  = parameterized_java_type_use
+  | simple_java_type_use
+;
+
+ArrayList qualified_name
+  = ID
+  | qualified_name DOT ID
+;
+
+
+JastAddList java_type_use_list
+  = java_type_use.u                                 {: return new JastAddList().add(u); :}
+  | java_type_use_list.l COMMA java_type_use.u      {: return l.add(u); :}
+;
+
+SimpleJavaTypeUse simple_java_type_use
+  = qualified_name.n
+    {:
+      return new SimpleJavaTypeUse((String)n.stream().map( x -> ((Symbol)x).value.toString()).collect(java.util.stream.Collectors.joining(".")));
+    :}
+;
+
+ParameterizedJavaTypeUse parameterized_java_type_use
+  = simple_java_type_use.i LT java_type_use_list.l GT
+    {:
+      return new ParameterizedJavaTypeUse(i.getName(), l);
+    :}
+;
+
+Relation relation
+  = RELATION unnamed_role.a LEFT navigable_role.b SCOL
+    {:
+       LeftDirectedRelation result = new LeftDirectedRelation();
+       result.setSource(b);
+       result.setTarget(a);
+       return result;
+    :}
+  | RELATION navigable_role.a RIGHT unnamed_role.b SCOL
+    {:
+       RightDirectedRelation result = new RightDirectedRelation();
+       result.setSource(a);
+       result.setTarget(b);
+       return result;
+    :}
+  | RELATION navigable_role.a BIDIRECTIONAL navigable_role.b SCOL
+    {:
+       BidirectionalRelation result = new BidirectionalRelation();
+       result.setLeft(a);
+       result.setRight(b);
+       return result;
+    :}
+;
+
+
+UnnamedRole unnamed_role
+  = ID.type
+    {:
+      UnnamedRole result = new UnnamedRole();
+      result.setType(TypeDecl.createRef(type));
+      return result;
+    :}
+  | navigable_role
+;
+
+NavigableRole navigable_role
+  = ID.type DOT ID.name
+    {:
+      NormalRole result = new NormalRole();
+      result.setName(name);
+      result.setType(TypeDecl.createRef(type));
+      return result;
+    :}
+  | ID.type DOT ID.name STAR
+    {:
+      ListRole result = new ListRole();
+      result.setName(name);
+      result.setType(TypeDecl.createRef(type));
+      return result;
+    :}
+  | ID.type DOT ID.name QUESTION_MARK
+    {:
+      OptRole result = new OptRole();
+      result.setName(name);
+      result.setType(TypeDecl.createRef(type));
+      return result;
+    :}
+;
diff --git a/src/main/jastadd/RelAst.relast b/src/main/jastadd/RelAst.relast
new file mode 100644
index 0000000000000000000000000000000000000000..2168413aef3510a889a1a2ea3f71ea4624938f1c
--- /dev/null
+++ b/src/main/jastadd/RelAst.relast
@@ -0,0 +1,49 @@
+
+
+Program ::= GrammarFile *;
+
+abstract Grammar ::= Declaration*;
+GrammarFile : Grammar ::= <FileName> ;
+
+abstract Declaration;
+
+TypeDecl:Declaration ::= <Name> <Abstract:boolean>  Component*;
+
+rel TypeDecl.SuperType? <-> TypeDecl.SubType*;
+
+abstract Component ::= <Name> <NTA:boolean>;
+abstract TypeComponent : Component;
+
+rel TypeComponent.TypeDecl <-> TypeDecl.PotentialParent*;
+
+NormalComponent : TypeComponent;
+ListComponent : TypeComponent;
+OptComponent : TypeComponent;
+
+TokenComponent : Component ::= JavaTypeUse;
+
+abstract JavaTypeUse ::= <Name>;
+SimpleJavaTypeUse : JavaTypeUse;
+ParameterizedJavaTypeUse : JavaTypeUse ::= JavaTypeUse*;
+
+abstract Relation : Declaration;
+// rel Source.Name -> Target;
+// rel Target <- Source.Name;
+abstract DirectedRelation : Relation ::= Source:NavigableRole Target:UnnamedRole ;
+LeftDirectedRelation : DirectedRelation;
+RightDirectedRelation : DirectedRelation;
+// rel Left.LeftName <-> Right.RightName;
+BidirectionalRelation : Relation ::= Left:NavigableRole Right:NavigableRole ;
+
+abstract Role;
+abstract NavigableRole : Role ::= <Name>;
+NormalRole : NavigableRole;
+ListRole : NavigableRole;
+OptRole : NavigableRole;
+
+UnnamedRole : Role ;
+
+rel Role.Type <-> TypeDecl.Role*;
+
+// comments
+Comment : Declaration ::= <Text>;
diff --git a/src/main/jastadd/Ros2Rag.ast b/src/main/jastadd/Ros2Rag.ast
deleted file mode 100644
index 3e88bb7e66ce2c2ecee71df70d03289ec0ca12e6..0000000000000000000000000000000000000000
--- a/src/main/jastadd/Ros2Rag.ast
+++ /dev/null
@@ -1,10 +0,0 @@
-Ros2Rag ::= MappingDefinition* SyncDefinition* Program; //MqttRoot ;
-
-abstract SyncDefinition ::= <AlwaysApply:Boolean> ;
-abstract TokenWritingSyncDefinition : SyncDefinition ::= TargetType:SimpleTypeUse <TargetChild> ;
-UpdateDefinition : TokenWritingSyncDefinition ::= <SourceAttribute> [MappingDefinitionUse] ;
-ReadFromMqttDefinition : TokenWritingSyncDefinition ::= [MappingDefinitionUse] ;
-WriteToMqttDefinition : SyncDefinition ::= SourceType:SimpleTypeUse <SourceChild> [MappingDefinitionUse] ;
-
-MappingDefinition ::= <ID> From:SimpleTypeUse To:SimpleTypeUse <Content> ;
-MappingDefinitionUse ::= <ID> ;
diff --git a/src/main/jastadd/Ros2Rag.relast b/src/main/jastadd/Ros2Rag.relast
new file mode 100644
index 0000000000000000000000000000000000000000..fb737a8cb950588c404f71181f2bb42c0077beb5
--- /dev/null
+++ b/src/main/jastadd/Ros2Rag.relast
@@ -0,0 +1,16 @@
+Ros2Rag ::= MappingDefinition* SyncDefinition* Program;
+
+abstract SyncDefinition ::= <AlwaysApply:Boolean> ;
+
+rel SyncDefinition.Mapping? -> MappingDefinition;
+
+abstract TokenSyncDefinition : SyncDefinition;
+rel TokenSyncDefinition.token -> TokenComponent;
+
+ReadFromMqttDefinition : TokenSyncDefinition;
+WriteToMqttDefinition  : TokenSyncDefinition;
+
+MappingDefinition ::= <ID> <Content> ;
+
+rel MappingDefinition.from -> TypeDecl;
+rel MappingDefinition.to -> TypeDecl;
diff --git a/src/main/jastadd/backend/AbstractGrammar.jadd b/src/main/jastadd/backend/AbstractGrammar.jadd
index a196370bb8fba8baf749eee185f4193dbd3ae5fc..606be6ea329fe361b1784e88489f6e34ac81ed1b 100644
--- a/src/main/jastadd/backend/AbstractGrammar.jadd
+++ b/src/main/jastadd/backend/AbstractGrammar.jadd
@@ -11,95 +11,161 @@ aspect BackendAbstractGrammar {
     return sb.toString();
   }
 
-  public void Program.generateAbstractGrammar(StringBuilder sb) {
-    for (TypeDecl td: getTypeDecls()) {
-      td.generateAbstractGrammar(sb);
+  public void Program.generateAbstractGrammar(StringBuilder b) {
+    for (GrammarFile file : getGrammarFileList()) {
+      file.generateAbstractGrammar(b);
     }
   }
 
-  public void TypeDecl.generateAbstractGrammar(StringBuilder sb) {
+  public void GrammarFile.generateAbstractGrammar(StringBuilder b) {
+    b.append("// Grammar for file ").append(getFileName()).append("\n");
+    super.generateAbstractGrammar(b);
+    b.append("\n");
+  }
+
+  public void Grammar.generateAbstractGrammar(StringBuilder b) {
+
+    for (Declaration decl : getDeclarationList()) {
+      decl.generateAbstractGrammar(b);
+    }
+  }
+
+  abstract public void Declaration.generateAbstractGrammar(StringBuilder b);
+
+  public void Comment.generateAbstractGrammar(StringBuilder b) {
+    b.append(getText()).append("\n");
+  }
+
+  public void TypeDecl.generateAbstractGrammar(StringBuilder b) {
     if (getAbstract()) {
-      sb.append("abstract ");
+      b.append("abstract ");
     }
-    sb.append(getID());
-    if (hasSuper()) {
-      sb.append(" : " + getSuper());
+    b.append(getName()).append(" ");
+    if (hasSuperType()) {
+      b.append(": ").append(getSuperType().getName()).append(" ");
     }
-
-    if (getNumComponent() > 0 || relationComponents().size() > 0) {
-      sb.append(" ::=");
+    b.append("::=");
+    for (Component component : getComponentList()) {
+      b.append(" ");
+      component.generateAbstractGrammar(b);
     }
-    for (Component c: getComponents()) {
-      sb.append(" ");
-      sb.append(c.generateAbstractGrammar());
+    b.append(";\n");
+  }
+
+  public abstract void Component.generateAbstractGrammar(StringBuilder b);
+
+  public void NormalComponent.generateAbstractGrammar(StringBuilder b) {
+    if (getNTA()) {
+      b.append("/");
     }
 
-    sb.append(";\n");
+    if (!getName().equals("")) {
+      b.append(getName()).append(":");
+    }
+    b.append(getTypeDecl().getName());
+    if (getNTA()) {
+      b.append("/");
+    }
   }
 
-  public String Component.generateAbstractGrammar() {
-    if (getID().equals(getTypeUse().toString())) {
-      return getTypeUse().toString();
-    } else {
-      return getID() + ":" + getTypeUse();
+  public void ListComponent.generateAbstractGrammar(StringBuilder b) {
+    if (getNTA()) {
+      b.append("/");
+    }
+
+    if (!getName().equals("")) {
+      b.append(getName()).append(":");
+    }
+    b.append(getTypeDecl().getName()).append("*");
+    if (getNTA()) {
+      b.append("/");
     }
   }
-  public String ListComponent.generateAbstractGrammar() {
-    return super.generateAbstractGrammar() + "*";
-  }
-  public String OptComponent.generateAbstractGrammar() {
-    return "[" + super.generateAbstractGrammar() + "]";
-  }
-  public String NTAComponent.generateAbstractGrammar() {
-    return "/" + super.generateAbstractGrammar() + "/";
-  }
-  public String NTAListComponent.generateAbstractGrammar() {
-    return "/" + super.generateAbstractGrammar() + "*/";
-  }
-  public String NTAOptComponent.generateAbstractGrammar() {
-    return "/[" + super.generateAbstractGrammar() + "]/";
-  }
-  public String TokenComponent.generateAbstractGrammar() {
-    return "<" + getID() + ":" + getTypeUse() + ">";
+
+  public void OptComponent.generateAbstractGrammar(StringBuilder b) {
+    if (getNTA()) {
+      b.append("/");
+    }
+    b.append("[");
+    if (!getName().equals("")) {
+      b.append(getName()).append(":");
+    }
+    b.append(getTypeDecl().getName()).append("]");
+    if (getNTA()) {
+      b.append("/");
+    }
   }
-  public String NTATokenComponent.generateAbstractGrammar() {
-    return "/<" + getID() + ":" + getTypeUse() + ">/";
+
+  public void TokenComponent.generateAbstractGrammar(StringBuilder b) {
+    if (getNTA()) {
+      b.append("/");
+    }
+    b.append("<");
+    if (!getName().equals("")) {
+      b.append(getName()).append(":");
+    }
+    getJavaTypeUse().generateAbstractGrammar(b);
+    b.append(">");
+    if (getNTA()) {
+      b.append("/");
+    }
   }
 
-  public String Relation.generateAbstractGrammar() {
-    return "rel "
-      + getLeft().generateAbstractGrammar() + " "
-      + getDirection().generateAbstractGrammar() + " "
-      + getRight().generateAbstractGrammar();
+  abstract public void JavaTypeUse.generateAbstractGrammar(StringBuilder b);
+
+  public void SimpleJavaTypeUse.generateAbstractGrammar(StringBuilder b) {
+    b.append(getName());
   }
 
-  public String RelationComponent.generateAbstractGrammar() {
-    if (getID().isEmpty()) {
-      return getTypeUse().toString();
-    } else {
-      return getTypeUse() + "." +  getID();
+  public void ParameterizedJavaTypeUse.generateAbstractGrammar(StringBuilder b) {
+    b.append("<");
+    boolean first = true;
+    for (JavaTypeUse javaTypeUse : getJavaTypeUseList()) {
+      if (first) {
+        first = false;
+      } else {
+        b.append(", ");
+      }
+      javaTypeUse.generateAbstractGrammar(b);
     }
+    b.append(">");
   }
 
-  public String OptionalRelationComponent.generateAbstractGrammar() {
-    return super.generateAbstractGrammar() + "?";
+  abstract public void Relation.generateAbstractGrammar(StringBuilder b);
+
+  public void DirectedRelation.generateAbstractGrammar(StringBuilder b) {
+    b.append("rel ");
+    getSource().generateAbstractGrammar(b);
+    b.append(" -> ");
+    getTarget().generateAbstractGrammar(b);
+    b.append(";\n");
   }
 
-  public String ManyRelationComponent.generateAbstractGrammar() {
-    return super.generateAbstractGrammar() + "*";
+  public void BidirectionalRelation.generateAbstractGrammar(StringBuilder b) {
+    b.append("rel ");
+    getLeft().generateAbstractGrammar(b);
+    b.append(" <-> ");
+    getRight().generateAbstractGrammar(b);
+    b.append(";\n");
   }
 
-  abstract public String Direction.generateAbstractGrammar();
-  public String RightDirection.generateAbstractGrammar() {
-    return "->";
+  abstract public void Role.generateAbstractGrammar(StringBuilder b);
+
+  public void NormalRole.generateAbstractGrammar(StringBuilder b) {
+    b.append(getType().getName()).append(".").append(getName());
+  }
+
+  public void ListRole.generateAbstractGrammar(StringBuilder b) {
+    b.append(getType().getName()).append(".").append(getName()).append("*");
   }
 
-  public String LeftDirection.generateAbstractGrammar() {
-    return "<-";
+  public void OptRole.generateAbstractGrammar(StringBuilder b) {
+    b.append(getType().getName()).append(".").append(getName()).append("?");
   }
 
-  public String Bidirectional.generateAbstractGrammar() {
-    return "<->";
+  public void UnnamedRole.generateAbstractGrammar(StringBuilder b) {
+    b.append(getType().getName());
   }
 
+
 }
diff --git a/src/main/jastadd/backend/Aspect.jadd b/src/main/jastadd/backend/Aspect.jadd
index 71491c9fb4d7dce4f70d14990f05f15c8588bd4a..c63ec13624c2c10589b070917eea9cc7fba2fa0e 100644
--- a/src/main/jastadd/backend/Aspect.jadd
+++ b/src/main/jastadd/backend/Aspect.jadd
@@ -39,10 +39,10 @@ aspect Aspect {
   }
 
   abstract void SyncDefinition.generateAspect(StringBuilder sb);
-  @Override
-  void UpdateDefinition.generateAspect(StringBuilder sb) {
-    // TODO
-  }
+//  @Override
+//  void UpdateDefinition.generateAspect(StringBuilder sb) {
+//    // TODO
+//  }
 
   // will be "addConnectionJoint_CurrentPosition" in example
 /* // see discussion in codimd (InstanceLocation), why this won't work here
@@ -60,14 +60,22 @@ aspect Aspect {
   void ReadFromMqttDefinition.generateAspect(StringBuilder sb) {
     sb.append("public void ").append("type").append(".connectTo(String topic) {\n")
       .append(aspectIndent).append("mqttUpdater().addConnection")
-      .append(getTargetType().getID()).append("_")
-      .append(getTargetChild())
+      .append(getToken().containingTypeDecl().getName())
+      .append("_")
+      .append(getToken().getName())
       .append("(this, topic);\n")
       .append("}\n");
   }
 
   @Override
   void WriteToMqttDefinition.generateAspect(StringBuilder sb) {
-    // TODO
+    sb.append("public void ").append("type").append(".connectTo(String topic) {\n")
+      .append(aspectIndent).append("mqttUpdater().addConnection")
+      .append(getToken().containingTypeDecl().getName())
+      .append("_")
+      .append(getToken().getName())
+      .append("(this, topic);\n")
+      .append("}\n");
   }
+
 }
diff --git a/src/main/java/org/jastadd/ros2rag/compiler/Compiler.java b/src/main/java/org/jastadd/ros2rag/compiler/Compiler.java
index a56a1264c9bc071d0da9532473586d35fce49bf8..1ba4fbb8531fa35b50f676252f5731e6a6be3e0d 100644
--- a/src/main/java/org/jastadd/ros2rag/compiler/Compiler.java
+++ b/src/main/java/org/jastadd/ros2rag/compiler/Compiler.java
@@ -1,10 +1,7 @@
 package org.jastadd.ros2rag.compiler;
 
 import beaver.Parser;
-import org.jastadd.ros2rag.ast.ErrorMessage;
-import org.jastadd.ros2rag.ast.Program;
-import org.jastadd.ros2rag.ast.Relation;
-import org.jastadd.ros2rag.ast.TypeDecl;
+import org.jastadd.ros2rag.ast.*;
 import org.jastadd.ros2rag.compiler.options.CommandLine;
 import org.jastadd.ros2rag.compiler.options.CommandLine.CommandLineException;
 import org.jastadd.ros2rag.compiler.options.Option;
@@ -46,19 +43,9 @@ public class Compiler {
     List<String> filenames = commandLine.getArguments();
     Program p = parseProgram(filenames);
 
+    writeToFile(outputDir + "/Grammar.ast", p.generateAbstractGrammar());
+    writeToFile(outputDir + "/ROS2RAG.jadd", p.generateAspect());
 
-    if (!p.errors().isEmpty()) {
-      System.err.println("Errors:");
-      for (ErrorMessage e : p.errors()) {
-        System.err.println(e);
-      }
-      System.exit(1);
-    } else {
-
-      writeToFile(outputDir + "/Grammar.ast", p.generateAbstractGrammar());
-      writeToFile(outputDir + "/ROS2RAG.jadd", p.generateAspect());
-
-    }
   }
 
 
@@ -110,6 +97,7 @@ public class Compiler {
 
       parse(program, reader, fileName);
     }
+    program.treeResolveAll();
     return program;
   }
 
@@ -118,15 +106,8 @@ public class Compiler {
     RelAstParser parser = new RelAstParser();
 
     try {
-      Program newProgram = (Program) parser.parse(scanner);
-      for (TypeDecl typeDecl : newProgram.getTypeDeclList()) {
-        typeDecl.setFileName(file);
-        program.addTypeDecl(typeDecl);
-      }
-      for (Relation relation : newProgram.getRelationList()) {
-        relation.setFileName(file);
-        program.addRelation(relation);
-      }
+      GrammarFile newFile = (GrammarFile) parser.parse(scanner);
+      program.addGrammarFile(newFile);
     } catch (IOException e) {
       error(e.getMessage());
     } catch (Parser.Exception e) {
diff --git a/src/main/java/org/jastadd/ros2rag/compiler/SimpleMain.java b/src/main/java/org/jastadd/ros2rag/compiler/SimpleMain.java
index e31a423afb7367177695dac5501c807b9382e89e..ae2b4a0312f43c3c82df5ff0d1f477e8888a25b4 100644
--- a/src/main/java/org/jastadd/ros2rag/compiler/SimpleMain.java
+++ b/src/main/java/org/jastadd/ros2rag/compiler/SimpleMain.java
@@ -51,8 +51,8 @@ public class SimpleMain {
 
     MappingDefinition mappingDefinition = new MappingDefinition();
     mappingDefinition.setID("PoseToPosition");
-    mappingDefinition.setFrom(new SimpleTypeUse("PBPose"));
-    mappingDefinition.setTo(new SimpleTypeUse("Position"));
+    mappingDefinition.setFrom(TypeDecl.createRef("PBPose"));
+    mappingDefinition.setTo(TypeDecl.createRef("Position"));
     mappingDefinition.setContent("      pose.position.x += sqrt(.5 * size.x)\n" +
         "      MAP round(2)\n" +
         "      x = x / 100\n" +
@@ -62,11 +62,12 @@ public class SimpleMain {
 
     ReadFromMqttDefinition readFromMqttDefinition = new ReadFromMqttDefinition();
     readFromMqttDefinition.setAlwaysApply(false);
-    readFromMqttDefinition.setTargetType(new SimpleTypeUse("Joint"));
-    readFromMqttDefinition.setTargetChild("CurrentPosition");
-    readFromMqttDefinition.setMappingDefinitionUse(new MappingDefinitionUse("PoseToPosition"));
+    readFromMqttDefinition.setToken(TokenComponent.createRef("Joint.CurrentPosition"));
+    readFromMqttDefinition.setMapping(mappingDefinition);
     model.addSyncDefinition(readFromMqttDefinition);
 
+    model.treeResolveAll();
+
     System.out.println(model.generateAspect());
   }