// Build MetricFilter from expression tree by depth-first evaluation private static MetricFilterExpression InterpretFilterExpressionTree(MetricFilterExpressionTree tree) { if (tree == null) { return(null); } // Leaf Node: Create simple Filter if (tree.LeftExpression == null && tree.RightExpression == null) { MetricFilterExpression expression = new MetricFilterExpression( tree.Value.Key == FilterParameter.TimeGrain ? tree.Value.Value : null, tree.Value.Key == FilterParameter.StartTime ? tree.Value.Value : null, tree.Value.Key == FilterParameter.EndTime ? tree.Value.Value : null, tree.Value.Key == FilterParameter.MetricName ? tree.Value.Value : null, tree.Value.Key == FilterParameter.DimensionName ? tree.Value.Value : null, tree.Value.Key == FilterParameter.DimensionValue ? tree.Value.Value : null); return(expression); } // Just in case (should never happen) if (tree.LeftExpression == null || tree.RightExpression == null) { throw new FormatException("Unexpected Parse Error."); } // Tree Node: Combine children return(tree.IsConjunction ? InterpretFilterExpressionTree(tree.LeftExpression).And(InterpretFilterExpressionTree(tree.RightExpression)) as MetricFilterExpression : InterpretFilterExpressionTree(tree.LeftExpression).Or(InterpretFilterExpressionTree(tree.RightExpression)) as MetricFilterExpression); }
// 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); }
/** * Parser implements a recursive-descent parser for the following grammar: * * E -> T OR E | T * T -> F AND T | F * F -> ID EQ VALUE | ( E ) * * E = Expression (ANDs and ORs) * T = Term (ANDs only) * F = Clause * ID = Identifier (token) * EQ = EQ operator (token) * VALUE = value (token) * OR = OR operator (token) * AND = AND operator (token) * ( and ) are also terminals (tokens) * */ private static MetricFilterExpressionTree ParseFilterExpressionTree(MetricFilterExpressionTokenizer tokenizer) { MetricFilterExpressionTree tree = ParseFilterExpression(tokenizer); if (!tokenizer.IsEmpty) { throw GenerateFilterParseException(tokenizer.Current, MetricFilterExpressionToken.TokenType.OrOperator); } return(tree); }
// 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); } }
// Build MetricFilter from expression tree by depth-first evaluation private static MetricFilterExpression InterpretFilterExpressionTree(MetricFilterExpressionTree tree) { if (tree == null) { return null; } // Leaf Node: Create simple Filter if (tree.LeftExpression == null && tree.RightExpression == null) { MetricFilterExpression expression = new MetricFilterExpression( tree.Value.Key == FilterParameter.TimeGrain ? tree.Value.Value : null, tree.Value.Key == FilterParameter.StartTime ? tree.Value.Value : null, tree.Value.Key == FilterParameter.EndTime ? tree.Value.Value : null, tree.Value.Key == FilterParameter.Name ? tree.Value.Value : null); return expression; } // Just in case (should never happen) if (tree.LeftExpression == null || tree.RightExpression == null) { throw new FormatException("Unexpected Parse Error."); } // Tree Node: Combine children return tree.IsConjunction ? InterpretFilterExpressionTree(tree.LeftExpression) .And(InterpretFilterExpressionTree(tree.RightExpression)) : InterpretFilterExpressionTree(tree.LeftExpression) .Or(InterpretFilterExpressionTree(tree.RightExpression)); }