Esempio n. 1
0
        public async Task <MorestachioDocumentResult> CreateAsync([NotNull] object data, CancellationToken token)
        {
            if (Errors.Any())
            {
                throw new AggregateException("You cannot Create this Template as there are one or more Errors. See Inner Exception for more infos.", Errors.Select(e => e.GetException())).Flatten();
            }

            var timeoutCancellation = new CancellationTokenSource();

            if (ParserOptions.Timeout != TimeSpan.Zero)
            {
                timeoutCancellation.CancelAfter(ParserOptions.Timeout);
                var anyCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(token, timeoutCancellation.Token);
                token = anyCancellationToken.Token;
            }
            var sourceStream = ParserOptions.SourceFactory();

            try
            {
                if (sourceStream == null)
                {
                    throw new NullReferenceException("The created stream is null.");
                }

                if (!sourceStream.CanWrite)
                {
                    throw new InvalidOperationException($"The stream '{sourceStream.GetType()}' is ReadOnly.");
                }

                using (var byteCounterStream = new ByteCounterStream(sourceStream,
                                                                     ParserOptions.Encoding, BufferSize, true))
                {
                    var context = new ContextObject(ParserOptions, "", null)
                    {
                        Value             = data,
                        CancellationToken = token
                    };

                    await MorestachioDocument.ProcessItemsAndChildren(new[] { Document }, byteCounterStream,
                                                                      context, new ScopeData());
                }

                if (timeoutCancellation.IsCancellationRequested)
                {
                    sourceStream.Dispose();
                    throw new TimeoutException($"The requested timeout of '{ParserOptions.Timeout:g}' for report generation was reached.");
                }
            }
            catch (Exception ex)
            {
                //If there is any exception while generating the template we must dispose any data written to the stream as it will never returned and might
                //create a memory leak with this. This is also true for a timeout
                sourceStream?.Dispose();
                throw;
            }
            return(new MorestachioDocumentResult()
            {
                Stream = sourceStream
            });
        }
Esempio n. 2
0
        public async MorestachioDocumentResultPromise CreateAsync(object data, CancellationToken token)
        {
            if (Errors.Any())
            {
                throw new AggregateException("You cannot Create this Template as there are one or more Errors. See Inner Exception for more infos.", Errors.Select(e => e.GetException())).Flatten();
            }

            if (Document is MorestachioDocument morestachioDocument && morestachioDocument.MorestachioVersion !=
                MorestachioDocument.GetMorestachioVersion())
            {
                throw new InvalidOperationException($"The supplied version in the Morestachio document " +
                                                    $"'{morestachioDocument.MorestachioVersion}'" +
                                                    $" is not compatible with the current morestachio version of " +
                                                    $"'{MorestachioDocument.GetMorestachioVersion()}'");
            }

            return(await CreateRenderer().RenderAsync(data, token));
        }
Esempio n. 3
0
        public CompilationResult Compile()
        {
            if (Errors.Any())
            {
                throw new AggregateException("You cannot Create this Template as there are one or more Errors. See Inner Exception for more infos.", Errors.Select(e => e.GetException())).Flatten();
            }

            if (Document is MorestachioDocument morestachioDocument && morestachioDocument.MorestachioVersion !=
                MorestachioDocument.GetMorestachioVersion())
            {
                throw new InvalidOperationException($"The supplied version in the Morestachio document " +
                                                    $"'{morestachioDocument.MorestachioVersion}'" +
                                                    $" is not compatible with the current morestachio version of " +
                                                    $"'{MorestachioDocument.GetMorestachioVersion()}'");
            }

            var compiledRenderer = new CompiledRenderer(Document, ParserOptions, CaptureVariables, new DocumentCompiler());

            compiledRenderer.PreCompile();
            return(async(data, token) => await compiledRenderer.RenderAsync(data, token));
        }
