public void Parse() { // If outpath doesn't exist, mkdir if (!Directory.Exists(outFilePath)) { Directory.CreateDirectory(outFilePath); } // Append filename this.outFilePath = Path.Combine(this.outFilePath, this.className + ".cs"); using (StreamWriter writer = new StreamWriter(outFilePath, false)) { writer.Write(MsgAutoGenUtilities.BLOCK_COMMENT + "\n"); // Message -> Lines // Lines -> Line Lines | e while (!IsEmpty()) { Line(); } // Write imports writer.Write(GenerateImports()); // Write namespace writer.Write( "namespace RosSharp.RosBridgeClient.MessageTypes." + MsgAutoGenUtilities.ResolvePackageName(rosPackageName) + "\n" + "{\n" ); // Write class declaration writer.Write( MsgAutoGenUtilities.ONE_TAB + "public class " + className + " : Message\n" + MsgAutoGenUtilities.ONE_TAB + "{\n" ); // Write ROS package name writer.Write(MsgAutoGenUtilities.TWO_TABS + "public const string RosMessageName = \"" + rosPackageName + "/" + rosMsgName + "\";\n\n"); // Write body writer.Write(body); writer.Write("\n"); // Write constructors writer.Write(GenerateDefaultValueConstructor()); if (symbolTable.Count != 0 && !new HashSet <string>(symbolTable.Keys).SetEquals(constants)) { writer.Write("\n"); writer.Write(GenerateParameterizedConstructor()); } // Close class writer.Write(MsgAutoGenUtilities.ONE_TAB + "}\n"); // Close namespace writer.Write("}\n"); writer.Flush(); writer.Close(); } }
public void WrapAction() { string wrapperName = inFileName + "Action"; string outPath = Path.Combine(this.outPath, wrapperName + ".cs"); string imports = "\n\n"; symbolTable = new Dictionary <string, string>(); using (StreamWriter writer = new StreamWriter(outPath, false)) { // Write block comment writer.Write(MsgAutoGenUtilities.BLOCK_COMMENT + "\n"); // Write imports writer.Write(imports); // Write namespace writer.Write( "namespace RosSharp.RosBridgeClient.MessageTypes." + MsgAutoGenUtilities.ResolvePackageName(rosPackageName) + "\n" + "{\n" ); // Write class declaration string[] genericParams = new string[] { inFileName + "ActionGoal", inFileName + "ActionResult", inFileName + "ActionFeedback", inFileName + "Goal", inFileName + "Result", inFileName + "Feedback" }; writer.Write( ONE_TAB + "public class " + wrapperName + " : Action<" + string.Join(", ", genericParams) + ">\n" + ONE_TAB + "{\n" ); // Write ROS package name writer.Write( TWO_TABS + "public const string RosMessageName = \"" + rosPackageName + "/" + wrapperName + "\";\n" ); // Record variables // Action Goal symbolTable.Add("action_goal", wrapperName + "Goal"); // Action Result symbolTable.Add("action_result", wrapperName + "Result"); //Action Feedback symbolTable.Add("action_feedback", wrapperName + "Feedback"); // Write default value constructor writer.Write("\n" + GenerateDefaultValueConstructor(wrapperName) + "\n"); // Close class writer.Write(ONE_TAB + "}\n"); // Close namespace writer.Write("}\n"); } }
public void WrapActionSections(string type) { string wrapperName = inFileName + "Action" + type; string msgName = inFileName + type; string outPath = Path.Combine(this.outPath, wrapperName + ".cs"); string imports = "using Newtonsoft.Json;\n\n" + "using RosSharp.RosBridgeClient.MessageTypes.Std;\n" + "using RosSharp.RosBridgeClient.MessageTypes.Actionlib;\n\n"; symbolTable = new Dictionary <string, string>(); using (StreamWriter writer = new StreamWriter(outPath, false)) { // Write block comment writer.Write(MsgAutoGenUtilities.BLOCK_COMMENT + "\n"); // Write imports writer.Write(imports); // Write namespace writer.Write( "namespace RosSharp.RosBridgeClient.MessageTypes." + MsgAutoGenUtilities.ResolvePackageName(rosPackageName) + "\n" + "{\n" ); // Write class declaration writer.Write( ONE_TAB + "public class " + wrapperName + " : Action" + type + "<" + inFileName + type + ">\n" + ONE_TAB + "{\n" ); // Write ROS package name writer.Write( TWO_TABS + "[JsonIgnore]\n" + TWO_TABS + "public const string RosMessageName = \"" + rosPackageName + "/" + wrapperName + "\";\n" ); // Record goal/result/feedback declaration symbolTable.Add(MsgAutoGenUtilities.LowerFirstLetter(type), msgName); writer.Write("\n"); // Write default value constructor writer.Write(GenerateDefaultValueConstructor(wrapperName) + "\n"); // Write parameterized constructor writer.Write(GenerateParameterizedConstructor(wrapperName, type)); // Close class writer.Write(ONE_TAB + "}\n"); // Close namespace writer.Write("}\n"); } }
public static List <string> GenerateSingleAction(string inPath, string outPath, string rosPackageName = "", bool verbose = false) { // If no ROS package name is provided, extract from path if (rosPackageName.Equals("")) { string[] hierarchy = inPath.Split(new char[] { '/', '\\' }); rosPackageName = hierarchy[hierarchy.Length - 3]; } outPath = Path.Combine(outPath, MsgAutoGenUtilities.ResolvePackageName(rosPackageName)); string inFileName = Path.GetFileNameWithoutExtension(inPath); if (verbose) { Console.WriteLine("Parsing: " + inPath); Console.WriteLine("Output Location: " + outPath); } MessageTokenizer tokenizer = new MessageTokenizer(inPath, new HashSet <string>(MsgAutoGenUtilities.builtInTypesMapping.Keys)); List <List <MessageToken> > listsOfTokens = tokenizer.Tokenize(); if (listsOfTokens.Count != 3) { throw new MessageParserException("Unexpected number of sections. Action should have 3 sections."); } List <string> warnings = new List <string>(); ActionWrapper actionWrapper = new ActionWrapper(inPath, rosPackageName, outPath); for (int i = 0; i < listsOfTokens.Count; i++) { List <MessageToken> tokens = listsOfTokens[i]; // Action is made up of goal, result, feedback string className = inFileName + types[i]; // Parse and generate goal, result, feedback messages MessageParser parser = new MessageParser(tokens, outPath, rosPackageName, "action", MsgAutoGenUtilities.builtInTypesMapping, MsgAutoGenUtilities.builtInTypesDefaultInitialValues, className, className); parser.Parse(); warnings.AddRange(parser.GetWarnings()); // Generate action section wrapper messages actionWrapper.WrapActionSections(types[i]); } // Generate action wrapper actionWrapper.WrapAction(); return(warnings); }
public static List <string> GenerateSingleMessage(string inPath, string outPath, string rosPackageName = "", bool verbose = false) { // If no ROS package name is provided, extract from path if (rosPackageName.Equals("")) { string[] hierarchy = inPath.Split(new char[] { '/', '\\' }); rosPackageName = hierarchy[hierarchy.Length - 3]; } outPath = Path.Combine(outPath, MsgAutoGenUtilities.ResolvePackageName(rosPackageName)); string inFileName = Path.GetFileNameWithoutExtension(inPath); if (!(rosPackageName.Equals("std_msgs") && (inFileName.Equals("Time") || inFileName.Equals("Duration")))) { if (verbose) { Console.WriteLine("Parsing: " + inPath); Console.WriteLine("Output Location: " + outPath); } MessageTokenizer tokenizer = new MessageTokenizer(inPath, new HashSet <string>(MsgAutoGenUtilities.builtInTypesMapping.Keys)); List <List <MessageToken> > listOfTokens = tokenizer.Tokenize(); if (listOfTokens.Count != 1) { throw new MessageParserException("Unexpected number of sections. Simple message should have 1 section."); } MessageParser parser = new MessageParser(listOfTokens[0], outPath, rosPackageName, "msg", MsgAutoGenUtilities.builtInTypesMapping, MsgAutoGenUtilities.builtInTypesDefaultInitialValues); parser.Parse(); return(parser.GetWarnings()); } else { if (verbose) { Console.WriteLine(inFileName + " will not be generated"); } return(new List <string>()); } }
// Declaration -> BuiltInType Identifier | BuiltInType Identifier ConstantDeclaration | BuiltInType ArrayDeclaration Identifier // Declaration -> DefinedType Identifier | DefinedType ArrayDeclaration Identifier // Declaration -> Header Identifier private void Declaration() { string declaration = ""; // Type MessageToken peeked = Peek(); string type = ""; bool canHaveConstDecl = false; declaration += MsgAutoGenUtilities.TWO_TABS + "public "; if (PeekType(MessageTokenType.BuiltInType)) { type = builtInTypeMapping[MatchByType(MessageTokenType.BuiltInType)]; if (!type.Equals("Time") && !type.Equals("Duration")) { // Time and Duration can't have constant declaration // See <wiki.ros.org/msg> canHaveConstDecl = true; } else { // Need to import Standard imports.Add("Std"); } } else if (PeekType(MessageTokenType.DefinedType)) { type = MatchByType(MessageTokenType.DefinedType); string[] hierarchy = type.Split(new char[] { '/', '\\' }); // Assume type can only be either: // Type // package/Type switch (hierarchy.Length) { case 1: break; case 2: if (hierarchy[0].Equals("") || hierarchy[1].Equals("")) { throw new MessageParserException( "Invalid field type '" + type + "'. + " + "(" + inFilePath + ":" + lineNum + ")"); } string package = MsgAutoGenUtilities.ResolvePackageName(hierarchy[0]); imports.Add(package); type = hierarchy[1]; break; default: throw new MessageParserException( "Invalid field type '" + type + "'. + " + "(" + inFilePath + ":" + lineNum + ")"); } } else { type = MatchByType(MessageTokenType.Header); if (PeekType(MessageTokenType.FixedSizeArray) || PeekType(MessageTokenType.VariableSizeArray)) { Warn( "By convention, there is only one header for each message." + "(" + inFilePath + ":" + lineNum + ")"); } if (PeekType(MessageTokenType.Identifier) && !Peek().content.Equals("header")) { Warn( "By convention, a ros message Header will be named 'header'. '" + Peek().content + "'. (" + inFilePath + ":" + lineNum + ")"); } imports.Add("Std"); } // Array Declaration int arraySize = -1; if (PeekType(MessageTokenType.FixedSizeArray)) { type += "[]"; canHaveConstDecl = false; arraySize = int.Parse(MatchByType(MessageTokenType.FixedSizeArray)); } if (PeekType(MessageTokenType.VariableSizeArray)) { type += "[]"; canHaveConstDecl = false; MatchByType(MessageTokenType.VariableSizeArray); arraySize = 0; } // Identifier string identifier = MatchByType(MessageTokenType.Identifier); // Check for duplicate declaration if (symbolTable.ContainsKey(identifier)) { throw new MessageParserException( "Field '" + identifier + "' at " + inFilePath + ":" + lineNum + " already declared!"); } // Check if identifier is a ROS message built-in type if (builtInTypeMapping.ContainsKey(identifier) && identifier.Equals("time") && identifier.Equals("duration")) { throw new MessageParserException( "Invalid field identifier '" + identifier + "' at " + inFilePath + ":" + lineNum + ". '" + identifier + "' is a ROS message built-in type."); } #if NETFRAMEWORK CodeDomProvider provider = CodeDomProvider.CreateProvider("C#"); // Check if identifier is a C# keyword if (!provider.IsValidIdentifier(identifier)) { Warn( "'" + identifier + "' is a C# keyword. We have appended \"_\" at the front to avoid C# compile-time issues." + "(" + inFilePath + ":" + lineNum + ")"); declaration = MsgAutoGenUtilities.TWO_TABS + "[JsonProperty(\"" + identifier + "\")]\n" + declaration; identifier = "_" + identifier; } #else Warn( "'CodeDomProvider class might not exist on your platform. We did not check whether " + identifier + "' is a C# keyword." + "(" + inFilePath + ":" + lineNum + ")"); #endif symbolTable.Add(identifier, type); // Array declaration table if (arraySize > -1) { arraySizes.Add(identifier, arraySize); } // Constant Declaration if (PeekType(MessageTokenType.ConstantDeclaration)) { if (canHaveConstDecl) { declaration += "const " + type + " " + identifier + " = "; declaration += ConstantDeclaration(type); constants.Add(identifier); } else { throw new MessageParserException( "Type " + type + "' at " + inFilePath + ":" + lineNum + " cannot have constant declaration"); } } else { declaration += type + " " + identifier + MsgAutoGenUtilities.PROPERTY_EXTENSION + "\n"; } body += declaration; }