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