1// https://github.com/apache/drill/raw/master/logical/src/main/antlr3/org/apache/drill/common/expression/parser/ExprParser.g
2parser grammar ExprParser;
3
4options{
5  output=AST;
6  language=Java;
7  tokenVocab=ExprLexer;
8  backtrack=true;
9  memoize=true;
10}
11
12
13
14@header {
15/*
16 * Licensed to the Apache Software Foundation (ASF) under one
17 * or more contributor license agreements.  See the NOTICE file
18 * distributed with this work for additional information
19 * regarding copyright ownership.  The ASF licenses this file
20 * to you under the Apache License, Version 2.0 (the
21 * "License"); you may not use this file except in compliance
22 * with the License.  You may obtain a copy of the License at
23 *
24 * http://www.apache.org/licenses/LICENSE-2.0
25 *
26 * Unless required by applicable law or agreed to in writing, software
27 * distributed under the License is distributed on an "AS IS" BASIS,
28 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29 * See the License for the specific language governing permissions and
30 * limitations under the License.
31 */
32
33package org.apache.drill.common.expression.parser;
34
35//Explicit import...
36import org.antlr.runtime.BitSet;
37import java.util.*;
38import org.apache.drill.common.expression.*;
39import org.apache.drill.common.expression.PathSegment.NameSegment;
40import org.apache.drill.common.expression.PathSegment.ArraySegment;
41import org.apache.drill.common.types.*;
42import org.apache.drill.common.types.TypeProtos.*;
43import org.apache.drill.common.types.TypeProtos.DataMode;
44import org.apache.drill.common.types.TypeProtos.MajorType;
45import org.apache.drill.common.exceptions.ExpressionParsingException;
46}
47
48@members{
49  private String fullExpression;
50  private int tokenPos;
51
52  public static void p(String s){
53    System.out.println(s);
54  }
55
56  public ExpressionPosition pos(Token token){
57    return new ExpressionPosition(fullExpression, token.getTokenIndex());
58  }
59
60  @Override
61  public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
62	String hdr = getErrorHeader(e);
63    String msg = getErrorMessage(e, tokenNames);
64    throw new ExpressionParsingException("Expression has syntax error! " + hdr + ":" + msg);
65  }
66}
67
68parse returns [LogicalExpression e]
69  :  expression EOF {
70    $e = $expression.e;
71    if(fullExpression == null) fullExpression = $expression.text;
72    tokenPos = $expression.start.getTokenIndex();
73  }
74  ;
75
76functionCall returns [LogicalExpression e]
77  :  Identifier OParen exprList? CParen {$e = FunctionCallFactory.createExpression($Identifier.text, pos($Identifier), $exprList.listE);  }
78  ;
79
80convertCall returns [LogicalExpression e]
81  :  Convert OParen expression Comma String CParen
82      { $e = FunctionCallFactory.createConvert($Convert.text, $String.text, $expression.e, pos($Convert));}
83  ;
84
85castCall returns [LogicalExpression e]
86	@init{
87  	  List<LogicalExpression> exprs = new ArrayList<LogicalExpression>();
88	  ExpressionPosition p = null;
89	}
90  :  Cast OParen expression As dataType repeat? CParen
91      {  if ($repeat.isRep!=null && $repeat.isRep.compareTo(Boolean.TRUE)==0)
92           $e = FunctionCallFactory.createCast(TypeProtos.MajorType.newBuilder().mergeFrom($dataType.type).setMode(DataMode.REPEATED).build(), pos($Cast), $expression.e);
93         else
94           $e = FunctionCallFactory.createCast($dataType.type, pos($Cast), $expression.e);}
95  ;
96
97repeat returns [Boolean isRep]
98  : Repeat { $isRep = Boolean.TRUE;}
99  ;
100
101dataType returns [MajorType type]
102	: numType  {$type =$numType.type;}
103	| charType {$type =$charType.type;}
104	| dateType {$type =$dateType.type;}
105	| booleanType {$type =$booleanType.type;}
106	;
107
108booleanType returns [MajorType type]
109	: BIT { $type = Types.required(TypeProtos.MinorType.BIT); }
110	;
111
112numType returns [MajorType type]
113	: INT    { $type = Types.required(TypeProtos.MinorType.INT); }
114	| BIGINT { $type = Types.required(TypeProtos.MinorType.BIGINT); }
115	| FLOAT4 { $type = Types.required(TypeProtos.MinorType.FLOAT4); }
116	| FLOAT8 { $type = Types.required(TypeProtos.MinorType.FLOAT8); }
117	| DECIMAL9 OParen precision Comma scale CParen { $type = TypeProtos.MajorType.newBuilder().setMinorType(TypeProtos.MinorType.DECIMAL9).setMode(DataMode.REQUIRED).setPrecision($precision.value.intValue()).setScale($scale.value.intValue()).build(); }
118	| DECIMAL18 OParen precision Comma scale CParen { $type = TypeProtos.MajorType.newBuilder().setMinorType(TypeProtos.MinorType.DECIMAL18).setMode(DataMode.REQUIRED).setPrecision($precision.value.intValue()).setScale($scale.value.intValue()).build(); }
119	| DECIMAL28DENSE OParen precision Comma scale CParen { $type = TypeProtos.MajorType.newBuilder().setMinorType(TypeProtos.MinorType.DECIMAL28DENSE).setMode(DataMode.REQUIRED).setPrecision($precision.value.intValue()).setScale($scale.value.intValue()).build(); }
120	| DECIMAL28SPARSE OParen precision Comma scale CParen { $type = TypeProtos.MajorType.newBuilder().setMinorType(TypeProtos.MinorType.DECIMAL28SPARSE).setMode(DataMode.REQUIRED).setPrecision($precision.value.intValue()).setScale($scale.value.intValue()).build(); }
121	| DECIMAL38DENSE OParen precision Comma scale CParen { $type = TypeProtos.MajorType.newBuilder().setMinorType(TypeProtos.MinorType.DECIMAL38DENSE).setMode(DataMode.REQUIRED).setPrecision($precision.value.intValue()).setScale($scale.value.intValue()).build(); }
122	| DECIMAL38SPARSE OParen precision Comma scale CParen { $type = TypeProtos.MajorType.newBuilder().setMinorType(TypeProtos.MinorType.DECIMAL38SPARSE).setMode(DataMode.REQUIRED).setPrecision($precision.value.intValue()).setScale($scale.value.intValue()).build(); }
123	;
124
125charType returns [MajorType type]
126	:  VARCHAR typeLen {$type = TypeProtos.MajorType.newBuilder().setMinorType(TypeProtos.MinorType.VARCHAR).setMode(DataMode.REQUIRED).setWidth($typeLen.length.intValue()).build(); }
127	|  VARBINARY typeLen {$type = TypeProtos.MajorType.newBuilder().setMinorType(TypeProtos.MinorType.VARBINARY).setMode(DataMode.REQUIRED).setWidth($typeLen.length.intValue()).build();}
128	;
129
130precision returns [Integer value]
131    : Number {$value = Integer.parseInt($Number.text); }
132    ;
133
134scale returns [Integer value]
135    : Number {$value = Integer.parseInt($Number.text); }
136    ;
137
138dateType returns [MajorType type]
139    : DATE { $type = Types.required(TypeProtos.MinorType.DATE); }
140    | TIMESTAMP   { $type = Types.required(TypeProtos.MinorType.TIMESTAMP); }
141    | TIME   { $type = Types.required(TypeProtos.MinorType.TIME); }
142    | TIMESTAMPTZ   { $type = Types.required(TypeProtos.MinorType.TIMESTAMPTZ); }
143    | INTERVAL { $type = Types.required(TypeProtos.MinorType.INTERVAL); }
144    | INTERVALYEAR { $type = Types.required(TypeProtos.MinorType.INTERVALYEAR); }
145    | INTERVALDAY { $type = Types.required(TypeProtos.MinorType.INTERVALDAY); }
146    ;
147
148typeLen returns [Integer length]
149    : OParen Number CParen {$length = Integer.parseInt($Number.text);}
150    ;
151
152ifStatement returns [LogicalExpression e]
153	@init {
154	  IfExpression.Builder s = IfExpression.newBuilder();
155	}
156	@after {
157	  $e = s.build();
158	}
159  :  i1=ifStat {s.setIfCondition($i1.i); s.setPosition(pos($i1.start)); } (elseIfStat { s.setIfCondition($elseIfStat.i); } )* Else expression { s.setElse($expression.e); }End
160  ;
161
162ifStat returns [IfExpression.IfCondition i]
163  : If e1=expression Then e2=expression { $i = new IfExpression.IfCondition($e1.e, $e2.e); }
164  ;
165elseIfStat returns [IfExpression.IfCondition i]
166  : Else If e1=expression Then e2=expression { $i = new IfExpression.IfCondition($e1.e, $e2.e); }
167  ;
168
169caseStatement returns [LogicalExpression e]
170	@init {
171	  IfExpression.Builder s = IfExpression.newBuilder();
172	}
173	@after {
174	  $e = s.build();
175	}
176  : Case (caseWhenStat {s.setIfCondition($caseWhenStat.e); }) + caseElseStat { s.setElse($caseElseStat.e); } End
177  ;
178
179caseWhenStat returns [IfExpression.IfCondition e]
180  : When e1=expression Then e2=expression {$e = new IfExpression.IfCondition($e1.e, $e2.e); }
181  ;
182
183caseElseStat returns [LogicalExpression e]
184  : Else expression {$e = $expression.e; }
185  ;
186
187exprList returns [List<LogicalExpression> listE]
188	@init{
189	  $listE = new ArrayList<LogicalExpression>();
190	}
191  :  e1=expression {$listE.add($e1.e); } (Comma e2=expression {$listE.add($e2.e); } )*
192  ;
193
194expression returns [LogicalExpression e]
195  :  ifStatement {$e = $ifStatement.e; }
196  |  caseStatement {$e = $caseStatement.e; }
197  |  condExpr {$e = $condExpr.e; }
198  ;
199
200condExpr returns [LogicalExpression e]
201  :  orExpr {$e = $orExpr.e; }
202  ;
203
204orExpr returns [LogicalExpression e]
205	@init{
206	  List<LogicalExpression> exprs = new ArrayList<LogicalExpression>();
207	  ExpressionPosition p = null;
208	}
209	@after{
210	  if(exprs.size() == 1){
211	    $e = exprs.get(0);
212	  }else{
213	    $e = FunctionCallFactory.createBooleanOperator("or", p, exprs);
214	  }
215	}
216  :  a1=andExpr { exprs.add($a1.e); p = pos( $a1.start );} (Or a2=andExpr { exprs.add($a2.e); })*
217  ;
218
219andExpr returns [LogicalExpression e]
220	@init{
221	  List<LogicalExpression> exprs = new ArrayList<LogicalExpression>();
222	  ExpressionPosition p = null;
223	}
224	@after{
225	  if(exprs.size() == 1){
226	    $e = exprs.get(0);
227	  }else{
228	    $e = FunctionCallFactory.createBooleanOperator("and", p, exprs);
229	  }
230	}
231  :  e1=equExpr { exprs.add($e1.e); p = pos( $e1.start );  } ( And e2=equExpr { exprs.add($e2.e);  })*
232  ;
233
234equExpr returns [LogicalExpression e]
235	@init{
236	  List<LogicalExpression> exprs = new ArrayList<LogicalExpression>();
237	  List<String> cmps = new ArrayList();
238	  ExpressionPosition p = null;
239	}
240	@after{
241	  $e = FunctionCallFactory.createByOp(exprs, p, cmps);
242	}
243  :  r1=relExpr { exprs.add($r1.e); p = pos( $r1.start );
244    } ( cmpr= ( Equals | NEquals ) r2=relExpr {exprs.add($r2.e); cmps.add($cmpr.text); })*
245  ;
246
247relExpr returns [LogicalExpression e]
248  :  left=addExpr {$e = $left.e; } (cmpr = (GTEquals | LTEquals | GT | LT) right=addExpr {$e = FunctionCallFactory.createExpression($cmpr.text, pos($left.start), $left.e, $right.e); } )?
249  ;
250
251addExpr returns [LogicalExpression e]
252	@init{
253	  List<LogicalExpression> exprs = new ArrayList<LogicalExpression>();
254	  List<String> ops = new ArrayList();
255	  ExpressionPosition p = null;
256	}
257	@after{
258	  $e = FunctionCallFactory.createByOp(exprs, p, ops);
259	}
260  :  m1=mulExpr  {exprs.add($m1.e); p = pos($m1.start); } ( op=(Plus|Minus) m2=mulExpr {exprs.add($m2.e); ops.add($op.text); })*
261  ;
262
263mulExpr returns [LogicalExpression e]
264	@init{
265	  List<LogicalExpression> exprs = new ArrayList<LogicalExpression>();
266	  List<String> ops = new ArrayList();
267	  ExpressionPosition p = null;
268	}
269	@after{
270	  $e = FunctionCallFactory.createByOp(exprs, p, ops);
271	}
272  :  p1=xorExpr  {exprs.add($p1.e); p = pos($p1.start);} (op=(Asterisk|ForwardSlash|Percent) p2=xorExpr {exprs.add($p2.e); ops.add($op.text); } )*
273  ;
274
275xorExpr returns [LogicalExpression e]
276	@init{
277	  List<LogicalExpression> exprs = new ArrayList<LogicalExpression>();
278	  List<String> ops = new ArrayList();
279	  ExpressionPosition p = null;
280	}
281	@after{
282	  $e = FunctionCallFactory.createByOp(exprs, p, ops);
283	}
284  :  u1=unaryExpr {exprs.add($u1.e); p = pos($u1.start);} (Caret u2=unaryExpr {exprs.add($u2.e); ops.add($Caret.text);} )*
285  ;
286
287unaryExpr returns [LogicalExpression e]
288  :  sign=(Plus|Minus)? Number {$e = ValueExpressions.getNumericExpression($sign.text, $Number.text, pos(($sign != null) ? $sign : $Number)); }
289  |  Minus atom {$e = FunctionCallFactory.createExpression("u-", pos($Minus), $atom.e); }
290  |  Excl atom {$e= FunctionCallFactory.createExpression("!", pos($Excl), $atom.e); }
291  |  atom {$e = $atom.e; }
292  ;
293
294atom returns [LogicalExpression e]
295  :  Bool {$e = new ValueExpressions.BooleanExpression($Bool.text, pos($Bool)); }
296  |  lookup {$e = $lookup.e; }
297  ;
298
299pathSegment returns [NameSegment seg]
300  : s1=nameSegment {$seg = $s1.seg;}
301  ;
302
303nameSegment returns [NameSegment seg]
304  : QuotedIdentifier ( (Period s1=pathSegment) | s2=arraySegment)? {$seg = new NameSegment($QuotedIdentifier.text, ($s1.seg == null ? $s2.seg : $s1.seg) ); }
305  | Identifier ( (Period s1=pathSegment) | s2=arraySegment)? {$seg = new NameSegment($Identifier.text, ($s1.seg == null ? $s2.seg : $s1.seg) ); }
306  ;
307
308arraySegment returns [PathSegment seg]
309  :  OBracket Number CBracket ( (Period s1=pathSegment) | s2=arraySegment)? {$seg = new ArraySegment($Number.text, ($s1.seg == null ? $s2.seg : $s1.seg) ); }
310  ;
311
312
313lookup returns [LogicalExpression e]
314  :  functionCall {$e = $functionCall.e ;}
315  | convertCall {$e = $convertCall.e; }
316  | castCall {$e = $castCall.e; }
317  | pathSegment {$e = new SchemaPath($pathSegment.seg, pos($pathSegment.start) ); }
318  | String {$e = new ValueExpressions.QuotedString($String.text, pos($String) ); }
319  | OParen expression CParen  {$e = $expression.e; }
320  | SingleQuote Identifier SingleQuote {$e = new SchemaPath($Identifier.text, pos($Identifier) ); }
321  ;
322
323
324
325