Esempio n. 4
0
        /// <summary>
        ///		Parses the Tokens into a Document.
        /// </summary>
        /// <param name="tokens">The tokens.</param>
        /// <param name="options">The options.</param>
        /// <returns></returns>
        internal static IDocumentItem Parse(Queue <TokenPair> tokens, ParserOptions options)
        {
            var buildStack = new Stack <FormattingScope>();

            //instead of recursive calling the parse function we stack the current document
            buildStack.Push(new FormattingScope(new MorestachioDocument(), false));

            while (tokens.Any())
            {
                var currentToken        = tokens.Dequeue();
                var currentDocumentItem = buildStack.Peek();                 //get the latest document

                if (currentToken.Type == TokenType.Comment)
                {
                    //just ignore this part and print nothing
                }
                else if (currentToken.Type == TokenType.Content)
                {
                    currentDocumentItem.Item1.Add(new ContentDocumentItem(currentToken.Value)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    });
                }
                else if (currentToken.Type == TokenType.CollectionOpen)
                {
                    var nestedDocument = new CollectionDocumentItem(currentToken.Value)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new FormattingScope(nestedDocument, false));
                    currentDocumentItem.Item1.Add(nestedDocument);
                }
                else if (currentToken.Type == TokenType.ElementOpen)
                {
                    var nestedDocument = new ExpressionScopeDocumentItem(currentToken.Value)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new FormattingScope(nestedDocument, false));
                    currentDocumentItem.Item1.Add(nestedDocument);
                }
                else if (currentToken.Type == TokenType.InvertedElementOpen)
                {
                    var invertedScope = new InvertedExpressionScopeDocumentItem(currentToken.Value)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new FormattingScope(invertedScope, false));
                    currentDocumentItem.Item1.Add(invertedScope);
                }
                else if (currentToken.Type == TokenType.CollectionClose || currentToken.Type == TokenType.ElementClose)
                {
                    // remove the last document from the stack and go back to the parents
                    buildStack.Pop();
                    if (buildStack.Peek().Item2)                     //is the remaining scope a formatting one. If it is pop it and return to its parent
                    {
                        buildStack.Pop();
                    }
                }
                else if (currentToken.Type == TokenType.PrintFormatted)
                {
                    currentDocumentItem.Item1.Add(new PrintFormattedItem());
                    buildStack.Pop();                     //Print formatted can only be followed by a Format and if not the parser should have not emited it
                }
                else if (currentToken.Type == TokenType.Format)
                {
                    if (buildStack.Peek().Item2)
                    {
                        buildStack.Pop();
                    }
                    var formatterItem = new IsolatedContextDocumentItem()
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new FormattingScope(formatterItem, true));
                    formatterItem.Add(new CallFormatterDocumentItem(currentToken.FormatString, currentToken.Value));
                    currentDocumentItem.Item1.Add(formatterItem);
                }
                else if (currentToken.Type == TokenType.EscapedSingleValue ||
                         currentToken.Type == TokenType.UnescapedSingleValue)
                {
                    currentDocumentItem.Item1.Add(new PathDocumentItem(currentToken.Value,
                                                                       currentToken.Type == TokenType.EscapedSingleValue)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    });
                }
                else if (currentToken.Type == 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
                    var nestedDocument = new MorestachioDocument();
                    buildStack.Push(new FormattingScope(nestedDocument, false));
                    currentDocumentItem.Item1.Add(new PartialDocumentItem(currentToken.Value, nestedDocument)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    });
                }
                else if (currentToken.Type == TokenType.PartialDeclarationClose)
                {
                    currentDocumentItem.Item1.Add(new RenderPartialDoneDocumentItem(currentToken.Value)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    });
                    buildStack.Pop();
                }
                else if (currentToken.Type == TokenType.RenderPartial)
                {
                    currentDocumentItem.Item1.Add(new RenderPartialDocumentItem(currentToken.Value)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    });
                }
            }

            if (buildStack.Count != 1)
            {
                //var invalidScopedElements = buildStack
                //throw new MorestachioSyntaxError(new Tokenizer.CharacterLocation(){Character = }, );
                throw new InvalidOperationException("There is an Error with the Parser. The Parser still contains unscoped builds: " + buildStack.Select(e => e.Item1.Kind).Aggregate((e, f) => e + ", " + f));
            }

            return(buildStack.Pop().Item1);
        }
