예제 #1
0
        // Line -> Comment | Declaration
        private void Line()
        {
            MessageToken peeked = Peek();

            if (PeekType(MessageTokenType.Comment))
            {
                Comment();
            }
            else if (PeekType(MessageTokenType.BuiltInType) || PeekType(MessageTokenType.DefinedType) || PeekType(MessageTokenType.Header))
            {
                Declaration();
            }
            else
            {
                // Mumble mumble
                if (peeked == null)
                {
                    throw new MessageParserException(
                              "Unexpected end of input " +
                              "' at " + inFilePath + ":" + lineNum);
                }
                else
                {
                    throw new MessageParserException(
                              "Unexpected token '" + peeked.content +
                              "' at " + inFilePath + ":" + lineNum +
                              ". Expecting a comment or field declaration.");
                }
            }
        }
예제 #2
0
        private string MatchByType(MessageTokenType type)
        {
            MessageToken token = tokens[0];

            if (token.type.Equals(type))
            {
                tokens.RemoveAt(0);
                // Update line num
                if (!IsEmpty())
                {
                    lineNum = tokens[0].lineNum;
                }
                return(token.content);
            }
            else
            {
                throw new MessageParserException(
                          "Unexpected token '" + token.content +
                          "' at " + inFilePath + ":" + token.lineNum +
                          ". Expecting a token of type " +
                          Enum.GetName(typeof(MessageTokenType), token.type));
            }
        }
예제 #3
0
        // 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 == "TimeMsg" || type == "DurationMsg")
                {
                    // Need to import BuiltinInterfaces
                    imports.Add("BuiltinInterfaces");
                }
                else
                {
                    // Time and Duration can't have constant declaration
                    // See <wiki.ros.org/msg>
                    canHaveConstDecl = true;
                }
            }
            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:
                    type = type + MsgAutoGenUtilities.MessageClassSuffix;
                    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]);
                    // Do not add package name if exists in current namespace
                    type = package.Equals(rosPackageNamespace) ? hierarchy[1] + MsgAutoGenUtilities.MessageClassSuffix :
                           package + "." + hierarchy[1] + MsgAutoGenUtilities.MessageClassSuffix;
                    break;

                default:
                    throw new MessageParserException(
                              "Invalid field type '" + type + "'. + " +
                              "(" + inFilePath + ":" + lineNum + ")");
                }
            }
            else
            {
                type = MatchByType(MessageTokenType.Header) + MsgAutoGenUtilities.MessageClassSuffix;
                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))
            {
                throw new MessageParserException(
                          "Invalid field identifier '" + identifier +
                          "' at " + inFilePath + ":" + lineNum +
                          ". '" + identifier + "' is a ROS message built-in type.");
            }

            // Check if identifier is a C# keyword
            if (MsgAutoGenUtilities.k_CSharpKeywords.Contains(identifier))
            {
                Warn(
                    "'" + identifier + "' is a C# keyword. It can be accessed under the name @" + identifier + "." +
                    "(" + inFilePath + ":" + lineNum + ")");
                identifier = "@" + identifier;
            }

            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 if (PeekType(MessageTokenType.DefaultValueDeclaration))
            {
                declaration += $"{type} {identifier} = {DefaultValueDeclaration(type)}";
                defaultValues.Add(identifier);
            }
            else
            {
                declaration += type + " " + identifier + ";\n";
            }
            body += declaration;
        }