All pastes #790851 Raw Edit

ImprovedTextParser

public text v1 · immutable
·published 2007-11-20 17:11 UTC
rendered paste body
using System;
using System.Data;
using System.Configuration;
using System.Text;
using System.Collections.Generic;
using System.Collections;

namespace BloggerLibrary
{

    public interface ITextParserTag
    {

        public string ProduceOutput(string content, string parameter);
    }
    public class TextParserTag : ITextParserTag
    {
        private string output;

        public string Output {
            get {
                return output.Replace(":questionmarkgoeshere:", "?").Replace(":moniesformepls:", "$");
            }
            set {
                output = value.Replace("?", ":questionmarkgoeshere:").Replace("$", ":moniesformepls:");
            }
        }

        protected string RealOutput {
            get {
                return output;
            }
            set {
                output = value;
            }
        }

        public virtual TextParserTag(string output)
        {
         
            this.Output = output;
        }

        private string ReplaceReservedChars(string str){
            return str.Replace("?", ":questionmarkgoeshere:").Replace("$", ":moniesformepls:");
        }

        private string ReplaceReservedCharsBack(string str){
            return str.Replace(":questionmarkgoeshere:", "?").Replace(":moniesformepls:", "$");
        }

        public string ProduceOutput(string content, string parameter){
            string value = ReplaceReservedCharsBack(Output.Replace("?", parameter).Replace("$", content));
            return value;
        }

    }
    public class ImprovedTextParser
    {

        class Tag
        {
            public StringBuilder Parameter;
            public StringBuilder Content;

            internal Tag()
            {
                Parameter = new StringBuilder();
                Content = new StringBuilder();
            }
        }

        private bool boolStripHTMLTags = true;

        public bool StripHTMLTags
        {
            get { return boolStripHTMLTags; }
            set { boolStripHTMLTags = value; }
        }

        private const char customOpenTag = '[';
        private const char customCloseTag = ']';
        private const char customEndToken = '/';

        private const char HTMLOpenTag = '<';
        private const char HTMLCloseTag = '>';
        private const char HTMLEndToken = '/';

        private Dictionary<string, TextParserTag> tagMap = new Dictionary<string, TextParserTag>();

        Stack<KeyValuePair<string, Tag>> tagStack = new Stack<KeyValuePair<string, Tag>>();

        private string textToParse;

        public string TextToParse
        {
            get { return textToParse; }
            set { textToParse = value; }
        }

        public ImprovedTextParser(string textToParse)
        {
            TextToParse = textToParse;
        }

        public ImprovedTextParser()
            : this(String.Empty)
        {
        }

        public void AddTag(string customTag, TextParserTag tagInfo)
        {
            tagMap.Add(customTag, tagInfo);
        }

        public string Parse()
        {
            string text = (StripHTMLTags) ? stripHTMLTags(TextToParse) : TextToParse;

            bool searchForNextTag = true;
            bool inTag = false, inCloseTag = false;

            string currentTag = String.Empty;

            StringBuilder sb = new StringBuilder();
            StringBuilder appendTo = sb;


            int i = 0, n = text.Length;
            while (i < n)
            {
                char curChar = text[i];
                if (searchForNextTag)
                {
                    int g = i;
                    i = text.IndexOf(customOpenTag, g);
                    if (i < 0)
                    {
                        i = n;
                    }

                    if (i != g)
                    {
                        string textToAppend = DoStuffWithToken(text.Substring(g, i - g));
                        
                        appendTo.Append(textToAppend);

                    }
                    if (i == n)
                    {
                        break; //we're done
                    }
                    searchForNextTag = false;
                    curChar = text[i]; //Make sure this one is pointing to the right character
                }

                if (curChar == customOpenTag)
                {
                    inTag = true;
                } else if (inTag)
                {
                    if (curChar == customEndToken)
                    {
                        inCloseTag = true;
                    }
                    else if (curChar == customCloseTag)
                    {
                        if (inCloseTag)
                        {
                            if (tagMap.ContainsKey(currentTag) && tagStack.Peek().Key == currentTag)
                            { //We have a closing tag which exists in the tagMap and is the next tag that needs to be closed

                                Tag tag = tagStack.Pop().Value;
                                StringBuilder tagContent = tag.Content; //Get all the content that is within this tag
                                StringBuilder tagParam = tag.Parameter;

                                if (tagStack.Count > 0) //Need to see if we need to append this to anything new
                                { //If there's any more tags we need to append it to that tag and not the outer most stringbuilder
                                    appendTo = tagStack.Peek().Value.Content;
                                }
                                else
                                {
                                    appendTo = sb;
                                }

                                appendTo.Append(tagMap[currentTag].ProduceOutput(tagContent.ToString(), tagParam.ToString()));

                            }
                            else
                            { //Tag non existent or would produce bad code, just output the code for it

                                appendTo.Append(customOpenTag + customEndToken + currentTag + customCloseTag);
                            }
                            inTag = false; //Reset to default values
                            inCloseTag = false;
                            currentTag = String.Empty;
                        }
                        else
                        { //Must be opening tag

                            //Check if the tag is something we need to act on or not
                            if (tagMap.ContainsKey(currentTag))
                            { //Lets rock

                                KeyValuePair<string, Tag> tagData = new KeyValuePair<string, Tag>(currentTag, new Tag());

                                tagStack.Push(tagData); //simply add the tag to the tagStack

                                appendTo = tagData.Value.Content; //Make sure all future stuff will go to this tag
                            }
                            else
                            { //No match - lets just output the stuff and pretend we never saw it
                                appendTo.Append(customOpenTag + currentTag + customCloseTag);
                            }
                            inTag = false;
                            currentTag = String.Empty;
                        }
                        searchForNextTag = true;
                    }
                    else
                    { //For now just assume it'll be a part of the tag - later on we need to parse parameters and etc
                        currentTag += curChar;
                    }
                }


                i++;
            }
            while(tagStack.Count > 0){
                KeyValuePair<string, Tag> tagData = tagStack.Pop();
                TextParserTag parserTag = tagMap[tagData.Key];
                sb.Append(parserTag.ProduceOutput(tagData.Value.Content.ToString(), tagData.Value.Content.ToString()));
            }
            
            return sb.ToString();
        }

        private string DoStuffWithToken(string p)
        {
            return p;
        }

        private string stripHTMLTags(string txt)
        {
            return txt.Replace(HTMLOpenTag.ToString(), "&lt;").Replace(HTMLCloseTag.ToString(), "&gt;");
        }
	
    }
}