diff --git a/src/main/jastadd/Printing.jrag b/src/main/jastadd/Printing.jrag index 96484151a05b4aea9707dfa60f71e2fb82e2a842..4d070f82a05b8acfc01028abbfe06a50b265f5c0 100644 --- a/src/main/jastadd/Printing.jrag +++ b/src/main/jastadd/Printing.jrag @@ -12,21 +12,23 @@ aspect Printing { return sb.toString(); } syn StringBuilder Element.prettyPrint(StringBuilder sb, boolean printIndent, String indent); - eq StringElement.prettyPrint(StringBuilder sb, boolean printIndent, String indent) { + eq ValueElement.prettyPrint(StringBuilder sb, boolean printIndent, String indent) { sb.append(getValue()); return sb; } - eq QuotedStringElement.prettyPrint(StringBuilder sb, boolean printIndent, String indent) { + eq StringElement.prettyPrint(StringBuilder sb, boolean printIndent, String indent) { sb.append("\"").append(getValue()).append("\""); return sb; } eq ListElement.prettyPrint(StringBuilder sb, boolean printIndent, String indent) { - for (Element element : getElementList()) { - sb.append(indent).append("- "); - element.prettyPrint(sb, false, indent + PRINT_INDENT); - sb.append("\n"); - } - if (getNumElement() > 0) { + if (isEmpty()) { + sb.append("[]"); + } else { + for (Element element : getElementList()) { + sb.append(indent).append("- "); + element.prettyPrint(sb, false, indent + PRINT_INDENT); + sb.append("\n"); + } // delete last newline sb.deleteCharAt(sb.length() - 1); } @@ -35,7 +37,7 @@ aspect Printing { eq KeyValuePair.prettyPrint(StringBuilder sb, boolean printIndent, String indent) { if (printIndent) sb.append(indent); sb.append(getKey()).append(": "); - if (getValue().isComplex()) { + if (getValue().isComplex() && !getValue().isEmpty()) { sb.append("\n"); getValue().prettyPrint(sb, true, indent + PRINT_INDENT); //); } else { @@ -44,14 +46,16 @@ aspect Printing { return sb; } eq MappingElement.prettyPrint(StringBuilder sb, boolean printIndent, String indent) { - boolean first = true; - for (KeyValuePair pair : getKeyValuePairList()) { - if (!first || printIndent) sb.append(indent); - first = false; - pair.prettyPrint(sb, false, indent); // + PRINT_INDENT - sb.append("\n"); - } - if (!first) { + if (isEmpty()) { + sb.append("{}"); + } else { + boolean first = true; + for (KeyValuePair pair : getKeyValuePairList()) { + if (!first || printIndent) sb.append(indent); + first = false; + pair.prettyPrint(sb, false, indent); // + PRINT_INDENT + sb.append("\n"); + } // delete last newline sb.deleteCharAt(sb.length() - 1); } diff --git a/src/main/jastadd/YAML.jrag b/src/main/jastadd/YAML.jrag new file mode 100644 index 0000000000000000000000000000000000000000..93dd0f34b7b7b0505cf0970b6541fa3ae5bee7fa --- /dev/null +++ b/src/main/jastadd/YAML.jrag @@ -0,0 +1,31 @@ +aspect Navigation { + eq Document.getChild().program() = null; + eq Document.getChild().ragconnect() = null; + eq Document.getChild().containedFile() = null; + eq Document.getChild().containedFileName() = getFileName(); + + syn boolean Element.isComplex() = false; + eq ComplexElement.isComplex() = true; + + syn boolean Element.isEmpty() = false; + eq MappingElement.isEmpty() = getNumKeyValuePair() == 0; + eq ListElement.isEmpty() = getNumElement() == 0; +} + +aspect Helper { + public static ValueElement ValueElement.of(int value) { + return new ValueElement(String.valueOf(value)); + } + public static ValueElement ValueElement.of(boolean value) { + return new ValueElement(String.valueOf(value)); + } + public static ValueElement ValueElement.of(String value) { + return new ValueElement(value); + } + public static StringElement StringElement.of(String value) { + return new StringElement(value); + } + public void MappingElement.addKeyValuePair(String key, Element value) { + addKeyValuePair(new KeyValuePair(key, value)); + } +} diff --git a/src/main/jastadd/YAML.relast b/src/main/jastadd/YAML.relast index 47a875edd39b90f1a582a9fa92e9a0178b61ac18..94f4ab20fdc3838348bd53b812b3d1477cae3558 100644 --- a/src/main/jastadd/YAML.relast +++ b/src/main/jastadd/YAML.relast @@ -5,5 +5,5 @@ MappingElement : ComplexElement ::= KeyValuePair* ; KeyValuePair : ComplexElement ::= <Key> Value:Element ; ListElement : ComplexElement ::= Element* ; abstract SimpleElement : Element ; +ValueElement : SimpleElement ::= <Value> ; StringElement : SimpleElement ::= <Value> ; -QuotedStringElement : SimpleElement ::= <Value> ; diff --git a/src/main/jastadd/YAML_Navigation.jrag b/src/main/jastadd/YAML_Navigation.jrag deleted file mode 100644 index 36240f5f6aadd744745bbaf57029023a9bd2e631..0000000000000000000000000000000000000000 --- a/src/main/jastadd/YAML_Navigation.jrag +++ /dev/null @@ -1,10 +0,0 @@ -aspect Navigation { - eq Document.getChild().program() = null; - eq Document.getChild().ragconnect() = null; - eq Document.getChild().containedFile() = null; - eq Document.getChild().containedFileName() = getFileName(); - - syn boolean Element.isComplex() = false; - eq ComplexElement.isComplex() = true; - -} diff --git a/src/main/jastadd/backend/MustacheNodesToYAML.jrag b/src/main/jastadd/backend/MustacheNodesToYAML.jrag new file mode 100644 index 0000000000000000000000000000000000000000..bdd032ad9ee27002413746ae3e3f12135c0d4e5c --- /dev/null +++ b/src/main/jastadd/backend/MustacheNodesToYAML.jrag @@ -0,0 +1,154 @@ +aspect MustacheNodesToYAML { + syn Document MRagConnect.toYAML() { + Document doc = new Document(); + MappingElement root = new MappingElement(); + root.addKeyValuePair("rootNodeName", StringElement.of(rootNodeName())); + root.addKeyValuePair("usesMqtt", ValueElement.of(usesMqtt)); + root.addKeyValuePair("usesRest", ValueElement.of(usesRest)); + // mqtt + root.addKeyValuePair("mqttHandlerField", StringElement.of(mqttHandlerField())); + root.addKeyValuePair("mqttHandlerAttribute", StringElement.of(mqttHandlerAttribute())); + root.addKeyValuePair("mqttSetupWaitUntilReadyMethod", StringElement.of(mqttSetupWaitUntilReadyMethod())); + + // rootTypeComponents + ListElement rootTypeComponents = new ListElement(); + for (MTypeComponent comp : getRootTypeComponentList()) { + MappingElement inner = new MappingElement(); + inner.addKeyValuePair("first", ValueElement.of(comp.isFirst())); + inner.addKeyValuePair("name", StringElement.of(comp.name())); + rootTypeComponents.addElement(inner); + } + root.addKeyValuePair("rootTypeComponents", rootTypeComponents); + + // rest + root.addKeyValuePair("restHandlerField", StringElement.of(restHandlerField())); + root.addKeyValuePair("restHandlerAttribute", StringElement.of(restHandlerAttribute())); + + // ReceiveDefinitions + ListElement receiveDefinitions = new ListElement(); + for (MReceiveDefinition def : getReceiveDefinitionList()) { + receiveDefinitions.addElement(def.toYAML()); + } + root.addKeyValuePair("ReceiveDefinitions", receiveDefinitions); + + // SendDefinitions + ListElement sendDefinitions = new ListElement(); + for (MSendDefinition def : getSendDefinitionList()) { + sendDefinitions.addElement(def.toYAML()); + } + root.addKeyValuePair("SendDefinitions", sendDefinitions); + + // MappingDefinitions + ListElement mappingDefinitions = new ListElement(); + for (MMappingDefinition def : getMappingDefinitionList()) { + mappingDefinitions.addElement(def.toYAML()); + } + root.addKeyValuePair("MappingDefinitions", mappingDefinitions); + + // DependencyDefinitions + ListElement dependencyDefinitions = new ListElement(); + for (MDependencyDefinition def : getDependencyDefinitionList()) { + dependencyDefinitions.addElement(def.toYAML()); + } + root.addKeyValuePair("DependencyDefinitions", dependencyDefinitions); + + // TokenComponents + ListElement tokenComponents = new ListElement(); + for (MTokenComponent comp : getTokenComponentList()) { + tokenComponents.addElement(comp.toYAML()); + } + root.addKeyValuePair("TokenComponents", tokenComponents); + + doc.addComplexElement(root); + return doc; + } + + syn Element MReceiveDefinition.toYAML() { + MappingElement inner = new MappingElement(); + inner.addKeyValuePair("parentTypeName", StringElement.of(parentTypeName())); + inner.addKeyValuePair("connectMethod", StringElement.of(connectMethod())); + inner.addKeyValuePair("connectParameterName", StringElement.of(connectParameterName())); + inner.addKeyValuePair("lastDefinitionToType", StringElement.of(lastDefinitionToType())); + inner.addKeyValuePair("resultVarPrefix", StringElement.of(resultVarPrefix())); + inner.addKeyValuePair("lastDefinitionName", StringElement.of(lastDefinitionName())); + inner.addKeyValuePair("preemptiveReturn", StringElement.of(preemptiveReturn())); + inner.addKeyValuePair("alwaysApply", ValueElement.of(alwaysApply())); + inner.addKeyValuePair("condition", StringElement.of(condition())); + inner.addKeyValuePair("loggingEnabledForReads", ValueElement.of(loggingEnabledForReads)); + inner.addKeyValuePair("tokenName", StringElement.of(tokenName())); + inner.addKeyValuePair("lastResult", StringElement.of(lastResult())); +// inner.addKeyValuePair("first", ValueElement.of(isFirst())); +// parentTypeName +// connectMethod +// connectParameterName +// lastDefinitionToType +// resultVarPrefix +// lastDefinitionName +// #InnerMappingDefinitions -> MInnerMappingDefinition +// last +// toType +// methodName +// inputVarName +// preemptiveReturn +// alwaysApply +// condition - special chars +// loggingEnabledForReads +// tokenName +// lastResult + return inner; + } + + syn Element MSendDefinition.toYAML() { + MappingElement inner = new MappingElement(); +// #SendDefinitions -> MSendDefinition +// parentTypeName +// sender +// lastValue +// connectMethod +// connectParameterName +// loggingEnabledForWrites +// updateMethod +// writeMethod +// tokenResetMethod +// lastResult + return inner; + } + + syn Element MMappingDefinition.toYAML() { + MappingElement inner = new MappingElement(); +// #MappingDefinitions -> MMappingDefinition +// toType +// methodName +// fromType +// fromVariableName +// content - special chars + return inner; + } + + syn Element MDependencyDefinition.toYAML() { + MappingElement inner = new MappingElement(); +// #DependencyDefinitions -> MDependencyDefinition +// targetParentTypeName +// dependencyMethod +// sourceParentTypeName +// internalRelationPrefix + return inner; + } + + syn Element MTokenComponent.toYAML() { + MappingElement inner = new MappingElement(); +// #TokenComponents -> MTokenComponent +// parentTypeName +// name +// javaType +// internalName +// #DependencyDefinitions -> MDependencyDefinition +// targetParentTypeName +// internalRelationPrefix +// #targetEndpointDefinition -> MSendDefinition +// updateMethod +// writeMethod + return inner; + } + +} diff --git a/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java b/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java index d44ef9e590abd09d3c7d7026c3da2dfe5f29511b..12fc212b9b10be507fffa6b56bc4a6816082e87a 100644 --- a/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java +++ b/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java @@ -21,6 +21,7 @@ public class Compiler extends AbstractCompiler { // private ValueOption optionOutputDir; private ValueOption optionRootNode; private ValueOption optionProtocols; + private BooleanOption optionPrintYaml; private BooleanOption optionVerbose; private BooleanOption optionLogReads; private BooleanOption optionLogWrites; @@ -53,6 +54,10 @@ public class Compiler extends AbstractCompiler { } } + if (!optionRootNode.isMatched()) { + return error("Root node not specified"); + } + RagConnect ragConnect = parseProgram(getConfiguration().getFiles()); if (!ragConnect.errors().isEmpty()) { @@ -63,6 +68,12 @@ public class Compiler extends AbstractCompiler { System.exit(1); } + if (optionPrintYaml.value()) { + ASTNode.rootNode = ragConnect.getProgram().resolveTypeDecl(optionRootNode.value()); + System.out.println(ragConnect.toMustache().toYAML().prettyPrint()); + return 0; + } + printMessage("Writing output files"); final List<String> handlers = new ArrayList<>(); if (ASTNode.usesMqtt) { @@ -99,7 +110,7 @@ public class Compiler extends AbstractCompiler { try { new Compiler().run(args); } catch (CompilerException e) { - System.err.println(e.getMessage()); + e.printStackTrace(); System.exit(1); } } @@ -148,6 +159,9 @@ public class Compiler extends AbstractCompiler { .addDefaultValue(OPTION_PROTOCOL_MQTT, "Enable MQTT") .addAcceptedValue(OPTION_PROTOCOL_REST, "Enable REST") ); + optionPrintYaml = addOption( + new BooleanOption("printYaml", "Print out YAML instead of generating files") + .defaultValue(false)); optionVerbose = addOption( new BooleanOption("verbose", "Print more messages while compiling.") .defaultValue(false)); @@ -161,6 +175,8 @@ public class Compiler extends AbstractCompiler { private RagConnect parseProgram(Collection<String> files) throws CompilerException { Program program = new Program(); + boolean atLeastOneGrammar = false; + boolean atLeastOneRagConnect = false; RagConnect ragConnect = new RagConnect(); ragConnect.setProgram(program); @@ -176,17 +192,28 @@ public class Compiler extends AbstractCompiler { case "relast": // processGrammar parseGrammar(program, filename); + atLeastOneGrammar = true; break; case "connect": case "ragconnect": // process ragConnect RagConnect parsedRagConnect = parseRagConnect(program, filename); mergeRagConnectDefinitions(ragConnect, parsedRagConnect); + atLeastOneRagConnect = true; break; default: throw new CompilerException("Unknown file extension in " + filename); } } + if (!atLeastOneGrammar) { + System.err.println("No grammar file specified! (*.ast, *.relast)"); + } + if (!atLeastOneRagConnect) { + System.err.println("No ragconnect file specified! (*.connect, *.ragconnect)"); + } + if (!atLeastOneGrammar && !atLeastOneRagConnect) { + System.exit(1); + } ragConnect.treeResolveAll(); ragConnect.additionalRelations().forEach(ragConnectGrammarPart::addDeclaration); ASTNode.loggingEnabledForReads = optionLogReads.value(); diff --git a/src/main/java/org/jastadd/ragconnect/compiler/SimpleMain.java b/src/main/java/org/jastadd/ragconnect/compiler/SimpleMain.java index 800ae6cf9b02911ab6eedd3525e8e985d62ceddf..ee9ed046348efeaa4b12dbc816c55414d93289cf 100644 --- a/src/main/java/org/jastadd/ragconnect/compiler/SimpleMain.java +++ b/src/main/java/org/jastadd/ragconnect/compiler/SimpleMain.java @@ -1,6 +1,12 @@ package org.jastadd.ragconnect.compiler; import org.jastadd.ragconnect.ast.*; +import org.jastadd.ragconnect.parser.RagConnectParser; +import org.jastadd.ragconnect.scanner.RagConnectScanner; + +import java.io.Reader; +import java.nio.file.Files; +import java.nio.file.Paths; /** * Testing Ros2Rag without parser. @@ -14,26 +20,26 @@ public class SimpleMain { KeyValuePair root = new KeyValuePair(); root.setKey("panda_mqtt_connector"); MappingElement firstLevel = new MappingElement(); - firstLevel.addKeyValuePair(new KeyValuePair("server", new QuotedStringElement("tcp://localhost:1883"))); - firstLevel.addKeyValuePair(new KeyValuePair("robot_speed_factor", new StringElement(".7"))); + firstLevel.addKeyValuePair(new KeyValuePair("server", new StringElement("tcp://localhost:1883"))); + firstLevel.addKeyValuePair(new KeyValuePair("robot_speed_factor", new ValueElement(".7"))); KeyValuePair topics = new KeyValuePair(); topics.setKey("topics"); MappingElement theTopics = new MappingElement(); - theTopics.addKeyValuePair(new KeyValuePair("robotConfig", new QuotedStringElement("robotconfig"))); - theTopics.addKeyValuePair(new KeyValuePair("trajectory", new QuotedStringElement("trajectory"))); - theTopics.addKeyValuePair(new KeyValuePair("nextStep", new QuotedStringElement("ros2rag/nextStep"))); + theTopics.addKeyValuePair(new KeyValuePair("robotConfig", new StringElement("robotconfig"))); + theTopics.addKeyValuePair(new KeyValuePair("trajectory", new StringElement("trajectory"))); + theTopics.addKeyValuePair(new KeyValuePair("nextStep", new StringElement("ros2rag/nextStep"))); topics.setValue(theTopics); firstLevel.addKeyValuePair(topics); - firstLevel.addKeyValuePair(new KeyValuePair("zone_size", new StringElement("0.5"))); + firstLevel.addKeyValuePair(new KeyValuePair("zone_size", new ValueElement("0.5"))); KeyValuePair zones = new KeyValuePair(); zones.setKey("zones"); ListElement theZones = new ListElement(); - theZones.addElement(new QuotedStringElement("1 1")); - theZones.addElement(new QuotedStringElement("0 1")); - theZones.addElement(new QuotedStringElement("-1 1")); + theZones.addElement(new StringElement("1 1")); + theZones.addElement(new StringElement("0 1")); + theZones.addElement(new StringElement("-1 1")); zones.setValue(theZones); firstLevel.addKeyValuePair(zones); @@ -42,15 +48,15 @@ public class SimpleMain { KeyValuePair pandaParts = new KeyValuePair(); pandaParts.setKey("panda"); MappingElement thePanda = new MappingElement(); - thePanda.addKeyValuePair(new KeyValuePair("Link0", new QuotedStringElement("panda_link0"))); - thePanda.addKeyValuePair(new KeyValuePair("Link1", new QuotedStringElement("panda_link1"))); - thePanda.addKeyValuePair(new KeyValuePair("Link2", new QuotedStringElement("panda_link2"))); - thePanda.addKeyValuePair(new KeyValuePair("Link3", new QuotedStringElement("panda_link3"))); - thePanda.addKeyValuePair(new KeyValuePair("Link4", new QuotedStringElement("panda_link4"))); - thePanda.addKeyValuePair(new KeyValuePair("Link5", new QuotedStringElement("panda_link5"))); - thePanda.addKeyValuePair(new KeyValuePair("Link6", new QuotedStringElement("panda_link6"))); - thePanda.addKeyValuePair(new KeyValuePair("RightFinger", new QuotedStringElement("panda_rightfinger"))); - thePanda.addKeyValuePair(new KeyValuePair("LeftFinger", new QuotedStringElement("panda_leftfinger"))); + thePanda.addKeyValuePair(new KeyValuePair("Link0", new StringElement("panda_link0"))); + thePanda.addKeyValuePair(new KeyValuePair("Link1", new StringElement("panda_link1"))); + thePanda.addKeyValuePair(new KeyValuePair("Link2", new StringElement("panda_link2"))); + thePanda.addKeyValuePair(new KeyValuePair("Link3", new StringElement("panda_link3"))); + thePanda.addKeyValuePair(new KeyValuePair("Link4", new StringElement("panda_link4"))); + thePanda.addKeyValuePair(new KeyValuePair("Link5", new StringElement("panda_link5"))); + thePanda.addKeyValuePair(new KeyValuePair("Link6", new StringElement("panda_link6"))); + thePanda.addKeyValuePair(new KeyValuePair("RightFinger", new StringElement("panda_rightfinger"))); + thePanda.addKeyValuePair(new KeyValuePair("LeftFinger", new StringElement("panda_leftfinger"))); pandaParts.setValue(thePanda); parts.setValue(pandaParts); firstLevel.addKeyValuePair(parts); @@ -59,7 +65,7 @@ public class SimpleMain { end_effectors.setKey("end_effectors"); KeyValuePair endEffectorParts = new KeyValuePair(); endEffectorParts.setKey("panda"); - endEffectorParts.setValue(new KeyValuePair("EndEffector", new QuotedStringElement("panda_hand"))); + endEffectorParts.setValue(new KeyValuePair("EndEffector", new StringElement("panda_hand"))); end_effectors.setValue(endEffectorParts); firstLevel.addKeyValuePair(end_effectors); @@ -83,9 +89,9 @@ public class SimpleMain { private static void addPose(ListElement theGoalPoses, String position) { MappingElement goalPose1 = new MappingElement(); - goalPose1.addKeyValuePair(new KeyValuePair("position", new QuotedStringElement(position))); - goalPose1.addKeyValuePair(new KeyValuePair("orientation", new QuotedStringElement("1 1 0 0"))); - goalPose1.addKeyValuePair(new KeyValuePair("work", new QuotedStringElement("20000"))); + goalPose1.addKeyValuePair(new KeyValuePair("position", new StringElement(position))); + goalPose1.addKeyValuePair(new KeyValuePair("orientation", new StringElement("1 1 0 0"))); + goalPose1.addKeyValuePair(new KeyValuePair("work", new StringElement("20000"))); theGoalPoses.addElement(goalPose1); } diff --git a/src/main/resources/mqtt.mustache b/src/main/resources/mqtt.mustache index f10ae88139d958d2f4b0a8f4245b64b41e0f1003..9391d1091c41eee257f9e6a1368297ef743e39ce 100644 --- a/src/main/resources/mqtt.mustache +++ b/src/main/resources/mqtt.mustache @@ -6,11 +6,11 @@ aspect MQTT { {{mqttHandlerField}}.setupWaitUntilReady(time, unit); } - {{#getRootTypeComponents}} + {{#RootTypeComponents}} {{#first}}inh MqttServerHandler ASTNode.{{mqttHandlerAttribute}}();{{/first}} eq {{rootNodeName}}.get{{name}}().{{mqttHandlerAttribute}}() = {{mqttHandlerField}}; - {{/getRootTypeComponents}} - {{^getRootTypeComponents}} + {{/RootTypeComponents}} + {{^RootTypeComponents}} syn MqttServerHandler {{rootNodeName}}.{{mqttHandlerAttribute}}() = {{mqttHandlerField}}; - {{/getRootTypeComponents}} + {{/RootTypeComponents}} }