// Parse Filter Term (conjunction) corresponds to T -> F AND T | F private static MetricFilterExpressionTree ParseFilterTerm(MetricFilterExpressionTokenizer tokenizer) { // Match Clause MetricFilterExpressionTree node = ParseFilterClause(tokenizer); // T -> F if (tokenizer.IsEmpty) { return(node); } if (tokenizer.Current.Type == MetricFilterExpressionToken.TokenType.AndOperator) { // Consume AND tokenizer.Advance(); // T -> F AND T return(new MetricFilterExpressionTree() { IsConjunction = true, LeftExpression = node, RightExpression = ParseFilterTerm(tokenizer) }); } return(node); }
// Parse Filter Expression (disjunction) corresponds to E -> T OR E | T private static MetricFilterExpressionTree ParseFilterExpression(MetricFilterExpressionTokenizer tokenizer) { MetricFilterExpressionTree node = ParseFilterTerm(tokenizer); // E -> T if (tokenizer.IsEmpty) { return(node); } if (tokenizer.Current.Type == MetricFilterExpressionToken.TokenType.OrOperator) { // Consume OR tokenizer.Advance(); // E -> T OR E return(new MetricFilterExpressionTree() { IsConjunction = false, LeftExpression = node, RightExpression = ParseFilterExpression(tokenizer) }); } return(node); }
// Parse filter clause (or parenthesized expression) corresponds to F -> ID EQ VALUE | (E) private static MetricFilterExpressionTree ParseFilterClause(MetricFilterExpressionTokenizer tokenizer) { if (tokenizer == null || tokenizer.IsEmpty) { throw GenerateFilterParseException(null, MetricFilterExpressionToken.TokenType.Identifier); } MetricFilterExpressionToken token = tokenizer.Current; switch (token.Type) { case MetricFilterExpressionToken.TokenType.Identifier: // F -> ID EQ VALUE // validate and store the parameter name FilterParameter parameter = ParseParameter(token.Value); // Consume name tokenizer.Advance(); // Verify and comsume EQ if (tokenizer.IsEmpty || tokenizer.Current.Type != MetricFilterExpressionToken.TokenType.EqOperator) { throw GenerateFilterParseException(tokenizer.Current, MetricFilterExpressionToken.TokenType.EqOperator); } tokenizer.Advance(); MetricFilterExpressionToken.TokenType expectedType = GetExpectedTokenTypeForParameter(parameter); // Verify, store, and consume value if (tokenizer.IsEmpty || tokenizer.Current.Type != expectedType) { throw GenerateFilterParseException(tokenizer.Current, expectedType); } string value = tokenizer.Current.Value; tokenizer.Advance(); return(new MetricFilterExpressionTree() { Value = new KeyValuePair <FilterParameter, string>(ParseParameter(token.Value), value) }); case MetricFilterExpressionToken.TokenType.OpenParen: // F -> (E) // Consume ( tokenizer.Advance(); // Match Expression MetricFilterExpressionTree node = ParseFilterExpression(tokenizer); // Verify and consume ) if (tokenizer.IsEmpty || tokenizer.Current.Type != MetricFilterExpressionToken.TokenType.CloseParen) { throw GenerateFilterParseException(tokenizer.Current, MetricFilterExpressionToken.TokenType.CloseParen); } tokenizer.Advance(); return(node); default: throw GenerateFilterParseException(token, MetricFilterExpressionToken.TokenType.Identifier); } }
// Parse filter clause (or parenthesized expression) corresponds to F -> ID EQ VALUE | (E) private static MetricFilterExpressionTree ParseFilterClause(MetricFilterExpressionTokenizer tokenizer) { if (tokenizer == null || tokenizer.IsEmpty) { throw GenerateFilterParseException(null, MetricFilterExpressionToken.TokenType.Identifier); } MetricFilterExpressionToken token = tokenizer.Current; switch (token.Type) { case MetricFilterExpressionToken.TokenType.Identifier: // F -> ID EQ VALUE // validate and store the parameter name FilterParameter parameter = ParseParameter(token.Value); // Consume name tokenizer.Advance(); // Verify and comsume EQ if (tokenizer.IsEmpty || tokenizer.Current.Type != MetricFilterExpressionToken.TokenType.EqOperator) { throw GenerateFilterParseException(tokenizer.Current, MetricFilterExpressionToken.TokenType.EqOperator); } tokenizer.Advance(); MetricFilterExpressionToken.TokenType expectedType = parameter == FilterParameter.TimeGrain ? MetricFilterExpressionToken.TokenType.DurationValue : parameter == FilterParameter.Name ? MetricFilterExpressionToken.TokenType.StringValue : MetricFilterExpressionToken.TokenType.DateTimeOffsetValue; // Verify, store, and consume value if (tokenizer.IsEmpty || tokenizer.Current.Type != expectedType) { throw GenerateFilterParseException(tokenizer.Current, expectedType); } string value = tokenizer.Current.Value; tokenizer.Advance(); return new MetricFilterExpressionTree() { Value = new KeyValuePair<FilterParameter, string>(ParseParameter(token.Value), value) }; case MetricFilterExpressionToken.TokenType.OpenParen: // F -> (E) // Consume ( tokenizer.Advance(); // Match Expression MetricFilterExpressionTree node = ParseFilterExpression(tokenizer); // Verify and consume ) if (tokenizer.IsEmpty || tokenizer.Current.Type != MetricFilterExpressionToken.TokenType.CloseParen) { throw GenerateFilterParseException(tokenizer.Current, MetricFilterExpressionToken.TokenType.CloseParen); } tokenizer.Advance(); return node; default: throw GenerateFilterParseException(token, MetricFilterExpressionToken.TokenType.Identifier); } }
// Parse Filter Term (conjunction) corresponds to T -> F AND T | F private static MetricFilterExpressionTree ParseFilterTerm(MetricFilterExpressionTokenizer tokenizer) { // Match Clause MetricFilterExpressionTree node = ParseFilterClause(tokenizer); // T -> F if (tokenizer.IsEmpty) { return node; } if (tokenizer.Current.Type == MetricFilterExpressionToken.TokenType.AndOperator) { // Consume AND tokenizer.Advance(); // T -> F AND T return new MetricFilterExpressionTree() { IsConjunction = true, LeftExpression = node, RightExpression = ParseFilterTerm(tokenizer) }; } return node; }
// Parse Filter Expression (disjunction) corresponds to E -> T OR E | T private static MetricFilterExpressionTree ParseFilterExpression(MetricFilterExpressionTokenizer tokenizer) { MetricFilterExpressionTree node = ParseFilterTerm(tokenizer); // E -> T if (tokenizer.IsEmpty) { return node; } if (tokenizer.Current.Type == MetricFilterExpressionToken.TokenType.OrOperator) { // Consume OR tokenizer.Advance(); // E -> T OR E return new MetricFilterExpressionTree() { IsConjunction = false, LeftExpression = node, RightExpression = ParseFilterExpression(tokenizer) }; } return node; }