private static IEnumerable Parse()

in src/Azure.IIoT.OpcUa.Publisher/src/Parser/RelativePathParser.cs [147:274]


        private static IEnumerable<RelativePathElementModel> Parse(string path)
        {
            var index = 0;
            while (index < path.Length)
            {
                //
                // Parse relative path reference information
                // This should allow
                // - "/targeturi"
                // - ".targeturi"
                // - "!.parenturi"
                // - "!/parenturi"
                // - "<!#uri>parenturi"
                //
                var parseReference = false;
                string? referenceTypeId = null;
                var inverse = false;
                var includeSubtypes = true;
                var exit = false;
                while (index < path.Length && !exit)
                {
                    switch (path[index])
                    {
                        case '<':
                            if (referenceTypeId == null && !parseReference)
                            {
                                parseReference = true;
                                break;
                            }
                            throw new FormatException("Reference type set.");
                        case '!':
                            inverse = true;
                            break;
                        case '#':
                            includeSubtypes = false;
                            break;
                        case '/':
                            if (referenceTypeId == null && !parseReference)
                            {
                                referenceTypeId =
                                    Opc.Ua.ReferenceTypeIds.HierarchicalReferences.ToString();
                                break;
                            }
                            throw new FormatException("Reference type set.");
                        case '.':
                            if (referenceTypeId == null && !parseReference)
                            {
                                referenceTypeId =
                                    Opc.Ua.ReferenceTypeIds.Aggregates.ToString();
                                break;
                            }
                            throw new FormatException("Reference type set.");
                        default:
                            if (referenceTypeId == null && !parseReference)
                            {
                                throw new FormatException(
                                    "No reference type specified.");
                            }
                            exit = true;
                            break;
                    }
                    index++;
                }
                index--;

                // Parse the reference type
                if (parseReference)
                {
                    var builder = new StringBuilder();
                    while (index < path.Length)
                    {
                        if (path[index] == '<' && path[index - 1] != '&')
                        {
                            throw new FormatException(
                                "Reference contains a < which is not allowed.");
                        }
                        if (path[index] == '>' && path[index - 1] != '&')
                        {
                            if (index + 1 < path.Length && path[index + 1] == '>')
                            {
                                throw new FormatException(
                                    "Reference path ends in > followed by >.");
                            }
                            break;
                        }
                        if (path[index] != '&' || path[index - 1] == '&')
                        {
                            builder.Append(path[index]);
                        }
                        index++;
                        if (index == path.Length)
                        {
                            throw new FormatException(
                                "Reference path starts in < but does not end in >");
                        }
                    }
                    index++; // Skip >

                    var reference = builder.ToString();
                    if (string.IsNullOrEmpty(reference))
                    {
                        throw new FormatException(
                            "Missed to provide a reference name between < and >.");
                    }
                    if (TypeMaps.ReferenceTypes.Value.TryGetIdentifier(reference,
                        out var id))
                    {
                        referenceTypeId = new Opc.Ua.NodeId(id).ToString();
                    }
                    else
                    {
                        referenceTypeId = reference;
                    }
                }

                // Parse target
                var target = ExtractTargetName(path, ref index);

                yield return new RelativePathElementModel
                {
                    IsInverse = inverse ? true : null,
                    NoSubtypes = includeSubtypes ? null : true,
                    ReferenceTypeId = referenceTypeId
                        ?? throw new FormatException("No reference type found"),
                    TargetName = target
                };
            }
        }