public void AndOrTests() { TagExpression onlyAnd = Parser.ParseExpression(NewState("1==2 and 2==2 AND 3==2 and 4==2 and 5==2")); Assert.That(onlyAnd.ToString(), Is.EqualTo("(((((1 == 2) AND (2 == 2)) AND (3 == 2)) AND (4 == 2)) AND (5 == 2))")); TagExpression onlyOr = Parser.ParseExpression(NewState("1==2 or 2==2 OR 3==2 or 4==2 or 5==2")); Assert.That(onlyOr.ToString(), Is.EqualTo("(((((1 == 2) OR (2 == 2)) OR (3 == 2)) OR (4 == 2)) OR (5 == 2))")); Exception e = null; try { TagExpression errorAndException = Parser.ParseExpression(NewState("1==2 and 2==2 OR 3==2")); } catch (ExpressionException ee) { e = ee; } Assert.That(e, Is.TypeOf(typeof(PriorityException))); TagExpression andException = Parser.ParseExpression(NewState("1==2 and 2==2 OR 3==2", true)); Assert.That(andException.ToString(), Is.EqualTo("(((1 == 2) AND (2 == 2)) OR (3 == 2))")); andException = Parser.ParseExpression(NewState("1==2 or 2==2 and 3==2", true)); Assert.That(andException.ToString(), Is.EqualTo("((1 == 2) OR ((2 == 2) AND (3 == 2)))")); }
private static List <TagExpression> ArgList(ParserState state) { List <TagExpression> args = new List <TagExpression>(); while (state.PeekTokenType() != TagTokenType.AtEof) { TagExpression expr = ArgValue(state); if (expr == null) { throw new ParserException(string.Format("Expected argument value instead of '{0}'", state.PeekToken()), state); } args.Add(expr); if (state.PeekTokenType() != TagTokenType.Comma) { break; } state.NextToken(); } return(args); }
static TagExpression BooleanExpression(ParserState state) { TagExpression baseExpression = Part(state); if (baseExpression == null) { return(null); // Should not happen } TagToken token; switch (state.PeekTokenType()) { case TagTokenType.IsEqual: case TagTokenType.IsNot: case TagTokenType.IsLte: case TagTokenType.IsLessThan: case TagTokenType.IsGreaterThan: case TagTokenType.IsGte: token = state.NextToken(); return(new CompareExpression(token, baseExpression, Part(state))); default: return(baseExpression); } }
public UnaryExpression(TagToken token, TagExpression inner) : base(token) { if (inner == null) { throw new ArgumentNullException("inner"); } _inner = inner; }
public void ParseExceptions() { Exception e = null; try { TagExpression expr = Parser.ParseExpression(NewState(" '$(Configuration)' == '' == 24")); } catch (ExpressionException ee) { e = ee; } Assert.That(e, Is.TypeOf(typeof(ParserException))); e = null; try { TagExpression expr = Parser.ParseExpression(NewState(" '$(Configuration)' == '' |")); } catch (ExpressionException ee) { e = ee; } Assert.That(e, Is.TypeOf(typeof(LexerException))); e = null; try { TagExpression expr = Parser.ParseExpression(NewState(" '$(Configuration)' == '' 12")); } catch (ExpressionException ee) { e = ee; } Assert.That(e, Is.TypeOf(typeof(ParserException))); e = null; try { TagExpression expr = Parser.ParseExpression(NewState("('$(Configuration)' == ''")); } catch (ExpressionException ee) { e = ee; } Assert.That(e, Is.TypeOf(typeof(ParserException))); e = null; try { TagExpression expr = Parser.ParseExpression(NewState(")'$(Configuration)' == ''")); } catch (ExpressionException ee) { e = ee; } Assert.That(e, Is.TypeOf(typeof(ParserException))); e = null; try { TagExpression expr = Parser.ParseExpression(NewState("'$(Configuration)' == '',")); } catch (ExpressionException ee) { e = ee; } Assert.That(e, Is.TypeOf(typeof(ParserException))); }
internal override void PrePrepare(TagBatchDefinition batchDefinition) { base.PrePrepare(batchDefinition); if (_expression == null) { _expression = QQn.TurtleUtils.Tags.ExpressionParser.Parser.Parse(Definition, ConditionArgs); } }
/// <summary> /// Parses the expression. /// </summary> /// <param name="state">The state.</param> /// <returns></returns> internal static TagExpression ParseExpression(ParserState state) { TagExpression expr = CompleteExpression(state); if (expr != null) { ResolveAndOrConflicts(expr, state); } return(expr); }
public void ParseSome() { TagExpression expr = Parser.ParseExpression(NewState(" '$(Configuration)' == '' ")); Assert.That(expr, Is.Not.Null); Assert.That(expr.ToString(), Is.EqualTo("('$(Configuration)' == '')")); expr = Parser.ParseExpression(NewState("( '$(ProjectOutput)' <= '@(Configuration)' AnD 12 < 24.0 ) Or 12==24")); Assert.That(expr, Is.Not.Null); Assert.That(expr.ToString(), Is.EqualTo("((('$(ProjectOutput)' <= '@(Configuration)') AND (12 < 24.0)) OR (12 == 24))")); }
protected BinaryExpression(TagToken token, TagExpression lhs, TagExpression rhs) : base(token) { if (lhs == null) { throw new ArgumentNullException("lhs"); } else if (rhs == null) { throw new ArgumentNullException("rhs"); } _lhs = lhs; _rhs = rhs; }
static void AddAndOr(TagExpression tagExpression, List <TagToken> tokens, List <TagExpression> exprs) { AndOrExpression andOr = tagExpression as AndOrExpression; if (andOr != null) { AddAndOr(andOr.LeftHand, tokens, exprs); tokens.Add(andOr.Token); AddAndOr(andOr.RightHand, tokens, exprs); } else { exprs.Add(tagExpression); } }
private static TagExpression Expr(ParserState state) { TagExpression expr = BooleanExpression(state); switch (state.PeekTokenType()) { case TagTokenType.Or: return(new AndOrExpression(state.NextToken(), expr, BooleanExpression(state))); case TagTokenType.And: return(new AndOrExpression(state.NextToken(), expr, BooleanExpression(state))); default: return(expr); } }
/// <summary> /// 表达式查询 /// </summary> /// <exception cref="InvalidExpressionException">查询表达式非法</exception> public async Task <List <FileItem> > QueryAsync(string expression) { #if DISPOSE_CONTEXT_IMMEDIATELY using (var context = Context) { #endif var files = new List <FileItem>(); var idList = TagExpression.Query(context.Relations, expression); foreach (int fileItemId in idList) { files.Add(await GetFileItemAsync(fileItemId)); } return(files); #if DISPOSE_CONTEXT_IMMEDIATELY } #endif }
internal void ForceExpression(TagToken token, TagExpression lhs, TagExpression rhs) { switch (token.TokenType) { case TagTokenType.And: _isAnd = true; break; case TagTokenType.Or: break; default: throw new ArgumentException("Only AND and OR are allowed"); } _token = token; SetEditable(true); LeftHand = lhs; RightHand = rhs; SetEditable(false); }
internal static TagExpression CompleteExpression(ParserState state) { TagExpression expr = Expr(state); while (state.PeekTokenType() != TagTokenType.AtEof) { TagToken tk = state.NextToken(); switch (tk.TokenType) { case TagTokenType.Or: expr = new AndOrExpression(tk, expr, BooleanExpression(state)); break; case TagTokenType.And: expr = new AndOrExpression(tk, expr, BooleanExpression(state)); break; default: throw new ParserException(string.Format("Unexpected token {0}", tk), tk, state); } } return(expr); }
public AndOrExpression(TagToken token, TagExpression lhs, TagExpression rhs) : base(token, lhs, rhs) { ForceExpression(token, lhs, rhs); }
public CompareExpression(TagToken token, TagExpression lhs, TagExpression rhs) : base(token, lhs, rhs) { }
public NotExpression(TagToken token, TagExpression inner) : base(token, inner) { }
internal static void ResolveAndOrConflicts(TagExpression expr, ParserState state) { if (expr == null) { throw new ArgumentNullException("expr"); } AndOrExpression andOr = expr as AndOrExpression; if (andOr != null && (andOr.LeftHand is AndOrExpression || andOr.RightHand is AndOrExpression)) { List <TagToken> tokens = new List <TagToken>(); List <TagExpression> exprs = new List <TagExpression>(); AddAndOr(andOr, tokens, exprs); // Create a list of tokens and separating expressions if (exprs.Count != tokens.Count + 1) { throw new InvalidOperationException(); // Not a valid token chain } TagTokenType tt = tokens[0].TokenType; bool hasConflict = false; for (int i = 1; i < tokens.Count; i++) { if (tokens[i].TokenType != tt) { if (!state.Args.ApplyAndOrPriority) { throw new PriorityException("And or conflict; please resolve using parens", tokens[i], state); } else { hasConflict = true; } } } if (hasConflict) { // We re-orden the children to prioritize 'and' above 'or' // We assume: we have at least one 'and' at least one 'or' int i; // Re-create all groups of and-s, from the back while (0 <= (i = LastToken(tokens, TagTokenType.And))) { exprs[i] = new AndOrExpression(tokens[i], exprs[i], exprs[i + 1]); tokens.RemoveAt(i); exprs.RemoveAt(i + 1); } // Re-create all groups of or-s, from the back while (1 <= (i = LastToken(tokens, TagTokenType.Or))) { exprs[i] = new AndOrExpression(tokens[i], exprs[i], exprs[i + 1]); tokens.RemoveAt(i); exprs.RemoveAt(i + 1); } if (exprs.Count != 2 && tokens.Count != 1) { throw new InvalidOperationException(); } andOr.ForceExpression(tokens[0], exprs[0], exprs[1]); } } foreach (TagExpression ee in expr.SubExpressions) { ResolveAndOrConflicts(ee, state); } }
public ParenExpression(TagToken token, TagExpression inner) : base(token, inner) { }
public MessageReceivedEventArgs(String Message) { //Console.WriteLine(Message); this.Tags = new Dictionary <string, string>(); this.RawMessage = Message; this.Type = MessageType.UNDEFINED; this.Permission = Permission.Everybody; if (String.IsNullOrEmpty(Message)) { return; } if (Message.StartsWith(@"PING")) { this.Type = MessageType.Ping; //return; } else if (Message.StartsWith(@":tmi.twitch.tv")) { this.Type = MessageType.Server; return; } else { String[] SpaceSplit = Message.Split(' '); if (SpaceSplit.Length < ((UsesTags) ? 3 : 2)) { this.Type = MessageType.Server; return; } this.Channel = SpaceSplit[(UsesTags) ? 3 : 2].Substring(1); // Tags if (UsesTags) { String[] TagSplit = SpaceSplit[0].Substring(1).Split(';'); foreach (String TagExpression in TagSplit) { String[] TagExpressionSplit = TagExpression.Split('='); Tags.Add(TagExpressionSplit[0], TagExpressionSplit[1]); } } String t_; Tags.TryGetValue("display-name", out t_); if (!Tags.ContainsKey("display-name") || String.IsNullOrWhiteSpace(t_)) { if (SpaceSplit[0].Contains(":[email protected]")) { IsSubMessage = true; Tags["display-name"] = SpaceSplit[3].Substring(1); } else { String RegexMatch = new Regex(@":([A-Za-z0-9_-]+)!\1@\1.tmi.twitch.tv").Match(this.RawMessage).Value; if (!String.IsNullOrEmpty(RegexMatch)) { Tags["display-name"] = RegexMatch.Substring(1).Split('!').FirstOrDefault(); } else { Tags["display-name"] = "**NO_NAME**"; } } } if (SpaceSplit[(UsesTags) ? 2 : 1] == @"PRIVMSG") { this.Type = MessageType.Chat; String m = String.Empty; for (int i = ((UsesTags) ? 4 : 3); i < SpaceSplit.Length; i++) { m += SpaceSplit[i]; if (i < SpaceSplit.Length - 1) { m += " "; } } this.Message = m.Substring(1); if (this.Message[0] == '\u0001') { //Console.WriteLine("Yay?"); IsAction = true; this.Message = this.Message.Substring(8); this.Message = this.Message.Substring(0, this.Message.Length - 1); } // Setup Permission //Console.WriteLine(this.Nick + " | " + this.Channel); if (IsSubscriber) { this.Permission = Permission.Subscriber; } if (IsModerator) { this.Permission = Permission.Moderator; } if (this.Nick.ToLower() == this.Channel) { this.Permission = Permission.Broadcaster; } if (this.Nick.ToLower() == @"imthe666st") { this.Permission = Permission.Developer; this.IsDeveloper = true; } } else if (SpaceSplit[(UsesTags) ? 2 : 1] == @"USERSTATE") { this.Type = MessageType.Userstate; } else if (SpaceSplit[(UsesTags) ? 2 : 1] == @"ROOMSTATE") { this.Type = MessageType.Roomstate; } else if (SpaceSplit[(UsesTags) ? 2 : 1] == @"USERNOTICE") { this.Type = MessageType.Usernotice; //Console.WriteLine(RawMessage); } else if (SpaceSplit[(UsesTags) ? 2 : 1] == @"CLEARCHAT") { this.Type = MessageType.Clearchat; //Console.WriteLine(RawMessage); } else if (SpaceSplit[(UsesTags) ? 2 : 1] == @"JOIN") { this.Type = MessageType.Join; //Console.WriteLine(RawMessage); } else if (SpaceSplit[(UsesTags) ? 2 : 1] == @"PART") { this.Type = MessageType.Part; //Console.WriteLine(RawMessage); } else if (SpaceSplit[(UsesTags) ? 2 : 1] == @"WHISPER") { this.Type = MessageType.Whisper; String m = String.Empty; for (int i = 4; i < SpaceSplit.Length; i++) { m += SpaceSplit[i]; if (i < SpaceSplit.Length - 1) { m += " "; } } this.Message = m.Substring(1); } else { this.Type = MessageType.Server; //Console.WriteLine(this.RawMessage); //Console.WriteLine("asdf {0}", SpaceSplit[(UsesTags) ? 2 : 1]); } } }
internal static TagExpression Part(ParserState state) { TagExpression expression = ArgValue(state); if (expression != null) { return(expression); } TagToken tk = state.NextToken(); TagToken next; if (tk == null) { return(null); } switch (tk.TokenType) { case TagTokenType.Function: next = state.NextToken(); if (next == null) { throw new ParserException("Expected '('", tk, state); } else if (next.TokenType != TagTokenType.ParenOpen) { throw new ParserException(string.Format("Expected '(' instead of '{0}')", next), state); } List <TagExpression> functionArgs = ArgList(state); next = state.NextToken(); if (next == null) { throw new ParserException(string.Format("Expected ')' before end of expression", state.PeekToken()), state); } else if (next.TokenType != TagTokenType.ParenClose) { throw new ParserException(string.Format("Expected ')' instead of '{0}'", next), state); } expression = new FunctionExpression(tk, functionArgs.AsReadOnly()); break; case TagTokenType.ParenOpen: expression = new ParenExpression(tk, Expr(state)); next = state.NextToken(); if (next == null) { throw new ParserException(string.Format("Expected ')' before end of expression", state.PeekToken()), state); } else if (next.TokenType != TagTokenType.ParenClose) { throw new ParserException(string.Format("Expected ')' instead of '{0}'", next), state); } break; case TagTokenType.Not: expression = new NotExpression(tk, Expr(state)); break; default: throw new ParserException(string.Format("Unexpected token '{0}'", tk), state); } return(expression); }