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 }
}