Esempio n. 1
0
        // :not(selector)
        private void Not()
        {
            tq.Consume(":not");
            string subQuery = tq.ChompBalanced('(', ')');

            if (subQuery.Length == 0)
            {
                throw DomFailure.NotSelectorSelectionCannotBeEmpty();
            }

            evals.Add(new StructuralEvaluator.Not(Parse(subQuery, _options)));
        }
Esempio n. 2
0
        // pseudo selector :has(el)
        private void Has()
        {
            tq.Consume(":has");
            string subQuery = tq.ChompBalanced('(', ')');

            // TODO Validation errors in a structured way
            if (subQuery.Length == 0)
            {
                throw DomFailure.HasSelectorCannotBeEmpty();
            }

            evals.Add(new StructuralEvaluator.Has(Parse(subQuery, _options)));
        }
Esempio n. 3
0
        public void Unwrap_cannot_unwrap_root_with_multiple_children()
        {
            DomDocument doc         = new DomDocument();
            var         e           = doc.AppendElement("t");
            var         firstChild  = e.AppendElement("u");
            var         secondChild = e.AppendElement("u");

            var ex = Record.Exception(() => e.Unwrap());

            Assert.IsInstanceOf <InvalidOperationException>(ex);
            Assert.Equal(DomFailure.CannotUnwrapWouldCreateMalformedDocument().Message,
                         ex.Message);
        }
        private Evaluator Contains(bool own, string tq)
        {
            string searchText = TokenQueue.Unescape(tq);

            if (searchText.Length == 0)
            {
                throw DomFailure.ContainsSelectorCannotBeEmpty();
            }

            if (own)
            {
                return(new Evaluator.ContainsOwnText(searchText));
            }
            return(new Evaluator.ContainsText(searchText));
        }
        private Evaluator Matches(bool own, string tq)
        {
            string regex = tq;

            if (string.IsNullOrEmpty(regex))
            {
                throw DomFailure.MatchesSelectorCannotBeEmpty();
            }

            if (own)
            {
                return(new Evaluator.MatchesOwn(new Regex(regex)));
            }
            return(new Evaluator.MatchesImpl(new Regex(regex)));
        }
Esempio n. 6
0
        public void Consume(string seq)
        {
            if (!Matches(seq))
            {
                throw DomFailure.QueueDidNotMatch();
            }

            int len = seq.Length;

            if (len > RemainingLength)
            {
                throw DomFailure.QueueNotLongEnoughToConsumeSequence();
            }

            pos += len;
        }
Esempio n. 7
0
        private void FindElements()
        {
            if (tq.MatchChomp("#"))
            {
                ById();
                return;
            }

            if (tq.MatchChomp("."))
            {
                ByClass();
                return;
            }

            if (tq.MatchesWord())
            {
                ByTag();
                return;
            }

            if (tq.Matches("["))
            {
                ByAttribute();
                return;
            }

            if (tq.MatchChomp("*"))
            {
                AllElements();
                return;
            }

            if (tq.Matches(":not("))
            {
                Not();
                return;
            }

            if (tq.Matches(":has("))
            {
                Has();
                return;
            }

            foreach (var exp in _options.Expressions)
            {
                if (!tq.Matches(exp.MatchToken))
                {
                    continue;
                }
                if (exp.HasArguments)
                {
                    tq.Consume(exp.Token);
                    string cq   = tq.ChompBalanced('(', ')');
                    var    eval = exp.CreateEvaluator(cq);
                    evals.Add(eval);
                    return;
                }
                else
                {
                    throw new NotImplementedException();
                }
            }

            // unhandled
            throw DomFailure.CouldNotParseQuery(query, tq.Remainder());
        }
Esempio n. 8
0
        private void Combinator(char combinator)
        {
            tq.ConsumeWhitespace();
            string subQuery = ConsumeSubQuery();                    // support multi > childs

            Evaluator rootEval;                                     // the new topmost evaluator
            Evaluator currentEval;                                  // the evaluator the new eval will be combined to. could be root, or rightmost or.
            Evaluator newEval          = Parse(subQuery, _options); // the evaluator to add into target evaluator
            bool      replaceRightMost = false;

            if (evals.Count == 1)
            {
                rootEval = currentEval = evals[0];
                // make sure OR (,) has precedence:
                if (rootEval is CombiningEvaluator.Or && combinator != ',')
                {
                    currentEval      = ((CombiningEvaluator.Or)currentEval).RightMostEvaluator();
                    replaceRightMost = true;
                }
            }

            else
            {
                rootEval = currentEval = new CombiningEvaluator.And(evals);
            }
            evals.Clear();

            // for most combinators: change the current eval into an AND of the current eval and the new eval
            switch (combinator)
            {
            case '>':
                currentEval = new CombiningEvaluator.And(newEval, new StructuralEvaluator.ImmediateParent(currentEval));
                break;

            case ' ':
                currentEval = new CombiningEvaluator.And(newEval, new StructuralEvaluator.Parent(currentEval));
                break;

            case '+':
                currentEval = new CombiningEvaluator.And(newEval, new StructuralEvaluator.ImmediatePreviousSibling(currentEval));
                break;

            case '~':
                currentEval = new CombiningEvaluator.And(newEval, new StructuralEvaluator.PreviousSibling(currentEval));
                break;

            case ',':     // group or.
                CombiningEvaluator.Or or = currentEval as CombiningEvaluator.Or;
                if (or != null)
                {
                    or.Add(newEval);
                }
                else
                {
                    or = new CombiningEvaluator.Or();
                    or.Add(currentEval);
                    or.Add(newEval);
                }
                currentEval = or;
                break;

            default:
                throw DomFailure.UnknownCombinator(combinator);
            }

            if (replaceRightMost)
            {
                ((CombiningEvaluator.Or)rootEval).ReplaceRightMostEvaluator(currentEval);
            }
            else
            {
                rootEval = currentEval;
            }
            evals.Add(rootEval);
        }