User:A2569875-bot/Code/WikiEntityDatatype.cs

维基百科,自由的百科全书
using System;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using WikiTemplateArgUtil;

namespace DotNetWikiBot
{
  public abstract class WikiEntity
    {
        public abstract string genCode();
    }

    public class WikiText : WikiEntity
    {
        public List<WikiEntity> WikiEntityList;
        public override string genCode() {
            string wikicode= "";
            for (int i = 0; i < WikiEntityList.Count; ++i)
            {
                wikicode += WikiEntityList[i].genCode();
            }
            return wikicode;
        }
        public WikiText(WikiEntity entity)
        {
            WikiEntityList = new List<WikiEntity> { entity };
        }
        public WikiText(TreeNode<ParsingTreeNode> parsing_tree)
        {
            WikiEntityList = new List<WikiEntity>();
            for (int i=0; i< parsing_tree.Children.Count; ++i)
            {
                WikiEntity the_entity = null;
                switch (parsing_tree[i].Value.symbol.TokenType)
                {
                    case TokenSymobl.SymbolType.XML:
                        the_entity = new WikiXml(parsing_tree[i]);
                        break;
                    case TokenSymobl.SymbolType.Template:
                        the_entity = new WikiTemplate(parsing_tree[i]);
                        break;
                    case TokenSymobl.SymbolType.Link:
                        the_entity = new WikiLink(parsing_tree[i]);
                        break;
                    case TokenSymobl.SymbolType.Variable:
                        the_entity = new WikiVariable(parsing_tree[i]);
                        break;
                    case TokenSymobl.SymbolType.Text:
                        the_entity = new WikiFlatText(parsing_tree[i]);
                        break;
                    case TokenSymobl.SymbolType.Comment:
                        the_entity = new WikiComment(parsing_tree[i]);
                        break;
                    default:
                        the_entity = new WikiText(parsing_tree[i]);
                        break;
                }
                if(the_entity != null)
                {
                    WikiEntityList.Add(the_entity);
                }
            }
        }
        public WikiText(TreeNode<ParsingTreeNode> parsing_tree, int start, int end)
        {
            WikiEntityList = new List<WikiEntity>();
            for (int i = start; i < parsing_tree.Children.Count && i < end; ++i)
            {
                WikiEntity the_entity = null;
                switch (parsing_tree[i].Value.symbol.TokenType)
                {
                    case TokenSymobl.SymbolType.XML:
                        the_entity = new WikiXml(parsing_tree[i]);
                        break;
                    case TokenSymobl.SymbolType.Template:
                        the_entity = new WikiTemplate(parsing_tree[i]);
                        break;
                    case TokenSymobl.SymbolType.Link:
                        the_entity = new WikiLink(parsing_tree[i]);
                        break;
                    case TokenSymobl.SymbolType.Variable:
                        the_entity = new WikiVariable(parsing_tree[i]);
                        break;
                    case TokenSymobl.SymbolType.Text:
                        the_entity = new WikiFlatText(parsing_tree[i]);
                        break;
                    case TokenSymobl.SymbolType.Comment:
                        the_entity = new WikiComment(parsing_tree[i]);
                        break;
                    default:
                        the_entity = new WikiText(parsing_tree[i]);
                        break;
                }
                if (the_entity != null)
                {
                    WikiEntityList.Add(the_entity);
                }
            }
        }

        public override string ToString()
        {
            string show_list = "[";
            for(int i=0; i< WikiEntityList.Count; ++i)
            {
                show_list += "{" + WikiEntityList[i].ToString() + "}" + ((i+1!= WikiEntityList.Count)? ", ":"");
            }
            show_list += "]";
            return "WikiText " + show_list;
        }
    }

    public class WikiXmlAttri
    {
        public string Name;
        public string Value;
        public readonly bool IsVoid;
        public WikiXmlAttri(string name)
        {
            Name = name;
            IsVoid = true;
        }
        public WikiXmlAttri(string name, string val)
        {
            Name = name;
            Value = val;
            IsVoid = false;
        }
        public override string ToString()
        {
            if (IsVoid) return Name;
            else return Name + "=" + Value;
        }
    }

