private HierarchicalExpression(string[] segments, Reflection.MemberPathSegment[] members)
        {
            _segments = segments ?? new string[0];
            _members  = members ?? new Reflection.MemberPathSegment[0];
            _anchor   = IO.PathAnchor.None;
            _path     = string.Empty;

            if (segments.Length > 0)
            {
                switch (segments[0])
                {
                case "":
                    _anchor = IO.PathAnchor.Root;
                    break;

                case ".":
                    _anchor = IO.PathAnchor.Current;
                    break;

                case "..":
                    _anchor = IO.PathAnchor.Parent;
                    break;
                }

                if (segments.Length == 1 && segments[0].Length == 0)
                {
                    _path = "/";
                }
                else
                {
                    _path = string.Join("/", segments);
                }
            }
        }
 public StateContext(ReadOnlySpan <char> data)
 {
     _data           = data;
     _anchorPosition = -1;
     _cursorPosition = -1;
     _whitespaces    = 0;
     this.State      = State.None;
     this.Character  = '\0';
     this.Anchor     = IO.PathAnchor.None;
 }
예제 #3
0
        private static void ParsePath(TextReader reader, out IO.PathAnchor anchor, out string name, out string path)
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            var state     = CommandPathState.None;
            var parts     = new List <string>();
            var valueRead = 0;

            //设置输出参数的默认值
            anchor = IO.PathAnchor.None;
            name   = string.Empty;
            path   = string.Empty;

            while ((valueRead = reader.Read()) > 0)
            {
                var chr = (char)valueRead;

                //首先对位于路径中间的点号进行转换,以方便后续的处理
                if (chr == '.' && state == CommandPathState.Part)
                {
                    chr = '/';
                }

                if (chr == '.')
                {
                    switch (state)
                    {
                    case CommandPathState.None:
                        state  = CommandPathState.Dot;
                        anchor = IO.PathAnchor.Current;
                        break;

                    case CommandPathState.Dot:
                        state  = CommandPathState.DoubleDot;
                        anchor = IO.PathAnchor.Parent;
                        break;

                    default:
                        throw new CommandExpressionException("Invalid anchor of command path.");
                    }
                }
                else if (chr == '/')
                {
                    if (state == CommandPathState.Slash)
                    {
                        throw new CommandExpressionException("Duplicate '/' slash characters.");
                    }

                    if (state == CommandPathState.None)
                    {
                        anchor = IO.PathAnchor.Root;
                    }
                    else if (state == CommandPathState.Part)
                    {
                        parts.Add(name);
                        name = string.Empty;
                    }

                    state = CommandPathState.Slash;
                }
                else if (Char.IsLetterOrDigit(chr) || chr == '_')
                {
                    if (state == CommandPathState.Dot || state == CommandPathState.DoubleDot)
                    {
                        throw new CommandExpressionException("Missing '/' slash character between dot and letter or digit.");
                    }

                    name += chr;
                    state = CommandPathState.Part;
                }
                else if (Char.IsWhiteSpace(chr))
                {
                    if (state == CommandPathState.None)
                    {
                        continue;
                    }
                    else
                    {
                        break;
                    }
                }
                else
                {
                    throw new CommandExpressionException($"Contains '{chr}' illegal character(s) in the command path.");
                }
            }

            //如果路径以斜杠符结尾,即为非法路径格式
            if (state == CommandPathState.Slash && ((parts != null && parts.Count > 0) || anchor != IO.PathAnchor.Root))
            {
                throw new CommandExpressionException("The command path can not at the end of '/' character.");
            }

            if (parts != null && parts.Count > 0)
            {
                path = string.Join(".", parts);
            }
            else if (string.IsNullOrEmpty(name))
            {
                switch (anchor)
                {
                case IO.PathAnchor.Root:
                    name = "/";
                    break;

                case IO.PathAnchor.Current:
                    name = ".";
                    break;

                case IO.PathAnchor.Parent:
                    name = "..";
                    break;
                }

                anchor = IO.PathAnchor.None;
            }
        }