// // Mixins // // // A Mixin call, with an optional argument list // // #mixins > .square(#fff); // .rounded(4px, black); // .button; // // The `while` loop is there because mixins can be // namespaced, but we only support the child and descendant // selector for now. // public MixinCall MixinCall(Parser parser) { var elements = new NodeList <Element>(); var index = parser.Tokenizer.Location.Index; RegexMatchResult e; Combinator c = null; PushComments(); for (var i = parser.Tokenizer.Location.Index; e = parser.Tokenizer.Match(@"[#.][a-zA-Z0-9_-]+"); i = parser.Tokenizer.Location.Index) { elements.Add(NodeProvider.Element(c, e.Value, i)); i = parser.Tokenizer.Location.Index; var match = parser.Tokenizer.Match('>'); c = match != null?NodeProvider.Combinator(match.Value, i) : null; } var args = new List <NamedArgument>(); if (parser.Tokenizer.Match('(')) { Expression arg; while (arg = Expression(parser)) { var value = arg; string name = null; if (arg.Value.Count == 1 && arg.Value[0] is Variable) { if (parser.Tokenizer.Match(':')) { if (value = Expression(parser)) { name = (arg.Value[0] as Variable).Name; } else { throw new ParsingException("Expected value", parser.Tokenizer.Location.Index); } } } args.Add(new NamedArgument { Name = name, Value = value }); if (!parser.Tokenizer.Match(',')) { break; } } if (!parser.Tokenizer.Match(')')) { throw new ParsingException("Expected ')'", parser.Tokenizer.Location.Index); } } if (elements.Count > 0) { // if elements then we've picked up chars so don't need to worry about remembering var postComments = GatherAndPullComments(parser); if (End(parser)) { var mixinCall = NodeProvider.MixinCall(elements, args, index); mixinCall.PostComments = postComments; PopComments(); return(mixinCall); } } PopComments(); return(null); }