/// <summary> /// All items that can incrementally parse their children should run their /// full parse in the same way. This function does that work. /// </summary> public static bool FullParseIncrementalItem( IIncrementalParseItem item, ItemFactory itemFactory, ITextProvider text, TokenStream tokens) { ComplexItem complexItem = (ComplexItem)item; ParseItem prevChild = null; while (true) { ParseItem newChild = item.CreateNextChild(prevChild, itemFactory, text, tokens); if (newChild != null) { complexItem.Children.Add(newChild); prevChild = newChild; } else { break; } } item.UpdateCachedChildren(); item.UpdateParseErrors(); return(complexItem.Children.Count > 0); }
internal void InsertChildIntoSubtree(ParseItem child) { ComplexItem parent = this; if (child.Start >= Children.TextStart && child.Start < Children.TextAfterEnd) { // Might need to be added in one of my children parent = ComplexItemFromRange(child.Start, child.Length) ?? this; } int insertIndex = parent.Children.FindInsertIndex(child.Start, beforeExisting: false); if (insertIndex > 0) { // If the comment is going to be added right after an unclosed item, // then put the comment into the unclosed item. It makes the tree look as expected // and it helps incremental parsing work when the item does get closed. if (parent.Children[insertIndex - 1] is ComplexItem previousChild && previousChild.IsUnclosed) { previousChild.InsertChildIntoSubtree(child); return; } } parent.Children.Insert(insertIndex, child); }
internal bool IsParentOf(ParseItem item) { ComplexItem parent = item?.Parent; while (parent != null && parent != this) { parent = parent.Parent; } return(parent == this); }
/// <summary> /// Search my subtree for the deepest item that contains a range of text /// </summary> internal ComplexItem ComplexItemFromRange(int start, int length) { ParseItem item = ItemFromRange(start, length); ComplexItem complexItem = item as ComplexItem; if (item != null) { return(complexItem ?? item.Parent); } return(null); }
/// <summary> /// Create parse item of any type as long as it is derived from ParseItem /// </summary> /// <typeparam name="T">Type of item to create</typeparam> /// <param name="parent">Parent element</param> /// <param name="type">Suggested type to create</param> /// <returns></returns> internal ParseItem Create <T>(ComplexItem parent, Type type) where T : ParseItem, new() { ParseItem item = null; if (ExternalFactory != null) { item = ExternalFactory.CreateItem(this, TextProvider, TokenStream, parent, type); } if (item == null) { item = new T(); } return(item); }
/// <summary> /// Create specific item. Called when parser cannot accept random type and rather /// needs a specific type. Returned item can be derived from type T. /// </summary> /// <typeparam name="T">Type of item to create</typeparam> /// <param name="parent">Parent element</param> /// <param name="type">Suggested item type</param> /// <returns></returns> internal T CreateSpecific <T>(ComplexItem parent, Type type) where T : ParseItem, new() { T item = default; if (ExternalFactory != null) { ParseItem pi = ExternalFactory.CreateItem(this, TextProvider, TokenStream, parent, type); if (pi != null) { item = pi as T; Debug.Assert(item != null); } } if (item == null) { item = new T(); } return(item); }
internal T CreateSpecific <T>(ComplexItem parent) where T : ParseItem, new() { return(CreateSpecific <T>(parent, typeof(T))); }
public ParseItem CreateItem(ItemFactory itemFactory, ITextProvider text, TokenStream tokens, ComplexItem parent, Type type) { Assert.AreSame(itemFactory.TextProvider, text); Assert.AreSame(itemFactory.TokenStream, tokens); if (type == typeof(Declaration)) { Assert.IsInstanceOfType(parent, typeof(RuleBlock)); return(new TestDeclaration()); } return(null); }