Esempio n. 5
0
        /// <summary>
        ///     Parses the Tokens into a Document.
        /// </summary>
        /// <param name="tokenizerResult">The result of an Tokenizer.Tokenize call.</param>
        /// <param name="options">The ParserOptions</param>
        /// <returns></returns>
        public static IDocumentItem Parse(TokenizerResult tokenizerResult, ParserOptions options)
        {
            var buildStack = new Stack <DocumentScope>();
            //this is the scope id that determines a scope that is using let or alias variables
            int variableScope = 1;
            var getScope      = new Func <int>(() => variableScope++);

            //instead of recursive calling the parse function we stack the current document
            buildStack.Push(new DocumentScope(new MorestachioDocument(), () => 0));

            DocumentScope GetVariabeScope()
            {
                return(buildStack.FirstOrDefault(e => e.VariableScopeNumber != -1));
            }

            foreach (var currentToken in tokenizerResult.Tokens)
            {
                var currentDocumentItem = buildStack.Peek();                 //get the latest document

                if (currentToken.Type.Equals(TokenType.Content))
                {
                    currentDocumentItem.Document.Add(new ContentDocumentItem(currentToken.Value)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    });
                }
                else if (currentToken.Type.Equals(TokenType.If))
                {
                    var nestedDocument = new IfExpressionScopeDocumentItem(currentToken.MorestachioExpression)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new DocumentScope(nestedDocument, getScope));
                    currentDocumentItem.Document.Add(nestedDocument);
                }
                else if (currentToken.Type.Equals(TokenType.IfNot))
                {
                    var nestedDocument = new IfNotExpressionScopeDocumentItem(currentToken.MorestachioExpression)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new DocumentScope(nestedDocument, getScope));
                    currentDocumentItem.Document.Add(nestedDocument);
                }
                else if (currentToken.Type.Equals(TokenType.Else))
                {
                    var nestedDocument = new ElseExpressionScopeDocumentItem()
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new DocumentScope(nestedDocument, getScope));
                    currentDocumentItem.Document.Add(nestedDocument);
                }
                else if (currentToken.Type.Equals(TokenType.CollectionOpen))
                {
                    var nestedDocument = new EachDocumentItem(currentToken.MorestachioExpression)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new DocumentScope(nestedDocument, getScope));
                    currentDocumentItem.Document.Add(nestedDocument);
                }
                else if (currentToken.Type.Equals(TokenType.WhileLoopOpen))
                {
                    var nestedDocument = new WhileLoopDocumentItem(currentToken.MorestachioExpression)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new DocumentScope(nestedDocument, getScope));
                    currentDocumentItem.Document.Add(nestedDocument);
                }
                else if (currentToken.Type.Equals(TokenType.DoLoopOpen))
                {
                    var nestedDocument = new DoLoopDocumentItem(currentToken.MorestachioExpression)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new DocumentScope(nestedDocument, getScope));
                    currentDocumentItem.Document.Add(nestedDocument);
                }
                else if (currentToken.Type.Equals(TokenType.ElementOpen))
                {
                    var nestedDocument = new ExpressionScopeDocumentItem(currentToken.MorestachioExpression)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new DocumentScope(nestedDocument, getScope));
                    currentDocumentItem.Document.Add(nestedDocument);
                }
                else if (currentToken.Type.Equals(TokenType.RepeatLoopOpen))
                {
                    var nestedDocument = new RepeatDocumentItem(currentToken.MorestachioExpression)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new DocumentScope(nestedDocument, getScope));
                    currentDocumentItem.Document.Add(nestedDocument);
                }
                else if (currentToken.Type.Equals(TokenType.InvertedElementOpen))
                {
                    var invertedScope = new InvertedExpressionScopeDocumentItem(currentToken.MorestachioExpression)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new DocumentScope(invertedScope, getScope));
                    currentDocumentItem.Document.Add(invertedScope);
                }
                else if (currentToken.Type.Equals(TokenType.CollectionClose) ||
                         currentToken.Type.Equals(TokenType.ElementClose) ||
                         currentToken.Type.Equals(TokenType.IfClose) ||
                         currentToken.Type.Equals(TokenType.ElseClose) ||
                         currentToken.Type.Equals(TokenType.WhileLoopClose) ||
                         currentToken.Type.Equals(TokenType.DoLoopClose) ||
                         currentToken.Type.Equals(TokenType.RepeatLoopClose))
                {
                    DocumentScope scope = buildStack.Peek();
                    if (scope.HasAlias)                     //are we in a alias then remove it
                    {
                        foreach (var scopeLocalVariable in scope.LocalVariables)
                        {
                            currentDocumentItem.Document.Add(new RemoveAliasDocumentItem(scopeLocalVariable, scope.VariableScopeNumber));
                        }
                    }
                    // remove the last document from the stack and go back to the parents
                    buildStack.Pop();
                }
                else if (currentToken.Type.Equals(TokenType.EscapedSingleValue) ||
                         currentToken.Type.Equals(TokenType.UnescapedSingleValue))
                {
                    currentDocumentItem.Document.Add(new PathDocumentItem(currentToken.MorestachioExpression,
                                                                          currentToken.Type.Equals(TokenType.EscapedSingleValue))
                    {
                        ExpressionStart = currentToken.TokenLocation
                    });
                }
                else if (currentToken.Type.Equals(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
                    var nestedDocument = new MorestachioDocument();
                    buildStack.Push(new DocumentScope(nestedDocument, getScope));
                    currentDocumentItem.Document.Add(new PartialDocumentItem(currentToken.Value, nestedDocument)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    });
                }
                else if (currentToken.Type.Equals(TokenType.PartialDeclarationClose))
                {
                    buildStack.Pop();
                }
                else if (currentToken.Type.Equals(TokenType.RenderPartial))
                {
                    currentDocumentItem.Document.Add(new RenderPartialDocumentItem(currentToken.Value, currentToken.MorestachioExpression)
                    {
                        ExpressionStart = currentToken.TokenLocation,
                    });
                }
                else if (currentToken.Type.Equals(TokenType.Alias))
                {
                    var scope             = GetVariabeScope();
                    var aliasDocumentItem = new AliasDocumentItem(currentToken.Value, scope.VariableScopeNumber)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    currentDocumentItem.Document.Add(aliasDocumentItem);
                    currentDocumentItem.LocalVariables.Add(currentToken.Value);
                }
                else if (currentToken.Type.Equals(TokenType.VariableVar))
                {
                    var evaluateVariableDocumentItem = new EvaluateVariableDocumentItem(currentToken.Value,
                                                                                        currentToken.MorestachioExpression);
                    currentDocumentItem.Document.Add(evaluateVariableDocumentItem);
                }
                else if (currentToken.Type.Equals(TokenType.WriteLineBreak))
                {
                    currentDocumentItem.Document.Add(new TextEditDocumentItem(new AppendLineBreakTextOperation()));
                }
                else if (currentToken.Type.Equals(TokenType.TrimLineBreak))
                {
                    currentDocumentItem.Document.Add(new TextEditDocumentItem(new TrimLineBreakTextOperation()
                    {
                        LineBreaks = 1
                    }));
                }
                else if (currentToken.Type.Equals(TokenType.TrimLineBreaks))
                {
                    currentDocumentItem.Document.Add(new TextEditDocumentItem(new TrimLineBreakTextOperation()
                    {
                        LineBreaks = -1
                    }));
                }
                else if (currentToken.Type.Equals(TokenType.TrimEverything))
                {
                    currentDocumentItem.Document.Add(new TextEditDocumentItem(new TrimAllWhitespacesTextOperation()));
                }
                else if (currentToken.Type.Equals(TokenType.VariableLet))
                {
                    var scope = 0;
                    if (buildStack.Count > 1)
                    {
                        scope = GetVariabeScope()
                                .VariableScopeNumber;
                    }
                    var evaluateVariableDocumentItem = new EvaluateVariableDocumentItem(currentToken.Value,
                                                                                        currentToken.MorestachioExpression, scope);
                    currentDocumentItem.Document.Add(evaluateVariableDocumentItem);
                    if (buildStack.Count > 1)
                    {
                        currentDocumentItem.LocalVariables.Add(currentToken.Value);
                    }
                }
                else if (currentToken.Type.Equals(TokenType.Comment) || currentToken.Type.Equals(TokenType.BlockComment))
                {
                    //just ignore this part and print nothing
                }
                else
                {
                    var customDocumentItemProvider =
                        options.CustomDocumentItemProviders.FirstOrDefault(e => e.ShouldParse(currentToken, options));
                    var documentItem = customDocumentItemProvider?.Parse(currentToken, options, buildStack, getScope);
                    if (documentItem != null)
                    {
                        currentDocumentItem.Document.Add(documentItem);
                    }
                }
            }

            if (buildStack.Count != 1)
            {
                //var invalidScopedElements = buildStack
                //throw new MorestachioSyntaxError(new Tokenizer.CharacterLocation(){Character = }, );
                throw new InvalidOperationException(
                          "There is an Error with the Parser. The Parser still contains unscoped builds: " +
                          buildStack.Select(e => e.Document.GetType().Name).Aggregate((e, f) => e + ", " + f));
            }

            return(buildStack.Pop().Document);
        }
