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); }
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); } }
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); }
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); } }
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); }
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); } }
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)); }