private static FilterOperatorBase CompileL7(TokenReader reader) { // parse not if (reader.LookAhead().Type == TokenType.Exclamation) { reader.AssertGet(TokenType.Exclamation); return(new FilterNegate { Value = CompileL7(reader) }); } if (reader.LookAhead().Type == TokenType.OperatorMinus) { reader.AssertGet(TokenType.OperatorMinus); return(new FilterOperatorMinusSingle { Value = CompileL7(reader) }); } if (reader.LookAhead().Value == "caseful") { reader.AssertGet(TokenType.Literal); return(new OperatorCaseful { Value = CompileL7(reader) }); } return(CompileL8(reader)); }
private static FilterOperatorBase CompileL8(TokenReader reader) { if (reader.LookAhead().Type == TokenType.OpenParenthesis) { // in bracket reader.AssertGet(TokenType.OpenParenthesis); if (reader.LookAhead().Type == TokenType.CloseParenthesis) { // empty bracket reader.AssertGet(TokenType.CloseParenthesis); return(new FilterBracket()); } var ret = CompileL0(reader); reader.AssertGet(TokenType.CloseParenthesis); return(new FilterBracket { Value = ret }); } if (reader.LookAhead().Type == TokenType.OpenSquareBracket) { reader.AssertGet(TokenType.OpenSquareBracket); var values = new HashSet <ValueBase>(); while (reader.LookAhead().Type != TokenType.CloseSquareBracket) { values.Add(GetValue(reader)); if (reader.LookAhead().Type == TokenType.Comma) { reader.AssertGet(TokenType.Comma); } } reader.AssertGet(TokenType.CloseSquareBracket); return(new UserSet(values)); } return(GetValue(reader)); }
private static FilterOperatorBase CompileL4(TokenReader reader) { // <- -> in contains var left = CompileL5(reader); if (!reader.IsRemainToken) { return(left); } var generate = (Func <TokenType, FilterTwoValueOperator, FilterOperatorBase>) ((type, oper) => GenerateSink(reader, left, type, oper, CompileL4)); switch (reader.LookAhead().Type) { case TokenType.OperatorContains: return(generate(TokenType.OperatorContains, new FilterOperatorContains())); case TokenType.OperatorIn: return(generate(TokenType.OperatorIn, new FilterOperatorContainedBy())); case TokenType.Literal: switch (reader.LookAhead().Value.ToLower()) { case "in": // <- return(generate(TokenType.Literal, new FilterOperatorContainedBy())); case "contains": // -> return(generate(TokenType.Literal, new FilterOperatorContains())); case "startswith": case "startwith": return(generate(TokenType.Literal, new OperatorStringStartsWith())); case "endswith": case "endwith": return(generate(TokenType.Literal, new OperatorStringEndsWith())); case "match": case "regex": return(generate(TokenType.Literal, new OperatorStringRegex())); default: return(left); } default: return(left); } }
/// <summary> /// Instantiate sources from tokens. /// </summary> private static IEnumerable <FilterSourceBase> CompileSources(IEnumerable <Token> token) { // filter // filter: "argument" // filter: "argument1", "argument2", ... -> filter: "argument1", filter: "argument2", ... var reader = new TokenReader(token); while (reader.IsRemainToken) { var filter = reader.Get(); if (filter.Type != TokenType.Literal && filter.Type != TokenType.OperatorMultiple) { throw CreateUnexpectedTokenError(filter.Value, reader.RemainQuery); } Type fstype; if (!FilterSourceResolver.TryGetValue(filter.Value, out fstype)) { throw new ArgumentException( QueryCompilerResources.QueryUnknownFilterSource + " " + filter.Value); } if (reader.IsRemainToken && reader.LookAhead().Type == TokenType.Collon) // with argument { reader.AssertGet(TokenType.Collon); do { var argument = reader.AssertGet(TokenType.String); yield return(Activator.CreateInstance(fstype, argument.Value) as FilterSourceBase); // separated by comma if (reader.IsRemainToken) { reader.AssertGet(TokenType.Comma); } } while (reader.IsRemainToken && reader.LookAhead().Type == TokenType.String); } else { yield return(Activator.CreateInstance(fstype) as FilterSourceBase); if (reader.IsRemainToken) { // filters are divided by comma reader.AssertGet(TokenType.Comma); } } } }
private static FilterOperatorBase CompileL3(TokenReader reader) { // < <= > >= var left = CompileL4(reader); if (!reader.IsRemainToken) { return(left); } var generate = (Func <TokenType, FilterTwoValueOperator, FilterOperatorBase>) ((type, oper) => GenerateSink(reader, left, type, oper, CompileL3)); switch (reader.LookAhead().Type) { case TokenType.OperatorLessThan: return(generate(TokenType.OperatorLessThan, new FilterOperatorLessThan())); case TokenType.OperatorLessThanOrEqual: return(generate(TokenType.OperatorLessThanOrEqual, new FilterOperatorLessThanOrEqual())); case TokenType.OperatorGreaterThan: return(generate(TokenType.OperatorGreaterThan, new FilterOperatorGreaterThan())); case TokenType.OperatorGreaterThanOrEqual: return(generate(TokenType.OperatorGreaterThanOrEqual, new FilterOperatorGreaterThanOrEqual())); default: return(left); } }
private static ValueBase GetAccountValue(string value, TokenReader reader) { var repl = GetUserExpr(value); if (reader.IsRemainToken && reader.LookAhead().Type == TokenType.Period) { reader.AssertGet(TokenType.Period); var literal = reader.AssertGet(TokenType.Literal); switch (literal.Value.ToLower()) { case "friend": case "friends": case "following": case "followings": return(new LocalUserFollowing(repl)); case "follower": case "followers": return(new LocalUserFollowers(repl)); case "block": case "blocks": case "blocking": case "blockings": return(new LocalUserBlockings(repl)); default: throw CreateUnexpectedTokenError( literal.Value, repl.ToQuery() + "." + literal.Value + " " + reader.RemainQuery); } } return(new LocalUser(repl)); }
/// <summary> /// Instantiate sources from tokens. /// </summary> private static IEnumerable <FilterSourceBase> CompileSources(IEnumerable <Token> token) { // filter // filter: "argument" // filter: "argument1", "argument2", ... -> filter: "argument1", filter: "argument2", ... var reader = new TokenReader(token); while (reader.IsRemainToken) { var filter = reader.Get(); if (filter.Type != TokenType.Literal && filter.Type != TokenType.OperatorMultiple) { throw new ArgumentException("このトークンは無効です: " + filter.Type + " (リテラルか \'*\' です。)"); } Type fstype; if (!FilterSourceResolver.TryGetValue(filter.Value, out fstype)) { throw new ArgumentException("フィルタ ソースが一致しません: " + filter.Value); } if (reader.IsRemainToken && reader.LookAhead().Type == TokenType.Collon) // with argument { reader.AssertGet(TokenType.Collon); do { var argument = reader.AssertGet(TokenType.String); yield return(Activator.CreateInstance(fstype, argument.Value) as FilterSourceBase); // separated by comma if (reader.IsRemainToken) { reader.AssertGet(TokenType.Comma); } } while (reader.IsRemainToken && reader.LookAhead().Type == TokenType.String); } else { yield return(Activator.CreateInstance(fstype) as FilterSourceBase); if (reader.IsRemainToken) { // filters are divided by comma reader.AssertGet(TokenType.Comma); } } } }
private static ValueBase GetValue(TokenReader reader) { var literal = reader.LookAhead(); if (literal.Type == TokenType.String) { // immediate string value return(new StringValue(reader.AssertGet(TokenType.String).Value)); } if (literal.Type == TokenType.OperatorMultiple) { // for parsing asterisk user var pseudo = reader.AssertGet(TokenType.OperatorMultiple); literal = new Token(TokenType.Literal, "*", pseudo.DebugIndex); } else { literal = reader.AssertGet(TokenType.Literal); } // check first letter switch (literal.Value[0]) { case '@': // user screen name return(GetAccountValue(literal.Value.Substring(1), reader)); case '#': // user id return(GetAccountValue(literal.Value, reader)); } // check first layers switch (literal.Value.ToLower()) { case "*": case "we": case "our": case "us": return(GetAccountValue("*", reader)); case "@": reader.AssertGet(TokenType.Period); return(GetAccountValue(reader.AssertGet(TokenType.Literal).Value, reader)); case "user": case "retweeter": return(GetUserValue(literal.Value == "retweeter", reader)); case "list": return(GetListValue(reader)); default: long iv; if (Int64.TryParse(literal.Value, out iv)) { return(new NumericValue(iv)); } return(GetStatusValue(literal.Value, reader)); } }
private static FilterOperatorBase CompileL1(TokenReader reader) { // & var left = CompileL2(reader); if (!reader.IsRemainToken) { return(left); } var generate = (Func <TokenType, FilterTwoValueOperator, FilterOperatorBase>) ((type, oper) => GenerateSink(reader, left, type, oper, CompileL1)); switch (reader.LookAhead().Type) { case TokenType.OperatorAnd: return(generate(TokenType.OperatorAnd, new FilterOperatorAnd())); default: return(left); } }
private static FilterOperatorBase CompileL6(TokenReader reader) { // parse arithmetic operators (faster) var left = CompileL7(reader); if (!reader.IsRemainToken) { return(left); } var generate = (Func <TokenType, FilterTwoValueOperator, FilterOperatorBase>) ((type, oper) => GenerateSink(reader, left, type, oper, CompileL6)); switch (reader.LookAhead().Type) { case TokenType.OperatorMultiple: return(generate(TokenType.OperatorMultiple, new FilterOperatorProduct())); case TokenType.OperatorDivide: return(generate(TokenType.OperatorDivide, new FilterOperatorDivide())); default: return(left); } }
private static FilterOperatorBase CompileL5(TokenReader reader) { // parse arithmetic operators var left = CompileL6(reader); if (!reader.IsRemainToken) { return(left); } var generate = (Func <TokenType, FilterTwoValueOperator, FilterOperatorBase>) ((type, oper) => GenerateSink(reader, left, type, oper, CompileL5)); switch (reader.LookAhead().Type) { case TokenType.OperatorPlus: return(generate(TokenType.OperatorPlus, new FilterOperatorPlus())); case TokenType.OperatorMinus: return(generate(TokenType.OperatorMinus, new FilterOperatorMinus())); default: return(left); } }
private static FilterOperatorBase CompileL5(TokenReader reader) { // parse arithmetic operators var left = CompileL6(reader); if (!reader.IsRemainToken) return left; var generate = (Func<TokenType, FilterTwoValueOperator, FilterOperatorBase>) ((type, oper) => GenerateSink(reader, left, type, oper, CompileL5)); switch (reader.LookAhead().Type) { case TokenType.OperatorPlus: return generate(TokenType.OperatorPlus, new FilterOperatorPlus()); case TokenType.OperatorMinus: return generate(TokenType.OperatorMinus, new FilterOperatorMinus()); default: return left; } }
private static FilterOperatorBase CompileL4(TokenReader reader) { // <- -> in contains var left = CompileL5(reader); if (!reader.IsRemainToken) return left; var generate = (Func<TokenType, FilterTwoValueOperator, FilterOperatorBase>) ((type, oper) => GenerateSink(reader, left, type, oper, CompileL4)); switch (reader.LookAhead().Type) { case TokenType.OperatorContains: return generate(TokenType.OperatorContains, new FilterOperatorContains()); case TokenType.OperatorIn: return generate(TokenType.OperatorIn, new FilterOperatorContainedBy()); case TokenType.Literal: switch (reader.LookAhead().Value.ToLower()) { case "in": // <- return generate(TokenType.Literal, new FilterOperatorContainedBy()); case "contains": // -> return generate(TokenType.Literal, new FilterOperatorContains()); case "startswith": case "startwith": return generate(TokenType.Literal, new OperatorStringStartsWith()); case "endswith": case "endwith": return generate(TokenType.Literal, new OperatorStringEndsWith()); case "match": case "regex": return generate(TokenType.Literal, new OperatorStringRegex()); default: return left; } default: return left; } }
private static FilterOperatorBase CompileL3(TokenReader reader) { // < <= > >= var left = CompileL4(reader); if (!reader.IsRemainToken) return left; var generate = (Func<TokenType, FilterTwoValueOperator, FilterOperatorBase>) ((type, oper) => GenerateSink(reader, left, type, oper, CompileL3)); switch (reader.LookAhead().Type) { case TokenType.OperatorLessThan: return generate(TokenType.OperatorLessThan, new FilterOperatorLessThan()); case TokenType.OperatorLessThanOrEqual: return generate(TokenType.OperatorLessThanOrEqual, new FilterOperatorLessThanOrEqual()); case TokenType.OperatorGreaterThan: return generate(TokenType.OperatorGreaterThan, new FilterOperatorGreaterThan()); case TokenType.OperatorGreaterThanOrEqual: return generate(TokenType.OperatorGreaterThanOrEqual, new FilterOperatorGreaterThanOrEqual()); default: return left; } }
private static FilterOperatorBase CompileL2(TokenReader reader) { // == != var left = CompileL3(reader); if (!reader.IsRemainToken) return left; var generate = (Func<TokenType, FilterTwoValueOperator, FilterOperatorBase>) ((type, oper) => GenerateSink(reader, left, type, oper, CompileL2)); switch (reader.LookAhead().Type) { case TokenType.OperatorEquals: return generate(TokenType.OperatorEquals, new FilterOperatorEquals()); case TokenType.OperatorNotEquals: return generate(TokenType.OperatorNotEquals, new FilterOperatorNotEquals()); default: return left; } }
/// <summary> /// Instantiate sources from tokens. /// </summary> private static IEnumerable<FilterSourceBase> CompileSources(IEnumerable<Token> token) { // filter // filter: "argument" // filter: "argument1", "argument2", ... -> filter: "argument1", filter: "argument2", ... var reader = new TokenReader(token); while (reader.IsRemainToken) { var filter = reader.Get(); if (filter.Type != TokenType.Literal && filter.Type != TokenType.OperatorMultiple) { throw new ArgumentException("このトークンは無効です: " + filter.Type + " (リテラルか \'*\' です。)"); } Type fstype; if (!FilterSourceResolver.TryGetValue(filter.Value, out fstype)) throw new ArgumentException("フィルタ ソースが一致しません: " + filter.Value); if (reader.IsRemainToken && reader.LookAhead().Type == TokenType.Collon) // with argument { reader.AssertGet(TokenType.Collon); do { var argument = reader.AssertGet(TokenType.String); yield return Activator.CreateInstance(fstype, argument.Value) as FilterSourceBase; // separated by comma if (reader.IsRemainToken) { reader.AssertGet(TokenType.Comma); } } while (reader.IsRemainToken && reader.LookAhead().Type == TokenType.String); } else { yield return Activator.CreateInstance(fstype) as FilterSourceBase; if (reader.IsRemainToken) { // filters are divided by comma reader.AssertGet(TokenType.Comma); } } } }
private static ValueBase InstantiateValue(TokenReader reader) { Token literal = reader.LookAhead(); if (literal.Type == TokenType.String) { // immediate string value return new StringValue(reader.AssertGet(TokenType.String).Value); } if (literal.Type == TokenType.OperatorMultiple) { // for parsing asterisk user Token pseudo = reader.AssertGet(TokenType.OperatorMultiple); literal = new Token(TokenType.Literal, "*", pseudo.DebugIndex); } else { literal = reader.AssertGet(TokenType.Literal); } // check first layers switch (literal.Value) { case "*": return InstantiateLocalUsers("*", reader); case "local": reader.AssertGet(TokenType.Period); return InstantiateLocalUsers(reader.AssertGet(TokenType.Literal).Value, reader); case "user": case "retweeter": return InstantiateUserValue(literal.Value == "retweeter", reader); default: long iv; if (Int64.TryParse(literal.Value, out iv)) { return new NumericValue(iv); } return InstantiateStatusValue(literal.Value, reader); } }
private static FilterOperatorBase CompileL8(TokenReader reader) { if (reader.LookAhead().Type == TokenType.OpenBracket) { // in bracket reader.AssertGet(TokenType.OpenBracket); if (reader.LookAhead().Type == TokenType.CloseBracket) { // empty bracket reader.AssertGet(TokenType.CloseBracket); return new FilterBracket(); } var ret = CompileL0(reader); reader.AssertGet(TokenType.CloseBracket); return new FilterBracket { Value = ret }; } if (reader.LookAhead().Type == TokenType.OpenSquareBracket) { reader.AssertGet(TokenType.OpenSquareBracket); var values = new HashSet<ValueBase>(); while (reader.LookAhead().Type != TokenType.CloseSquareBracket) { values.Add(GetValue(reader)); if (reader.LookAhead().Type == TokenType.Comma) { reader.AssertGet(TokenType.Comma); } } reader.AssertGet(TokenType.CloseSquareBracket); return new UserSet(values); } return GetValue(reader); }
private static ValueBase GetUserValue(bool isRetweeter, TokenReader reader) { var selector = (Func <ValueBase, ValueBase, ValueBase>) ((user, retweeter) => isRetweeter ? retweeter : user); if (reader.IsRemainToken && reader.LookAhead().Type != TokenType.Period) { // user expression return(selector(new User(), new Retweeter())); } reader.AssertGet(TokenType.Period); var literal = reader.AssertGet(TokenType.Literal); switch (literal.Value.ToLower()) { case "protected": case "isprotected": case "is_protected": return(selector(new UserIsProtected(), new RetweeterIsProtected())); case "verified": case "isverified": case "is_verified": return(selector(new UserIsVerified(), new RetweeterIsVerified())); case "translator": case "istranslator": case "is_translator": return(selector(new UserIsTranslator(), new RetweeterIsTranslator())); case "contributorsenabled": case "contributors_enabled": case "iscontributorsenabled": case "is_contributors_enabled": return(selector(new UserIsContributorsEnabled(), new RetweeterIsContributorsEnabled())); case "geoenabled": case "geo_enabled": case "isgeoenabled": case "is_geo_enabled": return(selector(new UserIsGeoEnabled(), new RetweeterIsGeoEnabled())); case "id": return(selector(new UserId(), new RetweeterId())); case "status": case "statuses": case "statuscount": case "status_count": case "statusescount": case "statuses_count": return(selector(new UserStatuses(), new RetweeterStatuses())); case "friend": case "friends": case "following": case "followings": case "friendscount": case "friends_count": case "followingscount": case "followings_count": return(selector(new UserFollowing(), new RetweeterFollowing())); case "follower": case "followers": case "followerscount": case "followers_count": return(selector(new UserFollowers(), new RetweeterFollowers())); case "fav": case "favs": case "favorite": case "favorites": case "favscount": case "favs_count": case "favoritescount": case "favorites_count": return(selector(new UserFavroites(), new RetweeterFavroites())); case "list": case "listed": case "listcount": case "list_count": case "listedcount": case "listed_count": return(selector(new UserListed(), new RetweeterListed())); case "screenname": case "screen_name": return(selector(new UserScreenName(), new RetweeterScreenName())); case "name": case "username": return(selector(new UserName(), new RetweeterName())); case "bio": case "desc": case "description": return(selector(new UserDescription(), new RetweeterDescription())); case "loc": case "location": return(selector(new UserLocation(), new RetweeterLocation())); case "lang": case "language": return(selector(new UserLanguage(), new RetweeterLanguage())); default: throw CreateUnexpectedTokenError(literal.Value, "user." + literal.Value + " " + reader.RemainQuery); } }
private static FilterOperatorBase CompileL4(TokenReader reader) { // <- -> FilterOperatorBase left = CompileL5(reader); if (!reader.IsRemainToken) return left; var generate = (Func<TokenType, FilterTwoValueOperator, FilterOperatorBase>) ((type, oper) => GenerateSink(reader, left, type, oper, CompileL4)); switch (reader.LookAhead().Type) { case TokenType.OperatorContains: return generate(TokenType.OperatorContains, new FilterOperatorContains()); case TokenType.OperatorContainedBy: return generate(TokenType.OperatorContainedBy, new FilterOperatorContainedBy()); default: return left; } }
private static ValueBase GetAccountValue(string value, TokenReader reader) { var repl = GetUserExpr(value); if (reader.IsRemainToken && reader.LookAhead().Type == TokenType.Period) { reader.AssertGet(TokenType.Period); var literal = reader.AssertGet(TokenType.Literal); switch (literal.Value.ToLower()) { case "friend": case "friends": case "following": case "followings": return new LocalUserFollowing(repl); case "follower": case "followers": return new LocalUserFollowers(repl); case "block": case "blocks": case "blocking": case "blockings": return new LocalUserBlockings(repl); default: throw CreateUnexpectedTokenError( literal.Value, repl.ToQuery() + "." + literal.Value + " " + reader.RemainQuery); } } return new LocalUser(repl); }
private static ValueBase InstantiateLocalUsers(string value, TokenReader reader) { UserRepresentationBase repl = GetRepresentation(value); if (reader.IsRemainToken && reader.LookAhead().Type == TokenType.Period) { reader.AssertGet(TokenType.Period); Token literal = reader.AssertGet(TokenType.Literal); switch (literal.Value) { case "friend": case "friends": case "following": case "followings": return new LocalUserFollowings(repl); case "follower": case "followers": return new LocalUserFollowers(repl); default: throw new FilterQueryException("Unexpected token: " + literal.Value, repl.ToQuery() + "." + literal.Value + " " + reader.RemainQuery); } } return new LocalUser(repl); }
private static ValueBase InstantiateUserValue(bool isRetweeter, TokenReader reader) { var selector = (Func<ValueBase, ValueBase, ValueBase>) ((user, retweeter) => isRetweeter ? retweeter : user); if (reader.IsRemainToken && reader.LookAhead().Type != TokenType.Period) { // user representation return selector(new User(), new Retweeter()); } reader.AssertGet(TokenType.Period); Token literal = reader.AssertGet(TokenType.Literal); switch (literal.Value) { case "protected": case "isProtected": case "is_protected": return selector(new UserIsProtected(), new RetweeterIsProtected()); case "verified": case "isVerified": case "is_verified": return selector(new UserIsVerified(), new RetweeterIsVerified()); case "translator": case "isTranslator": case "is_translator": return selector(new UserIsTranslator(), new RetweeterIsTranslator()); case "contributorsEnabled": case "contributors_enabled": case "isContributorsEnabled": case "is_contributors_enabled": return selector(new UserIsContributorsEnabled(), new RetweeterIsContributorsEnabled()); case "geoEnabled": case "geo_enabled": case "isGeoEnabled": case "is_geo_enabled": return selector(new UserIsGeoEnabled(), new RetweeterIsGeoEnabled()); case "id": return selector(new UserId(), new RetweeterId()); case "status": case "statuses": case "statusCount": case "status_count": case "statusesCount": case "statuses_count": return selector(new UserStatuses(), new RetweeterStatuses()); case "friend": case "friends": case "following": case "followings": case "friendsCount": case "friends_count": case "followingsCount": case "followings_count": return selector(new UserFriends(), new RetweeterFriends()); case "follower": case "followers": case "followersCount": case "followers_count": return selector(new UserFollowers(), new RetweeterFollowers()); case "fav": case "favCount": case "favorite": case "favorites": case "fav_count": case "favoriteCount": case "favorite_count": case "favoritesCount": case "favorites_count": return selector(new UserFavroites(), new RetweeterFavroites()); case "list": case "listed": case "listCount": case "list_count": case "listedCount": case "listed_count": return selector(new UserListed(), new RetweeterListed()); case "screenName": case "screen_name": return selector(new UserScreenName(), new RetweeterScreenName()); case "name": return selector(new UserName(), new RetweeterName()); case "bio": case "desc": case "description": return selector(new UserDescription(), new RetweeterDescription()); case "loc": case "location": return selector(new UserLocation(), new RetweeterLocation()); case "lang": case "language": return selector(new UserLanguage(), new RetweeterLanguage()); default: throw new FilterQueryException("Unexpected token: " + literal.Value, "user." + literal.Value + " " + reader.RemainQuery); } }
private static FilterOperatorBase CompileL6(TokenReader reader) { // parse arithmetic operators (faster) var left = CompileL7(reader); if (!reader.IsRemainToken) return left; var generate = (Func<TokenType, FilterTwoValueOperator, FilterOperatorBase>) ((type, oper) => GenerateSink(reader, left, type, oper, CompileL6)); switch (reader.LookAhead().Type) { case TokenType.OperatorMultiple: return generate(TokenType.OperatorMultiple, new FilterOperatorProduct()); case TokenType.OperatorDivide: return generate(TokenType.OperatorDivide, new FilterOperatorDivide()); default: return left; } }
private static FilterOperatorBase CompileL7(TokenReader reader) { // parse not if (reader.LookAhead().Type == TokenType.Exclamation) { reader.AssertGet(TokenType.Exclamation); return new FilterNegate { Value = CompileL7(reader) }; } if (reader.LookAhead().Value == "caseful") { reader.AssertGet(TokenType.Literal); return new OperatorCaseful { Value = CompileL7(reader) }; } return CompileL8(reader); }
private static FilterOperatorBase CompileL8(TokenReader reader) { if (reader.LookAhead().Type == TokenType.OpenBracket) { // in bracket reader.AssertGet(TokenType.OpenBracket); if (reader.LookAhead().Type == TokenType.CloseBracket) { // empty bracket reader.AssertGet(TokenType.CloseBracket); return new FilterBracket(null); } var ret = CompileL0(reader); reader.AssertGet(TokenType.CloseBracket); return new FilterBracket(ret); } return GetValue(reader); }
private static ValueBase GetValue(TokenReader reader) { var literal = reader.LookAhead(); if (literal.Type == TokenType.String) { // immediate string value return new StringValue(reader.AssertGet(TokenType.String).Value); } if (literal.Type == TokenType.OperatorMultiple) { // for parsing asterisk user var pseudo = reader.AssertGet(TokenType.OperatorMultiple); literal = new Token(TokenType.Literal, "*", pseudo.DebugIndex); } else { literal = reader.AssertGet(TokenType.Literal); } // check first letter switch (literal.Value[0]) { case '@': // user screen name return GetAccountValue(literal.Value.Substring(1), reader); case '#': // user id return GetAccountValue(literal.Value, reader); } // check first layers switch (literal.Value.ToLower()) { case "*": case "we": case "our": case "us": return GetAccountValue("*", reader); case "@": reader.AssertGet(TokenType.Period); return GetAccountValue(reader.AssertGet(TokenType.Literal).Value, reader); case "user": case "retweeter": return GetUserValue(literal.Value == "retweeter", reader); case "list": return GetListValue(reader); default: long iv; if (Int64.TryParse(literal.Value, out iv)) { return new NumericValue(iv); } return GetStatusValue(literal.Value, reader); } }
/// <summary> /// Instantiate sources from tokens. /// </summary> private static IEnumerable<FilterSourceBase> CompileSources(IEnumerable<Token> token) { // filter // filter: "argument" // filter: "argument1", "argument2", ... -> filter: "argument1", filter: "argument2", ... var reader = new TokenReader(token); while (reader.IsRemainToken) { var filter = reader.Get(); if (filter.Type != TokenType.Literal && filter.Type != TokenType.OperatorMultiple) { throw CreateUnexpectedTokenError(filter.Value, reader.RemainQuery); } Type fstype; if (!FilterSourceResolver.TryGetValue(filter.Value, out fstype)) { throw new ArgumentException( QueryCompilerResources.QueryUnknownFilterSource + " " + filter.Value); } if (reader.IsRemainToken && reader.LookAhead().Type == TokenType.Collon) // with argument { reader.AssertGet(TokenType.Collon); do { var argument = reader.AssertGet(TokenType.String); yield return Activator.CreateInstance(fstype, argument.Value) as FilterSourceBase; // separated by comma if (reader.IsRemainToken) { reader.AssertGet(TokenType.Comma); } } while (reader.IsRemainToken && reader.LookAhead().Type == TokenType.String); } else { yield return Activator.CreateInstance(fstype) as FilterSourceBase; if (reader.IsRemainToken) { // filters are divided by comma reader.AssertGet(TokenType.Comma); } } } }
private static ValueBase GetUserValue(bool isRetweeter, TokenReader reader) { var selector = (Func<ValueBase, ValueBase, ValueBase>) ((user, retweeter) => isRetweeter ? retweeter : user); if (reader.IsRemainToken && reader.LookAhead().Type != TokenType.Period) { // user expression return selector(new User(), new Retweeter()); } reader.AssertGet(TokenType.Period); var literal = reader.AssertGet(TokenType.Literal); switch (literal.Value.ToLower()) { case "protected": case "isprotected": case "is_protected": return selector(new UserIsProtected(), new RetweeterIsProtected()); case "verified": case "isverified": case "is_verified": return selector(new UserIsVerified(), new RetweeterIsVerified()); case "translator": case "istranslator": case "is_translator": return selector(new UserIsTranslator(), new RetweeterIsTranslator()); case "contributorsenabled": case "contributors_enabled": case "iscontributorsenabled": case "is_contributors_enabled": return selector(new UserIsContributorsEnabled(), new RetweeterIsContributorsEnabled()); case "geoenabled": case "geo_enabled": case "isgeoenabled": case "is_geo_enabled": return selector(new UserIsGeoEnabled(), new RetweeterIsGeoEnabled()); case "id": return selector(new UserId(), new RetweeterId()); case "status": case "statuses": case "statuscount": case "status_count": case "statusescount": case "statuses_count": return selector(new UserStatuses(), new RetweeterStatuses()); case "friend": case "friends": case "following": case "followings": case "friendscount": case "friends_count": case "followingscount": case "followings_count": return selector(new UserFollowing(), new RetweeterFollowing()); case "follower": case "followers": case "followerscount": case "followers_count": return selector(new UserFollowers(), new RetweeterFollowers()); case "fav": case "favs": case "favorite": case "favorites": case "favscount": case "favs_count": case "favoritescount": case "favorites_count": return selector(new UserFavroites(), new RetweeterFavroites()); case "list": case "listed": case "listcount": case "list_count": case "listedcount": case "listed_count": return selector(new UserListed(), new RetweeterListed()); case "screenname": case "screen_name": return selector(new UserScreenName(), new RetweeterScreenName()); case "name": case "username": return selector(new UserName(), new RetweeterName()); case "bio": case "desc": case "description": return selector(new UserDescription(), new RetweeterDescription()); case "loc": case "location": return selector(new UserLocation(), new RetweeterLocation()); case "lang": case "language": return selector(new UserLanguage(), new RetweeterLanguage()); default: throw CreateUnexpectedTokenError(literal.Value, "user." + literal.Value + " " + reader.RemainQuery); } }
private static FilterOperatorBase CompileL1(TokenReader reader) { // && FilterOperatorBase left = CompileL2(reader); if (!reader.IsRemainToken) return left; var generate = (Func<TokenType, FilterTwoValueOperator, FilterOperatorBase>) ((type, oper) => GenerateSink(reader, left, type, oper, CompileL1)); switch (reader.LookAhead().Type) { case TokenType.OperatorAnd: return generate(TokenType.OperatorAnd, new FilterOperatorAnd()); default: return left; } }