Irony mysql解析模板

模板可以解析大部分sql,自测通过。在其原有的demo基础上修改的。Irony源码地址:https://github.com/IronyProject/Irony

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using Irony.Parsing;
  6 
  7 namespace Irony.Samples.SQL {
  8   // Loosely based on SQL89 grammar from Gold parser. Supports some extra TSQL constructs.
  9 
 10   [Language("SQL", "89", "SQL 89 grammar")]
 11   public class SqlGrammar : Grammar {
 12     public SqlGrammar() : base(false) { //SQL is case insensitive
 13       //Terminals
 14       var comment = new CommentTerminal("comment", "/*", "*/");
 15       var lineComment = new CommentTerminal("line_comment", "--", "\n", "\r\n");
 16       NonGrammarTerminals.Add(comment);
 17       NonGrammarTerminals.Add(lineComment);
 18       var number = new NumberLiteral("number");
 19       var string_literal = new StringLiteral("string", "'", StringOptions.AllowsDoubledQuote);
 20       var Id_simple = TerminalFactory.CreateSqlExtIdentifier(this, "id_simple"); //covers normal identifiers (abc) and quoted id's ([abc d], "abc d")
 21       var comma = ToTerm(",");
 22       var dot = ToTerm(".");
 23       var star = ToTerm("*");
 24       var CREATE = ToTerm("CREATE"); 
 25       var NULL = ToTerm("NULL");
 26       var NOT = ToTerm("NOT");
 27       var UNIQUE = ToTerm("UNIQUE"); 
 28       var WITH = ToTerm("WITH");
 29       var TABLE = ToTerm("TABLE"); 
 30       var ALTER = ToTerm("ALTER"); 
 31       var ADD = ToTerm("ADD"); 
 32       var COLUMN = ToTerm("COLUMN"); 
 33       var DROP = ToTerm("DROP"); 
 34       var CONSTRAINT = ToTerm("CONSTRAINT");
 35       var INDEX = ToTerm("INDEX"); 
 36       var ON = ToTerm("ON");
 37       var KEY = ToTerm("KEY");
 38       var PRIMARY = ToTerm("PRIMARY"); 
 39       var INSERT = ToTerm("INSERT");
 40       var INTO = ToTerm("INTO");
 41       var UPDATE = ToTerm("UPDATE");
 42       var SET = ToTerm("SET"); 
 43       var VALUES = ToTerm("VALUES");
 44       var DELETE = ToTerm("DELETE");
 45       var SELECT = ToTerm("SELECT"); 
 46       var FROM = ToTerm("FROM");
 47       var AS = ToTerm("AS");
 48       var COUNT = ToTerm("COUNT");
 49       var JOIN = ToTerm("JOIN");
 50       var BY = ToTerm("BY");
 51       var @case = ToTerm("Case");
 52       var when = ToTerm("When");
 53       var then = ToTerm("then");
 54       var @if = ToTerm("if");
 55       var @else = ToTerm("else");
 56       var end = ToTerm("end");
 57       #region define
 58       //Non-terminals
 59       var Id = new NonTerminal("Id");
 60       var stmt = new NonTerminal("stmt");
 61       var createTableStmt = new NonTerminal("createTableStmt");
 62       var createIndexStmt = new NonTerminal("createIndexStmt");
 63       var alterStmt = new NonTerminal("alterStmt");
 64       var dropTableStmt = new NonTerminal("dropTableStmt");
 65       var dropIndexStmt = new NonTerminal("dropIndexStmt");
 66       var selectStmt = new NonTerminal("selectStmt");
 67       var insertStmt = new NonTerminal("insertStmt");
 68       var updateStmt = new NonTerminal("updateStmt");
 69       var deleteStmt = new NonTerminal("deleteStmt");
 70       var fieldDef = new NonTerminal("fieldDef");
 71       var fieldDefList = new NonTerminal("fieldDefList");
 72       var nullSpecOpt = new NonTerminal("nullSpecOpt");
 73       var typeName = new NonTerminal("typeName"); 
 74       var typeSpec = new NonTerminal("typeSpec");
 75       var typeParamsOpt = new NonTerminal("typeParams");
 76       var constraintDef = new NonTerminal("constraintDef");
 77       var constraintListOpt = new NonTerminal("constraintListOpt");
 78       var constraintTypeOpt = new NonTerminal("constraintTypeOpt");
 79       var idlist = new NonTerminal("idlist"); 
 80       var idlistPar = new NonTerminal("idlistPar"); 
 81       var uniqueOpt = new NonTerminal("uniqueOpt");
 82       var orderList = new NonTerminal("orderList");
 83       var orderMember = new NonTerminal("orderMember"); 
 84       var orderDirOpt = new NonTerminal("orderDirOpt");
 85       var withClauseOpt = new NonTerminal("withClauseOpt");
 86       var alterCmd = new NonTerminal("alterCmd");
 87       var insertData = new NonTerminal("insertData"); 
 88       var intoOpt = new NonTerminal("intoOpt");
 89       var assignList = new NonTerminal("assignList");
 90       var whereClauseOpt = new NonTerminal("whereClauseOpt");
 91       var assignment = new NonTerminal("assignment");
 92       var expression = new NonTerminal("expression");
 93       var exprList = new NonTerminal("exprList");
 94       var selRestrOpt = new NonTerminal("selRestrOpt");
 95       var selList = new NonTerminal("selList");
 96       var intoClauseOpt = new NonTerminal("intoClauseOpt");
 97       var fromClauseOpt = new NonTerminal("fromClauseOpt");
 98       var groupClauseOpt = new NonTerminal("groupClauseOpt");
 99       var havingClauseOpt = new NonTerminal("havingClauseOpt");
100       var orderClauseOpt = new NonTerminal("orderClauseOpt");
101       //
102       var selectClauseOpt = new NonTerminal("selectClauseOpt");
103       var pageOpt = new NonTerminal("pageOpt");
104       var sysFunc = new NonTerminal("sysFunc");
105       var sysFuncArg = new NonTerminal("sysFuncArg");
106       var sysFuncArgList = new NonTerminal("sysFuncArgList");
107       var sysFuncName = new NonTerminal("sysFuncName");
108       var casewhenClauseOpt = new NonTerminal("casewhenClauseOpt");
109       // var sysFuncOpt = new NonTerminal("sysFuncOpt");
110 
111       var columnItemList = new NonTerminal("columnItemList");
112       var columnItem = new NonTerminal("columnItem");
113       var columnSource = new NonTerminal("columnSource");
114       var asOpt = new NonTerminal("asOpt");
115       var aliasOpt = new NonTerminal("aliasOpt");
116       var aggregate = new NonTerminal("aggregate");
117       var aggregateArg = new NonTerminal("aggregateArg");
118       var aggregateName = new NonTerminal("aggregateName");
119       var tuple = new NonTerminal("tuple");
120       var joinChainOpt = new NonTerminal("joinChainOpt");
121       var joinKindOpt = new NonTerminal("joinKindOpt");
122       var term = new NonTerminal("term");
123       var unExpr = new NonTerminal("unExpr");
124       var unOp = new NonTerminal("unOp");
125       var binExpr = new NonTerminal("binExpr");
126       var binOp = new NonTerminal("binOp");
127       var betweenExpr = new NonTerminal("betweenExpr");
128       var inExpr = new NonTerminal("inExpr");
129       var parSelectStmt = new NonTerminal("parSelectStmt");
130       var notOpt = new NonTerminal("notOpt");
131       var funCall = new NonTerminal("funCall");
132       var stmtLine = new NonTerminal("stmtLine");
133       var semiOpt = new NonTerminal("semiOpt");
134       var stmtList = new NonTerminal("stmtList");
135       var funArgs = new NonTerminal("funArgs");
136       var inStmt = new NonTerminal("inStmt");
137 #endregion
138 
139       //BNF Rules
140       this.Root = stmtList;
141       stmtLine.Rule = stmt + semiOpt;
142       semiOpt.Rule = Empty | ";";
143       stmtList.Rule = MakePlusRule(stmtList, stmtLine);
144 
145       // 巴科斯范式(Backus-Naur Form)BnfExpression
146       //引号中的字符表示这些他们本身,quote表示引号
147       //引号外的字符表示语法。
148       //<> 尖括号中的内容表示必选项
149       //[] 方括号中的内容表示可选项
150       //{ }大括号中的内容表示可重复0到无数次的项
151       //   | 竖线表示左右任选一项
152       //:= 冒号等于时被定义为的意思
153       // 例如:
154       // <pp>:=<tt>|<tt><pp>
155 
156       //ID
157       Id.Rule = MakePlusRule(Id, dot, Id_simple)| MakePlusRule(Id, dot, star)|Id_simple+Id_simple|selectClauseOpt|casewhenClauseOpt;
158 
159       stmt.Rule = createTableStmt | createIndexStmt | alterStmt 
160                 | dropTableStmt | dropIndexStmt 
161                 | selectStmt | insertStmt | updateStmt | deleteStmt
162                 | "GO" ;
163       //Create table
164       #region createsql
165       createTableStmt.Rule = CREATE + TABLE + Id + "(" + fieldDefList + ")" + constraintListOpt;
166       fieldDefList.Rule = MakePlusRule(fieldDefList, comma, fieldDef);
167       fieldDef.Rule = Id + typeName + typeParamsOpt + nullSpecOpt;
168       nullSpecOpt.Rule = NULL | NOT + NULL | Empty;
169       typeName.Rule = ToTerm("BIT") | "DATE" | "TIME" | "TIMESTAMP" | "DECIMAL" | "REAL" | "FLOAT" | "SMALLINT" | "INTEGER"
170                                    /*| "INTERVAL" */| "CHARACTER"
171                                    // MS SQL types:  
172                                    | "DATETIME" | "INT" | "DOUBLE" | "CHAR" | "NCHAR" | "VARCHAR" | "NVARCHAR"
173                                    | "IMAGE" | "TEXT" | "NTEXT";
174       typeParamsOpt.Rule = "(" + number + ")" | "(" + number + comma + number + ")" | Empty;
175       constraintDef.Rule = CONSTRAINT + Id + constraintTypeOpt;
176       constraintListOpt.Rule = MakeStarRule(constraintListOpt, constraintDef );
177       constraintTypeOpt.Rule = PRIMARY + KEY + idlistPar | UNIQUE + idlistPar | NOT + NULL + idlistPar
178                              | "Foreign" + KEY + idlistPar + "References" + Id + idlistPar;
179       idlistPar.Rule = "(" + idlist + ")";
180       idlist.Rule = MakePlusRule(idlist, comma, Id);
181       #endregion
182       #region othersql
183       //Create Index
184       createIndexStmt.Rule = CREATE + uniqueOpt + INDEX + Id + ON + Id + orderList + withClauseOpt;
185       uniqueOpt.Rule = Empty | UNIQUE;
186       orderList.Rule = MakePlusRule(orderList, comma, orderMember);
187       orderMember.Rule = Id + orderDirOpt;
188       orderDirOpt.Rule = Empty | "ASC" | "DESC";
189       withClauseOpt.Rule = Empty | WITH + PRIMARY | WITH + "Disallow" + NULL | WITH + "Ignore" + NULL;
190 
191       //Alter 
192       alterStmt.Rule = ALTER + TABLE + Id + alterCmd;
193       alterCmd.Rule = ADD + COLUMN  + fieldDefList + constraintListOpt 
194                     | ADD + constraintDef
195                     | DROP + COLUMN + Id
196                     | DROP + CONSTRAINT + Id;
197 
198       //Drop stmts
199       dropTableStmt.Rule = DROP + TABLE + Id;
200       dropIndexStmt.Rule = DROP + INDEX + Id + ON + Id; 
201 
202       //Insert stmt
203       insertStmt.Rule = INSERT + intoOpt + Id + idlistPar + insertData;
204       insertData.Rule = selectStmt | VALUES + "(" + exprList + ")"; 
205       intoOpt.Rule = Empty | INTO; //Into is optional in MSSQL
206 
207       //Update stmt
208       updateStmt.Rule = UPDATE + Id + SET + assignList + whereClauseOpt;
209       assignList.Rule = MakePlusRule(assignList, comma, assignment);
210       assignment.Rule = Id + "=" + expression;
211 
212       //Delete stmt
213       deleteStmt.Rule = DELETE + FROM + Id + whereClauseOpt;
214       #endregion
215 
216       #region selectsql
217       //Select stmt
218       selectStmt.Rule = SELECT + selRestrOpt + selList + intoClauseOpt + fromClauseOpt + whereClauseOpt +
219                         groupClauseOpt + havingClauseOpt + orderClauseOpt+pageOpt;
220       selRestrOpt.Rule = Empty | "ALL" | "DISTINCT";
221       selList.Rule = columnItemList | "*";
222       // comma:逗号
223       columnItemList.Rule = MakePlusRule(columnItemList, comma, columnItem);
224       // alias:别名
225       // columnItem匹配的是 xxx as xx
226       // 问题:怎样匹配 xx.*?
227       columnItem.Rule = columnSource + aliasOpt|columnItem+comma+ columnSource + aliasOpt;
228       aliasOpt.Rule = Empty | asOpt + Id|Id; 
229       asOpt.Rule = Empty | AS;
230       columnSource.Rule = aggregate | Id|selectClauseOpt|sysFunc|expression;
231       // aggregate:聚合
232       aggregate.Rule = aggregateName + "(" + aggregateArg + ")" 
233         | aggregateName + "(" + aggregateArg + ")"+binOp+number;
234       aggregateArg.Rule = expression | "*"|"distinct"+Id; 
235       aggregateName.Rule = COUNT | "Avg" | "Min" | "Max" | "StDev" | "StDevP" | "Sum" | "Var" | "VarP";
236       //
237       var whenthenClause = new NonTerminal("whenthenClause");
238       var whenthenItem = new NonTerminal("whenthenItem");
239       whenthenItem.Rule = when + expression + then + term;
240       whenthenClause.Rule = MakePlusRule(whenthenClause, whenthenItem);
241       // Empty| when + expression + then + term| whenthenClause + when + expression + then + term;
242 
243       sysFunc.Rule = sysFuncName + "(" + sysFuncArgList + sysFuncArg + ")"
244         | sysFuncName + "(" + sysFuncArgList + "'%Y-%m-%d'" + ")" | sysFuncName + "(" + sysFuncArgList + ")"
245         | sysFuncName + number + term;
246         // | sysFuncName + "(" + sysFuncArg+comma+expression + ")"
247         ;// "date_format(, '%Y-%m-%d')";
248       sysFuncArg.Rule = expression | "*";
249       sysFuncArgList.Rule = Empty | MakePlusRule(sysFuncArgList, comma, sysFuncArg);// sysFuncArg + comma | sysFuncArgList+ sysFuncArg + comma;
250 
251       sysFuncName.Rule = COUNT|"date_format" | "GROUP_CONCAT"| "CONCAT"| "ROUND"
252         |"if"| "unix_timestamp"|"date_sub"| "CURDATE"|"interval";
253       casewhenClauseOpt.Rule = Empty | @case+ whenthenClause + @else+expression+ end
254         | @case +expression+ whenthenClause + @else + expression + end;
255 
256       intoClauseOpt.Rule = Empty | INTO + Id;
257       fromClauseOpt.Rule = Empty | FROM + columnItem + joinChainOpt; 
258 
259       joinChainOpt.Rule = Empty | joinKindOpt + JOIN + idlist + ON + Id + "=" + Id;
260       // 添加字段 joinChainOpt
261       var someClauseOpt = new NonTerminal("someClauseOpt");
262       someClauseOpt.Rule = expression;// Id + "=" + Id| someClauseOpt+"and"+ Id + "=" + Id | someClauseOpt + "&&" + Id + "=" + Id;
263       // 添加字段 joinChainOpt
264       joinChainOpt.Rule =  Empty | joinChainOpt+joinKindOpt + JOIN + selectClauseOpt + ON + someClauseOpt | joinChainOpt+joinKindOpt + JOIN + idlist + ON + someClauseOpt;
265 
266       // joinChainOpt.Rule = Empty | joinChainOpt+ joinKindOpt + JOIN + selectClauseOpt + ON + Id + "=" + Id| joinChainOpt + joinKindOpt + JOIN + idlist + ON + Id + "=" + Id;
267       joinKindOpt.Rule = Empty | "INNER" | "LEFT" | "RIGHT"| joinKindOpt+"OUTER";
268       whereClauseOpt.Rule = Empty | "WHERE" + expression;
269       groupClauseOpt.Rule = Empty | "GROUP" + BY + idlist;
270       havingClauseOpt.Rule = Empty | "HAVING" + expression; 
271       orderClauseOpt.Rule = Empty | "ORDER" + BY + orderList;
272       selectClauseOpt.Rule =  "(" + selectStmt.Rule + ")"+ aliasOpt ;
273       pageOpt.Rule = Empty | "limit" + number | "limit" + number + comma + number;
274 
275 #endregion
276 
277       //Expression
278       exprList.Rule = MakePlusRule(exprList, comma, expression);
279       expression.Rule = term | unExpr | binExpr| betweenExpr| sysFunc; //-- BETWEEN doesn't work - yet; brings a few parsing conflicts 
280       term.Rule = Id | string_literal | number | funCall | tuple | parSelectStmt;// | inStmt;
281       tuple.Rule = "(" + exprList + ")";
282       parSelectStmt.Rule = "(" + selectStmt + ")"; 
283       unExpr.Rule = unOp + term;
284       unOp.Rule = NOT | "+" | "-" | "~"; 
285       binExpr.Rule = expression + binOp + expression;
286       binOp.Rule = ToTerm("+") | "-" | "*" | "/" | "%" //arithmetic
287                  | "&" | "|" | "^" |"&&"|"||"                    //bit
288                  | "=" | ">" | "<" | ">=" | "<=" | "<>" | "!=" | "!<" | "!>"
289                  | "AND" | "OR" | "LIKE" | NOT + "LIKE" | "IN" | NOT + "IN" |ToTerm("is")| ToTerm("is")+NOT; 
290       betweenExpr.Rule = expression + notOpt + "BETWEEN" + expression + "AND" + expression;
291       notOpt.Rule = Empty | NOT;
292       //funCall covers some psedo-operators and special forms like ANY(...), SOME(...), ALL(...), EXISTS(...), IN(...)
293       funCall.Rule = Id + "(" + funArgs  + ")";
294       funArgs.Rule = selectStmt | exprList;
295       inStmt.Rule = expression + "IN" + "(" + exprList + ")";
296 
297       //Operators
298       RegisterOperators(10, "*", "/", "%"); 
299       RegisterOperators(9, "+", "-");
300       RegisterOperators(8, "=", ">", "<", ">=", "<=", "<>", "!=", "!<", "!>", "LIKE", "IN");
301       RegisterOperators(7, "^", "&", "|","||","&&");
302       RegisterOperators(6, NOT); 
303       RegisterOperators(5, "AND");
304       RegisterOperators(4, "OR");
305 
306       MarkPunctuation(",", "(", ")");
307       MarkPunctuation(asOpt, semiOpt);
308       //Note: we cannot declare binOp as transient because it includes operators "NOT LIKE", "NOT IN" consisting of two tokens. 
309       // Transient non-terminals cannot have more than one non-punctuation child nodes.
310       // Instead, we set flag InheritPrecedence on binOp , so that it inherits precedence value from it's children, and this precedence is used
311       // in conflict resolution when binOp node is sitting on the stack
312       base.MarkTransient(stmt, term, asOpt, aliasOpt, stmtLine, expression, unOp, tuple);
313       binOp.SetFlag(TermFlags.InheritPrecedence); 
314 
315     }//constructor
316 
317   }//class
318 }//namespace

 

posted @ 2020-06-16 09:02  编程渣渣125  阅读(338)  评论(0)    收藏  举报