/// <summary> /// Parses the token stream and gets the node. /// </summary> public DothtmlRootNode Parse(List <DothtmlToken> tokens) { Root = null; Tokens = tokens; CurrentIndex = 0; ElementHierarchy = new Stack <DothtmlNodeWithContent>(); // read file var root = new DothtmlRootNode(); root.Tokens.Add(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.AddWarning($"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.AddWarning($"The closing tag '</{element.FullTagName}>' 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 = { PeekPart() } }); } else { lastLiteral.Tokens.Add(PeekPart()); } } else { CurrentElementContent.Add(new DothtmlLiteralNode() { Tokens = { PeekPart() } }); } Read(); doNotAppend = false; } } // check element hierarchy if (ElementHierarchy.Count > 1) { ElementHierarchy.Peek().AddError($"Unexpected end of file! The tag '<{ElementHierarchy.Peek().CastTo<DothtmlElementNode>().TagName}>' was not closed!"); } ResolveParents(root); Root = root; return(root); }
private void ResolveParents(DothtmlRootNode root) { var parentResolver = new ParentResolvingVisitor(); root.Accept(parentResolver); }
public DothtmlRootNode Parse(List <DothtmlToken> tokens) { Root = null; Tokens = tokens; CurrentIndex = 0; ElementHierarchy.Clear(); // read file var root = new DothtmlRootNode(); root.Tokens.Add(Tokens); ElementHierarchy.Push(root); // read content var doNotAppend = false; while (Peek() is DothtmlToken token) { if (token.Type == DothtmlTokenType.DirectiveStart) { // directive root.Directives.Add(ReadDirective()); doNotAppend = true; } else if (token.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.AddWarning($"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.AddWarning($"The closing tag '</{element.FullTagName}>' doesn't have a matching opening tag!"); ResolveWrongClosingTag(element); if (ElementHierarchy.Peek() is DothtmlElementNode newBeginTag && beginTagName != newBeginTag.FullTagName) { newBeginTag.CorrespondingEndTag = element; ElementHierarchy.Pop(); } else { CurrentElementContent.Add(element); } } else { ElementHierarchy.Pop(); beginTag.CorrespondingEndTag = element; } } } }
public void Visit(DothtmlRootNode root) { LastFoundNode = root; }
public IAbstractTreeRoot BuildTreeRoot(IControlTreeResolver controlTreeResolver, IControlResolverMetadata metadata, DothtmlRootNode node, IDataContextStack dataContext) { return new ResolvedTreeRoot((ControlResolverMetadata)metadata, node, (DataContextStack)dataContext); }