private static bool DoSegement(ref StateContext context, int position, Action <string> complete, Action <string> error)
        {
            switch (context.Character)
            {
            case '@':
            case '[':
                context.State = State.Exit;
                complete(context.Accept(1));
                return(true);

            case '/':
            case '\\':
                context.State = State.Slash;
                complete(context.Accept(1));
                return(true);
            }

            if (Validate(context.Character))
            {
                return(true);
            }

            error(GetIllegalCharacterExceptionMessage(context.Character, position));
            return(false);
        }
Example #2
0
        private static bool DoString(ref StateContext context, int position)
        {
            if (context.Flags.IsEscaping())
            {
                context.Accept(Escape(context.Character));
                context.Flags.IsEscaping(false);
            }
            else
            {
                if (context.Character == '\\')
                {
                    context.Flags.IsEscaping(true);
                }
                else if (context.Character == context.Flags.GetStringQuote())
                {
                    context.State = State.Parameter;
                    context.AppendParameterConstant(context.Stack.Peek());
                }
                else
                {
                    context.Accept();
                }
            }

            return(true);
        }
        private static bool DoNone(ref StateContext context)
        {
            if (context.IsWhitespace())
            {
                return(true);
            }

            switch (context.Character)
            {
            case '*':
                context.State = State.Asterisk;
                return(true);

            case '!':
                context.State = State.Exclude;
                return(true);

            case '}':
                return(context.Pop() != null);

            case ',':
                return(true);

            default:
                if (context.IsLetterOrUnderscore())
                {
                    context.Accept();
                    context.State = State.Include;
                    return(true);
                }

                context.OnError($"SyntaxError: Contains the illegal character '{context.Character}' in the data schema.");
                return(false);
            }
        }
        private static bool DoAnchorCurrent(ref StateContext context, int position, Action <string> error)
        {
            if (char.IsWhiteSpace(context.Character))
            {
                return(true);
            }

            switch (context.Character)
            {
            case '.':
                if (context.HasWhitespaces)
                {
                    error("The path anchors cannot contain whitespace characters.");
                    return(false);
                }

                context.State  = State.AnchorParent;
                context.Anchor = IO.PathAnchor.Parent;
                return(true);

            case '/':
            case '\\':
                context.State = State.Slash;
                context.Accept(1);
                return(true);

            default:
                error(GetIllegalCharacterExceptionMessage(context.Character, position));
                return(false);
            }
        }