    public class WikiXml : WikiEntity
    {
        public string Name;
        public List<WikiXmlAttri> Attributes;
        public string FullEndTag;
        public WikiText InnerXml;
        bool IsVoid;
        public override string genCode()
        {
            string start_tag = "";
            string end_tag = "";
            if (FullEndTag != "") end_tag = FullEndTag;
            if (IsVoid)
            {
                if (FullEndTag != "") end_tag = FullEndTag;
                else end_tag = "<" + Name + ((start_tag == "") ? (" " + start_tag) : "") + "/>";
            }
            for (int i = 0; i < Attributes.Count; ++i)
            {
                start_tag += Attributes[i].ToString() + " ";
            }
            start_tag = "<" + Name + " " + start_tag + ">";
            if (!IsVoid) return start_tag + InnerXml.genCode() + end_tag;
            else return end_tag;
        }
        private static List<string> attri_string_list(string input)
        {
            string get_name_and_att = (input.Length > 2) ?  input.Substring(1, input.Length-2) : "";
            get_name_and_att = get_name_and_att.Trim(' ');
            get_name_and_att = get_name_and_att.Trim('/');
            get_name_and_att = get_name_and_att.Trim(' ');
            get_name_and_att += " $";
            string getter_buffer = "";
            string getter_val_buffer = "";
            List<string> token_list = new List<string>();
            bool has_name = false;
            bool has_val = false;
            for (int i = 0; i < get_name_and_att.Length; ++i)
            {
                string now_char = get_name_and_att.Substring(i, 1);
                string next_char = (i + 1 < get_name_and_att.Length) ? get_name_and_att.Substring(i + 1, 1) : "";
                if (!has_name)
                {
                    if (now_char == " " && next_char != " " && getter_buffer.Trim(' ').Trim('\n').Trim('\t').Trim('\r').Length > 0)
                    {
                        has_name = true;
                        token_list.Add(getter_buffer.Trim(' ').Trim('\n').Trim('\t').Trim('\r'));
                        getter_buffer = "";
                        continue;
                    }else
                    {
                        getter_buffer += now_char;
                    }
                }else
                {
                    if (!has_val && now_char == " " && next_char != " " && next_char != "=" && getter_buffer.Trim(' ').Trim('\n').Trim('\t').Trim('\r').Length > 0)
                    {
                        has_val = false;
                        token_list.Add(getter_buffer.Trim(' ').Trim('\n').Trim('\t').Trim('\r'));
                        getter_buffer = "";
                        continue;
                    } else if(!has_val && now_char == "=")
                    {
                        has_val = true;
                        getter_buffer += now_char;
                        getter_val_buffer = "";
                        continue;
                    }else if (has_val && now_char == " " && next_char != " " && next_char != "=" && getter_val_buffer.Trim(' ').Trim('\n').Trim('\t').Trim('\r').Length > 0)
                    {
                        has_val = false;
                        token_list.Add((getter_buffer + getter_val_buffer).Trim(' ').Trim('\n').Trim('\t').Trim('\r'));
                        getter_val_buffer = "";
                        getter_buffer = "";
                        continue;
                    }else
                    {
                        if(has_val) getter_val_buffer += now_char;
                        else getter_buffer += now_char;
                    }
                }
            }
            return token_list;
        }
        private void FillAttri(List<string> split)
        {
            Name = split[0];
            Attributes = new List<WikiXmlAttri>();
            for (int i = 1; i < split.Count; ++i)
            {
                string[] splitArg = split[i].Split(new char[] { '=' });
                if (splitArg.Length >= 2)
                {
                    string frk_arg = "";
                    for (int j = 1; j < splitArg.Length; ++j) frk_arg += splitArg[j];
                    Attributes.Add(new WikiXmlAttri(splitArg[0], frk_arg));
                    continue;
                }
                else
                {
                    Attributes.Add(new WikiXmlAttri(splitArg[0]));
                }
            }
        }
        public WikiXml(TreeNode<ParsingTreeNode> parsing_tree)
        {
            if(parsing_tree.Children.Count > 0)
            {
                if(parsing_tree.Children.Count == 1)
                {
                    IsVoid = true;
                    InnerXml = new WikiText(new WikiFlatText(""));
                    FillAttri(attri_string_list(parsing_tree[0].Value.Value));
                    FullEndTag = parsing_tree[0].Value.Value;
                }
                else
                {
                    IsVoid = false;
                    List<string> split = attri_string_list(parsing_tree[0].Value.Value);
                    FillAttri(attri_string_list(parsing_tree[0].Value.Value));
                    InnerXml = new WikiText(parsing_tree, 1, parsing_tree.Children.Count - 1);
                    FullEndTag = parsing_tree[parsing_tree.Children.Count - 1].Value.Value;
                }
            }else
            {
                IsVoid = true;
                InnerXml = new WikiText(new WikiFlatText(""));
                Attributes = new List<WikiXmlAttri>();
                FullEndTag = "";
                Name = " ";
            }
        }
        public override string ToString()
        {
            return "MarkupTag <" + Name + ">";
        }
    }

