예제 #1
0
 internal CppConstant(string name, string attributePrefix, string ns, string value, CppDataType dataType,
                      string[] usings) : base(name, attributePrefix)
 {
     Namespace = ns;
     Value     = value;
     DataType  = dataType;
     Usings    = usings;
 }
예제 #2
0
        public static IEnumerable <CppField> Parse(ParseNode declaration, string[] usings, string ns,
                                                   List <ParserMessage> messages, string attributePrefix,
                                                   CppType containingType)
        {
            if (!declaration.IsValidFieldDeclaration())
            {
                return(Enumerable.Empty <CppField>());
            }

            ParseNode[] identifiers = declaration.GetFieldIdentifier();
            if (identifiers.FirstOrDefault()?.ToString() == "using")
            {
                //using directive inside class/struct
                return(Enumerable.Empty <CppField>());
            }
            ParseNode[] typeNodes = declaration.GetFieldTypeNodes(identifiers);
            if (identifiers.SequenceEqual(typeNodes))
            {
                if (typeNodes.Any())
                {
                    (int line, int column)position = declaration.Position;
                    messages.Add(new ParserMessage("CPP0001", position.line, position.column));
                }

                //Empty group "private:"
                return(Enumerable.Empty <CppField>());
            }

            CppDataType dataType = typeNodes.GetFieldDataType(usings, ns);

            IEnumerable <ParseNode> fieldIdentifiers = identifiers.Intersect(typeNodes).Any()
                                                          ? identifiers.SkipWhile(i => !typeNodes.Contains(i))
                                                       .SkipWhile(typeNodes.Contains)
                                                          : identifiers;

            IEnumerable <(string name, string[] multiplicity)> fields = fieldIdentifiers
                                                                        .Select(i => (i.ToString(), i.GetParent().GetFieldMultiplicity()));

            CppComment[] comments = declaration.GetFieldComments();

            return(fields.Select(fd => new CppField(fd.name, dataType, comments, fd.multiplicity, attributePrefix, containingType)));
        }
예제 #3
0
        private IEnumerable <IConstant> GetConstants(ParseNode root, string[] usings)
        {
            List <IConstant>        constants    = new List <IConstant>();
            IEnumerable <ParseNode> declarations = root.GetHierarchy()
                                                   .Where(n => n.RuleName == "declaration" &&
                                                          n.RuleType == "choice" &&
                                                          n.ToString().Contains("const "));

            foreach (ParseNode declaration in declarations)
            {
                ParseConstant(declaration);
            }

            return(constants);

            void ParseConstant(ParseNode declaration)
            {
                if (declaration.IsValidFieldDeclaration() && ContainsConstIdentifier())
                {
                }
                if (!declaration.IsValidFieldDeclaration() ||
                    !ContainsConstIdentifier() ||
                    IsPartOfMethodDefinition() ||
                    HasTypeDeclarationParent(declaration))
                {
                    return;
                }

//paran_group
//declaration_list
                ParseNode[] identifiers = declaration.GetFieldIdentifier()
                                          .SkipWhile(i => i.ToString().Trim() != "const")
                                          .Skip(1)
                                          .ToArray();
                if (!identifiers.Any())
                {
                    return;
                }

                ParseNode[] typeNodes  = declaration.GetFieldTypeNodes(identifiers);
                ParseNode[] valueNodes = declaration.GetFieldValue();
                if (identifiers.SequenceEqual(typeNodes))
                {
                    return;
                }

                string               ns       = GetNamespace(declaration, skipFirst: false);
                CppDataType          dataType = typeNodes.GetFieldDataType(usings, ns);
                IEnumerable <string> fields   = identifiers.SkipWhile(i => !typeNodes.Contains(i))
                                                .SkipWhile(typeNodes.Contains)
                                                .Where(i => !i.GetParent().GetFieldMultiplicity().Any())
                                                .Select(i => i.ToString());
                IEnumerable <string> values = valueNodes.Where(i => !string.IsNullOrEmpty(i.ToString().Trim()))
                                              .Select(i => i.ToString().Trim());
                string value = string.Join(" ", values);

                if (string.IsNullOrEmpty(value))
                {
                    return;
                }

                foreach (string field in fields)
                {
                    constants.Add(new CppConstant(field, settingsProvider.Settings.AttributePrefix,
                                                  ns, value, dataType, usings));
                }

                bool ContainsConstIdentifier()
                {
                    return(declaration.GetFieldIdentifier().FirstOrDefault()?
                           .ToString().Trim() == "const");
                }

                bool IsPartOfMethodDefinition()
                {
                    return(declaration.GetDeclarationListParent()?.GetParent()?
                           .RuleName == "paran_group");
                }
            }
        }
