2007-07-26 Nagappan A <anagappan@novell.com>
[mono.git] / mcs / class / System.Data / Mono.Data.SqlExpressions / Parser.jay
1 %{
2 //
3 // Parser.jay
4 //
5 // Author:
6 //   Juraj Skripsky (juraj@hotfeet.ch)
7 //
8 // (C) 2004 HotFeet GmbH (http://www.hotfeet.ch)
9 //
10
11 using System;
12 using System.Collections;
13 using System.Data;
14
15 namespace Mono.Data.SqlExpressions {
16
17         internal class Parser {
18                 static Parser ()
19                 {
20                         if (Environment.GetEnvironmentVariable ("MONO_DEBUG_SQLEXPRESSIONS") != null)
21                                 yacc_verbose_flag = 2;
22                 }
23
24                 bool cacheAggregationResults = false;
25                 DataRow[] aggregationRows = null;
26                 static int yacc_verbose_flag;
27                 
28                 //called by DataTable.Select
29                 //called by DataColumn.set_Expression //FIXME: enable cache in this case?
30                 public Parser () {
31                         ErrorOutput = System.IO.TextWriter.Null;
32                         cacheAggregationResults = true;
33                 }
34                 
35                 //called by DataTable.Compute
36                 public Parser (DataRow[] aggregationRows)
37                 {
38                         ErrorOutput = System.IO.TextWriter.Null;
39                         this.aggregationRows = aggregationRows;
40                 }
41                 
42                 public IExpression Compile (string sqlExpr)
43                 {
44                         try {
45                                 Tokenizer tokenizer = new Tokenizer (sqlExpr);
46                                 if (yacc_verbose_flag > 1)
47                                         return (IExpression) yyparse (tokenizer,
48                                                 new yydebug.yyDebugSimple ());
49                                 else
50                                         return (IExpression) yyparse (tokenizer);
51                         } catch (yyParser.yyException e) {
52                                 throw new SyntaxErrorException (String.Format ("Expression '{0}' is invalid.", sqlExpr));
53                         }
54                 }
55 %}
56
57 %token PAROPEN PARCLOSE
58
59 %token AND OR
60 %token NOT
61
62 %token TRUE FALSE
63 %token NULL
64
65 %token PARENT CHILD
66
67 %token EQ LT GT
68
69 %token PLUS MINUS
70 %token MUL DIV MOD
71
72 %token DOT COMMA
73
74 %token IS IN LIKE
75
76 %token COUNT SUM AVG MAX MIN STDEV VAR
77 %token IIF SUBSTRING ISNULL LEN TRIM CONVERT
78
79 %token StringLiteral NumberLiteral DateLiteral
80 %token Identifier
81 %token FunctionName
82
83 %start Expr
84
85 %left OR
86 %left AND
87 %left NOT
88
89 %left EQ LT GT
90
91 %left PLUS MINUS
92 %left MUL DIV MOD
93
94 %left UMINUS
95
96 %%
97
98 Expr
99         : BoolExpr
100         | ArithExpr
101         ;
102
103 BoolExpr
104         : PAROPEN BoolExpr PARCLOSE
105         {
106                 $$ = (IExpression)$2;
107         }
108         | BoolExpr AND BoolExpr
109         {
110                 $$ = new BoolOperation (Operation.AND, (IExpression)$1, (IExpression)$3);
111         }
112         | BoolExpr OR BoolExpr
113         {
114                 $$ = new BoolOperation (Operation.OR, (IExpression)$1, (IExpression)$3);
115         }
116         | NOT BoolExpr
117         {
118                 $$ = new Negation ((IExpression)$2);
119         }
120         | Predicate
121         ;
122
123 Predicate
124         : CompPredicate
125         | IsPredicate
126         | LikePredicate
127         | InPredicate
128         ;
129
130 CompPredicate
131         : ArithExpr CompOp ArithExpr
132         {
133                 $$ = new Comparison ((Operation)$2, (IExpression)$1, (IExpression)$3);
134         }
135         ;
136
137 CompOp
138         : EQ    { $$ = Operation.EQ; }
139         | NE    { $$ = Operation.NE; }
140         | LT    { $$ = Operation.LT; }
141         | GT    { $$ = Operation.GT; }
142         | LE    { $$ = Operation.LE; }
143         | GE    { $$ = Operation.GE; }
144         ;
145
146 LE      : LT EQ;                // <=
147 NE      : LT GT;                // <>
148 GE      : GT EQ;                // >=
149         
150 ArithExpr
151         : PAROPEN ArithExpr PARCLOSE
152         {
153                 $$ = (IExpression)$2;
154         }
155         | ArithExpr MUL ArithExpr
156         {
157                 $$ = new ArithmeticOperation (Operation.MUL, (IExpression)$1, (IExpression)$3);
158         }
159         | ArithExpr DIV ArithExpr
160         {
161                 $$ = new ArithmeticOperation (Operation.DIV, (IExpression)$1, (IExpression)$3);
162         }
163         | ArithExpr MOD ArithExpr
164         {
165                 $$ = new ArithmeticOperation (Operation.MOD, (IExpression)$1, (IExpression)$3);
166         }
167         | ArithExpr PLUS ArithExpr
168         {
169                 $$ = new ArithmeticOperation (Operation.ADD, (IExpression)$1, (IExpression)$3);
170         }
171         | ArithExpr MINUS ArithExpr
172         {
173                 $$ = new ArithmeticOperation (Operation.SUB, (IExpression)$1, (IExpression)$3);
174         }
175         | MINUS ArithExpr %prec UMINUS
176         {
177                 $$ = new Negative ((IExpression)$2);
178         }
179         | Function
180         | Value
181         ;
182
183 Value
184         : LiteralValue
185         | SingleColumnValue
186         ;
187
188 LiteralValue
189         : StringLiteral { $$ = new Literal ($1); }
190         | NumberLiteral { $$ = new Literal ($1); }
191         | DateLiteral           { $$ = new Literal ($1); }
192         | BoolLiteral
193         ;
194
195 BoolLiteral
196         : TRUE  { $$ = new Literal (true); }
197         | FALSE { $$ = new Literal (false); }
198         ;
199
200 SingleColumnValue
201         : LocalColumnValue
202         | ParentColumnValue
203         ;       
204
205 MultiColumnValue
206         : LocalColumnValue
207         | ChildColumnValue
208         ;
209
210 LocalColumnValue
211         : ColumnName
212         {
213                 $$ = new ColumnReference ((string)$1);
214         }
215         ;
216
217 ParentColumnValue
218         : PARENT DOT ColumnName
219         {
220                 $$ = new ColumnReference (ReferencedTable.Parent, null, (string)$3);
221         }
222         | PARENT PAROPEN RelationName PARCLOSE DOT ColumnName
223         {
224                 $$ = new ColumnReference (ReferencedTable.Parent, (string)$3, (string)$6);
225         }
226         ;
227
228 ChildColumnValue
229         : CHILD DOT ColumnName
230         {
231                 $$ = new ColumnReference (ReferencedTable.Child, null, (string)$3);
232         }
233         | CHILD PAROPEN RelationName PARCLOSE DOT ColumnName
234         {
235                 $$ = new ColumnReference (ReferencedTable.Child, (string)$3, (string)$6);
236         }
237         ;
238         
239 ColumnName
240         : Identifier
241         | ColumnName DOT Identifier
242         {
243                 $$ = (string)$1 + "." + (string)$3;
244         }
245         ;
246         
247 RelationName
248         : Identifier;
249
250 Function
251         : CalcFunction
252         | AggFunction
253         ;
254
255 AggFunction
256         : AggFunctionName PAROPEN MultiColumnValue PARCLOSE
257         {
258                 $$ = new Aggregation (cacheAggregationResults, aggregationRows, (AggregationFunction)$1, (ColumnReference)$3);
259         }
260         ;
261
262 AggFunctionName
263         : COUNT         { $$ = AggregationFunction.Count; }
264         | SUM           { $$ = AggregationFunction.Sum; }
265         | AVG           { $$ = AggregationFunction.Avg; }
266         | MAX           { $$ = AggregationFunction.Max; }
267         | MIN           { $$ = AggregationFunction.Min; }
268         | STDEV { $$ = AggregationFunction.StDev; }
269         | VAR           { $$ = AggregationFunction.Var; }
270         ;
271
272 CalcFunction
273         : IIF PAROPEN BoolExpr COMMA Expr COMMA Expr PARCLOSE
274         {
275                 $$ = new IifFunction ((IExpression)$3, (IExpression)$5, (IExpression)$7);
276         }
277         | SUBSTRING PAROPEN Expr COMMA NumberLiteral COMMA NumberLiteral PARCLOSE
278         {
279                 long arg1 = (long) $5;
280                 long arg2 = (long) $7;
281                 $$ = new SubstringFunction ((IExpression)$3, Convert.ToInt32(arg1), Convert.ToInt32(arg2));
282         }
283         | ISNULL PAROPEN Expr COMMA Expr PARCLOSE
284         {
285                 $$ = new IsNullFunction ((IExpression)$3, (IExpression)$5);
286         }
287         | LEN PAROPEN Expr PARCLOSE
288         {
289                 $$ = new LenFunction ((IExpression)$3);
290         }
291         | TRIM PAROPEN Expr PARCLOSE
292         {
293                 $$ = new TrimFunction ((IExpression)$3);
294         }
295         | CONVERT PAROPEN Expr COMMA TypeSpecifier PARCLOSE
296         {
297                 $$ = new ConvertFunction ((IExpression)$3, (string)$5);
298         }
299         ;
300
301 TypeSpecifier
302         : StringLiteral
303         | Identifier
304         ;
305
306 IsPredicate
307         : SingleColumnValue IS NULL
308         {
309                 $$ = new Comparison (Operation.EQ, (IExpression)$1, new Literal (null));
310         }
311         | SingleColumnValue IS NOT NULL
312         {
313                 $$ = new Comparison (Operation.NE, (IExpression)$1, new Literal (null));
314         }
315         ;
316
317 LikePredicate
318         : ArithExpr LIKE StringLiteral
319         {
320                 $$ = new Like ((IExpression)$1, (string)$3);
321         }
322         | ArithExpr NOT LIKE StringLiteral
323         {
324                 $$ = new Negation (new Like ((IExpression)$1, (string)$3));
325         }
326         ;
327
328 InPredicate
329         : SingleColumnValue IN InPredicateValue
330         {
331                 $$ = new In ((IExpression)$1, (IList)$3);
332         }
333         | SingleColumnValue NOT IN InPredicateValue
334         {
335                 $$ = new Negation (new In ((IExpression)$1, (IList)$4));
336         }
337         ;
338
339 InPredicateValue
340         : PAROPEN InValueList PARCLOSE { $$ = $2; }
341         ;
342
343 InValueList
344         : LiteralValue
345         {
346                 $$ = new ArrayList();
347                 ((IList)$$).Add ($1);
348         }
349         | InValueList COMMA LiteralValue
350         {
351                 ((IList)($$ = $1)).Add ($3);
352         }
353         ;
354
355 %%
356 }