public static PivotsExpression ReadExpression(Dictionary <string, Pivots.Pivot> pivotVsPivotValues, GetChoiceDelegate get_choice_fn, string expression) { AstExpression expr = ParseExpression(pivotVsPivotValues, get_choice_fn, expression); return(expr.ToPivotsExpression(pivotVsPivotValues, get_choice_fn)); }
public static PivotsExpression ReadExpression(Dictionary<string, Pivots.Pivot> pivotVsPivotValues, GetChoiceDelegate get_choice_fn, string expression) { AstExpression expr = ParseExpression(pivotVsPivotValues, get_choice_fn, expression); return expr.ToPivotsExpression(pivotVsPivotValues, get_choice_fn); }
abstract internal PivotsExpression ToPivotsExpression(Dictionary<string, Pivots.Pivot> pivotVsPivotValues, GetChoiceDelegate get_choice_fn);
private static AstExpression ParseExpression(Dictionary<string, Pivots.Pivot> pivotVsPivotValues, GetChoiceDelegate get_choice_fn, string expression) { AstExpression result = null; var rxResult = Pivots.ExpressionRx.Match(expression); if (rxResult.Success) { var state = ExpressionState.None; AstExpression current = null; bool invert = false; foreach (var item in rxResult.Groups[1].Captures.Cast<Capture>().Select(each => each.Value.Trim()).Where(each => !string.IsNullOrEmpty(each))) { switch (item[0]) { case '!': if (result != null && state == ExpressionState.None) { throw new ClrPlusException("Invalid expression. (not expression must be separated from previous expression with an operator)"); } if (item.Length % 2 != 0) invert = !invert; continue; case '&': case ',': case '\\': case '/': if (state != ExpressionState.None) { throw new ClrPlusException("Invalid expression. (May not state two operators in a row)"); } if (result == null) { throw new ClrPlusException("Invalid expression. (may not start with an operator)"); } state = ExpressionState.HasAnd; continue; case '|': case '+': if (state != ExpressionState.None) { throw new ClrPlusException("Invalid expression. (May not state two operators in a row)"); } if (result == null) { throw new ClrPlusException("Invalid expression. (may not start with an operator)"); } state = ExpressionState.HasOr; continue; case '(': if (result != null && state == ExpressionState.None) { throw new ClrPlusException("Invalid expression. (nested expression must be separated from previous expression with an operator)"); } if (item.EndsWith(")")) { // parse nested expression. current = ParseExpression(pivotVsPivotValues, get_choice_fn, item.Substring(1, item.Length - 2)); break; } throw new ClrPlusException("Mismatched '(' in expression"); default: if (!Pivots.WordRx.IsMatch(item)) { throw new ClrPlusException("Invalid characters in expression"); } if (result != null && state == ExpressionState.None) { throw new ClrPlusException("Invalid expression. (expression must be separated from previous expression with an operator)"); } // otherwise, it's the word we're looking for. // string choice; string pivot; if (get_choice_fn(item, out choice, out pivot)) { current = new PivotExpression(pivot, choice, false); break; } else if (item.ToLowerInvariant() == "true") { current = TrueExpression.instance; break; } else if (item.ToLowerInvariant() == "false") { current = FalseExpression.instance; break; } throw new ClrPlusException(string.Format("Unmatched configuration choice '{0}", item)); } if (invert) current = current.Invert(); switch (state) { case ExpressionState.None: result = current; continue; case ExpressionState.HasAnd: result = new AndExpression(result, current); break; case ExpressionState.HasOr: result = new OrExpression(result, current); break; } current = null; state = ExpressionState.None; } } if (result == null) result = TrueExpression.instance; return result; }
internal override PivotsExpression ToPivotsExpression(Dictionary<string, Pivots.Pivot> pivotVsPivotValues, GetChoiceDelegate get_choice_fn) { var result = new PivotsExpression(); result.relevant_pivots = new HashSet<string>(); result.relevant_pivots.Add(pivot_name); result.matching_combinations = new ComparableHashSet<ComparableHashSet<string>>(); if (inverted) { foreach (string pivotValue in pivotVsPivotValues[pivot_name].Choices.Keys) { if (pivotValue != pivot_choice) { ComparableHashSet<string> choice = new ComparableHashSet<string>(); choice.Add(pivotValue); result.matching_combinations.Add(choice); } } } else { ComparableHashSet<string> choice = new ComparableHashSet<string>(); choice.Add(pivot_choice); result.matching_combinations.Add(choice); } return result; }
internal override PivotsExpression ToPivotsExpression(Dictionary<string, Pivots.Pivot> pivotVsPivotValues, GetChoiceDelegate get_choice_fn) { PivotsExpression left, right; left = left_child.ToPivotsExpression(pivotVsPivotValues, get_choice_fn); if (left.invariant) { if (left.invariant_result) return right_child.ToPivotsExpression(pivotVsPivotValues, get_choice_fn); else return left; } right = right_child.ToPivotsExpression(pivotVsPivotValues, get_choice_fn); if (right.invariant) { if (right.invariant_result) return left; else return right; } HashSet<string> shared_pivots = new HashSet<string>(left.relevant_pivots); shared_pivots.IntersectWith(right.relevant_pivots); if (shared_pivots.Count == left.relevant_pivots.Count) { // All pivots are shared, just intersect the sets. PivotsExpression result = new PivotsExpression(); result.relevant_pivots = left.relevant_pivots; result.matching_combinations = new ComparableHashSet<ComparableHashSet<string>>(left.matching_combinations); result.matching_combinations.IntersectWith(right.matching_combinations); return result.Simplify(pivotVsPivotValues); } if (shared_pivots.Count == 0) { // No shared pivots, so do a cross product PivotsExpression result = new PivotsExpression(); result.relevant_pivots = new HashSet<string>(left.relevant_pivots); result.relevant_pivots.UnionWith(right.relevant_pivots); result.matching_combinations = new ComparableHashSet<ComparableHashSet<string>>(); foreach (var left_combination in left.matching_combinations) { foreach (var right_combination in right.matching_combinations) { ComparableHashSet<string> new_combination = new ComparableHashSet<string>(left_combination); new_combination.UnionWith(right_combination); result.matching_combinations.Add(new_combination); } } // It shouldn't be necessary to simplify in this case, as any independent pivots should have been removed already return result; } HashSet<string> shared_pivot_values = new HashSet<string>(); foreach (string pivot in shared_pivots) { shared_pivot_values.UnionWith(pivotVsPivotValues[pivot].Choices.Keys); } // Sort by relevant pivot count if (left.relevant_pivots.Count > right.relevant_pivots.Count) { var tmp = left; left = right; right = tmp; } if (right.relevant_pivots.IsSupersetOf(left.relevant_pivots)) { // Filter the combintions in right by what's in left. PivotsExpression result = new PivotsExpression(); result.relevant_pivots = right.relevant_pivots; result.matching_combinations = new ComparableHashSet<ComparableHashSet<string>>(); foreach (var right_combination in right.matching_combinations) { ComparableHashSet<string> reduced_combination = new ComparableHashSet<string>(right_combination); reduced_combination.IntersectWith(shared_pivot_values); if (left.matching_combinations.Contains(reduced_combination)) result.matching_combinations.Add(right_combination); } return result.Simplify(pivotVsPivotValues); } else { Dictionary<ComparableHashSet<string>, List<ComparableHashSet<string>>> shared_values_to_left_values = new Dictionary<ComparableHashSet<string>, List<ComparableHashSet<string>>>(); foreach (var left_combination in left.matching_combinations) { ComparableHashSet<string> shared_values = new ComparableHashSet<string>(); foreach (var value in left_combination) { if (shared_pivot_values.Contains(value)) shared_values.Add(value); } List<ComparableHashSet<string>> combination_list; if (!shared_values_to_left_values.TryGetValue(shared_values, out combination_list)) combination_list = shared_values_to_left_values[shared_values] = new List<ComparableHashSet<string>>(); combination_list.Add(left_combination); } PivotsExpression result = new PivotsExpression(); result.relevant_pivots = new HashSet<string>(left.relevant_pivots); result.relevant_pivots.UnionWith(right.relevant_pivots); result.matching_combinations = new ComparableHashSet<ComparableHashSet<string>>(); foreach (var right_combination in right.matching_combinations) { ComparableHashSet<string> shared_values = new ComparableHashSet<string>(); foreach (var value in right_combination) { if (shared_pivot_values.Contains(value)) shared_values.Add(value); } List<ComparableHashSet<string>> left_combinations; if (shared_values_to_left_values.TryGetValue(shared_values, out left_combinations)) { foreach (var left_combination in left_combinations) { ComparableHashSet<string> new_combination = new ComparableHashSet<string>(right_combination); new_combination.UnionWith(left_combination); result.matching_combinations.Add(new_combination); } } } return result.Simplify(pivotVsPivotValues); } }
internal override PivotsExpression ToPivotsExpression(Dictionary<string, Pivots.Pivot> pivotVsPivotValues, GetChoiceDelegate get_choice_fn) { PivotsExpression left, right; left = left_child.ToPivotsExpression(pivotVsPivotValues, get_choice_fn); if (left.invariant) { if (left.invariant_result) return left; else return right_child.ToPivotsExpression(pivotVsPivotValues, get_choice_fn); } right = right_child.ToPivotsExpression(pivotVsPivotValues, get_choice_fn); if (right.invariant) { if (right.invariant_result) return right; else return left; } HashSet<string> pivots; ComparableHashSet<ComparableHashSet<string>> result; pivots = new HashSet<string>(left.relevant_pivots); pivots.UnionWith(right.relevant_pivots); result = GetExpandedChoices(left, pivots, pivotVsPivotValues); result.UnionWith(GetExpandedChoices(right, pivots, pivotVsPivotValues)); PivotsExpression res = new PivotsExpression(); res.relevant_pivots = pivots; res.matching_combinations = result; return res.Simplify(pivotVsPivotValues); }
internal override PivotsExpression ToPivotsExpression(Dictionary<string, Pivots.Pivot> pivotVsPivotValues, GetChoiceDelegate get_choice_fn) { return PivotsExpression.False; }
private static AstExpression ParseExpression(Dictionary <string, Pivots.Pivot> pivotVsPivotValues, GetChoiceDelegate get_choice_fn, string expression) { AstExpression result = null; var rxResult = Pivots.ExpressionRx.Match(expression); if (rxResult.Success) { var state = ExpressionState.None; AstExpression current = null; bool invert = false; foreach (var item in rxResult.Groups[1].Captures.Cast <Capture>().Select(each => each.Value.Trim()).Where(each => !string.IsNullOrEmpty(each))) { switch (item[0]) { case '!': if (result != null && state == ExpressionState.None) { throw new ClrPlusException("Invalid expression. (not expression must be separated from previous expression with an operator)"); } if (item.Length % 2 != 0) { invert = !invert; } continue; case '&': case ',': case '\\': case '/': if (state != ExpressionState.None) { throw new ClrPlusException("Invalid expression. (May not state two operators in a row)"); } if (result == null) { throw new ClrPlusException("Invalid expression. (may not start with an operator)"); } state = ExpressionState.HasAnd; continue; case '|': case '+': if (state != ExpressionState.None) { throw new ClrPlusException("Invalid expression. (May not state two operators in a row)"); } if (result == null) { throw new ClrPlusException("Invalid expression. (may not start with an operator)"); } state = ExpressionState.HasOr; continue; case '(': if (result != null && state == ExpressionState.None) { throw new ClrPlusException("Invalid expression. (nested expression must be separated from previous expression with an operator)"); } if (item.EndsWith(")")) { // parse nested expression. current = ParseExpression(pivotVsPivotValues, get_choice_fn, item.Substring(1, item.Length - 2)); break; } throw new ClrPlusException("Mismatched '(' in expression"); default: if (!Pivots.WordRx.IsMatch(item)) { throw new ClrPlusException("Invalid characters in expression"); } if (result != null && state == ExpressionState.None) { throw new ClrPlusException("Invalid expression. (expression must be separated from previous expression with an operator)"); } // otherwise, it's the word we're looking for. // string choice; string pivot; if (get_choice_fn(item, out choice, out pivot)) { current = new PivotExpression(pivot, choice, false); break; } else if (item.ToLowerInvariant() == "true") { current = TrueExpression.instance; break; } else if (item.ToLowerInvariant() == "false") { current = FalseExpression.instance; break; } throw new ClrPlusException(string.Format("Unmatched configuration choice '{0}", item)); } if (invert) { current = current.Invert(); } switch (state) { case ExpressionState.None: result = current; continue; case ExpressionState.HasAnd: result = new AndExpression(result, current); break; case ExpressionState.HasOr: result = new OrExpression(result, current); break; } current = null; state = ExpressionState.None; } } if (result == null) { result = TrueExpression.instance; } return(result); }
internal override PivotsExpression ToPivotsExpression(Dictionary <string, Pivots.Pivot> pivotVsPivotValues, GetChoiceDelegate get_choice_fn) { var result = new PivotsExpression(); result.relevant_pivots = new HashSet <string>(); result.relevant_pivots.Add(pivot_name); result.matching_combinations = new ComparableHashSet <ComparableHashSet <string> >(); if (inverted) { foreach (string pivotValue in pivotVsPivotValues[pivot_name].Choices.Keys) { if (pivotValue != pivot_choice) { ComparableHashSet <string> choice = new ComparableHashSet <string>(); choice.Add(pivotValue); result.matching_combinations.Add(choice); } } } else { ComparableHashSet <string> choice = new ComparableHashSet <string>(); choice.Add(pivot_choice); result.matching_combinations.Add(choice); } return(result); }
internal override PivotsExpression ToPivotsExpression(Dictionary <string, Pivots.Pivot> pivotVsPivotValues, GetChoiceDelegate get_choice_fn) { PivotsExpression left, right; left = left_child.ToPivotsExpression(pivotVsPivotValues, get_choice_fn); if (left.invariant) { if (left.invariant_result) { return(right_child.ToPivotsExpression(pivotVsPivotValues, get_choice_fn)); } else { return(left); } } right = right_child.ToPivotsExpression(pivotVsPivotValues, get_choice_fn); if (right.invariant) { if (right.invariant_result) { return(left); } else { return(right); } } HashSet <string> shared_pivots = new HashSet <string>(left.relevant_pivots); shared_pivots.IntersectWith(right.relevant_pivots); if (shared_pivots.Count == left.relevant_pivots.Count) { // All pivots are shared, just intersect the sets. PivotsExpression result = new PivotsExpression(); result.relevant_pivots = left.relevant_pivots; result.matching_combinations = new ComparableHashSet <ComparableHashSet <string> >(left.matching_combinations); result.matching_combinations.IntersectWith(right.matching_combinations); return(result.Simplify(pivotVsPivotValues)); } if (shared_pivots.Count == 0) { // No shared pivots, so do a cross product PivotsExpression result = new PivotsExpression(); result.relevant_pivots = new HashSet <string>(left.relevant_pivots); result.relevant_pivots.UnionWith(right.relevant_pivots); result.matching_combinations = new ComparableHashSet <ComparableHashSet <string> >(); foreach (var left_combination in left.matching_combinations) { foreach (var right_combination in right.matching_combinations) { ComparableHashSet <string> new_combination = new ComparableHashSet <string>(left_combination); new_combination.UnionWith(right_combination); result.matching_combinations.Add(new_combination); } } // It shouldn't be necessary to simplify in this case, as any independent pivots should have been removed already return(result); } HashSet <string> shared_pivot_values = new HashSet <string>(); foreach (string pivot in shared_pivots) { shared_pivot_values.UnionWith(pivotVsPivotValues[pivot].Choices.Keys); } // Sort by relevant pivot count if (left.relevant_pivots.Count > right.relevant_pivots.Count) { var tmp = left; left = right; right = tmp; } if (right.relevant_pivots.IsSupersetOf(left.relevant_pivots)) { // Filter the combintions in right by what's in left. PivotsExpression result = new PivotsExpression(); result.relevant_pivots = right.relevant_pivots; result.matching_combinations = new ComparableHashSet <ComparableHashSet <string> >(); foreach (var right_combination in right.matching_combinations) { ComparableHashSet <string> reduced_combination = new ComparableHashSet <string>(right_combination); reduced_combination.IntersectWith(shared_pivot_values); if (left.matching_combinations.Contains(reduced_combination)) { result.matching_combinations.Add(right_combination); } } return(result.Simplify(pivotVsPivotValues)); } else { Dictionary <ComparableHashSet <string>, List <ComparableHashSet <string> > > shared_values_to_left_values = new Dictionary <ComparableHashSet <string>, List <ComparableHashSet <string> > >(); foreach (var left_combination in left.matching_combinations) { ComparableHashSet <string> shared_values = new ComparableHashSet <string>(); foreach (var value in left_combination) { if (shared_pivot_values.Contains(value)) { shared_values.Add(value); } } List <ComparableHashSet <string> > combination_list; if (!shared_values_to_left_values.TryGetValue(shared_values, out combination_list)) { combination_list = shared_values_to_left_values[shared_values] = new List <ComparableHashSet <string> >(); } combination_list.Add(left_combination); } PivotsExpression result = new PivotsExpression(); result.relevant_pivots = new HashSet <string>(left.relevant_pivots); result.relevant_pivots.UnionWith(right.relevant_pivots); result.matching_combinations = new ComparableHashSet <ComparableHashSet <string> >(); foreach (var right_combination in right.matching_combinations) { ComparableHashSet <string> shared_values = new ComparableHashSet <string>(); foreach (var value in right_combination) { if (shared_pivot_values.Contains(value)) { shared_values.Add(value); } } List <ComparableHashSet <string> > left_combinations; if (shared_values_to_left_values.TryGetValue(shared_values, out left_combinations)) { foreach (var left_combination in left_combinations) { ComparableHashSet <string> new_combination = new ComparableHashSet <string>(right_combination); new_combination.UnionWith(left_combination); result.matching_combinations.Add(new_combination); } } } return(result.Simplify(pivotVsPivotValues)); } }
internal override PivotsExpression ToPivotsExpression(Dictionary <string, Pivots.Pivot> pivotVsPivotValues, GetChoiceDelegate get_choice_fn) { PivotsExpression left, right; left = left_child.ToPivotsExpression(pivotVsPivotValues, get_choice_fn); if (left.invariant) { if (left.invariant_result) { return(left); } else { return(right_child.ToPivotsExpression(pivotVsPivotValues, get_choice_fn)); } } right = right_child.ToPivotsExpression(pivotVsPivotValues, get_choice_fn); if (right.invariant) { if (right.invariant_result) { return(right); } else { return(left); } } HashSet <string> pivots; ComparableHashSet <ComparableHashSet <string> > result; pivots = new HashSet <string>(left.relevant_pivots); pivots.UnionWith(right.relevant_pivots); result = GetExpandedChoices(left, pivots, pivotVsPivotValues); result.UnionWith(GetExpandedChoices(right, pivots, pivotVsPivotValues)); PivotsExpression res = new PivotsExpression(); res.relevant_pivots = pivots; res.matching_combinations = result; return(res.Simplify(pivotVsPivotValues)); }
internal override PivotsExpression ToPivotsExpression(Dictionary <string, Pivots.Pivot> pivotVsPivotValues, GetChoiceDelegate get_choice_fn) { return(PivotsExpression.False); }
abstract internal PivotsExpression ToPivotsExpression(Dictionary <string, Pivots.Pivot> pivotVsPivotValues, GetChoiceDelegate get_choice_fn);