예제 #4
0
        public static IEnumerable <CppField> Parse(ParseNode declaration, string[] usings, string ns,
                                                   List <ParserMessage> messages, string attributePrefix,
                                                   CppType containingType)
        {
            if (declaration.GetHierarchy().Any(n => n.RuleName == "paran_group") ||
                declaration.GetHierarchy().Any(n => n.RuleName == "typedef_decl") ||
                declaration.GetHierarchy().Any(n => n.RuleName == "pp_directive"))
            {
                return(Enumerable.Empty <CppField>());
            }

            ParseNode[] identifiers = GetIdentifier();
            ParseNode[] typeNodes   = GetTypeDeclarationName() ?? GetTypeNodes(identifiers);
            if (identifiers.SequenceEqual(typeNodes))
            {
                if (typeNodes.Any())
                {
                    (int line, int column)position = declaration.Position;
                    messages.Add(new ParserMessage("CPP0001", position.line, position.column));
                }

                //Empty group "private:"
                return(Enumerable.Empty <CppField>());
            }

            string dataTypeName = typeNodes.Aggregate(string.Empty, (s, node) => $"{s}{node}");
            IEnumerable <(string name, int[] multiplicity)> fields = identifiers.Except(typeNodes).Select(i => (i.ToString(), GetMultiplicity(i.GetParent())));

            IComment[]  comments = GetComments();
            CppDataType dataType = new CppDataType(dataTypeName, usings, ns);

            return(fields.Select(fd => new CppField(fd.name, dataType, comments, fd.multiplicity, attributePrefix, containingType)));

            ParseNode[] GetTypeDeclarationName()
            {
                ParseNode typeDeclaration = declaration.GetHierarchy().FirstOrDefault(n => n.RuleName == "type_decl");

                return(typeDeclaration?.GetHierarchy().Select(Identifier).Where(n => n != null).ToArray());

                ParseNode Identifier(ParseNode node)
                {
                    if (node.RuleType == "leaf" && node.RuleName == "identifier")
                    {
                        return(node);
                    }

                    return(null);
                }
            }

            IComment[] GetComments()
            {
                ParseNode content = declaration.ChildrenSkipUnnamed().First(n => n.RuleType == "plus" && n.RuleName == "declaration_content");

                return(content.ChildrenSkipUnnamed()
                       .Where(IsComment)
                       .Where(c => !string.IsNullOrEmpty(c.ToString()))
                       .Select(CppComment.Parse)
                       .ToArray());

                bool IsComment(ParseNode node)
                {
                    return(node.RuleType == "sequence" && node.RuleName == "comment_set");
                }
            }

            ParseNode[] GetIdentifier()
            {
                ParseNode content = declaration.ChildrenSkipUnnamed().FirstOrDefault(n => n.RuleType == "plus" && n.RuleName == "declaration_content");

                if (content == null)
                {
                    return(Array.Empty <ParseNode>());
                }

                return(content.ChildrenSkipUnnamed()
                       .Select(Identifier).Where(n => n != null)
                       .ToArray());

                ParseNode Identifier(ParseNode parent)
                {
                    if (parent.RuleType == "choice" && parent.RuleName == "node")
                    {
                        ParseNode result = parent.FirstOrDefault();
                        if (result?.RuleType == "leaf" && result.RuleName == "identifier")
                        {
                            return(result);
                        }
                    }

                    return(null);
                }
            }

            int[] GetMultiplicity(ParseNode identifier)
            {
                identifier = identifier.SkipUnnamedParents();
                int        index                  = identifier.GetParentIndex();
                ParseNode  parent                 = identifier.GetParent();
                List <int> multiplicities         = new List <int>();
                bool       firstMultiplicityFound = false;

                foreach (ParseNode sibling in parent.Skip(index + 1).SkipUnnamed())
                {
                    if (sibling.RuleType == "choice" && sibling.RuleName == "node")
                    {
                        ParseNode child = sibling.FirstOrDefault();
                        if (child?.RuleType == "sequence" && child.RuleName == "bracketed_group")
                        {
                            string bracketGroup = child.ToString().Trim();
                            if (int.TryParse(bracketGroup.Substring(1, bracketGroup.Length - 2), out int result))
                            {
                                multiplicities.Add(result);
                                firstMultiplicityFound = true;
                            }
                        }
                        else if (firstMultiplicityFound)
                        {
                            break;
                        }
                    }
                }

                return(multiplicities.ToArray());
            }

            ParseNode[] GetTypeNodes(ParseNode[] parseNodes)
            {
                return(parseNodes.TakeWhile(n => n.ToString().EndsWith("::", StringComparison.Ordinal))
                       .Concat(parseNodes.SkipWhile(n => n.ToString().EndsWith("::", StringComparison.Ordinal)).Take(1))
                       .ToArray());
            }
        }