Example #1
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)));
        }
Example #2
0
 public void RegisterContainingType(CppType cppType)
 {
     ContainingType = cppType;
 }
Example #3
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());
            }
        }