Example #1
0
        public TextTree WordSegemete(TextTree text)
        {
            var    segement = segmenter.Cut(text.TreeValues);
            string str      = string.Join(" ", segement);

            str = str.Replace(" 。", ".");
            TextTree t = new TextTree();

            t.TreeValues = str;
            return(t);
        }
Example #2
0
        private static TextTree PlantTree(string treeId, TreeSpecification ts, Random r)
        {
            var root = new TreeNode {
                Symbol = ts.Lables[r.Next(0, ts.Lables.Count)]
            };

            root.SetParent(null);

            Germinate(root, ts.MaxDepth, ts.MaxDegree, ts.Lables, r);

            var mytree = new TextTree {
                TreeId = treeId, Root = root
            };

            return(mytree);
        }
Example #3
0
 public void Add(string[] texts, string text, int layer = -1)
 {
     if (layer == texts.Length - 1)
     {
         this.text = text;
     }
     else if (layer < texts.Length - 1)
     {
         if (layer >= 0)
         {
             path = texts[layer];
         }
         ++layer;
         TextTree child = null;
         children.TryGetValue(texts[layer], out child);
         if (child == null)
         {
             child = new TextTree();
             children.Add(texts[layer], child);
         }
         child.Add(texts, text, layer);
     }
 }
			// Rebalance the tree at this node.
			public override void Rebalance(TextTree tree)
					{
						// get this node
						TextGroup node = this;

						// rebalance up the tree
						while(node != null)
						{
							// enforce upper bound on child count
							while(node.childCount > MAX_CHILD_COUNT)
							{
								// create a new root before splitting current root
								if(node.parent == null)
								{
									// create the new root node
									TextGroup root = new TextGroup();

									// set the new root's level
									root.level = (node.level + 1);

									// insert the old root under the new root
									root.InsertChild(null, node);

									// set the root of the tree to the new root
									tree.root = root;
								}

								// create the new group for the excess children
								TextGroup group = new TextGroup();

								// set the new group's level
								group.level = node.level;

								// get the first child of the node to be split
								TextNode child = node.first;

								// find the first excess child
								for(int i = 1; i < MIN_CHILD_COUNT; ++i)
								{
									child = child.next;
								}

								// insert first excess child under the new group
								group.InsertChildren(null, child.next);

								// insert group under the current node's parent
								node.parent.InsertChild(node, group);

								// set the current node to the new group
								node = group;
							}

							// enforce lower bound on child count
							while(node.childCount < MIN_CHILD_COUNT)
							{
								// handle the root node case
								if(node.parent == null)
								{
									// root needs at least two children or one line
									if((node.childCount == 1) && (node.level > 1))
									{
										// set the root to its only child
										tree.root = (TextGroup)node.first;

										// remove new root from the old root
										node.RemoveChild(tree.root);
									}

									// we're done rebalancing
									return;
								}

								// rebalance the parent, if too few siblings
								if(node.parent.ChildCount < 2)
								{
									// rebalance the parent
									node.parent.Rebalance(tree);

									// try the current node again
									continue;
								}

								// get the next sibling of the current node
								TextGroup next = (TextGroup)node.next;

								// use previous and swap, if no next sibling
								if(next == null)
								{
									// set the next node to the current node
									next = node;

									// reset current node to previous sibling
									node = (TextGroup)node.prev;
								}

								// calculate the total child count for the nodes
								int fullCount = node.childCount + next.childCount;

								// merge the nodes or split up the children
								if(fullCount <= MAX_CHILD_COUNT)
								{
									// merge the children under a single node
									node.InsertChildren(node.last, next.first);

									// remove the empty node from the tree
									node.parent.RemoveChild(next);

									// continue rebalancing at this node, if needed
									if(fullCount < MIN_CHILD_COUNT) { continue; }
								}
								else
								{
									// calculate the first node's new child count
									int halfCount = (fullCount / 2);

									// move children around as needed
									if(node.childCount < halfCount)
									{
										// move the needed children to the first node
										node.InsertChildren
											(node.last, next.first,
											 (halfCount - node.childCount));
									}
									else if(node.childCount > halfCount)
									{
										// get the first child of the first node
										TextNode child = node.first;

										// get the first of the children to move
										for(int i = 1; i < halfCount; ++i)
										{
											child = child.next;
										}

										// move extra children to the second node
										next.InsertChildren(null, child);
									}
								}
							}

							// set the current node to its parent
							node = (TextGroup)node.parent;
						}
					}
			// Update after a removal.
			public static bool RemovalUpdate
						(TextTree tree, TextBuffer buffer,
						 int offset, int length)
					{
						// NOTE: this is here to keep the method calls down to
						//       a minimum... technically, this belongs in the
						//       tree, but it's more efficient to do this here,
						//       where we can access the line/node fields
						//       directly

						// set the default return value
						bool retval = false;

						// declare the start offset of the found lines
						int garbage;

						// get the first line affected by the removal
						TextLine startLine = tree.FindLineByCharOffset
							(offset, out garbage);

						// get the last line affected by the removal
						TextLine endLine = tree.FindLineByCharOffset
							((offset + length + 1), out garbage);

						// handle end of buffer case
						if(endLine == null)
						{
							// get the character count of the buffer
							int bufCount = buffer.CharCount;

							// insert an extra line at the end of the buffer
							buffer.Insert(bufCount, '\n');

							// find the last line of the tree
							endLine = tree.root.LastLine;

							// create the new line node
							TextLine newLine = new TextLine
								(buffer.MarkPosition(bufCount, true),
								 buffer.MarkPosition((bufCount + 1), true));

							// add the new line to the last line's parent
							endLine.parent.InsertChild(endLine, newLine);

							// rebalance the parent
							endLine.parent.Rebalance(tree);

							// set the end line to the new line
							endLine = newLine;

							// flag that an insertion was performed
							retval = true;
						}

						// handle single line case
						if(startLine == endLine)
						{
							// force a character count update for the line
							startLine.UpdateCharCount();

							// invalidate the line
							startLine.Invalidate();

							// we're done
							return retval;
						}

						// merge the content of the two lines into the first
						startLine.end.Move(endLine.EndOffset);

						// get the start line's next sibling
						TextNode first = startLine.next;

						// set the current line to the start's next sibling
						TextLine currLine = (TextLine)first;

						// get the start line's parent
						TextNode startParent = startLine.parent;

						// get the end line's parent
						TextNode endParent = endLine.parent;

						// handle single parent case
						if(startParent == endParent)
						{
							// set the default removal count
							int rmCount = 1;

							// delete the end line's start position
							endLine.start.Delete();

							// delete the end line's end position
							endLine.end.Delete();

							// count and delete the lines to be removed
							while(currLine != endLine)
							{
								// delete the current line's start position
								currLine.start.Delete();

								// delete the current line's end position
								currLine.end.Delete();

								// move to the next line
								currLine = (TextLine)currLine.next;

								// increment the removal count
								++rmCount;
							}

							// remove the deleted lines from their parent
							startParent.RemoveChildren(first, rmCount);

							// rebalance the parent
							startParent.Rebalance(tree);

							// we're done
							return retval;
						}

						// delete the lines to be removed from the start parent
						while(currLine != null)
						{
							// delete the current line's start position
							currLine.start.Delete();

							// delete the current line's end position
							currLine.end.Delete();

							// move to the next line
							currLine = (TextLine)currLine.next;
						}

						// remove the deleted lines from their parent
						if(first != null) { startParent.RemoveChildren(first); }

						// get the current parent
						TextNode currParent = startParent.FindNext();

						// remove lines and groups as needed
						while(currParent != endParent)
						{
							// get the first child of the current parent
							first = currParent.FirstChild;

							// get the current line
							currLine = (TextLine)first;

							// set the default before next line
							TextLine nextLine = null;

							// delete the lines to be removed
							while(currLine != null)
							{
								// delete the current line's start position
								currLine.start.Delete();

								// delete the current line's end position
								currLine.end.Delete();

								// get the before next line
								nextLine = currLine;

								// set the current line to the next
								currLine = (TextLine)currLine.next;
							}

							// find the actual next line
							nextLine = (TextLine)nextLine.FindNext();

							// remove the deleted lines from their parent
							currParent.RemoveChildren(first);

							// remove empty groups up the tree
							while(currParent.ChildCount == 0)
							{
								// get the current parent's parent
								TextNode parent = currParent.parent;

								// remove the current parent
								parent.RemoveChild(currParent);

								// move up the tree
								currParent = parent;
							}

							// set the next parent to the next line's parent
							currParent = nextLine.parent;
						}

						// delete and remove lines from the end parent
						{
							// set the default removal count
							int rmCount = 1;

							// get the first child of the end line's parent
							first = endParent.FirstChild;

							// get the current line
							currLine = (TextLine)first;

							// delete the end line's start position
							endLine.start.Delete();

							// delete the end line's end position
							endLine.end.Delete();

							// count and delete the lines to be removed
							while(currLine != endLine)
							{
								// delete the current line's start position
								currLine.start.Delete();

								// delete the current line's end position
								currLine.end.Delete();

								// move to the next line
								currLine = (TextLine)currLine.next;

								// increment the removal count
								++rmCount;
							}

							// remove the deleted lines from their parent
							endParent.RemoveChildren(first, rmCount);
						}

						// rebalance the end line's parent
						endParent.Rebalance(tree);

						// rebalance the start line's parent
						startLine.parent.Rebalance(tree);

						// return the inserted flag
						return retval;
					}
			// Update after an insertion.
			public static unsafe void InsertionUpdate
						(TextTree tree, TextBuffer buffer,
						 int offset, int length)
					{
						// NOTE: this is here to keep the method calls down to
						//       a minimum... technically, this belongs in the
						//       tree, but it's more efficient to do this here,
						//       where we can access the line/node fields
						//       directly

						// declare the start offset of the insertion line
						int lineStart;

						// find the insertion line
						TextLine line = tree.FindLineByCharOffset
							(offset, out lineStart);

						// get the parent of the insertion line
						TextNode parent = line.Parent;

						// get the end offset of the insertion line
						int lineEnd = line.end.Offset;

						// create a text slice
						TextSlice slice = new TextSlice();

						// get the inserted data into the slice
						buffer.GetSlice(offset, length, slice);

						// get the current line start position
						int currStart = lineStart;

						// get the current line end position
						int currEnd = (offset + 1);

						// set the default new line list
						TextLine first = null;

						// set the default previous new line
						TextLine prev = null;

						// find and create new lines, quickly
						fixed(char* start = &slice.chars[slice.start])
						{
							char* curr = start;
							// get the insertion end position
							char* end = (curr + slice.length);

							// find and create new lines
							while(curr != end)
							{
								if(*curr == '\n')
								{
									if(currStart == lineStart)
									{
										// shorten the insertion line
										line.end.Move(currEnd);
									}
									else
									{
										// create a new line
										TextLine newline = new TextLine
											(buffer.MarkPosition(currStart, true),
											 buffer.MarkPosition(currEnd, true));

										// update list links
										if(first == null)
										{
											// set the current line as the first
											first = newline;
										}
										else
										{
											// set the current line's prev
											newline.prev = prev;

											// set the previous line's next
											prev.next = newline;
										}

										// set the previous line to the current
										prev = newline;
									}

									// update the current line start position
									currStart = currEnd;
								}

								// increment the current input pointer
								++curr;

								// increment the current line end position
								++currEnd;
							}
						}

						// insert new lines and rebalance parent, if needed
						if(first != null)
						{
							// add any remaining characters to new line
							if(currEnd < lineEnd)
							{
								// create a new line
								TextLine newline = new TextLine
									(buffer.MarkPosition(currStart, true),
									 buffer.MarkPosition(currEnd, true));

								// set the current line's prev reference
								newline.prev = prev;

								// set the previous line's next reference
								prev.next = newline;
							}

							// insert the new lines
							parent.InsertChildren(line, first);

							// rebalance, starting at the new lines' parent
							parent.Rebalance(tree);
						}
					}
			// Rebalance the tree at this node.
			public virtual void Rebalance(TextTree tree)
					{
						throw new InvalidOperationException();
					}