public MultiLineStringNode GetChildAddresedByStringLineNumber(int number) { EnsureProperType(NodeChildrenType.multiLineString); // ensure proper number of child string nodes exist var indentation = GetProperChildIndentation(); for(int i = ChildNodes.Count; i <= number; i++) { var newnode = new MultiLineStringNode(indentation, File); AddChild(newnode); } return ChildNodes[number] as MultiLineStringNode; }
/// <summary> /// Parses lines of SUCC into a data structure /// </summary> internal static (List <Line>, Dictionary <string, KeyNode>) DataStructureFromSUCC(string[] lines, DataFileBase fileRef) // I am so, so sorry. If you need to understand this function for whatever reason... may god give you guidance. { // if the file is empty // do this because otherwise new files are created with a newline at the top if (lines.Length == 1 && lines[0] == "") { return(new List <Line>(), new Dictionary <string, KeyNode>()); } var TopLevelLines = new List <Line>(); var TopLevelNodes = new Dictionary <string, KeyNode>(); var NestingNodeStack = new Stack <Node>(); // the top of the stack is the node that new nodes should be children of bool DoingMultiLineString = false; var file = fileRef as DataFile; // this will be null if fileRef is a ReadOnlyDataFile // parse the input line by line for (int i = 0; i < lines.Length; i++) { var line = lines[i]; if (line.Contains('\t')) { throw new FormatException("a SUCC file cannot contain tabs. Please use spaces instead."); } if (DoingMultiLineString) { if (NestingNodeStack.Peek().ChildNodeType != NodeChildrenType.multiLineString) { throw new Exception("oh f**k, we were supposed to be doing a multi-line string but the top of the node stack isn't a multi-line string node!"); } var newboi = new MultiLineStringNode(rawText: line, file); NestingNodeStack.Peek().AddChild(newboi); if (newboi.IsTerminator) { DoingMultiLineString = false; NestingNodeStack.Pop(); } continue; } if (LineHasData(line)) { Node node = GetNodeFromLine(line, file); boobies: if (NestingNodeStack.Count == 0) // if this is a top-level node { if (!(node is KeyNode)) { throw new FormatException($"top level lines must be key nodes. Line {i} does not conform to this: '{line}'"); } TopLevelLines.Add(node); KeyNode heck = node as KeyNode; TopLevelNodes.Add(heck.Key, heck); } else // if this is NOT a top-level node { int StackTopIndentation = NestingNodeStack.Peek().IndentationLevel; int LineIndentation = line.GetIndentationLevel(); if (LineIndentation > StackTopIndentation) // if this should be a child of the stack top { Node newParent = NestingNodeStack.Peek(); if (newParent.ChildNodes.Count == 0) // if this is the first child of the parent, assign the parent's child type { if (node is KeyNode) { newParent.ChildNodeType = NodeChildrenType.key; } else if (node is ListNode) { newParent.ChildNodeType = NodeChildrenType.list; } else { throw new Exception("what the f**k?"); } } else // if the parent already has children, check for errors with this line { CheckNewSiblingForErrors(child: node, newParent: newParent); } newParent.AddChild(node); } else // if this should NOT be a child of the stack top { NestingNodeStack.Pop(); goto boobies; } } if (node.Value == "") // if this is a node with children { NestingNodeStack.Push(node); } if (node.Value == MultiLineStringNode.Terminator) // if this is the start of a multi line string { NestingNodeStack.Push(node); node.ChildNodeType = NodeChildrenType.multiLineString; DoingMultiLineString = true; } } else // line has no data { Line NoDataLine = new Line(rawText: line); if (NestingNodeStack.Count == 0) { TopLevelLines.Add(NoDataLine); } else { NestingNodeStack.Peek().AddChild(NoDataLine); } } } return(TopLevelLines, TopLevelNodes); }