Beispiel #1
0
 public void MakeAction(AsyncParserAction syncAction)
 {
     Elements.Add(syncAction);
 }
Beispiel #2
0
        internal static AsyncParserAction Parse(Queue <TokenPair> tokens, ParserOptions options, ScopeData scopeData,
                                                InferredTemplateModel currentScope = null)
        {
            var buildArray = new ParserActions();

            while (tokens.Any())
            {
                var currentToken = tokens.Dequeue();
                switch (currentToken.Type)
                {
                case TokenType.Comment:
                    break;

                case TokenType.Content:
                    buildArray.MakeAction(HandleContent(currentToken.Value));
                    break;

                case TokenType.CollectionOpen:
                    buildArray.MakeAction(HandleCollectionOpen(currentToken, tokens, options, scopeData, currentScope));
                    break;

                case TokenType.ElementOpen:
                    buildArray.MakeAction(HandleElementOpen(currentToken, tokens, options, scopeData, currentScope));
                    break;

                case TokenType.InvertedElementOpen:
                    buildArray.MakeAction(HandleInvertedElementOpen(currentToken, tokens, options, scopeData, currentScope));
                    break;

                case TokenType.CollectionClose:
                case TokenType.ElementClose:
                    // This should immediately return if we're in the element scope,
                    // -and if we're not, this should have been detected by the tokenizer!
                    return(async(builder, context) =>
                    {
                        await buildArray.ExecuteWith(builder, context);
                    });

                case TokenType.Format:
                    buildArray.MakeAction(ParseFormatting(currentToken, tokens, options, scopeData, currentScope));
                    break;

                case TokenType.EscapedSingleValue:
                case TokenType.UnescapedSingleValue:
                    buildArray.MakeAction(HandleSingleValue(currentToken, options, scopeData, currentScope));
                    break;

                case TokenType.PartialDeclarationOpen:
                    // currently same named partials will override each other
                    // to allow recursive calls of partials we first have to declare the partial and then load it as we would parse
                    // -the partial as a whole and then add it to the list would lead to unknown calls of partials inside the partial
                    AsyncParserAction handlePartialDeclaration = null;
                    scopeData.Partials[currentToken.Value] = async(outputStream, context) =>
                    {
                        if (handlePartialDeclaration != null)
                        {
                            await handlePartialDeclaration(outputStream, context);
                        }
                        else
                        {
                            throw new InvalidOperationException($"Partial '{currentToken.Value}' was executed before created was completed.");
                        }
                    };
                    handlePartialDeclaration = HandlePartialDeclaration(currentToken, tokens, options, scopeData, currentScope);
                    break;

                case TokenType.RenderPartial:
                    var partialName = currentToken.Value;
                    var partialCode = scopeData.Partials[partialName];
                    buildArray.MakeAction(async(a, f) =>
                    {
                        var currentPartial = partialName + "_" + scopeData.PartialDepth.Count;
                        scopeData.PartialDepth.Push(currentPartial);
                        if (scopeData.PartialDepth.Count >= options.PartialStackSize)
                        {
                            switch (options.StackOverflowBehavior)
                            {
                            case ParserOptions.PartialStackOverflowBehavior.FailWithException:
                                throw new MustachioStackOverflowException(
                                    $"You have exceeded the maximum stack Size for nested Partial calls of '{options.PartialStackSize}'. See Data for call stack")
                                {
                                    Data =
                                    {
                                        { "Callstack", scopeData.PartialDepth }
                                    }
                                };
                                break;

                            case ParserOptions.PartialStackOverflowBehavior.FailSilent:

                                break;

                            default:
                                throw new ArgumentOutOfRangeException();
                            }
                        }
                        else
                        {
                            await partialCode(a, f);
                        }
                        scopeData.PartialDepth.Pop();
                    });
                    break;
                }
            }

            return(async(builder, context) =>
            {
                await buildArray.ExecuteWith(builder, context);
            });
        }