Example #5
0
        private static bool DoMethod(ref StateContext context, int position)
        {
            if (context.IsWhitespace())
            {
                return(true);
            }

            if (context.Character == '\'' || context.Character == '\"')
            {
                context.State = State.String;
                context.Flags.SetConstantType(TypeCode.String);
                context.Flags.SetStringQuote(context.Character);
                return(true);
            }

            if (context.Character >= '0' && context.Character <= '9')
            {
                context.State = State.Number;
                context.Flags.SetConstantType(TypeCode.Int32);
                context.Accept();
                return(true);
            }

            if (context.IsLetterOrUnderscore())
            {
                context.State = State.Identifier;
                context.Accept();
                return(true);
            }

            if (context.Character == '[')
            {
                context.AppendIndexer();
                return(true);
            }

            if (context.Character == ')')
            {
                context.Stack.Pop();
                context.ResetState();
                return(true);
            }

            context.OnError(GetIllegalCharacterExceptionMessage(context.Character, position));
            return(false);
        }
        private static bool DoInclude(ref StateContext context)
        {
            switch (context.Character)
            {
            case ',':
                context.Include();
                context.State = State.None;
                break;

            case ':':
                context.Include();
                context.State = State.PagingCount;
                break;

            case '(':
                context.Include();
                context.State = State.SortingField;
                break;

            case '{':
                context.Include();
                context.Push();
                context.State = State.None;
                break;

            case '}':
                context.Include();
                context.Pop();
                context.State = State.None;
                break;

            default:
                if (context.IsLetterOrDigitOrUnderscore())
                {
                    //判断标识中间是否含有空白字符
                    if (context.Flags.HasWhitespace())
                    {
                        context.OnError("SyntaxError: The identifier of the data schema contains whitespace characters.");
                        return(false);
                    }

                    context.Accept();
                }
                else if (!context.IsWhitespace())
                {
                    context.OnError($"SyntaxError: The identifier of the data schema contains '{context.Character}' illegal character.");
                    return(false);
                }

                break;
            }

            //重置是否含有空格的标记
            context.Flags.HasWhitespace(context.IsWhitespace());

            return(true);
        }
        private static bool DoSortingField(ref StateContext context)
        {
            switch (context.Character)
            {
            case '~':
            case '!':
                if (context.HasBuffer())
                {
                    context.OnError("");
                    return(false);
                }

                context.Accept();
                return(true);

            case ',':
                if (context.AddSorting())
                {
                    context.State = State.SortingGutter;
                    return(true);
                }

                return(false);

            case ')':
                if (context.AddSorting())
                {
                    context.State = State.Include;
                    return(true);
                }

                return(false);

            default:
                if (context.IsLetterOrDigitOrUnderscore())
                {
                    context.Accept();
                    return(true);
                }

                context.OnError("");
                return(false);
            }
        }
        private static bool DoSortingField(ref StateContext context)
        {
            switch (context.Character)
            {
            case '~':
            case '!':
                if (context.HasBuffer())
                {
                    context.OnError("SyntaxError: Expected sorting field in the data schema, but missing.");
                    return(false);
                }

                context.Accept();
                return(true);

            case ',':
                if (context.AddSorting())
                {
                    context.State = State.SortingGutter;
                    return(true);
                }

                return(false);

            case ')':
                if (context.AddSorting())
                {
                    context.State = State.Include;
                    return(true);
                }

                return(false);

            default:
                if (context.IsLetterOrDigitOrUnderscore())
                {
                    context.Accept();
                    return(true);
                }

                context.OnError($"SyntaxError: The sorting field of the data schema contains '{context.Character}' illegal character.");
                return(false);
            }
        }
        private static bool DoExclude(ref StateContext context)
        {
            switch (context.Character)
            {
            case ',':
                context.Exclude();
                context.State = State.None;
                break;

            case '}':
                context.Exclude();
                context.Pop();
                context.State = State.None;
                break;

            default:
                if (context.IsLetterOrDigitOrUnderscore())
                {
                    //如果首字符是数字,则激发错误
                    if (char.IsDigit(context.Character) && !context.HasBuffer())
                    {
                        context.OnError("SyntaxError: The identifier of the data schema cannot start with a digit.");
                        return(false);
                    }

                    //判断标识中间是否含有空白字符
                    if (context.Flags.HasWhitespace())
                    {
                        context.OnError("SyntaxError: The identifier of the data schema contains whitespace characters.");
                        return(false);
                    }

                    context.Accept();
                }
                else if (!context.IsWhitespace())
                {
                    context.OnError($"SyntaxError: The identifier of the data schema contains '{context.Character}' illegal character.");
                    return(false);
                }

                break;
            }

            //重置是否含有空格的标记
            context.Flags.HasWhitespace(context.IsWhitespace());

            return(true);
        }
        private static bool DoExclude(ref StateContext context)
        {
            switch (context.Character)
            {
            case ',':
                context.Exclude();
                context.State = State.None;
                break;

            case '}':
                context.Exclude();
                context.Pop();
                context.State = State.None;
                break;

            default:
                if (context.IsLetterOrDigitOrUnderscore())
                {
                    //如果首字符是数字,则激发错误
                    if (char.IsDigit(context.Character) && !context.HasBuffer())
                    {
                        context.OnError("");
                        return(false);
                    }

                    //判断标识中间是否含有空白字符
                    if (context.Flags.HasWhitespace())
                    {
                        context.OnError("");
                        return(false);
                    }

                    context.Accept();
                }
                else if (!context.IsWhitespace())
                {
                    context.OnError("");
                    return(false);
                }

                break;
            }

            //重置是否含有空格的标记
            context.Flags.HasWhitespace(context.IsWhitespace());

            return(true);
        }
