Hey all, Just finished something neat - a very rudimentary notecard parser :-) Right now it just splits the raw text into Scopes, Statements and Text. Lemme know what you think, I dont have much experience with parsing.
-Chris
using System.Collections.Generic; using System.Text; using System.IO; using System; namespace libsecondlife { public class NotecardParser { public const char LLNewline = '\n'; public static void Main(string[] args) { StreamReader reader = File.OpenText(args[0]); string text = reader.ReadToEnd(); reader.Close(); Console.WriteLine("Read {0}", args[0]); Console.WriteLine(text); Console.WriteLine("Parsing..."); NotecardRoot root = new NotecardRoot(new StringBuilder(text)); Console.WriteLine("Parsed."); string outputfile = args[0] + ".parsed.txt"; if (File.Exists(outputfile)) File.Delete(outputfile); StreamWriter writer = File.CreateText(outputfile); writer.WriteLine(root.ToString()); writer.Close(); } } public abstract class NotecardElement { public abstract string ToString(int depth); public override string ToString() { return ToString(0); } } public class NotecardRoot : NotecardScope { public NotecardRoot(StringBuilder raw) : base(raw) { } public override string ToString(int depth) { StringBuilder builder = new StringBuilder(); foreach (NotecardElement child in Children) { builder.Append(child.ToString(0)); builder.Append(NotecardParser.LLNewline); } return builder.ToString(); } } public class NotecardScope : NotecardElement { public List<NotecardElement> Children; public NotecardScope(StringBuilder raw) { Children = new List<NotecardElement>(); while (raw.Length > 0 && raw[0] != '}') { if (!char.IsWhiteSpace(raw[0])) { if (raw[0] != '{') { NotecardStatement statement = new NotecardStatement(raw); Children.Add(statement); if (statement.Name == "Text") { string[] parsed = statement.Parameter.Split(new char[] {'\t', ' '}, StringSplitOptions.RemoveEmptyEntries); if (parsed[0] == "length") { int txtLen = int.Parse(parsed[1]); Children.Add(new NotecardText(raw, txtLen)); } } } else { raw.Remove(0, 1); // Consume the scope's beginning bracket. Children.Add(new NotecardScope(raw)); } } else { raw.Remove(0, 1); } } if (raw.Length > 0) raw.Remove(0, 1); } public override string ToString(int depth) { StringBuilder tabs = new StringBuilder(depth); for (int i = 0; i < depth; ++i) tabs.Append('\t'); string prefix = tabs.ToString(); StringBuilder builder = new StringBuilder(); builder.Append(tabs).Append('{').Append(NotecardParser.LLNewline); foreach (NotecardElement child in Children) { builder.Append(child.ToString(depth + 1)); builder.Append(NotecardParser.LLNewline); } builder.Append(tabs).Append('}'); return builder.ToString(); } } public class NotecardStatement : NotecardElement { public string Name; public string Parameter; public NotecardStatement(StringBuilder raw) { while (char.IsWhiteSpace(raw[0])) raw.Remove(0, 1); // Parse name: int len = 0; while (!char.IsWhiteSpace(raw[len])) ++len; char[] NameChars = new char[len]; raw.CopyTo(0, NameChars, 0, len); Name = new string(NameChars); raw.Remove(0, len); // Parse parameter: while (char.IsWhiteSpace(raw[0])) raw.Remove(0, 1); int eol = 0; while (raw[eol] != NotecardParser.LLNewline) ++eol; char[] ParamChars = new char[eol]; raw.CopyTo(0, ParamChars, 0, eol); Parameter = new string(ParamChars); raw.Remove(0, eol + 1); // Consume the newline. } public override string ToString(int depth) { StringBuilder tabs = new StringBuilder(depth); for (int i = 0; i < depth; ++i) tabs.Append('\t'); string prefix = tabs.ToString(); return string.Format("{0}{1}\t{2}", tabs, Name, Parameter); } } public class NotecardText : NotecardElement { public string Text; public NotecardText(StringBuilder raw, int length) { char[] chars = new char[length]; raw.CopyTo(0, chars, 0, length); Text = new string(chars); raw.Remove(0, length); } public override string ToString(int depth) { return Text; } } }
_______________________________________________ libsl-dev mailing list libsl-dev@opensecondlife.org http://opensecondlife.org/cgi-bin/mailman/listinfo/libsl-dev