private void _parser_main(YamlFileData file) { Output = new ParserArray(file.LineNumber); Output.Indent = -1; Output.ChildrenIndent = -1; _readNode(file, Output, 0, YamlListType.NotDefined); if (Output.ParserType == ParserTypes.Array) { var parserArray = Output.To <ParserArray>(); // Copy pate handling if (parserArray.Objects.Count > 0 && parserArray.Objects[0].ParserType == ParserTypes.Array) { var tmp_list = new ParserList(0); var tmp_keyValue = new ParserKeyValue("copy_paste", 0); tmp_list.Objects.AddRange(parserArray.Objects); tmp_keyValue.Value = tmp_list; parserArray.Objects.Clear(); parserArray.Objects.Add(tmp_keyValue); } } // Calculate lengths if (Output != null) { _calculateLength(Output); Output.Length = _getLength(Output); } }
private void _readNode(YamlFileData file, ParserObject parent, int indent, YamlListType listType) { string word_s = null; while (file.CanRead) { char c = file.PeekChar(); switch (c) { case '#': file.SkipLine(); continue; case '\r': // Ignore character file.Position++; continue; case '\n': file.Position++; file.NextLine(); continue; case '-': file.SetupParent(parent, indent); if (listType == YamlListType.NotDefined) { listType = YamlListType.Array; } // Validate parent indent switch (parent.ParserType) { case ParserTypes.List: case ParserTypes.Array: if (file.CurrentLineIndent < parent.ChildrenIndent) { return; } if (file.CurrentLineIndent > parent.ChildrenIndent) { throw file.GetException("Unexpected indent (parent indent: " + parent.Indent + ", parent child indent: " + parent.ChildrenIndent + ", current indent: " + file.CurrentLineIndent + ")."); } break; } if (!(file.Position + 2 < file.Length && file.Data[file.Position + 1] == ' ' && file.IsLetter((char)file.Data[file.Position + 2]))) { throw file.GetException("Expected a space after the hyphen for the list declaration."); } // Array declaration ParserArray array = new ParserArray(file.LineNumber); array.Indent = file.CurrentLineIndent; file.CurrentLineIndent += 2; array.ChildrenIndent = file.CurrentLineIndent; file.Position += 2; _readNode(file, array, file.CurrentLineIndent, YamlListType.NotDefined); switch (parent.ParserType) { case ParserTypes.List: ((ParserList)parent).AddElement(array); break; case ParserTypes.Array: // Used for copy pasting only ((ParserArray)parent).AddElement(array); break; default: throw file.GetException("Unexpected parent node type. It can either be a list or an array, found a '" + parent.ParserType + "'."); } continue; case ' ': file.CurrentLineIndent++; file.Position++; continue; case ':': if (string.IsNullOrEmpty(word_s)) { throw file.GetException("Missing declaration key before ':'."); } file.Position++; file.Trim(); ParserKeyValue keyValue = new ParserKeyValue(word_s, file.LineNumber); keyValue.Indent = parent.Indent; word_s = null; // List declaration if (file.EoL()) { ParserList list = new ParserList(file.LineNumber); list.Indent = -1; list.ChildrenIndent = -1; keyValue.Value = list; _readNode(file, list, file.CurrentLineIndent, YamlListType.NotDefined); } else if (file.Data[file.Position] == '[') // Aggregate parsing, does not support multi-line { file.Position++; ParserAggregate aggregate = new ParserAggregate(file.LineNumber); aggregate.Parent = parent; while (file.CanRead) { c = file.PeekChar(); if (c == '\r' || c == '\n') { throw file.GetException("Unexpected syntax; multi-line aggregate arrays are not supported."); } if (c == ']') { break; } word_s = c == '\"' ? file.ReadValue() : file.ReadWord(); aggregate.AddElement(new ParserString(word_s.Trim(' '), file.LineNumber)); c = file.PeekChar(); while (c != '\n' && (c == ',' || c == ' ' || c == '\r')) { file.Position++; c = file.PeekChar(); } } word_s = null; keyValue.Value = aggregate; } else // KeyValue, get the line number first! { var parserString = new ParserString(null, file.LineNumber); parserString.Value = file.ReadValue(); parserString.Length = file.ValueLength; keyValue.Value = parserString; } switch (parent.ParserType) { case ParserTypes.List: ((ParserList)parent).AddElement(keyValue); break; case ParserTypes.Array: ((ParserArray)parent).AddElement(keyValue); break; } continue; default: file.SetupParent(parent, indent); if (listType == YamlListType.NotDefined) { listType = YamlListType.KeyValue; } // Validate parent indent switch (parent.ParserType) { case ParserTypes.List: if (file.CurrentLineIndent < parent.ChildrenIndent) { return; } if (file.CurrentLineIndent == parent.ChildrenIndent && listType != YamlListType.KeyValue) { return; } if (file.CurrentLineIndent > parent.ChildrenIndent) { throw file.GetException("Unexpected indent while reading key (parent indent: " + parent.Indent + ", parent child indent: " + parent.ChildrenIndent + ", current indent: " + file.CurrentLineIndent + ")."); } break; case ParserTypes.Array: if (file.CurrentLineIndent < parent.ChildrenIndent) { return; } if (file.CurrentLineIndent > parent.ChildrenIndent) { throw file.GetException("Unexpected indent while reading key (parent indent: " + parent.Indent + ", parent child indent: " + parent.ChildrenIndent + ", current indent: " + file.CurrentLineIndent + ")."); } break; } word_s = file.ReadKey(); if (word_s.Length == 0) { throw file.GetException("Null-length word. This is most likely caused by an unexpected character in a string."); } file.Trim(); continue; } } }