public void Visit(DothtmlRootNode root)
 {
     ResolveFromParent(root);
 }
Example #2
0
        /// <summary>
        /// Parses the token stream and gets the node.
        /// </summary>
        public DothtmlRootNode Parse(IList <DothtmlToken> tokens)
        {
            Root             = null;
            Tokens           = tokens;
            CurrentIndex     = 0;
            ElementHierarchy = new Stack <DothtmlNodeWithContent>();

            // read file
            var root = new DothtmlRootNode();

            root.Tokens.AddRange(Tokens);
            ElementHierarchy.Push(root);

            // read content
            var doNotAppend = false;

            while (Peek() != null)
            {
                if (Peek().Type == DothtmlTokenType.DirectiveStart)
                {
                    // directive
                    root.Directives.Add(ReadDirective());
                    doNotAppend = true;
                }
                else if (Peek().Type == DothtmlTokenType.OpenTag)
                {
                    // element - check element hierarchy
                    var element = ReadElement();
                    if (ElementHierarchy.Any())
                    {
                        element.ParentNode = ElementHierarchy.Peek() as DothtmlElementNode;
                    }

                    if (!element.IsSelfClosingTag)
                    {
                        if (!element.IsClosingTag)
                        {
                            // open tag
                            CurrentElementContent.Add(element);
                            ElementHierarchy.Push(element);
                        }
                        else
                        {
                            // close tag
                            if (ElementHierarchy.Count <= 1)
                            {
                                element.NodeErrors.Add($"The closing tag '</{element.FullTagName}>' doesn't have a matching opening tag!");
                                CurrentElementContent.Add(element);
                            }
                            else
                            {
                                var beginTag     = (DothtmlElementNode)ElementHierarchy.Peek();
                                var beginTagName = beginTag.FullTagName;
                                if (!beginTagName.Equals(element.FullTagName, StringComparison.OrdinalIgnoreCase))
                                {
                                    element.NodeErrors.Add($"The closing tag '</{beginTagName}>' doesn't have a matching opening tag!");
                                    ResolveWrongClosingTag(element);
                                    beginTag = ElementHierarchy.Peek() as DothtmlElementNode;

                                    if (beginTag != null && beginTagName != beginTag.FullTagName)
                                    {
                                        beginTag.CorrespondingEndTag = element;
                                        ElementHierarchy.Pop();
                                    }
                                    else
                                    {
                                        CurrentElementContent.Add(element);
                                    }
                                }
                                else
                                {
                                    ElementHierarchy.Pop();
                                    beginTag.CorrespondingEndTag = element;
                                }
                            }
                        }
                    }
                    else
                    {
                        // self closing tag
                        CurrentElementContent.Add(element);
                    }
                }
                else if (Peek().Type == DothtmlTokenType.OpenBinding)
                {
                    // binding
                    CurrentElementContent.Add(ReadBinding());
                }
                else if (Peek().Type == DothtmlTokenType.OpenCData)
                {
                    CurrentElementContent.Add(ReadCData());
                }
                else if (Peek().Type == DothtmlTokenType.OpenComment)
                {
                    CurrentElementContent.Add(ReadComment());
                }
                else if (Peek().Type == DothtmlTokenType.OpenServerComment)
                {
                    // skip server-side comment
                    CurrentElementContent.Add(ReadServerComment());
                }
                else
                {
                    // text
                    if (!doNotAppend &&
                        CurrentElementContent.Count > 0 &&
                        CurrentElementContent[CurrentElementContent.Count - 1].GetType() == typeof(DothtmlLiteralNode) &&
                        !(CurrentElementContent[CurrentElementContent.Count - 1] is DotHtmlCommentNode))
                    {
                        // append to the previous literal
                        var lastLiteral = (DothtmlLiteralNode)CurrentElementContent[CurrentElementContent.Count - 1];
                        if (lastLiteral.Escape)
                        {
                            CurrentElementContent.Add(new DothtmlLiteralNode()
                            {
                                Tokens = { Peek() }, StartPosition = Peek().StartPosition
                            });
                        }
                        else
                        {
                            lastLiteral.Tokens.Add(Peek());
                        }
                    }
                    else
                    {
                        CurrentElementContent.Add(new DothtmlLiteralNode()
                        {
                            Tokens = { Peek() }, StartPosition = Peek().StartPosition
                        });
                    }
                    Read();

                    doNotAppend = false;
                }
            }

            // check element hierarchy
            if (ElementHierarchy.Count > 1)
            {
                root.NodeErrors.Add($"Unexpected end of file! The tag '<{ElementHierarchy.Peek()}>' was not closed!");
            }

            ResolveParents(root);

            Root = root;
            return(root);
        }
