KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > tests > jfun > parsec > mssql > SqlParser


1 /*
2  * Created on 2004-11-15
3  *
4  * Author Ben Yu
5  */

6 package tests.jfun.parsec.mssql;
7 import jfun.parsec.Parser;
8 import jfun.parsec.Parsers;
9 import jfun.parsec.tokens.TokenQuoted;
10 //import jfun.parsec.scanner.Scanner;
11
import jfun.parsec.DefaultPositionMap;
12 import jfun.parsec.Map;
13 import jfun.parsec.Map2;
14 import jfun.parsec.Mapn;
15 import jfun.parsec.Scanners;
16 import jfun.parsec.Lexers;
17 import jfun.parsec.Terms;
18 import jfun.parsec.FromString;
19 import jfun.parsec.FromString3;
20 import jfun.parsec.Tokenizer;
21
22
23 import jfun.parsec.ParserEval;
24 import jfun.parsec.ToParser;
25 import jfun.parsec.OperatorTable;
26 import jfun.parsec.Expressions;
27 /**
28  * @author Ben Yu
29  *
30  * 2004-11-15
31  */

32 public final class SqlParser {
33   //In this parser, we allow trailing comma after a list.
34
//1. this is to test the Parsers.sepEndBy1 combinator.
35
//2. our parser can be more tolerant.
36
private static final Terms words = Terms.getCaseInsensitiveInstance(
37       new String JavaDoc[]{
38           ".", ",", "(", ")", "+", "-", "*", "/", "%", "&", "|",
39           "<", ">", ">=", "<=", "=", "<>", "!="
40       },
41       new String JavaDoc[]{
42           "null", "Is", "and", "or", "not", "NOT", //to test the case insensitivity and duplicate.
43
"case", "when", "case", "then", "else", "end",
44           "select", "begin", "set", "update", "insert",
45           "values", "from", "where", "order", "by",
46           "group", "having", "inner", "outer", "left",
47           "right", "full", "join", "on", "in",
48           "between", "exists", "if", "as", "cross",
49           "desc", "asc", "like", "escape"
50           
51       }
52   );
53   public static Parser word(String JavaDoc n){
54     return words.getParser(n);
55   }
56   public static Parser expr(){return ExprP.parser;}
57   
58   public static Parser bool_expr(){return BoolExprP.parser;}
59
60   private static final Parser dot = word(".");
61   private static final Parser lparen = word("(");
62   private static final Parser rparen = word(")");
63   private static final Parser comma = word(",");
64   private static final Parser word_select = word("select");
65   //private static final Parser subquery_start = lparen.seq("(select", word_select).atomize();
66
private static final Parser id = Parsers.plus(
67       Terms.wordParser(new FromString(){
68         public Object JavaDoc fromString(int from, int len, final String JavaDoc name){
69           return Id.instance(name.toString());
70         }
71       }),
72       Terms.quotedWordParser(new FromString3(){
73         public Object JavaDoc fromString3(int from, int len,
74             final String JavaDoc open, final String JavaDoc name, final String JavaDoc close){
75           if(open.equals("["))
76             return Id.bracketed(name.toString());
77           else if(open.equals("\""))
78             return Id.quoted(name.toString());
79           else return null;
80         }
81       })
82     );
83   //Parser Id[]
84
private static final Parser qualifiedId = Parsers.sepBy1("qualifiedId", Id.class, dot, id);
85   //Parser QualifiedName
86
private static final Parser qualifiedName = qualifiedId.map(new Map(){
87       public Object JavaDoc map(final Object JavaDoc o){
88         final Id[] names = (Id[])o;
89         return new QualifiedName(names);
90       }
91     });
92
93   
94
95
96
97
98
99   private static final Parser lazy_expr = Parsers.lazy("lazy_expr", new ParserEval(){
100     public Parser eval(){return ExprP.parser;}
101   });
102   private static final Parser lazy_bool_expr = Parsers.lazy("lazy_bool_expr", new ParserEval(){
103     public Parser eval(){return BoolExprP.parser;}
104   });
105   
106   private static final Parser lazy_relation = Parsers.lazy(new ParserEval(){
107     public Parser eval(){return parseRelation();}
108   });
109   
110   /*Parsers.lazy("lazy subquery", new ParserEval(){
111     public Parser eval(){return subquery();}
112   });*/

113
114   private static Map2 toMap2(final LogicalBinaryOp op){
115     return new Map2(){
116       public Object JavaDoc map(final Object JavaDoc o1, final Object JavaDoc o2){
117         return op.apply((Expression)o1, (Expression)o2);
118       }
119     };
120   }
121   private static Map2 toMap2(final BoolBinaryOp op){
122     return new Map2(){
123       public Object JavaDoc map(final Object JavaDoc o1, final Object JavaDoc o2){
124         return op.apply((BoolExpression)o1, (BoolExpression)o2);
125       }
126     };
127   }
128
129   private static Parser lretnMap2(final LogicalBinaryOp op){
130     return Parsers.retn(toMap2(op));
131   }
132   private static Parser bretnMap2(final BoolBinaryOp op){
133     return Parsers.retn(toMap2(op));
134   }
135   private static final Parser subquery = Parsers.lazy(new ParserEval(){
136     public Parser eval(){
137       return Parsers.between(lparen, rparen, parseSelectStmt());
138     }
139   }).map(new Map(){
140     public Object JavaDoc map(final Object JavaDoc o){
141       final Select sel = (Select)o;
142       return Table.select(sel);
143     }
144   });
145   
146 /****************************expression*****************/
147   private static final class ExprP{
148     private static final Parser bar = word("|");
149     private static final Parser ampersand = word("&");
150     private static final Parser plus = word("+");
151     private static final Parser minus = word("-");
152     private static final Parser mul = word("*");
153     private static final Parser div = word("/");
154     private static final Parser mod = word("%");
155
156     private static final Parser word_case = word("case");
157     private static final Parser word_when = word("when");
158     private static final Parser word_then = word("then");
159     private static final Parser word_else = word("else");
160     private static final Parser word_end = word("end");
161     private static final Parser word_null = word("null");
162     
163     
164     private static Map2 toMap2(final BinaryOp op){
165       return new Map2(){
166         public Object JavaDoc map(final Object JavaDoc o1, final Object JavaDoc o2){
167           return op.apply((Expression)o1, (Expression)o2);
168         }
169       };
170     }
171     private static Map toMap(final UnaryOp op){
172       return new Map(){
173         public Object JavaDoc map(final Object JavaDoc o){
174           return op.apply((Expression)o);
175         }
176       };
177     }
178     private static Parser retnMap2(final BinaryOp op){
179       return Parsers.retn(toMap2(op));
180     }
181     private static Parser retnMap(final UnaryOp op){
182       return Parsers.retn(toMap(op));
183     }
184     private static Parser parse(){
185       final Parser decimalLiteral = Terms.decimalParser(new FromString(){
186         public Object JavaDoc fromString(int from, int len, final String JavaDoc s){
187           return new DecimalLiteral(s.toString());
188         }
189       });
190       final Parser stringLiteral = Terms.stringParser(new FromString(){
191         public Object JavaDoc fromString(int from, int len, final String JavaDoc s){
192           return new StringLiteral(s.toString());
193         }
194       });
195       final Parser name_fun = qualifiedId.bind(new ToParser(){
196         public Parser toParser(final Object JavaDoc o){
197           final QualifiedName qn = new QualifiedName((Id[])o);
198           final Parser fun = Parsers.between(lparen, rparen,
199               Parsers.sepBy(Expression.class, comma, expr())).map(new Map(){
200                 public Object JavaDoc map(final Object JavaDoc a){
201                   return new FunctionCall(qn, (Expression[])a);
202                 }
203               });
204           return Parsers.plus(fun, Parsers.retn(new QualifiedNameLiteral(qn)));
205         }
206       });
207     
208       final Map2 _make_whenthen1 = new Map2(){
209         public Object JavaDoc map(final Object JavaDoc o1, final Object JavaDoc o2){
210           final Expression e1 = (Expression)o1;
211           final Expression e2 = (Expression)o2;
212           return new WhenThen(e1, e2);
213         }
214       };
215       final Parser whenthen1 =
216         word_when.seq(lazy_expr.followedBy(word_then).and(lazy_expr, _make_whenthen1));
217     
218       final Map2 _make_whenthen2 = new Map2(){
219         public Object JavaDoc map(final Object JavaDoc o1, final Object JavaDoc o2){
220           final BoolExpression e1 = (BoolExpression)o1;
221           final Expression e2 = (Expression)o2;
222           return new BoolWhenThen(e1, e2);
223         }
224       };
225       final Parser whenthen2 =
226         word_when.seq(lazy_bool_expr.followedBy(word_then).and(lazy_expr, _make_whenthen2));
227       final Parser default_case = word_else.seq(lazy_expr);
228       //case expr when ... then ... else ... end
229
final ToParser _case1_rest = new ToParser(){
230         public Parser toParser(final Object JavaDoc o){
231           final Expression e = (Expression)o;
232           final Parser whenthens = whenthen1.many1(WhenThen.class);
233           final Parser def = Parsers.option(null, default_case);
234           
235           
236           return whenthens.and(def, new Map2(){
237             public Object JavaDoc map(final Object JavaDoc o1, final Object JavaDoc o2){
238               final WhenThen[] wts = (WhenThen[])o1;
239               final Expression d = (Expression)o2;
240               return new ExpressionCase(e, wts, d);
241             }
242           });
243         }
244       };
245       final Parser case1 = word_case.seq(lazy_expr.bind(_case1_rest)).followedBy(word_end);
246     
247       final Parser casewhen_ind = word_case.seq(word_when.peek()).atomize();
248       final Map2 _make_case2 = new Map2(){
249         public Object JavaDoc map(final Object JavaDoc o1, final Object JavaDoc o2){
250           final BoolWhenThen[] bwts = (BoolWhenThen[])o1;
251           final Expression d = (Expression)o2;
252           return new ExpressionCaseWhen(bwts, d);
253         }
254       };
255       final Parser _case2_rest = Parsers.lazy("case when", new ParserEval(){
256         public Parser eval(){
257           final Parser whenthens = whenthen2.many1(BoolWhenThen.class);
258           final Parser def = Parsers.option(null, default_case);
259           return whenthens.and(def, _make_case2);
260         }
261       });
262       final Parser case2 = casewhen_ind.seq(_case2_rest).followedBy(word_end);
263       final Parser retn_null = Parsers.retn(NullLiteral.instance());
264       final Parser expr_null = word_null.seq(retn_null);
265       final Parser op_plus = plus.seq(retnMap2(PlusOp.instance()));
266       final Parser op_minus = minus.seq(retnMap2(MinusOp.instance()));
267       final Parser op_mul = mul.seq(retnMap2(MulOp.instance()));
268       final Parser op_div = div.seq(retnMap2(DivOp.instance()));
269       final Parser op_positive = plus.seq(retnMap(PositiveOp.instance()));
270       final Parser op_negative = minus.seq(retnMap(NegativeOp.instance()));
271       final Parser op_bitand = ampersand.seq(retnMap2(BitAndOp.instance()));
272       final Parser op_bitor = bar.seq(retnMap2(BitOrOp.instance()));
273       final Parser op_mod = mod.seq(retnMap2(ModOp.instance()));
274       //Parser BinaryOp
275
/*
276       final Parser addsub = Parsers.plus(
277             plus.then(retnMap2(PlusOp.instance())),
278             minus.then(retnMap2(MinusOp.instance()))
279         );
280       final Parser bitandor = Parsers.plus(
281           ampersand.then(retnMap2(BitAndOp.instance())),
282           bar.then(retnMap2(BitOrOp.instance()))
283       );
284       final Parser muldivmod = Parsers.plus(
285               mul.then(retnMap2(MulOp.instance())),
286               div.then(retnMap2(DivOp.instance())),
287               mod.then(retnMap2(ModOp.instance()))
288         );
289       final Parser sign =Parsers.plus(
290             plus.then(retnMap(PositiveOp.instance())),
291             minus.then(retnMap(NegativeOp.instance()))
292         );
293       */

294
295       final Parser atom_expr= Parsers.sum(
296             new Parser[]{
297                 expr_null,
298                 stringLiteral,
299                 decimalLiteral,
300                 name_fun,
301                 case2,
302                 case1
303             }
304         );
305       final Parser term = Parsers.plus(
306             Parsers.between(lparen, rparen, lazy_expr),
307             atom_expr
308         );
309       final OperatorTable operators = new OperatorTable();
310       operators.prefix(op_positive, Precedences.positive())
311       .prefix(op_negative, Precedences.negative())
312       .infixl(op_bitand, Precedences.bitand())
313       .infixl(op_bitor, Precedences.bitor())
314       .infixl(op_plus, Precedences.plus())
315       .infixl(op_minus, Precedences.minus())
316       .infixl(op_mul, Precedences.mul())
317       .infixl(op_div, Precedences.div())
318       .infixl(op_mod, Precedences.mod());
319       return Expressions.buildExpressionParser("expression", term, operators);
320       /*
321       final Parser signed = Parsers.prefix(sign, term);
322       //Parser Expression
323       final Parser muldivmod_expr =
324         Parsers.infixl(muldivmod, signed);
325       final Parser bitandor_expr =
326         Parsers.infixl(bitandor, muldivmod_expr);
327       //Parser Expression
328       final Parser addsub_expr =
329         Parsers.infixl(addsub, bitandor_expr);
330       return addsub_expr;
331       */

332     }
333     private static final Parser parser = parse();
334   }
335 /***************************expression***********/
336   
337   
338   
339 /*******************************bool expression ********/
340   private static final class BoolExprP{
341     private static final Parser word_and = word("and");
342     private static final Parser word_or = word("or");
343     private static final Parser eq = word("=");
344     private static final Parser ne = Parsers.plus(word("<>"), word("!="));
345     private static final Parser word_is = word("is");
346     private static final Parser word_not = word("not");
347     private static final Parser word_null = word("null");
348     private static final Parser word_between = word("between");
349     private static final Parser word_in = word("in");
350     private static final Parser word_exists = word("exists");
351     private static final Parser word_like = word("like");
352     private static final Parser word_escape = word("escape");
353
354     private static final Parser lt = word("<");
355     private static final Parser le = word("<=");
356     private static final Parser gt = word(">");
357     private static final Parser ge = word(">=");
358     private static final Parser expr = expr();
359     private static Parser parse(){
360       final Parser word_notlike = word_not.seq(word_like).atomize();
361       final Parser word_notin = word_not.seq(word_in).atomize();
362       final Parser word_notnull = word_not.seq(word_null);
363       final Parser op_not = word_not.seq(Parsers.retn(new Map(){
364         public Object JavaDoc map(final Object JavaDoc o){
365           final BoolExpression e = (BoolExpression)o;
366           return new ExpressionNot(e);
367         }
368       }));
369       //Parser LogicalBinaryOp
370
final Parser logical_infix = Parsers.sum(new Parser[]{
371             eq.seq(lretnMap2(EqOp.instance())),
372             ne.seq(lretnMap2(NeOp.instance())),
373             le.seq(lretnMap2(LeOp.instance())),
374             ge.seq(lretnMap2(GeOp.instance())),
375             lt.seq(lretnMap2(LtOp.instance())),
376             gt.seq(lretnMap2(GtOp.instance()))
377         });
378       //Parser Map
379

380       final ToParser _bool_atom_rest = new ToParser(){
381         public Parser toParser(final Object JavaDoc obj){
382           final Expression e1 = (Expression)obj;
383           final Parser compare =
384             logical_infix.and(expr, new Map2(){
385               public Object JavaDoc map(final Object JavaDoc oop, final Object JavaDoc oe2){
386                 final Map2 op = (Map2)oop;
387                 return op.map(e1, oe2);
388               }
389             });
390           final Parser nulls = word_is.seq(
391               Parsers.plus(
392                 word_notnull
393                   .seq(Parsers.retn(new IsNotNull(e1))),
394                 word_null
395                   .seq(Parsers.retn(new IsNull(e1)))
396               )
397           );
398           final Parser between = word_between.seq(
399               expr.followedBy(word_and).and(expr, new Map2(){
400                 public Object JavaDoc map(final Object JavaDoc o1, final Object JavaDoc o2){
401                   final Expression a = (Expression)o1;
402                   final Expression b = (Expression)o2;
403                   return new ExpressionBetween(e1, a, b);
404                 }
405               })
406           );
407           final Parser expr_list = Parsers.between(lparen, rparen,
408               Parsers.sepEndBy1(Expression.class, comma, expr));
409     
410           final Parser in = word_in.seq(expr_list)
411               .map(new Map(){
412                 public Object JavaDoc map(final Object JavaDoc a){
413                   return new ExpressionIn(e1, (Expression[])a);
414                 }
415               });
416           final Parser not_in = word_notin.seq(expr_list).map(new Map(){
417             public Object JavaDoc map(final Object JavaDoc o){
418               return BoolExpressions.notIn(e1, (Expression[])o);
419             }
420           });
421           //we will do relational predicate later.
422

423           final Parser in_relation = word_in.seq(subquery)
424           .map(new Map(){
425             public Object JavaDoc map(final Object JavaDoc o){
426               final Table tab = (Table)o;
427               return BoolExpressions.inQuery(e1, tab.getStmt());
428             }
429           });
430           
431           
432           final Parser not_in_relation = word_notin.seq(subquery)
433             .map(new Map(){
434               public Object JavaDoc map(final Object JavaDoc o){
435                 final Table tab = (Table)o;
436                 return BoolExpressions.notInQuery(e1, tab.getStmt());
437               }
438             });
439           final Parser like = word_like.seq(expr)
440             .and(word_escape.seq(expr).option(null), new Map2(){
441               public Object JavaDoc map(final Object JavaDoc a, final Object JavaDoc b){
442                 return BoolExpressions.like(e1, (Expression)a, (Expression)b);
443               }
444             });
445           final Parser notlike = word_notlike.seq(expr)
446           .and(word_escape.seq(expr).option(null), new Map2(){
447             public Object JavaDoc map(final Object JavaDoc a, final Object JavaDoc b){
448               return BoolExpressions.notLike(e1, (Expression)a, (Expression)b);
449             }
450           });
451           
452           
453           return Parsers.sum(new Parser[]{
454               compare, nulls, between, like, notlike,
455               Parsers.plus(in_relation, in).lookahead(3),
456               Parsers.plus(not_in_relation, not_in).lookahead(3)});
457         }
458       };
459       final Map _make_exists = new Map(){
460         public Object JavaDoc map(final Object JavaDoc o){
461           final Table tab = (Table)o;
462           return BoolExpressions.exists(tab.getStmt());
463         }
464       };
465       final Parser bool_atom =
466         //we could use is_null.or(is_not_null).or(binary_exp)
467
//Just that incurs too much backtracking.
468
Parsers.plus(word_exists.seq(subquery).map(_make_exists), expr.bind(_bool_atom_rest));
469       
470       final Parser bool_term = Parsers.plus(
471             Parsers.between(lparen, rparen, lazy_bool_expr)
472             ,bool_atom
473         );
474       final OperatorTable logical_operators = new OperatorTable()
475       .prefix(op_not, Precedences.not())
476       .infixl(word_or.seq(bretnMap2(OrOp.instance())), Precedences.or())
477       .infixl(word_and.seq(bretnMap2(AndOp.instance())), Precedences.and());
478       return Expressions.buildExpressionParser("bool_expr", bool_term, logical_operators);
479       /*
480       return Parsers.infixl(
481           word_or.then(bretnMap2(OrOp.instance())),
482           Parsers.infixl(
483               word_and.then(bretnMap2(AndOp.instance())),
484               Parsers.prefix(op_not, bool_term))
485       );*/

486     }
487     private static final Parser parser = parse();
488   }
489 /********************************bool expression****************/
490   /*
491    *
492    * select = 'select' select_exp+ [from] [where] [group] [having] [order]
493    * select_expr = '*' | expr
494    * from = 'from' relation+
495    * relation_term = table_name | '(' relation ')' | '(' select ')' ['as'] id
496    * relation = relation_term | join | product
497    * join = relation jointype join relation on bool_expr
498    * product = relation cross join relation
499    * table_name = qualified_id | alias
500    * alias = table ['as'] id
501    * table = qualified_id | '(' select ')'
502    * jointype = ['inner'] | 'left' ['outer'] | 'right' ['outer'] | 'full' ['outer']
503    * where = 'where' bool_expr
504    * order = 'order' 'by' order_expr+
505    * order_expr = expr 'desc' | expr 'asc' | expr
506    * group = 'group' 'by' expr+
507    * having = 'having' bool_expr
508    *
509    */

510   
511
512   public static final Parser word_from = word("from");
513   public static final Parser word_where = word("where");
514   public static final Parser word_group = word("group");
515   public static final Parser word_having = word("having");
516   public static final Parser word_order = word("order");
517   public static final Parser word_by = word("by");
518   public static final Parser word_desc = word("desc");
519   public static final Parser word_asc = word("asc");
520   public static final Parser word_inner = word("inner");
521   public static final Parser word_outer = word("outer");
522   public static final Parser word_left = word("left");
523   public static final Parser word_right = word("right");
524   public static final Parser word_full = word("full");
525   public static final Parser word_join = word("join");
526   public static final Parser word_cross = word("cross");
527   public static final Parser word_as = word("as");
528   public static final Parser word_on = word("on");
529   public static final Parser word_wildcard = word("*");
530   final static Map fromAlias = new Map(){
531     public Object JavaDoc map(final Object JavaDoc o){
532       return TableName.alias((Alias)o);
533     }
534   };
535   final static Map fromQname = new Map(){
536     public Object JavaDoc map(final Object JavaDoc o){
537       return TableName.qname((QualifiedName)o);
538     }
539   };
540   private static Map2 joinMap2(final int type){
541     return new Map2(){
542       public Object JavaDoc map(final Object JavaDoc o1, final Object JavaDoc o2){
543         return new Map(){
544           public Object JavaDoc map(final Object JavaDoc o){
545             return Relations.join((Relation)o, type, (Relation)o1, (BoolExpression)o2);
546           }
547         };
548       }
549     };
550   }
551
552   //Parser TableName
553
final static Parser naked_table_name = qualifiedName.bind(new ToParser(){
554     public Parser toParser(final Object JavaDoc o){
555       final QualifiedName qn = (QualifiedName)o;
556       return aliased(Parsers.retn(Table.qname(qn))).map(fromAlias)
557         .option(TableName.qname(qn));
558     }
559   });
560   private static final Parser alias_as = word_as.optional().seq(id);
561   private static final Map2 _make_alias = new Map2(){
562     public Object JavaDoc map(final Object JavaDoc o1, final Object JavaDoc o2){
563       return new Alias((Id)o2, (Table)o1);
564     }
565   };
566   private static final Parser optional_alias = alias_as.option(null);
567   public static Parser aliased(final Parser p){//referenced by naked_table_name
568
return p.and(alias_as, _make_alias);
569   }
570   private static final Parser table_name = Parsers.plus(
571         aliased(subquery).map(fromAlias), naked_table_name
572     );
573
574   //Parser (Map Relation Relation)
575
final static Parser inner = word_inner.optional();
576   final static Parser left = word_left.seq(word_outer.optional());
577   final static Parser right = word_right.seq(word_outer.optional());
578   final static Parser full = word_full.seq(word_outer.optional());
579   private static final Parser join_op = Parsers.lazy("lazy join", new ParserEval(){
580       public Parser eval(){
581         return Parsers.plus(
582             parseJoinRest(inner, Join.INNER),
583             parseJoinRest(left, Join.LEFT),
584             parseJoinRest(right, Join.RIGHT),
585             parseJoinRest(full, Join.FULL)
586         );
587       }
588     });
589
590   private static final Parser relation_term =
591     Parsers.plus(
592         table_name.map("table name", new Map(){
593           public Object JavaDoc map(final Object JavaDoc o){
594             return Relations.tablename((TableName)o);
595           }
596         }),
597         Parsers.between("joined relations", lparen, rparen,
598               lazy_relation
599           ).atomize()
600     ).lookahead(2);
601   //subquery is (select ...), joined relation is (a join b ...),
602
//lookahead(2) resolves the ambiguity.
603
private static final Parser lazy_relation_term = Parsers.lazy(new ParserEval(){
604     public Parser eval(){return relation_term;}
605   });
606   private static final Parser crossjoin = word_cross.seq(word_join);
607   private static final Parser cross_op = crossjoin.seq(lazy_relation_term)
608       .map(new Map(){
609         public Object JavaDoc map(final Object JavaDoc o){
610           return new Map(){
611             public Object JavaDoc map(final Object JavaDoc o1){
612               return Relations.product((Relation)o1, (Relation)o);
613             }
614           };
615         }
616       });
617   private static final Parser parseRelation =
618     Parsers.postfix("relation",
619         Parsers.plus(join_op, cross_op),
620         relation_term
621     );
622   private static Parser parseRelation(){return parseRelation;}
623   private static Parser parseJoinRest(final Parser p, final int type){
624     return p.seq(word_join).seq(parseRelation)
625     .and(word_on.seq(bool_expr()), joinMap2(type));
626   }
627
628
629 //Parser (Map Relation Relation)
630

631
632
633   private static final Parser expr1 = Parsers.sepEndBy1("expr+", Expression.class, comma, expr());
634   //Parser BoolExpression
635
private static final Parser whereClause = word_where.seq("where", bool_expr());
636   private static final Parser having = word_having.seq("having", bool_expr());
637   //Parser GroupBy
638
private static final Parser word_groupby = word_group.seq(word_by);
639   private static final Map2 to_group_by = new Map2(){
640     public Object JavaDoc map(final Object JavaDoc o1, final Object JavaDoc o2){
641       return new GroupBy((Expression[])o1, (BoolExpression)o2);
642     }
643   };
644   private static final Parser groupbyClause = word_groupby
645     .seq("group by", expr1)
646     .and(having.option(null), to_group_by);
647   //Parser OrderExpr
648
private static Parser defaultValue(final Parser p, final Parser v){
649     return Parsers.plus(p.seq(v), v);
650   }
651   private static final Parser order_expr =
652     Parsers.map2(expr(),
653         Parsers.plus(word_desc.seq(Parsers.retn(Boolean.valueOf(false))),
654             defaultValue(word_asc, Parsers.retn(Boolean.valueOf(true)))
655         ),
656         new Map2(){
657           public Object JavaDoc map(final Object JavaDoc a, final Object JavaDoc b){
658             final Expression e = (Expression)a;
659             final Boolean JavaDoc ord = (Boolean JavaDoc)b;
660             return new OrderExpr(e, ord.booleanValue());
661           }
662         }
663     );
664   private static final Parser order_expr1 =
665     Parsers.sepEndBy1("order_expr+", OrderExpr.class, comma, order_expr);
666   //Parser [OrderExpr]
667
private static final Parser word_orderby = word_order.seq(word_by);
668   private static final Parser orderbyClause =
669     word_orderby.seq(order_expr1);
670
671   //Parser Relation[]
672
private static final Parser fromClause =
673     word_from.seq(
674         Parsers.sepEndBy1("from", Relation.class, comma,
675             parseRelation()
676         )
677     );
678   //Parser SelectExpr
679
private static final Parser retn_asterisk = Parsers.retn(SelectExpr.asterisk());
680   private static final Map2 _make_select_expr = new Map2(){
681     public Object JavaDoc map(final Object JavaDoc a, final Object JavaDoc b){
682       return SelectExpr.expr((Expression)a, (Id)b);
683     }
684   };
685   private static final Parser select_expr =
686     Parsers.plus("*|expr [[as] id]",
687         word_wildcard.seq(retn_asterisk),
688         expr().and(optional_alias, _make_select_expr)
689     );
690   //Parser SelectExpr[]
691
private static final Parser select_expr1 =
692     Parsers.sepEndBy1("(*|select_expr)+", SelectExpr.class, comma, select_expr);
693   private static Parser parseSelectStmt(){
694     final Parser sel = word_select.seq(select_expr1);
695     final Parser from = fromClause.option(null);
696     final Parser where = whereClause.option(null);
697     final Parser group = groupbyClause.option(null);
698     final Parser order = orderbyClause.option(null);
699     return Parsers.mapn(new Parser[]{
700         sel, from, where, group, order
701     }, new Mapn(){
702       public Object JavaDoc map(final Object JavaDoc[] arr){
703         return new Select((SelectExpr[])arr[0], (Relation[])arr[1], (BoolExpression)arr[2],
704             (GroupBy)arr[3], (OrderExpr[])arr[4]);
705       }
706     });
707   }
708
709   private static final Parser selectStmt = parseSelectStmt();
710   public static Expression parse_expr(
711       final CharSequence JavaDoc src, String JavaDoc module){
712     return (Expression)parse(
713         src,
714         getSqlLexer(),
715         expr().followedBy(Parsers.eof()),
716         module);
717   }
718   public static Object JavaDoc parse(final Parser p,
719       final CharSequence JavaDoc src, String JavaDoc module){
720     return parse(
721         src,
722         getSqlLexer(),
723         p.followedBy(Parsers.eof()),
724         module
725     );
726   }
727   public static Select parse_select(
728       final CharSequence JavaDoc src, String JavaDoc module){
729     return (Select)parse(
730         src,
731         getSqlLexer(),
732         selectStmt.followedBy(Parsers.eof()),
733         module
734     );
735   }
736   private static Object JavaDoc parse(final CharSequence JavaDoc src, final Parser lexer,
737       final Parser p, String JavaDoc module){
738     return Parsers.runParser(src, Parsers.parseTokens(lexer, p, module),
739         new DefaultPositionMap(src, 1, 1), module);
740   }
741   private static Parser getSqlLexer(){
742     return Lexers.lexeme(Scanners.sqlDelimiter(),
743         Parsers.plus(Lexers.sqlStringLiteral(), Lexers.decimal(), words.getLexer(),
744         quotedId('"', '"'),
745         quotedId('[', ']')
746     ));
747   }
748   private static Parser quotedId(final char open, final char close){
749     //return Lexers.quoted("quotedId", open, close);
750
return Lexers.lexer(Scanners.quoted(open, close), TokenQuoted.getTokenizer(open, close));
751   }
752   private static Parser toLexer(Parser s, Tokenizer tn){
753     return Lexers.lexer(s, tn);
754   }
755 }
Popular Tags