Пример #1
0
        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));
        }
Пример #2
0
        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);
        }
Пример #3
0
 abstract internal PivotsExpression ToPivotsExpression(Dictionary<string, Pivots.Pivot> pivotVsPivotValues, GetChoiceDelegate get_choice_fn);
Пример #4
0
        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;
        }
Пример #5
0
            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;
            }
Пример #6
0
            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);
                }
            }
Пример #7
0
            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);
            }
Пример #8
0
 internal override PivotsExpression ToPivotsExpression(Dictionary<string, Pivots.Pivot> pivotVsPivotValues, GetChoiceDelegate get_choice_fn) {
     return PivotsExpression.False;
 }
Пример #9
0
        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);
        }
Пример #10
0
            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);
            }
Пример #11
0
            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));
                }
            }
Пример #12
0
            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));
            }
Пример #13
0
 internal override PivotsExpression ToPivotsExpression(Dictionary <string, Pivots.Pivot> pivotVsPivotValues, GetChoiceDelegate get_choice_fn)
 {
     return(PivotsExpression.False);
 }
Пример #14
0
 abstract internal PivotsExpression ToPivotsExpression(Dictionary <string, Pivots.Pivot> pivotVsPivotValues, GetChoiceDelegate get_choice_fn);