AXmlText MakeText(int start, int end) { AXmlParser.DebugAssert(end > start, "Empty text"); AXmlText text = new AXmlText() { StartOffset = start, EndOffset = end, EscapedValue = GetText(start, end), Type = TextType.Other }; OnParsed(text); return(text); }
AXmlElement ReadElement(IEnumerator <AXmlObject> objStream) { AXmlElement element = new AXmlElement(); element.IsProperlyNested = true; // Read start tag AXmlTag startTag = ReadSingleObject(objStream) as AXmlTag; AXmlParser.DebugAssert(startTag != null, "Start tag expected"); AXmlParser.DebugAssert(startTag.IsStartOrEmptyTag || startTag == StartTagPlaceholder, "Start tag expected"); if (startTag == StartTagPlaceholder) { element.HasStartOrEmptyTag = false; element.IsProperlyNested = false; TagReader.OnSyntaxError(element, objStream.Current.StartOffset, objStream.Current.EndOffset, "Matching openning tag was not found"); } else { element.HasStartOrEmptyTag = true; element.AddChild(startTag); } // Read content and end tag if (startTag == StartTagPlaceholder || // Check first in case the start tag is null element.StartTag.IsStartTag) { while (true) { AXmlTag currTag = objStream.Current as AXmlTag; // Peek if (currTag == EndTagPlaceholder) { TagReader.OnSyntaxError(element, element.LastChild.EndOffset, element.LastChild.EndOffset, "Expected '</{0}>'", element.StartTag.Name); ReadSingleObject(objStream); element.HasEndTag = false; element.IsProperlyNested = false; break; } else if (currTag != null && currTag.IsEndTag) { if (element.HasStartOrEmptyTag && currTag.Name != element.StartTag.Name) { TagReader.OnSyntaxError(element, currTag.StartOffset + 2, currTag.StartOffset + 2 + currTag.Name.Length, "Expected '{0}'. End tag must have same name as start tag.", element.StartTag.Name); } element.AddChild(ReadSingleObject(objStream)); element.HasEndTag = true; break; } AXmlObject nested = ReadTextOrElement(objStream); if (nested is AXmlElement) { if (!((AXmlElement)nested).IsProperlyNested) { element.IsProperlyNested = false; } element.AddChildren(Split((AXmlElement)nested).ToList()); } else { element.AddChild(nested); } } } else { element.HasEndTag = false; } element.StartOffset = element.FirstChild.StartOffset; element.EndOffset = element.LastChild.EndOffset; AXmlParser.Assert(element.HasStartOrEmptyTag || element.HasEndTag, "Must have at least start or end tag"); AXmlParser.Log("Constructed {0}", element); trackedSegments.AddParsedObject(element, null); // Need all elements in cache for offset tracking return(element); }
/// <summary> Get posible configurations after considering given object </summary> Configurations ProcessObject(Configurations oldConfigs, AXmlObject obj) { AXmlParser.Log("Processing {0}", obj); AXmlTag objAsTag = obj as AXmlTag; AXmlElement objAsElement = obj as AXmlElement; AXmlParser.DebugAssert(objAsTag != null || objAsElement != null || obj is AXmlText, obj.GetType().Name + " not expected"); if (objAsElement != null) { AXmlParser.Assert(objAsElement.IsProperlyNested, "Element not properly nested"); } Configurations newConfigs = new Configurations(); foreach (var kvp in oldConfigs) { Configuration oldConfig = kvp.Value; var oldStartTags = oldConfig.StartTags; var oldDocument = oldConfig.Document; int oldCost = oldConfig.Cost; if (objAsTag != null && objAsTag.IsStartTag) { newConfigs.Add(new Configuration { // Push start-tag (cost 0) StartTags = oldStartTags.Push(objAsTag), Document = oldDocument.Push(objAsTag), Cost = oldCost, }); } else if (objAsTag != null && objAsTag.IsEndTag) { newConfigs.Add(new Configuration { // Ignore (cost 1) StartTags = oldStartTags, Document = oldDocument.Push(StartTagPlaceholder).Push(objAsTag), Cost = oldCost + 1, }); if (!oldStartTags.IsEmpty && oldStartTags.Peek().Name != objAsTag.Name) { newConfigs.Add(new Configuration { // Pop 1 item (cost 1) - not mathcing StartTags = oldStartTags.Pop(), Document = oldDocument.Push(objAsTag), Cost = oldCost + 1, }); } int popedCount = 0; var startTags = oldStartTags; var doc = oldDocument; foreach (AXmlTag poped in oldStartTags) { popedCount++; if (poped.Name == objAsTag.Name) { newConfigs.Add(new Configuration { // Pop 'x' items (cost x-1) - last one is matching StartTags = startTags.Pop(), Document = doc.Push(objAsTag), Cost = oldCost + popedCount - 1, }); } startTags = startTags.Pop(); doc = doc.Push(EndTagPlaceholder); } } else { // Empty tag or other tag type or text or properly nested element newConfigs.Add(new Configuration { // Ignore (cost 0) StartTags = oldStartTags, Document = oldDocument.Push(obj), Cost = oldCost, }); } } // Log("New configurations:" + newConfigs.ToString()); Configurations bestNewConfigurations = new Configurations( newConfigs.Values.OrderBy(v => v.Cost).Take(maxConfigurationCount) ); // AXmlParser.Log("Best new configurations:" + bestNewConfigurations.ToString()); return(bestNewConfigurations); }