protected SON(string field, SON parent, bool container) { this.field = field; this.parent = parent; if (container) { InitialiseContainer(); } }
protected SON AddSON(string field, bool container) { if (!IsContainer) { InitialiseContainer(); } else if (field != null && container) { TestKey(field); } SON son = new SON(field, this, container); list.Add(son); if (field != null && container) { map[field] = son; } return(son); }
/////////////////////////////////////////////////////////// //Add a field making sure it's syntax is correct protected void AddField(string field) { if (!IsContainer) { InitialiseContainer(); } if (field != "") { if (RegexStrip(ref field, quotePattern)) { AddSON(field); } else if (RegexStrip(ref field, fieldPattern)) { AddSON(field); } else if (RegexStrip(ref field, refPattern)) { TestKey(field); SON reference = FindUpward(field); if (reference != null) { map[field] = reference; list.Add(reference); } else { ReferenceException(field); } } else { InvalidFieldException(field); } //Bad Field!! } else { AddSON(null); } }
/////////////////////////////////////////////////////////// //Finds upwardly along chain of parents, but skips previous parents. public SON FindUpward(string key) { SON previous = this; for (SON parent = Parent; parent != null; parent = parent.Parent) { for (int i = 0; i < parent.Count; i++) { if (parent[i] == previous) { continue; } SON child = parent.FindDownard(key); if (child != null) { return(child); } } previous = parent; } return(null); }
/////////////////////////////////////////////////////////// //Finds the first child with "key", skips references. public SON FindDownard(string key) { try { return(map[key]); } catch { if (IsContainer) { foreach (SON son in list) { if (son.Parent != this) { continue; } SON child = son.FindDownard(key); if (child != null) { return(child); } } } } return(null); }
protected SON(string field, SON parent, bool container) { this.field = field; this.parent = parent; if(container) { InitialiseContainer(); } }
protected SON AddSON(string field, bool container) { if(!IsContainer) { InitialiseContainer(); } else if(field != null && container) { TestKey(field); } SON son = new SON(field, this, container); list.Add(son); if(field != null && container) { map[field] = son; } return son; }
/////////////////////////////////////////////////////////// //Finds upwardly along chain of parents, but skips previous parents. public SON FindUpward(string key) { SON previous = this; for(SON parent = Parent; parent != null; parent = parent.Parent) { for(int i = 0; i < parent.Count; i++) { if(parent[i] == previous) { continue; } SON child = parent.FindDownard(key); if(child != null) { return child; } } previous = parent; } return null; }
/////////////////////////////////////////////////////////// //Parses the SON format protected void Parse(string text, ref int index) { string field = ""; bool quoted = false; bool parsedChild = false; Action ParseChild = () => {}; //Begin Parsing text! ////////////// for ( ; index < text.Length; index++) { char character = text[index]; if (character == quoteChar) { quoted = !quoted; } if (!quoted && character == startChar) { //Begin a new parsedChild! //If the previous element was a parsedChild, then we shouldn't start a new one. if (parsedChild) { SyntaxException(); } index++; field = field.Trim(); SON newSon = null; //Add the newSon to this son, it will be filled later as a container. if (field == "") { newSon = AddSON(null, true); } else if (RegexStrip(ref field, fieldPattern)) { newSon = AddSON(field, true); } else { InvalidFieldException(field); } //Pass the current index to parse later & skip over this text. int passedIndex = index; ParseChild += () => { newSon.Parse(text, ref passedIndex); }; //NOTE: Ideally I'd like a better way to skip over a parsedChild. int depth = 1; for ( ; index < text.Length && depth > 0; index++) { if (text[index] == quoteChar) { quoted = !quoted; } if (!quoted && text[index] == startChar) { depth++; } else if (!quoted && text[index] == endChar) { depth--; } } //Make sure the syntax of the parsed element is correct. if (depth != 0) { SyntaxException(); } index--; parsedChild = true; field = ""; } //Add an element to this object else if (!quoted && (character == endChar || character == addChar)) { //making sure we don't have too many closing braces and that we don't have extraneous characcters. if ((character == endChar && parent == null) || (parsedChild && field.Trim() != "")) { SyntaxException(); } //If a child hasn't been parsed, add the field. if (parsedChild) { parsedChild = false; } else if (character == addChar) { AddField(field); field = ""; } //We only want to add if there's something there in the case of an end character else if (index - field.Length <= 0 || text[index - field.Length - 1] == addChar || field.Trim() != "") { AddField(field); field = ""; } //If this is an ending character, parse elements and return. if (character == endChar) { ParseChild(); return; } } else { field += character; continue; } } ParseChild(); //This adds any trailing members. Kind of an exception if (index - field.Length <= 0 || text[index - field.Length - 1] == addChar) { AddField(field); } }