Example #3
0
 public void Visit(DothtmlRootNode root)
 {
     LastFoundNode = root;
 }
Example #4
0
        private void ResolveParents(DothtmlRootNode root)
        {
            var parentResolver = new ParentResolvingVisitor();

            root.Accept(parentResolver);
        }
Example #5
0
        /// <summary>
        /// Parses the token stream and gets the node.
        /// </summary>
        public DothtmlRootNode Parse(IList<DothtmlToken> tokens)
        {
            Root = null;
            Tokens = tokens;
            CurrentIndex = 0;
            ElementHierarchy = new Stack<DothtmlNodeWithContent>();

            // read file
            var root = new DothtmlRootNode();
            root.Tokens.AddRange(Tokens);
            ElementHierarchy.Push(root);
            SkipWhitespace();

            // read directives
            while (Peek() != null && Peek().Type == DothtmlTokenType.DirectiveStart)
            {
                root.Directives.Add(ReadDirective());
            }

            SkipWhitespace();

            // read content
            while (Peek() != null)
            {
                if (Peek().Type == DothtmlTokenType.OpenTag)
                {
                    // element - check element hierarchy
                    var element = ReadElement();
                    if (ElementHierarchy.Any())
                    {
                        element.ParentElement = ElementHierarchy.Peek() as DothtmlElementNode;
                    }

                    if (!element.IsSelfClosingTag)
                    {
                        if (!element.IsClosingTag)
                        {
                            // open tag
                            CurrentElementContent.Add(element);
                            ElementHierarchy.Push(element);
                        }
                        else
                        {
                            // close tag
                            if (ElementHierarchy.Count <= 1)
                            {
                                element.NodeErrors.Add(string.Format(DothtmlParserErrors.ClosingTagHasNoMatchingOpenTag, element.FullTagName));
                            }
                            else
                            {
                                var beginTag = (DothtmlElementNode)ElementHierarchy.Peek();
                                var beginTagName = beginTag.FullTagName;
                                if (beginTagName != element.FullTagName)
                                {
                                    element.NodeErrors.Add(string.Format(DothtmlParserErrors.ClosingTagHasNoMatchingOpenTag, beginTagName));
                                    ResolveWrongClosingTag(element);
                                    beginTag = (DothtmlElementNode)ElementHierarchy.Peek();
                                }
                                else
                                {
                                    ElementHierarchy.Pop();
                                }

                                beginTag.CorrespondingEndTag = element;
                            }
                        }
                    }
                    else
                    {
                        // self closing tag
                        CurrentElementContent.Add(element);
                    }
                }
                else if (Peek().Type == DothtmlTokenType.OpenBinding)
                {
                    // binding
                    CurrentElementContent.Add(ReadBinding());
                }
                else if (Peek().Type == DothtmlTokenType.OpenCData)
                {
                    CurrentElementContent.Add(ReadCData());
                }
                else
                {
                    // text
                    if (CurrentElementContent.Count > 0 && CurrentElementContent[CurrentElementContent.Count - 1].GetType() == typeof(DothtmlLiteralNode))
                    {
                        // append to the previous literal
                        var lastLiteral = (DothtmlLiteralNode)CurrentElementContent[CurrentElementContent.Count - 1];
                        if (lastLiteral.Escape != false)
                            CurrentElementContent.Add(new DothtmlLiteralNode() { Value = Peek().Text, Tokens = { Peek() }, StartPosition = Peek().StartPosition });
                        else
                        {
                            lastLiteral.Value += Peek().Text;
                            lastLiteral.Tokens.Add(Peek());
                        }
                    }
                    else
                    {
                        CurrentElementContent.Add(new DothtmlLiteralNode() { Value = Peek().Text, Tokens = { Peek() }, StartPosition = Peek().StartPosition });
                    }
                    Read();
                }
            }

            // check element hierarchy
            if (ElementHierarchy.Count > 1)
            {
                root.NodeErrors.Add(string.Format(DothtmlParserErrors.UnexpectedEndOfInputTagNotClosed, ElementHierarchy.Peek()));
            }

            // set lengths to all nodes
            foreach (var node in root.EnumerateNodes())
            {
                node.Length = node.Tokens.Select(t => t.Length).DefaultIfEmpty(0).Sum();
            }

            Root = root;
            return root;
        }