예제 #1
0
 public void PushSelector(SelectorExpression expression)
 {
     if (_selectors.Count > 0) {
         var parent = _selectors.Peek();
         expression = CrossGroup(parent, expression);
     }
     _selectors.Push(expression);
 }
예제 #2
0
 private static void ExpandGroups(SelectorExpression expression, List<SelectorExpression> target)
 {
     var gr = expression as GroupCombinator;
     if (gr != null) {
         foreach (var sub in gr.Expressions) {
             ExpandGroups(sub, target);
         }
     } else {
         target.Add(expression);
     }
 }
예제 #3
0
 private static SelectorExpression CrossGroup(SelectorExpression parent, SelectorExpression child)
 {
     var parentList = ExpandGroups(parent);
     var childList = ExpandGroups(child);
     var list = new SelectorExpression[parentList.Count * childList.Count];
     var index = 0;
     foreach (var parentItem in parentList) {
         foreach (var childItem in childList) {
             list[index++] = Combinate(parentItem, childItem);
         }
     }
     if (list.Length == 1) return list[0];
     return new GroupCombinator(list);
 }
예제 #4
0
 private static List<SelectorExpression> ExpandGroups(SelectorExpression expression)
 {
     var target = new List<SelectorExpression>();
     ExpandGroups(expression, target);
     return target;
 }
예제 #5
0
 private static SelectorExpression Combinate(SelectorExpression parent, SelectorExpression child)
 {
     if (child.HasExplicitParent) return child;
     return new DescendantCombinator(parent, child);
 }
예제 #6
0
 private static SelectorExpression ParseOperand(TokensQueue tokens, SelectorExpression parent = null)
 {
     tokens.SkipWhiteAndComments();
     var token = tokens.Read();
     switch (token.Type) {
         case TokenType.Literal: return ParseTypeSelector(token, tokens);
         case TokenType.Dot: return ParseClassSelector(token, tokens);
         case TokenType.Hash: return ParseIdSelector(token, tokens);
         case TokenType.Colon: return ParsePseudoSelector(token, tokens);
         case TokenType.OpenSquareBracket: return ParseAttributeSelector(token, tokens);
         case TokenType.Ampersand: return new ParentSelector(parent);
         default:
             throw new TokenException("unexpected token " + token.StringValue, token);
     }
 }
예제 #7
0
 public static SelectorExpression Parse(TokensQueue tokens, SelectorExpression parent = null)
 {
     return ParseWithPriority(tokens, 0, parent);
 }
예제 #8
0
 private static SelectorExpression ProcessBinaryExpression(CombinatorType type, SelectorExpression left, TokensQueue tokens)
 {
     var tokenPriority = GetPriority(type);
     var other = ParseWithPriority(tokens, tokenPriority + 1);
     switch (type) {
         case CombinatorType.Combine:
             var combineCombinator = left as CombineCombinator;
             return combineCombinator != null ? combineCombinator.Add(other) : new CombineCombinator(left, other);
         case CombinatorType.Child: return new ChildCombinator(left, other);
         case CombinatorType.Sibling: return new SiblingCombinator(left, other);
         case CombinatorType.Descendant:
             var descendantCombinator = left as DescendantCombinator;
             return descendantCombinator != null ? descendantCombinator.Add(other) : new DescendantCombinator(left, other);
         case CombinatorType.Group:
             var groupCombinator = left as GroupCombinator;
             return groupCombinator != null ? groupCombinator.Add(other) : new GroupCombinator(left, other);
         default:
             throw new TokenException("unexpected operator", tokens.LastReadToken);
     }
 }
예제 #9
0
        private static SelectorExpression ParseWithPriority(TokensQueue tokens, int priority, SelectorExpression parent = null)
        {
            var left = ParseOperand(tokens, parent);
            while (!tokens.Empty) {
                tokens.SkipComments();
                var preview = tokens.Peek();
                switch (preview.Type) {
                    case TokenType.CloseParenthesis:
                    case TokenType.OpenCurlyBracket:
                        return left;
                }
                var combinatorType = PeekCombinatorType(tokens);

                var tokenPriority = GetPriority(combinatorType);
                if (tokenPriority < priority) {
                    return left;
                }
                combinatorType = ReadCombinatorType(tokens);
                if (combinatorType == CombinatorType.Stop) return left;
                left = ProcessBinaryExpression(combinatorType, left, tokens);
            }

            return left;
        }
예제 #10
0
 public static void AreEqual(SelectorExpression expected, SelectorExpression actual, string message = "")
 {
     Assert.AreEqual(expected.GetType(), actual.GetType(), message + "/Type");
     if (expected is GroupCombinator) {
         AreEqual((GroupCombinator)expected, (GroupCombinator)actual, message);
     } else if (expected is DescendantCombinator) {
         AreEqual((DescendantCombinator)expected, (DescendantCombinator)actual, message);
     } else if (expected is CombineCombinator) {
         AreEqual((CombineCombinator)expected, (CombineCombinator)actual, message);
     } else if (expected is ChildCombinator) {
         AreEqual((ChildCombinator)expected, (ChildCombinator)actual, message);
     } else if (expected is TypeSelector) {
         AreEqual((TypeSelector)expected, (TypeSelector)actual, message);
     } else if (expected is ClassSelector) {
         AreEqual((ClassSelector)expected, (ClassSelector)actual, message);
     } else if (expected is IdSelector) {
         AreEqual((IdSelector)expected, (IdSelector)actual, message);
     } else if (expected is PseudoClassSelector) {
         AreEqual((PseudoClassSelector)expected, (PseudoClassSelector)actual, message);
     } else if (expected is NotExpression) {
         AreEqual((NotExpression)expected, (NotExpression)actual, message);
     } else if (expected is AttributeSelector) {
         AreEqual((AttributeSelector)expected, (AttributeSelector)actual, message);
     } else {
         throw new AssertionException(message + "/Type: unknown expression type " + expected.GetType());
     }
 }
예제 #11
0
 public void PushRule(SelectorExpression expression)
 {
     var rule = new CssQualifiedRule { Selector = expression.Evaluate(this) };
     _scssRules.Push(expression);
     _cssRules.Push(rule);
 }