using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace AIMSObjectQuery
{
	internal class SyntaxAnalyzer
    {
        /// 
        /// 由对象查询语句解析为Sql语句
        /// 
        /// 
        /// 
        /// 
        public static string ParseSql(string oql,IMap map)
        {
			if(oql==string.Empty)
			    return string.Empty;
            SyntaxNode syntaxNode=new SyntaxNode();
            syntaxNode.Sentence = oql;
            if (syntaxNode.Map == null)
                syntaxNode.Map = map;
            string sql = syntaxNode.GetSql();
            return sql;
        }
    }
    class SyntaxNode
    {
        private static List keywords=new List();
        private static List funKeywords = new List();
        /// 
        /// 关键字列表
        /// 
        static SyntaxNode()
        {
            keywords.Add("in");
            keywords.Add("and");
            keywords.Add("or");
            keywords.Add("like");
            keywords.Add("not");
            keywords.Add("between");
            keywords.Add("to");
            keywords.Add("as");
            keywords.Add("is");
			keywords.Add("null");
            keywords.Add("tinyint");
            keywords.Add("smallint");
            keywords.Add("int");
            keywords.Add("bigint");
            keywords.Add("decimal");
            keywords.Add("numeric");
            keywords.Add("smallmoney");
            keywords.Add("money");
            keywords.Add("float");
            keywords.Add("real");
            keywords.Add("char");
            keywords.Add("text");
            keywords.Add("varchar");
            keywords.Add("nchar");
            keywords.Add("ntext");
            keywords.Add("nvarchar");
            keywords.Add("desc");
            keywords.Add("asc");
            funKeywords.Add("dateadd");
            funKeywords.Add("datediff");
            funKeywords.Add("datename");
            funKeywords.Add("datepart");
        }
        private IMap map;
        /// 
        /// 属性和字段间的映射
        /// 
        public IMap Map
        {
            get { return map; }
            set { map = value; }
        }
        private string sentence;
        public string Sentence
        {
            get { return sentence; }
            set
            {
                sentence = value;
                if (this.sentenceType == SentenceType.Segment || this.sentenceType == SentenceType.InBracket)
                    Parse();
            }
        }
        private SentenceType sentenceType=SentenceType.Segment;
        /// 
        /// 语句类型
        /// 
        public SentenceType SentenceType
        {
            get { return sentenceType; }
            set 
            { 
                sentenceType = value;
            }
        }
        private SyntaxNode parentNode;
        /// 
        /// 父节点
        /// 
        public SyntaxNode ParentNode
        {
            get { return parentNode; }
            set { parentNode = value; }
        }
        private List nodes=new List();
        /// 
        /// 子节点集合
        /// 
        public List Nodes
        {
            get { return nodes; }
            set { nodes = value; }
        }
        /// 
        /// 在碰到“(”后,取出与之对应的“)”之间的内容
        /// 
        /// 字符数组
        /// 当前字符位置
        private void ParseInBracket(ref Char[] charArray, ref int index)
        {
            int bracketDepth=1;//括号深度,“(”加1,“)”减1
            bool inQuotation = false;//是否在引号内
            string inBracketString=string.Empty;
            index++;
            //遍历当前字符串到倒数第二个字符
            for (; index < charArray.Length - 1; index++)
            {
                char c = charArray[index];
                if (inQuotation)                         //如果在引号内,后面有两个连续的“'”则当成普通字符,一个“'”则结束字符串
                {
                    if (c == '\'')                       //出现一个引号后再出现了另一个引号
                    {
                        if (charArray[index + 1] == '\'')//如果“'”后面的还是“'”,SQL解析为一个“'”
                        {
                            inBracketString += "''";
                            index++;                     //跳过第二个“'”
                        }
                        else
                        {
                            inQuotation = false;
                            inBracketString += "'";
                        }
                    }
                    else                                 //除“'”号之外的其它字符则加到字符串中
                    {
                        inBracketString += c.ToString(); 
                    }
                }
                else                                     //不在引号内
                {
                    if (c == '\'')                       //出现了第一个引号,设置inQuotation为true
                    {
                        inQuotation = true;
                        inBracketString += "'";
                    }
                    else if (c == '(')                   //出现了“(”则括号计数加1
                    {
                        inBracketString += "(";
                        bracketDepth++;
                    }
                    else if (c == ')')                   //出现了“)”则括号计数减1,如果计数为0则表示此次整个括号的内容结束
                    {
                        bracketDepth--;
                        if (bracketDepth == 0)
                        {
                            SyntaxNode node = new SyntaxNode();
                            node.SentenceType = SentenceType.InBracket;
                            node.Sentence = inBracketString;
                            node.parentNode = this;
                            nodes.Add(node);
                            return;
                        }
                        else
                        {
                            inBracketString += ")";
                        }
                    }
                    else
                    {
                        inBracketString += c.ToString();
                    }
                }
            }
            //处理最后一个字符
            char lastChar = charArray[charArray.Length - 1];
            if (lastChar == ')' && bracketDepth==1)
            {
                SyntaxNode node = new SyntaxNode(); 
                node.parentNode = this;
                node.SentenceType = SentenceType.InBracket;
                node.Sentence = inBracketString;
                nodes.Add(node);
            }
            else
            {
                throw new Exception("缺少“)”");
            }
        }
        /// 
        /// 在碰到“'”后,取出整个字符串的内容
        /// 
        /// 字符数组
        /// 当前字符位置
        private void ParseInQuotation(ref Char[] charArray, ref int index)
        {
            string inQuotationString = "'";
            index++;
            //遍历当前字符串到倒数第二个字符
            for (; index < charArray.Length - 1; index++)
            {
                char c = charArray[index];
                if (c == '\'')
                {
                    if (charArray[index + 1] == '\'')   //如果“'”后面的还是“'”,SQL解析为一个“'”
                    {
                        inQuotationString += "''";
                        index++;                        //跳过第二个“'”
                    }
                    else                                //出现了另一个“'”号,记录整个字符串
                    {
                        inQuotationString += "'";
                        SyntaxNode node = new SyntaxNode();
                        node.ParentNode = this;
                        node.SentenceType = SentenceType.String;
                        node.sentence = inQuotationString;
                        nodes.Add(node);
                        return;
                    }
                }
                else
                {
                    inQuotationString += c.ToString();
                }
            }
            //处理最后一个字符
            char lastChar = charArray[charArray.Length - 1];
            if (lastChar == '\'')
            {
                SyntaxNode node = new SyntaxNode();
                node.ParentNode = this;
                node.SentenceType = SentenceType.String;
                node.sentence = inQuotationString+"'";
                nodes.Add(node);
            }
            else
            {
                throw new Exception("缺少“'”");
            }
        }
        /// 
        /// 解析整条语句,生成树型结构
        /// 
        public void Parse()
        {
            string s = string.Empty;
            Char[] charArray = sentence.ToCharArray();
            for (int i = 0; i < charArray.Length; i++)
            {
                char c=charArray[i];
                if (c == '\'')                                      //如果碰见一个“'”,调用ParseInQuotation记录从该处开始其后的字符串
                {
                    if (s != string.Empty)
                    {
                        throw new Exception("“'”附近有语法错误");
                    }
                    ParseInQuotation(ref charArray, ref i);
                }
                else if (c == '(')                                  //如果碰见一个“(”,调用ParseInBracket记录从该处开始到与之对应的“)”之间的内容
                {
                    string funName = string.Empty;
                    if (s != string.Empty)
                    {
                        SyntaxNode node = new SyntaxNode();
                        node.ParentNode = this;
                        node.sentence = s;
                        node.SentenceType = SentenceType.Function;
                        this.nodes.Add(node);
                        funName = s.ToLower();
                        s = string.Empty;
                    }
                    ParseInBracket(ref charArray, ref i);
                    if (funKeywords.Contains(funName) && this.nodes[this.nodes.Count - 1].nodes.Count > 0)
                        this.nodes[this.nodes.Count - 1].nodes[0].SentenceType = SentenceType.Keyword;
                }
                else if (c == ' ')                                  //如果碰见一个空格,记录空格前的内容
                {
                    if (s != string.Empty)
                    {
                        SyntaxNode node = new SyntaxNode();
                        node.ParentNode = this;
                        if (nodes.Count > 0 && nodes[nodes.Count - 1].sentenceType == SentenceType.From)
                        {
                            node.sentenceType = SentenceType.Entity;
                            EntityInfo entityInfo = EntityMap.GetEntityInfo(GetName(s));
                            if (entityInfo == null)
                                throw new Exception("from后有语法错误,使用了一个不存在的实体名");
							this.map = entityInfo.PropertyMap;
                        }
                        else
                            node.SentenceType = GetSentenceType(s);
                        node.sentence = GetName(s) + " ";
                        this.nodes.Add(node);
                        s = string.Empty;
                    }
                }
                else if (c == '+' || c == '-' || c == '*' || c == '/' || c == '=' || c == '!' || c == '<' || c == '>' || c == ',')//如果碰见一个符号,记录符号前的内容及符号本身
                {
                    if (s != string.Empty)
                    {
                        SyntaxNode node = new SyntaxNode();
                        node.ParentNode = this;
                        node.SentenceType = GetSentenceType(s);
                        node.sentence = s;
                        this.nodes.Add(node);
                    }
                    SyntaxNode operatorNode = new SyntaxNode();
                    operatorNode.ParentNode = this;
                    operatorNode.SentenceType = SentenceType.Symbol;
                    operatorNode.sentence = c.ToString();
                    this.nodes.Add(operatorNode);
                    s = string.Empty;
                }
                else
                {
                    s += c.ToString();
                }
            }
            //记录最后的内容
            if (s != string.Empty)
            {
                SyntaxNode node = new SyntaxNode();
                node.parentNode = this;
                if (nodes.Count > 0 && nodes[nodes.Count - 1].sentenceType == SentenceType.From)
                {
                    node.sentenceType = SentenceType.Entity;
                    EntityInfo entityInfo = EntityMap.GetEntityInfo(GetName(s));
                    if (entityInfo == null)
                        throw new Exception("from后有语法错误,使用了一个不存在的实体名");
					this.map = entityInfo.PropertyMap;
                }
                else
                    node.SentenceType = GetSentenceType(s);
                node.sentence = GetName(s);
                this.nodes.Add(node);
            }
        }
        private string GetName(string str)
        {
            string s = str.ToLower().Trim();
            if (s.IndexOf('[') == 0 && s.LastIndexOf(']') == s.Length - 1)
                s = s.Substring(1, s.Length - 2);
            return s;
        }
        /// 
        /// 获取语句的类型
        /// 
        /// 语句
        /// 语句类型
        public SentenceType GetSentenceType(string sentence)
        {
            if (IsNumeric(sentence))
                return SentenceType.Numeric;
            if (sentence.Substring(0, 1) == "@")
                return SentenceType.Parameter;
            string s = sentence.ToLower();
            if (keywords.Contains(sentence))
                return SentenceType.Keyword;
            switch (s)
            {
                case "select":return SentenceType.Select;
                case "from": return SentenceType.From;
                case "where": return SentenceType.Where;
                case "group": return SentenceType.Group;
                case "order": return SentenceType.Order;
                case "by": return SentenceType.By;
                default: return SentenceType.Property;
            }
        }
        /// 
        /// 判断字符串是否是数值格式
        /// 
        /// 字符串
        /// true:是数值格式 false:不是数值格式
        private bool IsNumeric(string str)
        {
            Regex regex = new Regex("^(-?[0-9]*[.]*[0-9]{0,3})$");
            return regex.IsMatch(str);
        }
        /// 
        /// 获取解析后的Sql语句
        /// 
        /// 
        public string GetSql()
        {
			if (this.map == null)
                this.map = this.parentNode.map;
            string sql = "";
			if (this.SentenceType == SentenceType.Segment)
            {
                foreach (SyntaxNode node in nodes)
                {
                    sql += node.GetSql();
                }
            }
            else if (this.SentenceType == SentenceType.InBracket)
            {
                foreach (SyntaxNode node in nodes)
                {
                    sql += node.GetSql();
                }
                sql = "(" + sql + ")";
            }
            else if(this.SentenceType==SentenceType.Property)
            {
                sql += this.sentence.Replace(this.sentence.Trim(), "["+this.map[this.sentence.Trim()]+"]");
            }
            else if (this.SentenceType == SentenceType.Entity)
            {
                sql += this.sentence.Replace(this.sentence.Trim(), "["+EntityMap.GetEntityInfo(this.sentence.Trim()).TableName+"]");
            }
			else if (this.SentenceType == SentenceType.String)
            {
                sql = this.sentence+" ";
            }
            else
            {
                sql = this.sentence;
            }
            return sql;
        }
        /// 
        /// 获取语句中包含的参数列表
        /// 
        /// 
        public List GetParameters()
        {
            List parameters = new List();
            if (this.SentenceType == SentenceType.Parameter)
            {
                parameters.Add(this.sentence.Trim());
            }
            else if (this.SentenceType == SentenceType.InBracket)
            {
                foreach (SyntaxNode node in nodes)
                {
                    List childParameters = node.GetParameters();
                    foreach (string para in childParameters)
                    {
                        parameters.Add(para);
                    }
                }
            }
            return parameters;
        }
    }
    enum SentenceType { Segment, InBracket, String, Numeric, Parameter, Entity, Property, Symbol, Keyword, Function, Select, From, Where, Group, By, Order }
}