Example #11
0
        private static bool DoSeparator(ref StateContext context, int position)
        {
            if (context.IsWhitespace())
            {
                return(true);
            }

            if (context.IsLetterOrUnderscore())
            {
                context.State = State.Identifier;
                context.Accept();
                return(true);
            }

            context.OnError(GetIllegalCharacterExceptionMessage(context.Character, position));
            return(false);
        }
        private static bool DoSortingGutter(ref StateContext context)
        {
            if (context.IsWhitespace())
            {
                return(true);
            }

            if (context.IsLetterOrUnderscore())
            {
                context.Accept();
                context.State = State.SortingField;
                return(true);
            }

            context.OnError($"SyntaxError: Contains the illegal character '{context.Character}' in the data schema.");
            return(false);
        }
        private static bool DoSortingGutter(ref StateContext context)
        {
            if (context.IsWhitespace())
            {
                return(true);
            }

            if (context.IsLetterOrUnderscore())
            {
                context.Accept();
                context.State = State.SortingField;
                return(true);
            }

            context.OnError("");
            return(false);
        }
        private static bool DoAnchorParent(ref StateContext context, int position, Action <string> error)
        {
            if (char.IsWhiteSpace(context.Character))
            {
                return(true);
            }

            if (context.Character == '/' || context.Character == '\\')
            {
                context.State = State.Slash;
                context.Accept(1);
                return(true);
            }

            error(GetIllegalCharacterExceptionMessage(context.Character, position));
            return(false);
        }
        private static bool DoNone(ref StateContext context)
        {
            if (context.IsWhitespace())
            {
                return(true);
            }

            switch (context.Character)
            {
            case '*':
                //context.Accept();
                context.State = State.Asterisk;
                return(true);

            case '!':
                context.State = State.Exclude;
                return(true);

            case '}':
                return(context.Pop() != null);

            case ',':
                return(true);

            default:
                if (context.IsLetterOrUnderscore())
                {
                    context.Accept();
                    context.State = State.Include;
                    return(true);
                }

                context.OnError("");
                return(false);
            }
        }
Example #16
0
        private static bool DoNone(ref StateContext context, int position)
        {
            if (context.IsWhitespace())
            {
                return(true);
            }

            if (context.IsLetterOrUnderscore())
            {
                context.State = State.Identifier;
                context.Accept();
                return(true);
            }

            if (context.Character == '[')
            {
                context.State = State.Indexer;
                context.Stack.Push(context.Head = MemberExpression.Indexer());
                return(true);
            }

            context.OnError(GetIllegalCharacterExceptionMessage(context.Character, position));
            return(false);
        }
