public void PushSelector(SelectorExpression expression) { if (_selectors.Count > 0) { var parent = _selectors.Peek(); expression = CrossGroup(parent, expression); } _selectors.Push(expression); }
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); } }
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); }
private static List<SelectorExpression> ExpandGroups(SelectorExpression expression) { var target = new List<SelectorExpression>(); ExpandGroups(expression, target); return target; }
private static SelectorExpression Combinate(SelectorExpression parent, SelectorExpression child) { if (child.HasExplicitParent) return child; return new DescendantCombinator(parent, child); }
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); } }
public static SelectorExpression Parse(TokensQueue tokens, SelectorExpression parent = null) { return ParseWithPriority(tokens, 0, parent); }
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); } }
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; }
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()); } }
public void PushRule(SelectorExpression expression) { var rule = new CssQualifiedRule { Selector = expression.Evaluate(this) }; _scssRules.Push(expression); _cssRules.Push(rule); }