public void MakeAction(AsyncParserAction syncAction) { Elements.Add(syncAction); }
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); }); }