コード例 #1
0
        public Template Compile(string source)
        {
            Stack <CompilerContext> stack = new Stack <CompilerContext> ();
            Tokenizer tokenizer           = new Tokenizer(source);
            Template  template            = new Template(InternalTags [@"template"]);

            CompilerContext context = new CompilerContext
            {
                CurrentElement    = template,
                InConditionalPath = false
            };

            bool   inPartial      = false;
            string currentPartial = String.Empty;

            foreach (var token in tokenizer.Tokens.Where(token => !token.IsEmpty))
            {
                if (token.Type == TokenTypes.StaticText)
                {
                    // Static content.
                    context.AddStatement(new StaticElement(token.Data, InternalTags [@"static"]));
                }
                else
                {
                    // A moustache ...
                    if (token.Subtype == TokenSubtypes.BeginTag)
                    {
                        // A begin tag can be a conditional separator (#if -> #else).
                        bool isConditionalPath = false;
                        ITag tag = GetBestTag(token.TagName, out isConditionalPath);

                        if (isConditionalPath)
                        {
                            if (context.Tag == tag)
                            {
                                // We're switching to the conditional brach.
                                context.InConditionalPath = true;
                            }
                            else
                            {
                                throw new Exception(@"Syntax error. Unexpected conditional branch.");
                            }
                        }
                        else
                        {
                            // We're creating a new element.
                            IRenderable statement = InstantiateTag(tag, token.Arguments);

                            if (tag is IInlineTag)
                            {
                                context.AddStatement(statement);
                            }
                            else
                            {
                                stack.Push(context);
                                context = new CompilerContext
                                {
                                    CurrentElement    = statement,
                                    InConditionalPath = false
                                };
                            }
                        }
                    }
                    else if (token.Subtype == TokenSubtypes.EndTag)
                    {
                        if (inPartial && token.TagName == currentPartial)
                        {
                            var element = context.CurrentElement as BlockElement;
                            context = stack.Pop();

                            template.Partials.Add(currentPartial, element);

                            inPartial      = false;
                            currentPartial = String.Empty;
                        }
                        else
                        {
                            // We're closing a tag.
                            bool isConditionalPath = false;
                            ITag tag = GetBestTag(token.TagName, out isConditionalPath);

                            // It can't be a conditional branch.
                            if (isConditionalPath)
                            {
                                throw new Exception(@"Syntax error. Unexpected conditional branch.");
                            }

                            if (context.Tag == tag)
                            {
                                var element = context.CurrentElement;
                                context = stack.Pop();

                                context.AddStatement(element);
                            }
                            else
                            {
                                throw new Exception(@"Syntax error. Unexpected ending tag.");
                            }
                        }
                    }
                    else if (token.Subtype == TokenSubtypes.DeclarePartialTag)
                    {
                        if (inPartial)
                        {
                            throw new Exception(@"Syntax error. Nested partials are not allowed.");
                        }

                        stack.Push(context);
                        context = new CompilerContext
                        {
                            CurrentElement    = new Template(InternalTags [@"template"]),
                            InConditionalPath = false
                        };

                        currentPartial = token.TagName;
                        inPartial      = true;
                    }
                    else if (token.Subtype == TokenSubtypes.RenderPartialTag)
                    {
                        context.AddStatement(InstantiateTag(InternalTags [@"renderpartial"], token.Arguments.Prepend("partial", new StringArgument(token.TagName))));
                    }
                    else if (token.Subtype == TokenSubtypes.Variable)
                    {
                        context.AddStatement(new VariableElement(InternalTags [@"variable"], token.Type == TokenTypes.DoubleMustache)
                        {
                            Arguments = token.Arguments
                        });
                    }
                }
            }

            // Validation.
            if (stack.Count > 0 || context.Tag != InternalTags [@"template"])
            {
                throw new Exception(@"Syntax error. Unexpected end of template.");
            }

            return(template);
        }