Example #1
0
        static void SetCurrentSelector(ref Selector root, ref Selector workingRoot, ref Operator workingRootParent, Operator op, Selector sel)
        {
            var updateRoot = root == workingRoot;

            op.Left     = workingRoot;
            op.Right    = sel;
            workingRoot = op;
            if (workingRootParent != null)
            {
                workingRootParent.Right = workingRoot;
            }

            if (updateRoot)
            {
                root = workingRoot;
            }

            if (workingRoot is Or)
            {
                workingRootParent = (Operator)workingRoot;
                workingRoot       = sel;
            }
        }
Example #2
0
        public static Selector Parse(CssReader reader, char stopChar = '\0')
        {
            Selector root = All, workingRoot = All;
            Operator workingRootParent = null;
            Action <Operator, Selector> setCurrentSelector = (op, sel) => SetCurrentSelector(ref root, ref workingRoot, ref workingRootParent, op, sel);

            int p;

            reader.SkipWhiteSpaces();
            while ((p = reader.Peek()) > 0)
            {
                switch (unchecked ((char)p))
                {
                case '*':
                    setCurrentSelector(new And(), All);
                    reader.Read();
                    break;

                case '.':
                    reader.Read();
                    var className = reader.ReadIdent();
                    if (className == null)
                    {
                        return(Invalid);
                    }
                    setCurrentSelector(new And(), new Class(className));
                    break;

                case '#':
                    reader.Read();
                    var id = reader.ReadName();
                    if (id == null)
                    {
                        return(Invalid);
                    }
                    setCurrentSelector(new And(), new Id(id));
                    break;

                case '[':
                    throw new NotImplementedException("Attributes not implemented");

                case ',':
                    reader.Read();
                    setCurrentSelector(new Or(), All);
                    reader.SkipWhiteSpaces();
                    break;

                case '+':
                    reader.Read();
                    setCurrentSelector(new Adjacent(), All);
                    reader.SkipWhiteSpaces();
                    break;

                case '~':
                    reader.Read();
                    setCurrentSelector(new Sibling(), All);
                    reader.SkipWhiteSpaces();
                    break;

                case '>':
                    reader.Read();
                    setCurrentSelector(new Child(), All);
                    reader.SkipWhiteSpaces();
                    break;

                case '^':                                               //not in CSS spec
                    reader.Read();
                    var element = reader.ReadIdent();
                    if (element == null)
                    {
                        return(Invalid);
                    }
                    setCurrentSelector(new And(), new Base(element));
                    break;

                case ' ':
                case '\t':
                case '\n':
                case '\r':
                case '\f':
                    reader.Read();
                    bool processWs = false;
                    while ((p = reader.Peek()) > 0)
                    {
                        var c = unchecked ((char)p);
                        if (char.IsWhiteSpace(c))
                        {
                            reader.Read();
                            continue;
                        }
                        processWs = (c != '+' &&
                                     c != '>' &&
                                     c != ',' &&
                                     c != '~' &&
                                     c != stopChar);
                        break;
                    }
                    if (!processWs)
                    {
                        break;
                    }
                    setCurrentSelector(new Descendent(), All);
                    reader.SkipWhiteSpaces();
                    break;

                default:
                    if (unchecked ((char)p) == stopChar)
                    {
                        return(root);
                    }

                    var elementName = reader.ReadIdent();
                    if (elementName == null)
                    {
                        return(Invalid);
                    }
                    setCurrentSelector(new And(), new Element(elementName));
                    break;
                }
            }
            return(root);
        }