diff --git a/src/main/jastadd/Ros2Rag.ast b/src/main/jastadd/Ros2Rag.ast
new file mode 100644
index 0000000000000000000000000000000000000000..3e88bb7e66ce2c2ecee71df70d03289ec0ca12e6
--- /dev/null
+++ b/src/main/jastadd/Ros2Rag.ast
@@ -0,0 +1,10 @@
+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/backend/Aspect.jadd b/src/main/jastadd/backend/Aspect.jadd
index 76b74a88b6e16cdc511350f75b53041441d399f1..61247c819d00e8be9a8618b5a8d5ed1657474e63 100644
--- a/src/main/jastadd/backend/Aspect.jadd
+++ b/src/main/jastadd/backend/Aspect.jadd
@@ -8,6 +8,7 @@ aspect Aspect {
     return sb.toString();
   }
 
+  @Deprecated
   public void Program.generateAspect(StringBuilder sb) {
 
     sb.append("aspect ROS2RAG {\n");
@@ -16,4 +17,58 @@ aspect Aspect {
 
     sb.append("}\n");
   }
+
+  public String Ros2Rag.generateAspect() {
+    StringBuilder sb = new StringBuilder();
+    generateAspect(sb);
+    return sb.toString();
+  }
+
+  // from "[always] read Joint.CurrentPosition using PoseToPosition;" generate method connectTo
+//    Joint j;
+//    j.getCurrentPosition().connectTo("/robot/joint2/pos");
+
+  public void Ros2Rag.generateAspect(StringBuilder sb) {
+    sb.append("aspect ROS2RAG {\n");
+
+    for (SyncDefinition def : getSyncDefinitionList()) {
+      def.generateAspect(sb);
+    }
+
+    sb.append("}\n");
+  }
+
+  abstract void SyncDefinition.generateAspect(StringBuilder sb);
+  @Override
+  void UpdateDefinition.generateAspect(StringBuilder sb) {
+    // TODO
+  }
+
+  // will be "addConnectionJoint_CurrentPosition" in example
+/* // see discussion in codimd (InstanceLocation), why this won't work here
+  Position.connectTo(String topic) {
+    mqttUpdater().addConnectionJoint_CurrentPosition(this, topic);
+  }
+  MqttUpdater.addConnectionJoint_CurrentPosition(Position target, String topic) {
+    // either
+    topicActionMap.put(topic, new Action(JOINT_CURRENTPOSITION, target));
+    // or
+    topicForJoint_CurrentPosition.put(topic, target);
+  }
+ */
+ */
+  @Override
+  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("(this, topic);\n")
+      .append("}\n");
+  }
+
+  @Override
+  void WriteToMqttDefinition.generateAspect(StringBuilder sb) {
+    // TODO
+  }
 }
diff --git a/src/main/java/org/jastadd/ros2rag/compiler/SimpleMain.java b/src/main/java/org/jastadd/ros2rag/compiler/SimpleMain.java
new file mode 100644
index 0000000000000000000000000000000000000000..e31a423afb7367177695dac5501c807b9382e89e
--- /dev/null
+++ b/src/main/java/org/jastadd/ros2rag/compiler/SimpleMain.java
@@ -0,0 +1,83 @@
+package org.jastadd.ros2rag.compiler;
+
+import beaver.Parser;
+import org.jastadd.ros2rag.ast.*;
+import org.jastadd.ros2rag.parser.RelAstParser;
+import org.jastadd.ros2rag.scanner.RelAstScanner;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+/**
+ * Testing Ros2Rag without parser.
+ *
+ * @author rschoene - Initial contribution
+ */
+public class SimpleMain {
+  public static void main(String[] args) {
+    /*
+    // as soon as the cache of isInSafetyZone is invalidated, update the value of Robot.ShouldUseLowSpeed with its value
+    [always] update Robot.ShouldUseLowSpeed with isInSafetyZone() using transformation();
+
+    // when a (new?) value for ShouldUseLowSpeed is set, send it over via mqtt
+    [always] write Robot.ShouldUseLowSpeed;
+
+    // when an update of pose is read via mqtt, then update current position
+    [always] read Joint.CurrentPosition using PoseToPosition;
+
+    // PBPose is a datatype defined in protobuf
+    PoseToPosition: map PBPose to Position using
+      pose.position.x += sqrt(.5 * size.x)
+      MAP round(2)
+      x = x / 100
+      IGNORE_IF_SAME
+    ;
+
+    --- using generated methods ---
+    Joint j;
+    j.getCurrentPosition().connectTo("/robot/joint2/pos");
+
+    RobotArm r;
+    // this should not be required
+    r.getShouldUseLowSpeed().addObserver(j.getCurrentPosition());
+    r.getShouldUseLowSpeed().connectTo("/robot/config/speed");
+     */
+    Ros2Rag model = new Ros2Rag();
+    Program program = parseProgram(Paths.get("src", "test", "resources", "MinimalExample.relast"));
+    model.setProgram(program);
+
+    MappingDefinition mappingDefinition = new MappingDefinition();
+    mappingDefinition.setID("PoseToPosition");
+    mappingDefinition.setFrom(new SimpleTypeUse("PBPose"));
+    mappingDefinition.setTo(new SimpleTypeUse("Position"));
+    mappingDefinition.setContent("      pose.position.x += sqrt(.5 * size.x)\n" +
+        "      MAP round(2)\n" +
+        "      x = x / 100\n" +
+        "      IGNORE_IF_SAME\n" +
+        "    ;");
+    model.addMappingDefinition(mappingDefinition);
+
+    ReadFromMqttDefinition readFromMqttDefinition = new ReadFromMqttDefinition();
+    readFromMqttDefinition.setAlwaysApply(false);
+    readFromMqttDefinition.setTargetType(new SimpleTypeUse("Joint"));
+    readFromMqttDefinition.setTargetChild("CurrentPosition");
+    readFromMqttDefinition.setMappingDefinitionUse(new MappingDefinitionUse("PoseToPosition"));
+    model.addSyncDefinition(readFromMqttDefinition);
+
+    System.out.println(model.generateAspect());
+  }
+
+  private static Program parseProgram(Path path) {
+    try (BufferedReader reader = Files.newBufferedReader(path)) {
+      RelAstScanner scanner = new RelAstScanner(reader);
+      RelAstParser parser = new RelAstParser();
+      return (Program) parser.parse(scanner);
+    } catch (IOException | Parser.Exception e) {
+      e.printStackTrace();
+    }
+    return null;
+  }
+}
diff --git a/src/test/resources/MinimalExample.relast b/src/test/resources/MinimalExample.relast
index c9cf30085267ac7df5b2d2a13fbdb31e9321d626..b7f34c9cfb78e60e51d7947c145a66824afb1faf 100644
--- a/src/test/resources/MinimalExample.relast
+++ b/src/test/resources/MinimalExample.relast
@@ -1,12 +1,13 @@
 Model ::= RobotArm ZoneModel ;
 
-ZoneModel ::= <Size:Position> SafetyZone:Zone*;
+ZoneModel ::= Size:Position SafetyZone:Zone*;
 
 Zone ::= Position*;
 
 RobotArm ::= Joint* EndEffector /<ShouldUseLowSpeed:Boolean>/ ;
 
-Joint ::= <Name> <CurrentPosition:Position>;
+Joint ::= <Name> ;
+rel Join.CurrentPosition -> Position ;
 
 EndEffector : Joint;