Пример #1
0
        //
        // 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);
        }
Пример #2
0
        //
        // 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);
        }