Example #17
0
        private static bool DoNumber(ref StateContext context, int position)
        {
            switch (context.Character)
            {
            case ',':
                var ownerState = context.GetOwnerState();

                if (ownerState != State.Indexer && ownerState != State.Method)
                {
                    context.OnError(EXCEPTION_UNKNOWN_MESSAGE);
                    return(false);
                }

                context.State = ownerState;
                context.AppendParameterConstant(context.Stack.Peek());

                break;

            case ']':
                if (context.GetOwnerState() != State.Indexer)
                {
                    context.OnError(GetIllegalCharacterExceptionMessage(context.Character, position));
                    return(false);
                }

                context.AppendParameterConstant(context.Stack.Pop());
                context.ResetState();

                break;

            case ')':
                if (context.GetOwnerState() != State.Method)
                {
                    context.OnError(GetIllegalCharacterExceptionMessage(context.Character, position));
                    return(false);
                }

                context.AppendParameterConstant(context.Stack.Pop());
                context.ResetState();

                break;

            case '.':
                var numberType = context.Flags.GetConstantType();

                if (numberType == TypeCode.Double || numberType == TypeCode.Single || numberType == TypeCode.Decimal)
                {
                    context.OnError(GetIllegalCharacterExceptionMessage(context.Character, position));
                    return(false);
                }

                context.Flags.SetConstantType(TypeCode.Double);
                context.Accept();

                break;

            case 'L':
                context.State = State.Parameter;
                context.Flags.SetConstantType(TypeCode.Int64);
                context.AppendParameterConstant(context.Stack.Peek());

                break;

            case 'f':
            case 'F':
                context.State = State.Parameter;
                context.Flags.SetConstantType(TypeCode.Single);
                context.AppendParameterConstant(context.Stack.Peek());

                break;

            case 'm':
            case 'M':
                context.State = State.Parameter;
                context.Flags.SetConstantType(TypeCode.Decimal);
                context.AppendParameterConstant(context.Stack.Peek());

                break;

            default:
                if (context.Character >= '0' && context.Character <= '9')
                {
                    context.Accept();
                }
                else if (context.IsWhitespace())
                {
                    context.State = State.Parameter;
                    context.AppendParameterConstant(context.Stack.Peek());
                }
                else
                {
                    context.OnError(GetIllegalCharacterExceptionMessage(context.Character, position));
                    return(false);
                }

                break;
            }

            return(true);
        }
        private static bool DoPagingCount(ref StateContext context)
        {
            string buffer;

            switch (context.Character)
            {
            case '?':
                if (context.HasBuffer())
                {
                    context.OnError("");
                    return(false);
                }

                context.Current.Paging = null;
                context.State          = State.Include;
                return(true);

            case '*':
                if (context.HasBuffer())
                {
                    context.OnError("");
                    return(false);
                }

                context.Current.Paging = Paging.Disable;
                context.State          = State.Include;
                return(true);

            case '/':
                if (!context.TryGetBuffer(out buffer))
                {
                    context.OnError("");
                    return(false);
                }

                context.Current.Paging = Paging.Page(int.Parse(buffer));
                context.State          = State.PagingSize;

                return(true);

            case '(':
                if (!context.TryGetBuffer(out buffer))
                {
                    context.OnError("");
                    return(false);
                }

                context.Current.Paging = Paging.Page(1, int.Parse(buffer));
                context.State          = State.SortingField;
                return(true);

            case '{':
                if (!context.TryGetBuffer(out buffer))
                {
                    context.OnError("");
                    return(false);
                }

                context.Current.Paging = Paging.Page(1, int.Parse(buffer));
                context.Push();
                context.State = State.None;
                return(true);

            default:
                if (char.IsDigit(context.Character))
                {
                    context.Accept();
                    return(true);
                }

                context.OnError("");
                return(false);
            }
        }