    public class WikiTemplate : WikiTemplateBase
    {
        protected override string StartSymbol { get {
            //if (Head_Tail[0] == null)
                    return "{{";
            //if (Head_Tail[0] == "") return "{{";
            //return Head_Tail[0];
        } }
        protected override string EndSymbol { get {
            //if (Head_Tail[1] == null)
                    return "}}";
            //if (Head_Tail[1] == "") return "}}";
            //return Head_Tail[1];
        } }
        private string[] Head_Tail;
        public WikiTemplate(TreeNode<ParsingTreeNode> parsing_tree)
        {
            start_pos = parsing_tree[0].Value.token_pos;
            if (parsing_tree[parsing_tree.Children.Count - 1].Value.fullText == null) stop_pos = parsing_tree[parsing_tree.Children.Count - 1].Value.token_pos + parsing_tree[parsing_tree.Children.Count - 1].Value.Value.Length;
            else stop_pos = parsing_tree[parsing_tree.Children.Count - 1].Value.token_pos + parsing_tree[parsing_tree.Children.Count - 1].Value.fullText.Length;
            Name = new WikiText(parsing_tree[1]);
            arg_list = new List<WikiTemplateArgBase>();
            for (int i = 2; i < parsing_tree.Children.Count - 1; ++i) 
            {
                arg_list.Add(WikiTemplateArgBase.Create(parsing_tree[i]));
            }
            Head_Tail = new string[] { parsing_tree[0].Value.fullText, parsing_tree[parsing_tree.Children.Count - 1].Value.fullText };
        }
        public override string ToString()
        {
            return "Template name=" + Name.ToString();
        }
    }
    public class WikiLink : WikiTemplateBase
    {
        protected override string StartSymbol { get {
            if (Head_Tail[0] == null) return "[[";
            if (Head_Tail[0] == "") return "[[";
            return Head_Tail[0];
        } }
        protected override string EndSymbol { get {
            if (Head_Tail[1] == null) return "]]";
            if (Head_Tail[1] == "") return "]]";
            return Head_Tail[1];
        } }
        private string[] Head_Tail;
        public WikiLink(TreeNode<ParsingTreeNode> parsing_tree)
        {
            start_pos = parsing_tree[0].Value.token_pos;
            if(parsing_tree[parsing_tree.Children.Count - 1].Value.fullText == null) stop_pos = parsing_tree[parsing_tree.Children.Count - 1].Value.token_pos + parsing_tree[parsing_tree.Children.Count - 1].Value.Value.Length;
            else stop_pos = parsing_tree[parsing_tree.Children.Count - 1].Value.token_pos + parsing_tree[parsing_tree.Children.Count - 1].Value.fullText.Length;
            Name = new WikiText(parsing_tree[1]);
            arg_list = new List<WikiTemplateArgBase>();
            for (int i = 2; i < parsing_tree.Children.Count - 1; ++i)
            {
                arg_list.Add(WikiTemplateArgBase.Create(parsing_tree[i]));
            }
            Head_Tail = new string[] { parsing_tree[0].Value.fullText, parsing_tree[parsing_tree.Children.Count - 1].Value.fullText };
        }
        public override string ToString()
        {
            return "Link page=" + Name.ToString();
        }
    }
    public class WikiVariable : WikiTemplateBase
    {
        protected override string StartSymbol { get {
            if (Head_Tail[0] == null) return "{{{";
            if (Head_Tail[0] == "") return "{{{";
            return Head_Tail[0];
        } }
        protected override string EndSymbol { get {
            if (Head_Tail[1] == null) return "}}}";
            if (Head_Tail[1] == "") return "}}}";
            return Head_Tail[1];
        } }
        private string[] Head_Tail;
        public WikiVariable(TreeNode<ParsingTreeNode> parsing_tree)
        {
            start_pos = parsing_tree[0].Value.token_pos;
            if (parsing_tree[parsing_tree.Children.Count - 1].Value.fullText == null) stop_pos = parsing_tree[parsing_tree.Children.Count - 1].Value.token_pos + parsing_tree[parsing_tree.Children.Count - 1].Value.Value.Length;
            else stop_pos = parsing_tree[parsing_tree.Children.Count - 1].Value.token_pos + parsing_tree[parsing_tree.Children.Count - 1].Value.fullText.Length;
            Name = new WikiText(parsing_tree[1]);
            arg_list = new List<WikiTemplateArgBase>();
            for (int i = 2; i < parsing_tree.Children.Count - 1; ++i)
            {
                arg_list.Add(WikiTemplateArgBase.Create(parsing_tree[i]));
            }
            Head_Tail = new string[] { parsing_tree[0].Value.fullText, parsing_tree[parsing_tree.Children.Count - 1].Value.fullText };
        }
        public override string ToString()
        {
            return "Variable name=" + Name.ToString();
        }
    }
    public class WikiFlatTextBase : WikiEntity
    {
        public String Value = "";
        public String FullText = "";
        public override string genCode()
        {
            return Value;
        }
    }
    public class WikiFlatText : WikiFlatTextBase {
        public WikiFlatText(TreeNode<ParsingTreeNode> parsing_tree)
        {
            Value = parsing_tree.Value.Value;
            FullText = parsing_tree.Value.fullText;
        }
        public WikiFlatText(string str)
        {
            Value = str;
            FullText = str;
        }
        public override string ToString()
        {
            return Value;
        }
    }
    public class WikiComment : WikiFlatTextBase {
        public WikiComment(TreeNode<ParsingTreeNode> parsing_tree)
        {
            Value = parsing_tree.Value.Value;
            FullText = parsing_tree.Value.fullText;
        }
        public WikiComment(string str)
        {
            Value = str;
            FullText = str;
        }
        public override string ToString()
        {
            return "(Comment) " + Value;
        }
    }
}