Exemplo n.º 1
0
        private Filter <T> Reduce(QuickFilterToken token)
        {
            while (stack.Count > 0)
            {
                Filter <T> top = stack.Pop();

                if (stack.Count == 0)
                {
                    return(top);
                }

                Filter <T> op = stack.Peek();
                if (token > op.Precidence)
                {
                    return(top);
                }

                op = stack.Pop();

                // now combine "top" and "op"
                if (op is FilterKeyword <T> )
                {
                    FilterKeyword <T> keyword = (FilterKeyword <T>)op;
                    op = Combine(keyword, top);
                }
                else if (op is FilterAnd <T> )
                {
                    FilterAnd <T> and = (FilterAnd <T>)op;
                    and.Right = Combine(and.Right, top);
                }
                else if (op is FilterOr <T> )
                {
                    FilterOr <T> or = (FilterOr <T>)op;
                    or.Right = Combine(or.Right, top);
                }
                else if (op is FilterNot <T> )
                {
                    FilterNot <T> not = (FilterNot <T>)op;
                    not.Right = Combine(not.Right, top);
                }
                else if (op is FilterParens <T> )
                {
                    FilterParens <T> parens = (FilterParens <T>)op;
                    parens.Expression = Combine(parens.Expression, top);
                }
                stack.Push(op);
            }
            return(null);
        }
Exemplo n.º 2
0
        /// <summary>
        /// This is the tokenizer, it returns a stream of tokens found in the given string.
        /// </summary>
        /// <param name="quickFilter">The string to tokenize</param>
        /// <returns></returns>
        private IEnumerable <Tuple <QuickFilterToken, string> > GetFilterTokens(string quickFilter)
        {
            StringBuilder sb = new StringBuilder();

            for (int i = 0, n = quickFilter.Length; i < n; i++)
            {
                QuickFilterToken token   = QuickFilterToken.None;
                string           literal = null;
                bool             previousCouldBeKeyword = false;
                bool             thisCouldBeKeyword     = false;

                char ch = quickFilter[i];
                if (ch == '&' || ch == '+')
                {
                    token   = QuickFilterToken.And;
                    literal = ch.ToString();
                }
                else if (ch == '"')
                {
                    int j = quickFilter.IndexOf('"', i + 1);
                    if (j > i + 1)
                    {
                        sb.Append(quickFilter.Substring(i + 1, j - i - 1));
                        i         = j;
                        token     = QuickFilterToken.Literal;
                        literal   = sb.ToString();
                        sb.Length = 0;
                        previousCouldBeKeyword = true;
                    }
                    else
                    {
                        sb.Append(ch);
                    }
                }
                else if (ch == '|') // we do not recognize "," as "or" because "," exists as a thousands separator in $amounts, so that would be ambiguous.
                {
                    token   = QuickFilterToken.Or;
                    literal = ch.ToString();
                }
                else if (ch == '!')
                {
                    token   = QuickFilterToken.Not;
                    literal = ch.ToString();
                }
                else if (ch == '(')
                {
                    token   = QuickFilterToken.LeftParen;
                    literal = ch.ToString();
                    previousCouldBeKeyword = true;
                }
                else if (ch == ')')
                {
                    token   = QuickFilterToken.RightParen;
                    literal = ch.ToString();
                }
                else if (Char.IsWhiteSpace(ch))
                {
                    token              = QuickFilterToken.Literal;
                    literal            = sb.ToString();
                    sb.Length          = 0;
                    thisCouldBeKeyword = true;
                }
                else
                {
                    sb.Append(ch);
                }

                if (token != QuickFilterToken.None)
                {
                    string previous = sb.ToString();
                    sb.Length = 0;

                    if (!string.IsNullOrEmpty(previous))
                    {
                        if (previousCouldBeKeyword && string.Compare(previous, "and", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            yield return(new Tuple <QuickFilterToken, string>(QuickFilterToken.And, previous));
                        }
                        else if (previousCouldBeKeyword && string.Compare(previous, "or", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            yield return(new Tuple <QuickFilterToken, string>(QuickFilterToken.Or, previous));
                        }
                        else if (previousCouldBeKeyword && string.Compare(previous, "not", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            yield return(new Tuple <QuickFilterToken, string>(QuickFilterToken.Not, previous));
                        }
                        yield return(new Tuple <QuickFilterToken, string>(QuickFilterToken.Literal, previous));
                    }

                    if (!string.IsNullOrEmpty(literal))
                    {
                        if (thisCouldBeKeyword && string.Compare(literal, "and", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            yield return(new Tuple <QuickFilterToken, string>(QuickFilterToken.And, literal));
                        }
                        else if (thisCouldBeKeyword && string.Compare(literal, "or", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            yield return(new Tuple <QuickFilterToken, string>(QuickFilterToken.Or, literal));
                        }
                        else if (thisCouldBeKeyword && string.Compare(literal, "not", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            yield return(new Tuple <QuickFilterToken, string>(QuickFilterToken.Not, literal));
                        }
                        else
                        {
                            yield return(new Tuple <QuickFilterToken, string>(token, literal));
                        }
                    }
                }
            }

            if (sb.Length > 0)
            {
                yield return(new Tuple <QuickFilterToken, string>(QuickFilterToken.Literal, sb.ToString()));
            }
        }