Example #19
0
        private static bool DoIdentifier(ref StateContext context, int position)
        {
            switch (context.Character)
            {
            case '.':
                context.State = State.Separator;

                context.AppendIdentifier(context.Peek());
                context.Flags.IsAttaching(true);

                break;

            case '[':
                context.State = State.Indexer;

                context.AppendIdentifier(context.Peek());
                context.AppendIndexer();
                context.Flags.IsAttaching(false);

                break;

            case '(':
                context.State = State.Method;

                context.AppendMethod();
                context.Flags.IsAttaching(false);

                break;

            case ',':
                var ownerState = context.GetOwnerState();

                if (ownerState == State.Indexer || ownerState == State.Method)
                {
                    context.State = ownerState;
                }
                else
                {
                    context.OnError(GetIllegalCharacterExceptionMessage(context.Character, position));
                    return(false);
                }

                context.AppendIdentifier(context.Peek());
                context.Flags.IsAttaching(false);

                break;

            case ']':
                if (context.GetOwnerState() != State.Indexer)
                {
                    context.OnError(GetIllegalCharacterExceptionMessage(context.Character, position));
                    return(false);
                }

                context.AppendIdentifier(context.Stack.Pop());
                context.Flags.IsAttaching(false);

                //重置状态
                context.ResetState();

                break;

            case ')':
                if (context.GetOwnerState() != State.Method)
                {
                    context.OnError(GetIllegalCharacterExceptionMessage(context.Character, position));
                    return(false);
                }

                context.AppendIdentifier(context.Stack.Pop());
                context.Flags.IsAttaching(false);

                //重置状态
                context.ResetState();

                break;

            default:
                if (context.IsLetterOrDigitOrUnderscore())
                {
                    //判断标识表达式中间是否含有空白字符
                    if (context.Flags.HasWhitespace())
                    {
                        context.OnError(string.Format(EXCEPTION_IDENTIFIER_WHITESPACE_MESSAGE, position));
                        return(false);
                    }

                    context.Accept();
                }
                else if (!context.IsWhitespace())
                {
                    context.OnError(GetIllegalCharacterExceptionMessage(context.Character, position));
                    return(false);
                }

                break;
            }

            //重置是否含有空格的标记
            context.Flags.HasWhitespace(context.IsWhitespace());

            return(true);
        }
        private static bool DoPagingSize(ref StateContext context)
        {
            string buffer;

            switch (context.Character)
            {
            case '?':
                if (context.HasBuffer())
                {
                    context.OnError("");
                    return(false);
                }

                context.Current.Paging.PageSize = 20;
                context.State = State.Include;
                return(true);

            case ',':
                if (!context.TryGetBuffer(out buffer))
                {
                    context.OnError("");
                    return(false);
                }

                context.Current.Paging.PageSize = int.Parse(buffer);
                context.State = State.None;
                return(true);

            case '(':
                if (!context.TryGetBuffer(out buffer))
                {
                    context.OnError("");
                    return(false);
                }

                if (buffer != "?")
                {
                    context.Current.Paging.PageSize = int.Parse(buffer);
                }

                context.State = State.SortingField;
                return(true);

            case '{':
                if (!context.TryGetBuffer(out buffer))
                {
                    context.OnError("");
                    return(false);
                }

                if (buffer != "?")
                {
                    context.Current.Paging.PageSize = int.Parse(buffer);
                }

                context.Push();
                context.State = State.None;
                return(true);

            default:
                if (char.IsDigit(context.Character))
                {
                    context.Accept();
                    return(true);
                }

                context.OnError("");
                return(false);
            }
        }
        private static bool DoPagingSize(ref StateContext context)
        {
            string buffer;

            switch (context.Character)
            {
            case '?':
                if (context.HasBuffer())
                {
                    context.OnError("SyntaxError: The pagination size format of the data schema is incorrect.");
                    return(false);
                }

                context.Current.Paging.PageSize = 20;
                context.State = State.Include;
                return(true);

            case ',':
                if (!context.TryGetBuffer(out buffer))
                {
                    context.OnError("SyntaxError: Expected pagination size in the data schema, but missing.");
                    return(false);
                }

                context.Current.Paging.PageSize = int.Parse(buffer);
                context.State = State.None;
                return(true);

            case '(':
                if (!context.TryGetBuffer(out buffer))
                {
                    context.OnError("SyntaxError: Expected pagination size in the data schema, but missing.");
                    return(false);
                }

                if (buffer != "?")
                {
                    context.Current.Paging.PageSize = int.Parse(buffer);
                }

                context.State = State.SortingField;
                return(true);

            case '{':
                if (!context.TryGetBuffer(out buffer))
                {
                    context.OnError("SyntaxError: Expected pagination size in the data schema, but missing.");
                    return(false);
                }

                if (buffer != "?")
                {
                    context.Current.Paging.PageSize = int.Parse(buffer);
                }

                context.Push();
                context.State = State.None;
                return(true);

            default:
                if (char.IsDigit(context.Character))
                {
                    context.Accept();
                    return(true);
                }

                context.OnError($"SyntaxError: The pagination size of the data schema contains '{context.Character}' illegal character.");
                return(false);
            }
        }
        private static bool DoPagingCount(ref StateContext context)
        {
            string buffer;

            switch (context.Character)
            {
            case '?':
                if (context.HasBuffer())
                {
                    context.OnError("SyntaxError: The pagination number format of the data schema is incorrect.");
                    return(false);
                }

                context.Current.Paging = null;
                context.State          = State.Include;
                return(true);

            case '*':
                if (context.HasBuffer())
                {
                    context.OnError("SyntaxError: The pagination number format of the data schema is incorrect.");
                    return(false);
                }

                context.Current.Paging = Paging.Disabled;
                context.State          = State.Include;
                return(true);

            case '/':
                if (!context.TryGetBuffer(out buffer))
                {
                    context.OnError("SyntaxError: Expected pagination number in the data schema, but missing.");
                    return(false);
                }

                context.Current.Paging = Paging.Page(int.Parse(buffer));
                context.State          = State.PagingSize;

                return(true);

            case '(':
                if (!context.TryGetBuffer(out buffer))
                {
                    context.OnError("SyntaxError: Expected pagination number in the data schema, but missing.");
                    return(false);
                }

                context.Current.Paging = Paging.Page(1, int.Parse(buffer));
                context.State          = State.SortingField;
                return(true);

            case '{':
                if (!context.TryGetBuffer(out buffer))
                {
                    context.OnError("SyntaxError: Expected pagination number in the data schema, but missing.");
                    return(false);
                }

                context.Current.Paging = Paging.Page(1, int.Parse(buffer));
                context.Push();
                context.State = State.None;
                return(true);

            default:
                if (char.IsDigit(context.Character))
                {
                    context.Accept();
                    return(true);
                }

                context.OnError($"SyntaxError: The pagination number of the data schema contains '{context.Character}' illegal character.");
                return(false);
            }
        }
        public static HierarchicalExpression Parse(string text, int start, int count, Action <string> onError)
        {
            if (string.IsNullOrEmpty(text))
            {
                return(null);
            }

            if (start < 0 || start >= text.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(start));
            }

            if (count < 1)
            {
                count = text.Length - start;
            }
            else if (count > text.Length - start)
            {
                throw new ArgumentOutOfRangeException(nameof(count));
            }

            //创建解析上下文对象
            var context = new StateContext(text.AsSpan(start, count));

            Reflection.Expressions.IMemberExpression accessor = null;
            IList <string> segments = null;

            //状态迁移驱动
            for (int i = start; i < start + count; i++)
            {
                if (context.State == State.Exit)
                {
                    var index = context.Character == '@' ? i : i - 1;

                    if ((accessor = Reflection.Expressions.MemberExpressionParser.Parse(text, index, -1, onError)) == null)
                    {
                        return(null);
                    }
                    else
                    {
                        break;
                    }
                }

                if (!context.Read())
                {
                    continue;
                }

                switch (context.State)
                {
                case State.None:
                    if (!DoNone(ref context, i, onError))
                    {
                        return(null);
                    }

                    break;

                case State.Slash:
                    if (!DoSlash(ref context, i, onError))
                    {
                        return(null);
                    }

                    break;

                case State.AnchorCurrent:
                    if (!DoAnchorCurrent(ref context, i, onError))
                    {
                        return(null);
                    }

                    break;

                case State.AnchorParent:
                    if (!DoAnchorParent(ref context, i, onError))
                    {
                        return(null);
                    }

                    break;

                case State.Segment:
                    if (!DoSegement(ref context, i, segment =>
                    {
                        if (segments == null)
                        {
                            segments = new List <string>();
                        }

                        segments.Add(segment);
                    }, onError))
                    {
                        return(null);
                    }

                    break;
                }
            }

            if (context.State == State.Segment)
            {
                //获取最终的解析结果
                var segment = context.Accept(0);

                if (segment != null && segment.Length > 0)
                {
                    if (segments == null)
                    {
                        segments = new string[] { segment }
                    }
                    ;
                    else
                    {
                        segments.Add(segment);
                    }
                }
            }

            return(new HierarchicalExpression(context.Anchor, segments?.ToArray(), accessor));
        }