Esempio n. 6
0
        /// <summary>
        ///     Parses the Tokens into a Document.
        /// </summary>
        /// <param name="tokens">The tokens.</param>
        /// <returns></returns>
        internal static IDocumentItem Parse(Queue <TokenPair> tokens, ParserOptions options)
        {
            var buildStack = new Stack <DocumentScope>();

            //instead of recursive calling the parse function we stack the current document
            buildStack.Push(new DocumentScope(new MorestachioDocument()));

            while (tokens.Any())
            {
                var currentToken        = tokens.Dequeue();
                var currentDocumentItem = buildStack.Peek();                 //get the latest document

                if (currentToken.Type.Equals(TokenType.Comment))
                {
                    //just ignore this part and print nothing
                }
                else if (currentToken.Type.Equals(TokenType.Content))
                {
                    currentDocumentItem.Document.Add(new ContentDocumentItem(currentToken.Value)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    });
                }
                else if (currentToken.Type.Equals(TokenType.If))
                {
                    var nestedDocument = new IfExpressionScopeDocumentItem(currentToken.MorestachioExpression)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new DocumentScope(nestedDocument));
                    currentDocumentItem.Document.Add(nestedDocument);
                }
                else if (currentToken.Type.Equals(TokenType.IfNot))
                {
                    var nestedDocument = new IfNotExpressionScopeDocumentItem(currentToken.MorestachioExpression)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new DocumentScope(nestedDocument));
                    currentDocumentItem.Document.Add(nestedDocument);
                }
                else if (currentToken.Type.Equals(TokenType.Else))
                {
                    var nestedDocument = new ElseExpressionScopeDocumentItem()
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new DocumentScope(nestedDocument));
                    currentDocumentItem.Document.Add(nestedDocument);
                }
                else if (currentToken.Type.Equals(TokenType.CollectionOpen))
                {
                    var nestedDocument = new EachDocumentItem(currentToken.MorestachioExpression)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new DocumentScope(nestedDocument));
                    currentDocumentItem.Document.Add(nestedDocument);
                }
                else if (currentToken.Type.Equals(TokenType.WhileLoopOpen))
                {
                    var nestedDocument = new WhileLoopDocumentItem(currentToken.MorestachioExpression)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new DocumentScope(nestedDocument));
                    currentDocumentItem.Document.Add(nestedDocument);
                }
                else if (currentToken.Type.Equals(TokenType.DoLoopOpen))
                {
                    var nestedDocument = new DoLoopDocumentItem(currentToken.MorestachioExpression)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new DocumentScope(nestedDocument));
                    currentDocumentItem.Document.Add(nestedDocument);
                }
                else if (currentToken.Type.Equals(TokenType.ElementOpen))
                {
                    var nestedDocument = new ExpressionScopeDocumentItem(currentToken.MorestachioExpression)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new DocumentScope(nestedDocument));
                    currentDocumentItem.Document.Add(nestedDocument);
                }
                else if (currentToken.Type.Equals(TokenType.InvertedElementOpen))
                {
                    var invertedScope = new InvertedExpressionScopeDocumentItem(currentToken.MorestachioExpression)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    buildStack.Push(new DocumentScope(invertedScope));
                    currentDocumentItem.Document.Add(invertedScope);
                }
                else if (currentToken.Type.Equals(TokenType.CollectionClose) ||
                         currentToken.Type.Equals(TokenType.ElementClose) ||
                         currentToken.Type.Equals(TokenType.IfClose) ||
                         currentToken.Type.Equals(TokenType.ElseClose) ||
                         currentToken.Type.Equals(TokenType.WhileLoopClose) ||
                         currentToken.Type.Equals(TokenType.DoLoopClose))
                {
                    if (buildStack.Peek().HasAlias)                     //are we in a alias then remove it
                    {
                        currentDocumentItem.Document.Add(new RemoveAliasDocumentItem(buildStack.Peek().AliasName));
                        buildStack.Pop();
                    }
                    // remove the last document from the stack and go back to the parents
                    buildStack.Pop();
                }
                else if (currentToken.Type.Equals(TokenType.EscapedSingleValue) ||
                         currentToken.Type.Equals(TokenType.UnescapedSingleValue))
                {
                    currentDocumentItem.Document.Add(new PathDocumentItem(currentToken.MorestachioExpression,
                                                                          currentToken.Type.Equals(TokenType.EscapedSingleValue))
                    {
                        ExpressionStart = currentToken.TokenLocation
                    });
                }
                else if (currentToken.Type.Equals(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
                    var nestedDocument = new MorestachioDocument();
                    buildStack.Push(new DocumentScope(nestedDocument));
                    currentDocumentItem.Document.Add(new PartialDocumentItem(currentToken.Value, nestedDocument)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    });
                }
                else if (currentToken.Type.Equals(TokenType.PartialDeclarationClose))
                {
                    currentDocumentItem.Document.Add(new RenderPartialDoneDocumentItem(currentToken.Value)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    });
                    buildStack.Pop();
                }
                else if (currentToken.Type.Equals(TokenType.RenderPartial))
                {
                    currentDocumentItem.Document.Add(new RenderPartialDocumentItem(currentToken.Value)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    });
                }
                else if (currentToken.Type.Equals(TokenType.Alias))
                {
                    var aliasDocumentItem = new AliasDocumentItem(currentToken.Value)
                    {
                        ExpressionStart = currentToken.TokenLocation
                    };
                    currentDocumentItem.Document.Add(aliasDocumentItem);
                    buildStack.Push(new DocumentScope(aliasDocumentItem, currentToken.Value));
                }
                else if (currentToken.Type.Equals(TokenType.VariableDeclaration))
                {
                    var evaluateVariableDocumentItem = new EvaluateVariableDocumentItem(currentToken.Value, currentToken.MorestachioExpression);
                    currentDocumentItem.Document.Add(evaluateVariableDocumentItem);
                }
                else
                {
                    var customDocumentItemProvider =
                        options.CustomDocumentItemProviders.FirstOrDefault(e => e.ShouldParse(currentToken, options));
                    if (customDocumentItemProvider != null)
                    {
                        var documentItem = customDocumentItemProvider.Parse(currentToken, options, buildStack);
                        currentDocumentItem.Document.Add(documentItem);
                    }
                }
            }

            if (buildStack.Count != 1)
            {
                //var invalidScopedElements = buildStack
                //throw new MorestachioSyntaxError(new Tokenizer.CharacterLocation(){Character = }, );
                throw new InvalidOperationException(
                          "There is an Error with the Parser. The Parser still contains unscoped builds: " +
                          buildStack.Select(e => e.Document.Kind).Aggregate((e, f) => e + ", " + f));
            }

            return(buildStack.Pop().Document);
        }
        public async MorestachioDocumentResultPromise CreateAsync([NotNull] object data, CancellationToken token)
        {
            if (Errors.Any())
            {
                throw new AggregateException("You cannot Create this Template as there are one or more Errors. See Inner Exception for more infos.", Errors.Select(e => e.GetException())).Flatten();
            }

            if (Document is MorestachioDocument morestachioDocument && morestachioDocument.MorestachioVersion !=
                MorestachioDocument.GetMorestachioVersion())
            {
                throw new InvalidOperationException($"The supplied version in the Morestachio document " +
                                                    $"'{morestachioDocument.MorestachioVersion}'" +
                                                    $" is not compatible with the current morestachio version of " +
                                                    $"'{MorestachioDocument.GetMorestachioVersion()}'");
            }

            var timeoutCancellation = new CancellationTokenSource();

            if (ParserOptions.Timeout != TimeSpan.Zero)
            {
                timeoutCancellation.CancelAfter(ParserOptions.Timeout);
                var anyCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(token, timeoutCancellation.Token);
                token = anyCancellationToken.Token;
            }

            PerformanceProfiler profiler = null;

            using (var byteCounterStream = ParserOptions.StreamFactory.GetByteCounterStream(ParserOptions))
            {
                if (byteCounterStream?.Stream == null)
                {
                    throw new NullReferenceException("The created stream is null.");
                }
                var context   = ParserOptions.CreateContextObject("", token, data);
                var scopeData = new ScopeData();
                try
                {
                    if (ParserOptions.ProfileExecution)
                    {
                        scopeData.Profiler = profiler = new PerformanceProfiler(true);
                    }
                    await MorestachioDocument.ProcessItemsAndChildren(new[] { Document }, byteCounterStream,
                                                                      context, scopeData);

                    if (timeoutCancellation.IsCancellationRequested)
                    {
                        throw new TimeoutException($"The requested timeout of '{ParserOptions.Timeout:g}' for template generation was reached.");
                    }
                }
                finally
                {
                    if (!CaptureVariables)
                    {
                        scopeData.Dispose();
                        scopeData.Variables.Clear();
                    }
                }

                return(new MorestachioDocumentResult(byteCounterStream.Stream,
                                                     profiler,
                                                     scopeData.Variables.ToDictionary(e => e.Key, e => scopeData.GetFromVariable(e.Value).Value)));
            }
        }