public static HtmlNode Build(IEnumerable <Token> tokens) { var documentNode = new HtmlDocumentNode(); HtmlNode currentNode = documentNode; var stack = new Stack <HtmlNode>(); HtmlAttributeNode currentAttribute = null; foreach (Token token in tokens) { switch (token.Type) { case TokenType.OpenTag: var node = new HtmlElementNode(token.Value); currentNode = PopCurrentNodeParentIfCurrentNodeIsEmptyTag(stack, currentNode); currentNode.AppendChild(node); stack.Push(currentNode); currentNode = node; break; case TokenType.CloseTag: currentNode = stack.Pop(); break; case TokenType.AttributeName: currentAttribute = new HtmlAttributeNode(token.Value); currentNode.AppendAttribute(currentAttribute); break; case TokenType.AttributeValue: currentAttribute.Value = token.Value; break; case TokenType.Text: currentNode = PopCurrentNodeParentIfCurrentNodeIsEmptyTag(stack, currentNode); currentNode.AppendChild(new HtmlTextNode(token.Value)); break; case TokenType.Comment: currentNode = PopCurrentNodeParentIfCurrentNodeIsEmptyTag(stack, currentNode); currentNode.AppendChild(new HtmlCommentNode(token.Value)); break; default: throw new ArgumentOutOfRangeException(); } } return(documentNode); }