// // A Mixin definition, with a list of parameters // // .rounded (@radius: 2px, @color) { // ... // } // // Until we have a finer grained state-machine, we have to // do a look-ahead, to make sure we don't have a mixin call. // See the `rule` function for more information. // // We start by matching `.rounded (`, and then proceed on to // the argument list, which has optional default values. // We store the parameters in `params`, with a `value` key, // if there is a value, such as in the case of `@radius`. // // Once we've got our params list, and a closing `)`, we parse // the `{...}` block. // public MixinDefinition MixinDefinition(Parser parser) { if ((parser.Tokenizer.CurrentChar != '.' && parser.Tokenizer.CurrentChar != '#') || parser.Tokenizer.Peek(@"[^{]*(;|})")) { return(null); } var index = parser.Tokenizer.Location.Index; var match = parser.Tokenizer.Match(@"([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\("); if (!match) { return(null); } //mixin definition ignores comments before it - a css hack can't be part of a mixin definition, //so it may as well be a rule before the definition PushComments(); GatherAndPullComments(parser); // no store as mixin definition not output var name = match[1]; var parameters = new NodeList <Rule>(); RegexMatchResult param = null; Node param2 = null; Func <bool> matchParam = () => (param = parser.Tokenizer.Match(@"@[\w-]+")) || (param2 = Literal(parser) || Keyword(parser)); for (var i = parser.Tokenizer.Location.Index; matchParam(); i = parser.Tokenizer.Location.Index) { if (param != null) { GatherAndPullComments(parser); if (parser.Tokenizer.Match(':')) { GatherComments(parser); var value = Expression(parser); if (value) { parameters.Add(NodeProvider.Rule(param.Value, value, i)); } else { throw new ParsingException("Expected value", i); } } else { parameters.Add(NodeProvider.Rule(param.Value, null, i)); } } else { parameters.Add(NodeProvider.Rule(null, param2, i)); } GatherAndPullComments(parser); if (!parser.Tokenizer.Match(',')) { break; } GatherAndPullComments(parser); } if (!parser.Tokenizer.Match(')')) { throw new ParsingException("Expected ')'", parser.Tokenizer.Location.Index); } GatherAndPullComments(parser); var rules = Block(parser); PopComments(); if (rules != null) { return(NodeProvider.MixinDefinition(name, parameters, rules, index)); } return(null); }
// // A Mixin definition, with a list of parameters // // .rounded (@radius: 2px, @color) { // ... // } // // Until we have a finer grained state-machine, we have to // do a look-ahead, to make sure we don't have a mixin call. // See the `rule` function for more information. // // We start by matching `.rounded (`, and then proceed on to // the argument list, which has optional default values. // We store the parameters in `params`, with a `value` key, // if there is a value, such as in the case of `@radius`. // // Once we've got our params list, and a closing `)`, we parse // the `{...}` block. // public MixinDefinition MixinDefinition(Parser parser) { if (parser.Tokenizer.CurrentChar != '.' || parser.Tokenizer.Peek(@"[^{]*(;|})")) { return(null); } var index = parser.Tokenizer.Location.Index; var match = parser.Tokenizer.Match(@"([#.][a-zA-Z0-9_-]+)\s*\("); if (!match) { return(null); } var name = match[1]; var parameters = new NodeList <Rule>(); RegexMatchResult param = null; Node param2 = null; Func <bool> matchParam = () => (param = parser.Tokenizer.Match(@"@[\w-]+")) || (param2 = Literal(parser) || Keyword(parser)); for (var i = parser.Tokenizer.Location.Index; matchParam(); i = parser.Tokenizer.Location.Index) { if (param != null) { if (parser.Tokenizer.Match(':')) { var value = Expression(parser); if (value) { parameters.Add(NodeProvider.Rule(param.Value, value, i)); } else { throw new ParsingException("Expected value", i); } } else { parameters.Add(NodeProvider.Rule(param.Value, null, i)); } } else { parameters.Add(NodeProvider.Rule(null, param2, i)); } if (!parser.Tokenizer.Match(',')) { break; } } if (!parser.Tokenizer.Match(')')) { throw new ParsingException("Expected ')'", parser.Tokenizer.Location.Index); } var rules = Block(parser); if (rules != null) { return(NodeProvider.MixinDefinition(name, parameters, rules, index)); } return(null); }