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

Reply via email to