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;
        }
Example #2
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);
        }