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))); }
public void RegisterContainingType(CppType cppType) { ContainingType = cppType; }
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()); } }