Unary operator expression.
Inheritance: IConditionExpression
        public void ToStringInvalidOperatorTest()
        {
            ElementAttributeExpression attributeExpression = new ElementAttributeExpression(
                ElementAttributeType.Name);
            StringExpression stringExpression = new StringExpression("Test");
            BinaryOperatorExpression equalsExpression = new BinaryOperatorExpression(
                BinaryExpressionOperator.Equal,
                attributeExpression,
                stringExpression);
            UnaryOperatorExpression operatorExpression = new UnaryOperatorExpression(
                (UnaryExpressionOperator) int.MinValue,
                equalsExpression);

            Assert.AreEqual(string.Format("{0}(($(Element.Name) == 'Test'))", int.MinValue), operatorExpression.ToString());
        }
        public void ToStringTest()
        {
            ElementAttributeExpression attributeExpression = new ElementAttributeExpression(
                ElementAttributeType.Name);
            StringExpression stringExpression = new StringExpression("Test");
            BinaryOperatorExpression equalsExpression = new BinaryOperatorExpression(
                BinaryExpressionOperator.Equal,
                attributeExpression,
                stringExpression);
            UnaryOperatorExpression operatorExpression = new UnaryOperatorExpression(
                UnaryExpressionOperator.Negate,
                equalsExpression);

            Assert.AreEqual("!(($(Element.Name) == 'Test'))", operatorExpression.ToString());
        }
        /// <summary>
        /// Parses and expression to an expression tree.
        /// </summary>
        /// <param name="expression">Condition expression text.</param>
        /// <returns>A condition expression instance.</returns>
        public IConditionExpression Parse(string expression)
        {
            const int DefaultExpressionLength = 128;
            IConditionExpression conditionExpression = null;

            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }
            else if (expression.Trim().Length == 0)
            {
                throw new ArgumentException("expression");
            }

            List<IConditionExpression> nodes = new List<IConditionExpression>();

            StringReader reader = new StringReader(expression);

            StringBuilder expressionBuilder = new StringBuilder(DefaultExpressionLength);

            bool inString = false;
            bool inAttribute = false;
            int depth = 0;

            int data = reader.Read();
            while (data > 0)
            {
                char ch = (char)data;
                char nextCh = (char)reader.Peek();

                if (inString && ch != '\'')
                {
                    expressionBuilder.Append(ch);
                }
                else
                {
                    switch (ch)
                    {
                        case ' ':
                        case '\t':
                        case '\r':
                        case '\n':
                            // Eat whitespace
                            break;

                        case ExpressionPrefix:
                            CheckForInvalidOperator(expression, expressionBuilder);
                            if (nextCh == ExpressionStart)
                            {
                                inAttribute = true;
                                reader.Read();
                            }
                            break;

                        case '=':
                            if (nextCh == '=')
                            {
                                nodes.Add(new OperatorExpressionPlaceholder(BinaryExpressionOperator.Equal));
                                reader.Read();
                            }
                            else if (nextCh == '~')
                            {
                                nodes.Add(new OperatorExpressionPlaceholder(BinaryExpressionOperator.Matches));
                                reader.Read();
                            }
                            break;

                        case '!':
                            if (nextCh == '=')
                            {
                                nodes.Add(new OperatorExpressionPlaceholder(BinaryExpressionOperator.NotEqual));
                                reader.Read();
                            }
                            else
                            {
                                expressionBuilder.Append(ch);
                            }
                            break;

                        case ':':
                            nodes.Add(new OperatorExpressionPlaceholder(BinaryExpressionOperator.Contains));
                            reader.Read();
                            break;

                        case 'O':
                            if (nextCh == 'r' && !inAttribute && !inString)
                            {
                                nodes.Add(new OperatorExpressionPlaceholder(BinaryExpressionOperator.Or));
                                reader.Read();
                            }
                            else
                            {
                                expressionBuilder.Append(ch);
                            }
                            break;

                        case 'A':
                            if (nextCh == 'n' && !inAttribute && !inString)
                            {
                                reader.Read();
                                nextCh = (char)reader.Peek();
                                if (nextCh == 'd')
                                {
                                    nodes.Add(new OperatorExpressionPlaceholder(BinaryExpressionOperator.And));
                                    reader.Read();
                                }
                            }
                            else
                            {
                                expressionBuilder.Append(ch);
                            }
                            break;

                        case ExpressionEnd:
                            if (inAttribute)
                            {
                                string attribute = expressionBuilder.ToString();
                                expressionBuilder = new StringBuilder(DefaultExpressionLength);
                                ElementAttributeScope elementScope = ElementAttributeScope.Element;
                                bool isFileExpression = false;

                                int separatorIndex = attribute.LastIndexOf(ScopeSeparator);
                                if (separatorIndex > 0)
                                {
                                    try
                                    {
                                        string attributeScope = attribute.Substring(0, separatorIndex);
                                        attribute = attribute.Substring(separatorIndex + 1);

                                        if (attributeScope == FileAttributeScope)
                                        {
                                            isFileExpression = true;
                                        }
                                        else
                                        {
                                            elementScope = (ElementAttributeScope)
                                                Enum.Parse(typeof(ElementAttributeScope), attributeScope);
                                        }
                                    }
                                    catch (ArgumentException ex)
                                    {
                                        OnInvalidExpression(expression, "Unknown attribute scope: {0}", ex.Message);
                                    }
                                }

                                if (isFileExpression)
                                {
                                    FileAttributeType fileAttribute = FileAttributeType.None;

                                    try
                                    {
                                        fileAttribute = (FileAttributeType)
                                            Enum.Parse(typeof(FileAttributeType), attribute);
                                    }
                                    catch (ArgumentException ex)
                                    {
                                        OnInvalidExpression(expression, "Unknown attribute: {0}", ex.Message);
                                    }

                                    FileAttributeExpression attributeExpresion = new FileAttributeExpression(
                                        fileAttribute);
                                    nodes.Add(attributeExpresion);
                                }
                                else
                                {
                                    ElementAttributeType elementAttribute = ElementAttributeType.None;

                                    try
                                    {
                                        elementAttribute = (ElementAttributeType)
                                            Enum.Parse(typeof(ElementAttributeType), attribute);
                                    }
                                    catch (ArgumentException ex)
                                    {
                                        OnInvalidExpression(expression, "Unknown attribute: {0}", ex.Message);
                                    }

                                    ElementAttributeExpression attributeExpresion = new ElementAttributeExpression(
                                        elementAttribute, elementScope);
                                    nodes.Add(attributeExpresion);
                                }

                                inAttribute = false;
                            }
                            else if (expressionBuilder.Length > 0 && nodes.Count > 0)
                            {
                                IConditionExpression innerExpression = nodes[nodes.Count - 1];
                                nodes.RemoveAt(nodes.Count - 1);

                                string unaryOperatorString = expressionBuilder.ToString().Trim();
                                expressionBuilder = new StringBuilder(DefaultExpressionLength);

                                UnaryExpressionOperator? unaryOperator = null;

                                if (unaryOperatorString == "!")
                                {
                                    unaryOperator = UnaryExpressionOperator.Negate;
                                }
                                else
                                {
                                    OnInvalidExpression(expression,
                                        "Invalid operator {0}", unaryOperatorString);
                                }

                                UnaryOperatorExpression unaryOperatorExpression = new UnaryOperatorExpression(
                                    unaryOperator.Value, innerExpression);

                                nodes.Add(unaryOperatorExpression);
                                depth--;
                            }
                            else
                            {
                                depth--;
                            }
                            break;

                        case ExpressionStart:
                            IConditionExpression nestedExpression = null;
                            StringBuilder childExpressionBuilder = new StringBuilder(DefaultExpressionLength);
                            data = reader.Read();
                            ch = (char)data;
                            nextCh = (char)reader.Peek();
                            depth++;
                            while (data > 0)
                            {
                                if (ch == ExpressionPrefix && nextCh == ExpressionStart)
                                {
                                    inAttribute = true;
                                    childExpressionBuilder.Append(ExpressionPrefix);
                                    data = reader.Read();
                                    childExpressionBuilder.Append(ExpressionStart);
                                }
                                else if (ch == ExpressionStart && !inAttribute)
                                {
                                    depth++;
                                    childExpressionBuilder.Append(ExpressionStart);
                                }
                                else if (nextCh == ExpressionEnd)
                                {
                                    childExpressionBuilder.Append(ch);

                                    if (inAttribute || depth > 1)
                                    {
                                        if (inAttribute)
                                        {
                                            inAttribute = false;
                                        }
                                        else if (depth > 1)
                                        {
                                            depth--;
                                        }
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                                else
                                {
                                    childExpressionBuilder.Append(ch);
                                }

                                data = reader.Read();
                                ch = (char)data;
                                nextCh = (char)reader.Peek();
                            }

                            try
                            {
                                nestedExpression = Parse(childExpressionBuilder.ToString());
                            }
                            catch (ArgumentException)
                            {
                                OnInvalidExpression(expression);
                            }
                            nodes.Add(nestedExpression);
                            break;

                        case '\'':
                            if (inString)
                            {
                                if (nextCh == '\'')
                                {
                                    expressionBuilder.Append(ch);
                                    reader.Read();
                                }
                                else
                                {
                                    string str = expressionBuilder.ToString();
                                    expressionBuilder = new StringBuilder(DefaultExpressionLength);
                                    StringExpression stringExpression = new StringExpression(str);
                                    nodes.Add(stringExpression);
                                    inString = false;
                                }
                            }
                            else
                            {
                                CheckForInvalidOperator(expression, expressionBuilder);
                                inString = true;
                            }

                            break;

                        default:
                            expressionBuilder.Append(ch);
                            break;
                    }
                }

                data = reader.Read();
            }

            if (inString)
            {
                OnInvalidExpression(expression, "Expected '");
            }
            else if (inAttribute || depth > 0)
            {
                OnInvalidExpression(expression, "Expected )");
            }
            else if (depth < 0)
            {
                OnInvalidExpression(expression, "Unmatched )");
            }

            //
            // Assembly the flat list of expressions and expression placeholders into an
            // expression tree.
            //
            conditionExpression = AssembleExpressionTree(nodes.AsReadOnly(), expression);

            return conditionExpression;
        }
Example #4
0
        /// <summary>
        /// Parses and expression to an expression tree.
        /// </summary>
        /// <param name="expression">Condition expression text.</param>
        /// <returns>A condition expression instance.</returns>
        public IConditionExpression Parse(string expression)
        {
            const int            DefaultExpressionLength = 128;
            IConditionExpression conditionExpression     = null;

            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }
            else if (expression.Trim().Length == 0)
            {
                throw new ArgumentException("expression");
            }

            List <IConditionExpression> nodes = new List <IConditionExpression>();

            StringReader reader = new StringReader(expression);

            StringBuilder expressionBuilder = new StringBuilder(DefaultExpressionLength);

            bool inString    = false;
            bool inAttribute = false;
            int  depth       = 0;

            int data = reader.Read();

            while (data > 0)
            {
                char ch     = (char)data;
                char nextCh = (char)reader.Peek();

                if (inString && ch != '\'')
                {
                    expressionBuilder.Append(ch);
                }
                else
                {
                    switch (ch)
                    {
                    case ' ':
                    case '\t':
                    case '\r':
                    case '\n':
                        // Eat whitespace
                        break;

                    case ExpressionPrefix:
                        CheckForInvalidOperator(expression, expressionBuilder);
                        if (nextCh == ExpressionStart)
                        {
                            inAttribute = true;
                            reader.Read();
                        }
                        break;

                    case '=':
                        if (nextCh == '=')
                        {
                            nodes.Add(new OperatorExpressionPlaceholder(BinaryExpressionOperator.Equal));
                            reader.Read();
                        }
                        else if (nextCh == '~')
                        {
                            nodes.Add(new OperatorExpressionPlaceholder(BinaryExpressionOperator.Matches));
                            reader.Read();
                        }
                        break;

                    case '!':
                        if (nextCh == '=')
                        {
                            nodes.Add(new OperatorExpressionPlaceholder(BinaryExpressionOperator.NotEqual));
                            reader.Read();
                        }
                        else
                        {
                            expressionBuilder.Append(ch);
                        }
                        break;

                    case ':':
                        nodes.Add(new OperatorExpressionPlaceholder(BinaryExpressionOperator.Contains));
                        reader.Read();
                        break;

                    case 'O':
                        if (nextCh == 'r' && !inAttribute && !inString)
                        {
                            nodes.Add(new OperatorExpressionPlaceholder(BinaryExpressionOperator.Or));
                            reader.Read();
                        }
                        else
                        {
                            expressionBuilder.Append(ch);
                        }
                        break;

                    case 'A':
                        if (nextCh == 'n' && !inAttribute && !inString)
                        {
                            reader.Read();
                            nextCh = (char)reader.Peek();
                            if (nextCh == 'd')
                            {
                                nodes.Add(new OperatorExpressionPlaceholder(BinaryExpressionOperator.And));
                                reader.Read();
                            }
                        }
                        else
                        {
                            expressionBuilder.Append(ch);
                        }
                        break;

                    case ExpressionEnd:
                        if (inAttribute)
                        {
                            string attribute = expressionBuilder.ToString();
                            expressionBuilder = new StringBuilder(DefaultExpressionLength);
                            ElementAttributeScope elementScope = ElementAttributeScope.Element;
                            bool isFileExpression = false;

                            int separatorIndex = attribute.LastIndexOf(ScopeSeparator);
                            if (separatorIndex > 0)
                            {
                                try
                                {
                                    string attributeScope = attribute.Substring(0, separatorIndex);
                                    attribute = attribute.Substring(separatorIndex + 1);

                                    if (attributeScope == FileAttributeScope)
                                    {
                                        isFileExpression = true;
                                    }
                                    else
                                    {
                                        elementScope = (ElementAttributeScope)
                                                       Enum.Parse(typeof(ElementAttributeScope), attributeScope);
                                    }
                                }
                                catch (ArgumentException ex)
                                {
                                    OnInvalidExpression(expression, "Unknown attribute scope: {0}", ex.Message);
                                }
                            }

                            if (isFileExpression)
                            {
                                FileAttributeType fileAttribute = FileAttributeType.None;

                                try
                                {
                                    fileAttribute = (FileAttributeType)
                                                    Enum.Parse(typeof(FileAttributeType), attribute);
                                }
                                catch (ArgumentException ex)
                                {
                                    OnInvalidExpression(expression, "Unknown attribute: {0}", ex.Message);
                                }

                                FileAttributeExpression attributeExpresion = new FileAttributeExpression(
                                    fileAttribute);
                                nodes.Add(attributeExpresion);
                            }
                            else
                            {
                                ElementAttributeType elementAttribute = ElementAttributeType.None;

                                try
                                {
                                    elementAttribute = (ElementAttributeType)
                                                       Enum.Parse(typeof(ElementAttributeType), attribute);
                                }
                                catch (ArgumentException ex)
                                {
                                    OnInvalidExpression(expression, "Unknown attribute: {0}", ex.Message);
                                }

                                ElementAttributeExpression attributeExpresion = new ElementAttributeExpression(
                                    elementAttribute, elementScope);
                                nodes.Add(attributeExpresion);
                            }

                            inAttribute = false;
                        }
                        else if (expressionBuilder.Length > 0 && nodes.Count > 0)
                        {
                            IConditionExpression innerExpression = nodes[nodes.Count - 1];
                            nodes.RemoveAt(nodes.Count - 1);

                            string unaryOperatorString = expressionBuilder.ToString().Trim();
                            expressionBuilder = new StringBuilder(DefaultExpressionLength);

                            UnaryExpressionOperator?unaryOperator = null;

                            if (unaryOperatorString == "!")
                            {
                                unaryOperator = UnaryExpressionOperator.Negate;
                            }
                            else
                            {
                                OnInvalidExpression(expression,
                                                    "Invalid operator {0}", unaryOperatorString);
                            }

                            UnaryOperatorExpression unaryOperatorExpression = new UnaryOperatorExpression(
                                unaryOperator.Value, innerExpression);

                            nodes.Add(unaryOperatorExpression);
                            depth--;
                        }
                        else
                        {
                            depth--;
                        }
                        break;

                    case ExpressionStart:
                        IConditionExpression nestedExpression       = null;
                        StringBuilder        childExpressionBuilder = new StringBuilder(DefaultExpressionLength);
                        data   = reader.Read();
                        ch     = (char)data;
                        nextCh = (char)reader.Peek();
                        depth++;
                        while (data > 0)
                        {
                            if (ch == ExpressionPrefix && nextCh == ExpressionStart)
                            {
                                inAttribute = true;
                                childExpressionBuilder.Append(ExpressionPrefix);
                                data = reader.Read();
                                childExpressionBuilder.Append(ExpressionStart);
                            }
                            else if (ch == ExpressionStart && !inAttribute)
                            {
                                depth++;
                                childExpressionBuilder.Append(ExpressionStart);
                            }
                            else if (nextCh == ExpressionEnd)
                            {
                                childExpressionBuilder.Append(ch);

                                if (inAttribute || depth > 1)
                                {
                                    if (inAttribute)
                                    {
                                        inAttribute = false;
                                    }
                                    else if (depth > 1)
                                    {
                                        depth--;
                                    }
                                }
                                else
                                {
                                    break;
                                }
                            }
                            else
                            {
                                childExpressionBuilder.Append(ch);
                            }

                            data   = reader.Read();
                            ch     = (char)data;
                            nextCh = (char)reader.Peek();
                        }

                        try
                        {
                            nestedExpression = Parse(childExpressionBuilder.ToString());
                        }
                        catch (ArgumentException)
                        {
                            OnInvalidExpression(expression);
                        }
                        nodes.Add(nestedExpression);
                        break;

                    case '\'':
                        if (inString)
                        {
                            if (nextCh == '\'')
                            {
                                expressionBuilder.Append(ch);
                                reader.Read();
                            }
                            else
                            {
                                string str = expressionBuilder.ToString();
                                expressionBuilder = new StringBuilder(DefaultExpressionLength);
                                StringExpression stringExpression = new StringExpression(str);
                                nodes.Add(stringExpression);
                                inString = false;
                            }
                        }
                        else
                        {
                            CheckForInvalidOperator(expression, expressionBuilder);
                            inString = true;
                        }

                        break;

                    default:
                        expressionBuilder.Append(ch);
                        break;
                    }
                }

                data = reader.Read();
            }

            if (inString)
            {
                OnInvalidExpression(expression, "Expected '");
            }
            else if (inAttribute || depth > 0)
            {
                OnInvalidExpression(expression, "Expected )");
            }
            else if (depth < 0)
            {
                OnInvalidExpression(expression, "Unmatched )");
            }

            //
            // Assembly the flat list of expressions and expression placeholders into an
            // expression tree.
            //
            conditionExpression = AssembleExpressionTree(nodes.AsReadOnly(), expression);

            return(conditionExpression);
        }