vtlengine 1.0.1__py3-none-any.whl → 1.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of vtlengine might be problematic. Click here for more details.
- vtlengine/API/_InternalApi.py +9 -5
- vtlengine/API/__init__.py +1 -1
- vtlengine/AST/ASTConstructorModules/Expr.py +96 -5
- vtlengine/AST/ASTConstructorModules/ExprComponents.py +76 -2
- vtlengine/AST/ASTTemplate.py +16 -0
- vtlengine/AST/Grammar/Vtl.g4 +49 -20
- vtlengine/AST/Grammar/VtlTokens.g4 +13 -1
- vtlengine/AST/Grammar/lexer.py +1293 -1183
- vtlengine/AST/Grammar/parser.py +5758 -3939
- vtlengine/AST/Grammar/tokens.py +12 -0
- vtlengine/AST/VtlVisitor.py +9 -1
- vtlengine/AST/__init__.py +19 -0
- vtlengine/DataTypes/TimeHandling.py +2 -0
- vtlengine/Exceptions/__init__.py +44 -0
- vtlengine/Exceptions/messages.py +16 -8
- vtlengine/Interpreter/__init__.py +52 -26
- vtlengine/Model/__init__.py +7 -0
- vtlengine/Operators/Analytic.py +53 -21
- vtlengine/Operators/Boolean.py +1 -1
- vtlengine/Operators/Conditional.py +143 -2
- vtlengine/Operators/Numeric.py +40 -2
- vtlengine/Operators/Time.py +134 -0
- vtlengine/Utils/__init__.py +37 -1
- vtlengine/files/parser/__init__.py +2 -0
- vtlengine/files/parser/_time_checking.py +2 -0
- {vtlengine-1.0.1.dist-info → vtlengine-1.0.2.dist-info}/METADATA +14 -5
- {vtlengine-1.0.1.dist-info → vtlengine-1.0.2.dist-info}/RECORD +29 -29
- {vtlengine-1.0.1.dist-info → vtlengine-1.0.2.dist-info}/LICENSE.md +0 -0
- {vtlengine-1.0.1.dist-info → vtlengine-1.0.2.dist-info}/WHEEL +0 -0
vtlengine/API/_InternalApi.py
CHANGED
|
@@ -8,7 +8,9 @@ from s3fs import S3FileSystem # type: ignore[import-untyped]
|
|
|
8
8
|
|
|
9
9
|
from vtlengine.AST import PersistentAssignment, Start
|
|
10
10
|
from vtlengine.DataTypes import SCALAR_TYPES
|
|
11
|
-
from vtlengine.
|
|
11
|
+
from vtlengine.Exceptions import check_key
|
|
12
|
+
from vtlengine.Model import (ValueDomain, Dataset, Scalar, Component, Role,
|
|
13
|
+
ExternalRoutine, Role_keys)
|
|
12
14
|
from vtlengine.files.parser import _validate_pandas, _fill_dataset_empty_data
|
|
13
15
|
|
|
14
16
|
base_path = Path(__file__).parent
|
|
@@ -30,15 +32,17 @@ def _load_dataset_from_structure(structures: Dict[str, Any]) -> Dict[str, Any]:
|
|
|
30
32
|
if "datasets" in structures:
|
|
31
33
|
for dataset_json in structures["datasets"]:
|
|
32
34
|
dataset_name = dataset_json["name"]
|
|
33
|
-
components = {
|
|
34
|
-
|
|
35
|
+
components = {}
|
|
36
|
+
|
|
37
|
+
for component in dataset_json["DataStructure"]:
|
|
38
|
+
check_key("data_type", SCALAR_TYPES.keys(), component["type"])
|
|
39
|
+
check_key("role", Role_keys, component["role"])
|
|
40
|
+
components[component["name"]] = Component(
|
|
35
41
|
name=component["name"],
|
|
36
42
|
data_type=SCALAR_TYPES[component["type"]],
|
|
37
43
|
role=Role(component["role"]),
|
|
38
44
|
nullable=component["nullable"],
|
|
39
45
|
)
|
|
40
|
-
for component in dataset_json["DataStructure"]
|
|
41
|
-
}
|
|
42
46
|
|
|
43
47
|
datasets[dataset_name] = Dataset(name=dataset_name, components=components, data=None)
|
|
44
48
|
if "scalars" in structures:
|
vtlengine/API/__init__.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import re
|
|
2
2
|
from copy import copy
|
|
3
|
+
from typing import Any
|
|
3
4
|
|
|
4
5
|
from antlr4.tree.Tree import TerminalNodeImpl
|
|
5
6
|
|
|
@@ -25,6 +26,8 @@ from vtlengine.AST import (
|
|
|
25
26
|
Analytic,
|
|
26
27
|
Windowing,
|
|
27
28
|
VarID,
|
|
29
|
+
Case,
|
|
30
|
+
CaseObj,
|
|
28
31
|
)
|
|
29
32
|
from vtlengine.AST.ASTConstructorModules.ExprComponents import ExprComp
|
|
30
33
|
from vtlengine.AST.ASTConstructorModules.Terminals import Terminals
|
|
@@ -59,6 +62,7 @@ class Expr(VtlVisitor):
|
|
|
59
62
|
| left=expr op=AND right=expr # booleanExpr # noqa E501
|
|
60
63
|
| left=expr op=(OR|XOR) right=expr # booleanExpr # noqa E501
|
|
61
64
|
| IF conditionalExpr=expr THEN thenExpr=expr ELSE elseExpr=expr # ifExpr # noqa E501
|
|
65
|
+
| CASE WHEN expr THEN expr ELSE expr END # caseExpr # noqa E501
|
|
62
66
|
| constant # constantExpr # noqa E501
|
|
63
67
|
| varID # varIdExpr # noqa E501
|
|
64
68
|
;
|
|
@@ -115,6 +119,26 @@ class Expr(VtlVisitor):
|
|
|
115
119
|
|
|
116
120
|
return if_node
|
|
117
121
|
|
|
122
|
+
# CASE WHEN expr THEN expr ELSE expr END # caseExpr
|
|
123
|
+
elif isinstance(c, TerminalNodeImpl) and (c.getSymbol().type == Parser.CASE):
|
|
124
|
+
|
|
125
|
+
if len(ctx_list) % 4 != 3:
|
|
126
|
+
raise ValueError("Syntax error.")
|
|
127
|
+
|
|
128
|
+
else_node = self.visitExpr(ctx_list[-1])
|
|
129
|
+
ctx_list = ctx_list[1:-2]
|
|
130
|
+
cases = []
|
|
131
|
+
|
|
132
|
+
for i in range(0, len(ctx_list), 4):
|
|
133
|
+
condition = self.visitExpr(ctx_list[i + 1])
|
|
134
|
+
thenOp = self.visitExpr(ctx_list[i + 3])
|
|
135
|
+
case_obj = CaseObj(condition, thenOp)
|
|
136
|
+
cases.append(case_obj)
|
|
137
|
+
|
|
138
|
+
case_node = Case(cases, else_node)
|
|
139
|
+
|
|
140
|
+
return case_node
|
|
141
|
+
|
|
118
142
|
# constant
|
|
119
143
|
elif isinstance(ctx, Parser.ConstantExprContext):
|
|
120
144
|
return Terminals().visitConstant(c)
|
|
@@ -755,7 +779,8 @@ class Expr(VtlVisitor):
|
|
|
755
779
|
|
|
756
780
|
def visitTimeFunctions(self, ctx: Parser.TimeFunctionsContext):
|
|
757
781
|
if isinstance(ctx, Parser.PeriodAtomContext):
|
|
758
|
-
return self.visitPeriodAtom(ctx)
|
|
782
|
+
# return self.visitPeriodAtom(ctx)
|
|
783
|
+
return self.visitTimeUnaryAtom(ctx)
|
|
759
784
|
elif isinstance(ctx, Parser.FillTimeAtomContext):
|
|
760
785
|
return self.visitFillTimeAtom(ctx)
|
|
761
786
|
elif isinstance(ctx, Parser.FlowAtomContext):
|
|
@@ -766,13 +791,30 @@ class Expr(VtlVisitor):
|
|
|
766
791
|
return self.visitTimeAggAtom(ctx)
|
|
767
792
|
elif isinstance(ctx, Parser.CurrentDateAtomContext):
|
|
768
793
|
return self.visitCurrentDateAtom(ctx)
|
|
794
|
+
elif isinstance(ctx, Parser.DateDiffAtomContext):
|
|
795
|
+
return self.visitTimeDiffAtom(ctx)
|
|
796
|
+
elif isinstance(ctx, Parser.DateAddAtomContext):
|
|
797
|
+
return self.visitTimeAddAtom(ctx)
|
|
798
|
+
elif isinstance(ctx, Parser.YearAtomContext):
|
|
799
|
+
return self.visitTimeUnaryAtom(ctx)
|
|
800
|
+
elif isinstance(ctx, Parser.MonthAtomContext):
|
|
801
|
+
return self.visitTimeUnaryAtom(ctx)
|
|
802
|
+
elif isinstance(ctx, Parser.DayOfMonthAtomContext):
|
|
803
|
+
return self.visitTimeUnaryAtom(ctx)
|
|
804
|
+
elif isinstance(ctx, Parser.DayOfYearAtomContext):
|
|
805
|
+
return self.visitTimeUnaryAtom(ctx)
|
|
806
|
+
elif isinstance(ctx, Parser.DayToYearAtomContext):
|
|
807
|
+
return self.visitTimeUnaryAtom(ctx)
|
|
808
|
+
elif isinstance(ctx, Parser.DayToMonthAtomContext):
|
|
809
|
+
return self.visitTimeUnaryAtom(ctx)
|
|
810
|
+
elif isinstance(ctx, Parser.YearTodayAtomContext):
|
|
811
|
+
return self.visitTimeUnaryAtom(ctx)
|
|
812
|
+
elif isinstance(ctx, Parser.MonthTodayAtomContext):
|
|
813
|
+
return self.visitTimeUnaryAtom(ctx)
|
|
769
814
|
else:
|
|
770
815
|
raise NotImplementedError
|
|
771
816
|
|
|
772
|
-
def
|
|
773
|
-
"""
|
|
774
|
-
periodExpr: PERIOD_INDICATOR '(' expr? ')' ;
|
|
775
|
-
"""
|
|
817
|
+
def visitTimeUnaryAtom(self, ctx: Any):
|
|
776
818
|
ctx_list = list(ctx.getChildren())
|
|
777
819
|
c = ctx_list[0]
|
|
778
820
|
|
|
@@ -789,6 +831,26 @@ class Expr(VtlVisitor):
|
|
|
789
831
|
|
|
790
832
|
return UnaryOp(op=op, operand=operand_node[0])
|
|
791
833
|
|
|
834
|
+
# def visitPeriodAtom(self, ctx: Parser.PeriodAtomContext):
|
|
835
|
+
# """
|
|
836
|
+
# periodExpr: PERIOD_INDICATOR '(' expr? ')' ;
|
|
837
|
+
# """
|
|
838
|
+
# ctx_list = list(ctx.getChildren())
|
|
839
|
+
# c = ctx_list[0]
|
|
840
|
+
#
|
|
841
|
+
# op = c.getSymbol().text
|
|
842
|
+
# operand_node = [
|
|
843
|
+
# self.visitExpr(operand)
|
|
844
|
+
# for operand in ctx_list
|
|
845
|
+
# if isinstance(operand, Parser.ExprContext)
|
|
846
|
+
# ]
|
|
847
|
+
#
|
|
848
|
+
# if len(operand_node) == 0:
|
|
849
|
+
# # AST_ASTCONSTRUCTOR.15
|
|
850
|
+
# raise NotImplementedError
|
|
851
|
+
#
|
|
852
|
+
# return UnaryOp(op=op, operand=operand_node[0])
|
|
853
|
+
|
|
792
854
|
def visitTimeShiftAtom(self, ctx: Parser.TimeShiftAtomContext):
|
|
793
855
|
"""
|
|
794
856
|
timeShiftExpr: TIMESHIFT '(' expr ',' INTEGER_CONSTANT ')' ;
|
|
@@ -872,6 +934,35 @@ class Expr(VtlVisitor):
|
|
|
872
934
|
c = list(ctx.getChildren())[0]
|
|
873
935
|
return MulOp(op=c.getSymbol().text, children=[])
|
|
874
936
|
|
|
937
|
+
def visitTimeDiffAtom(self, ctx: Parser.TimeShiftAtomContext):
|
|
938
|
+
""" """
|
|
939
|
+
ctx_list = list(ctx.getChildren())
|
|
940
|
+
c = ctx_list[0]
|
|
941
|
+
|
|
942
|
+
op = c.getSymbol().text
|
|
943
|
+
left_node = self.visitExpr(ctx_list[2])
|
|
944
|
+
right_node = self.visitExpr(ctx_list[4])
|
|
945
|
+
|
|
946
|
+
return BinOp(left=left_node, op=op, right=right_node)
|
|
947
|
+
|
|
948
|
+
def visitTimeAddAtom(self, ctx: Parser.TimeShiftAtomContext):
|
|
949
|
+
""" """
|
|
950
|
+
|
|
951
|
+
ctx_list = list(ctx.getChildren())
|
|
952
|
+
c = ctx_list[0]
|
|
953
|
+
|
|
954
|
+
op = c.getSymbol().text
|
|
955
|
+
children_node = [self.visitExpr(ctx_list[2])]
|
|
956
|
+
|
|
957
|
+
param_constant_node = []
|
|
958
|
+
|
|
959
|
+
if len(ctx_list) > 4:
|
|
960
|
+
param_constant_node = [self.visitExpr(ctx_list[4])]
|
|
961
|
+
if len(ctx_list) > 6:
|
|
962
|
+
param_constant_node.append(self.visitExpr(ctx_list[6]))
|
|
963
|
+
|
|
964
|
+
return ParamOp(op=op, children=children_node, params=param_constant_node)
|
|
965
|
+
|
|
875
966
|
"""
|
|
876
967
|
-----------------------------------
|
|
877
968
|
Conditional Functions
|
|
@@ -16,6 +16,8 @@ from vtlengine.AST import (
|
|
|
16
16
|
VarID,
|
|
17
17
|
Analytic,
|
|
18
18
|
UDOCall,
|
|
19
|
+
Case,
|
|
20
|
+
CaseObj,
|
|
19
21
|
)
|
|
20
22
|
from vtlengine.AST.ASTConstructorModules.Terminals import Terminals
|
|
21
23
|
from vtlengine.AST.Grammar.parser import Parser
|
|
@@ -87,6 +89,10 @@ class ExprComp(VtlVisitor):
|
|
|
87
89
|
elif isinstance(ctx, Parser.IfExprCompContext):
|
|
88
90
|
return self.visitIfExprComp(ctx)
|
|
89
91
|
|
|
92
|
+
# CASE WHEN conditionalExpr=expr THEN thenExpr=expr ELSE elseExpr=expr END # caseExpr
|
|
93
|
+
elif isinstance(ctx, Parser.CaseExprCompContext):
|
|
94
|
+
return self.visitCaseExprComp(ctx)
|
|
95
|
+
|
|
90
96
|
# constant
|
|
91
97
|
elif isinstance(ctx, Parser.ConstantExprCompContext):
|
|
92
98
|
return Terminals().visitConstant(c)
|
|
@@ -169,6 +175,26 @@ class ExprComp(VtlVisitor):
|
|
|
169
175
|
|
|
170
176
|
return if_node
|
|
171
177
|
|
|
178
|
+
def visitCaseExprComp(self, ctx: Parser.CaseExprCompContext):
|
|
179
|
+
ctx_list = list(ctx.getChildren())
|
|
180
|
+
|
|
181
|
+
if len(ctx_list) % 4 != 3:
|
|
182
|
+
raise ValueError("Syntax error.")
|
|
183
|
+
|
|
184
|
+
else_node = self.visitExprComponent(ctx_list[-1])
|
|
185
|
+
ctx_list = ctx_list[1:-2]
|
|
186
|
+
cases = []
|
|
187
|
+
|
|
188
|
+
for i in range(0, len(ctx_list), 4):
|
|
189
|
+
condition = self.visitExprComponent(ctx_list[i + 1])
|
|
190
|
+
thenOp = self.visitExprComponent(ctx_list[i + 3])
|
|
191
|
+
case_obj = CaseObj(condition, thenOp)
|
|
192
|
+
cases.append(case_obj)
|
|
193
|
+
|
|
194
|
+
case_node = Case(cases, else_node)
|
|
195
|
+
|
|
196
|
+
return case_node
|
|
197
|
+
|
|
172
198
|
def visitOptionalExprComponent(self, ctx: Parser.OptionalExprComponentContext):
|
|
173
199
|
"""
|
|
174
200
|
optionalExpr: expr
|
|
@@ -541,7 +567,7 @@ class ExprComp(VtlVisitor):
|
|
|
541
567
|
|
|
542
568
|
def visitTimeFunctionsComponents(self, ctx: Parser.TimeFunctionsComponentsContext):
|
|
543
569
|
if isinstance(ctx, Parser.PeriodAtomComponentContext):
|
|
544
|
-
return self.
|
|
570
|
+
return self.visitTimeUnaryAtomComponent(ctx)
|
|
545
571
|
elif isinstance(ctx, Parser.FillTimeAtomComponentContext):
|
|
546
572
|
return self.visitFillTimeAtomComponent(ctx)
|
|
547
573
|
elif isinstance(ctx, Parser.FlowAtomComponentContext):
|
|
@@ -552,10 +578,30 @@ class ExprComp(VtlVisitor):
|
|
|
552
578
|
return self.visitTimeAggAtomComponent(ctx)
|
|
553
579
|
elif isinstance(ctx, Parser.CurrentDateAtomComponentContext):
|
|
554
580
|
return self.visitCurrentDateAtomComponent(ctx)
|
|
581
|
+
elif isinstance(ctx, Parser.DateDiffAtomComponentContext):
|
|
582
|
+
return self.visitDateAddAtomComponentContext(ctx)
|
|
583
|
+
elif isinstance(ctx, Parser.DateAddAtomComponentContext):
|
|
584
|
+
return self.visitDateAddAtomComponentContext(ctx)
|
|
585
|
+
elif isinstance(ctx, Parser.YearAtomComponentContext):
|
|
586
|
+
return self.visitTimeUnaryAtomComponent(ctx)
|
|
587
|
+
elif isinstance(ctx, Parser.MonthAtomComponentContext):
|
|
588
|
+
return self.visitTimeUnaryAtomComponent(ctx)
|
|
589
|
+
elif isinstance(ctx, Parser.DayOfMonthAtomComponentContext):
|
|
590
|
+
return self.visitTimeUnaryAtomComponent(ctx)
|
|
591
|
+
elif isinstance(ctx, Parser.DayOfYearAtomComponentContext):
|
|
592
|
+
return self.visitTimeUnaryAtomComponent(ctx)
|
|
593
|
+
elif isinstance(ctx, Parser.DayToYearAtomComponentContext):
|
|
594
|
+
return self.visitTimeUnaryAtomComponent(ctx)
|
|
595
|
+
elif isinstance(ctx, Parser.DayToMonthAtomComponentContext):
|
|
596
|
+
return self.visitTimeUnaryAtomComponent(ctx)
|
|
597
|
+
elif isinstance(ctx, Parser.YearToDayAtomComponentContext):
|
|
598
|
+
return self.visitTimeUnaryAtomComponent(ctx)
|
|
599
|
+
elif isinstance(ctx, Parser.MonthToDayAtomComponentContext):
|
|
600
|
+
return self.visitTimeUnaryAtomComponent(ctx)
|
|
555
601
|
else:
|
|
556
602
|
raise NotImplementedError
|
|
557
603
|
|
|
558
|
-
def
|
|
604
|
+
def visitTimeUnaryAtomComponent(self, ctx: Parser.PeriodAtomComponentContext):
|
|
559
605
|
"""
|
|
560
606
|
periodExpr: PERIOD_INDICATOR '(' expr? ')' ;
|
|
561
607
|
"""
|
|
@@ -653,6 +699,34 @@ class ExprComp(VtlVisitor):
|
|
|
653
699
|
c = list(ctx.getChildren())[0]
|
|
654
700
|
return MulOp(op=c.getSymbol().text, children=[])
|
|
655
701
|
|
|
702
|
+
def visitDateDiffAtomComponent(self, ctx: Parser.TimeShiftAtomComponentContext):
|
|
703
|
+
""" """
|
|
704
|
+
ctx_list = list(ctx.getChildren())
|
|
705
|
+
c = ctx_list[0]
|
|
706
|
+
|
|
707
|
+
op = c.getSymbol().text
|
|
708
|
+
left_node = self.visitExprComponent(ctx_list[2])
|
|
709
|
+
right_node = Constant("INTEGER_CONSTANT", int(ctx_list[4].getSymbol().text))
|
|
710
|
+
|
|
711
|
+
return BinOp(left=left_node, op=op, right=right_node)
|
|
712
|
+
|
|
713
|
+
def visitDateAddAtomComponentContext(self, ctx: Parser.DateAddAtomComponentContext):
|
|
714
|
+
""" """
|
|
715
|
+
ctx_list = list(ctx.getChildren())
|
|
716
|
+
c = ctx_list[0]
|
|
717
|
+
|
|
718
|
+
op = c.getSymbol().text
|
|
719
|
+
children_node = [self.visitExprComponent(ctx_list[2])]
|
|
720
|
+
|
|
721
|
+
param_constant_node = []
|
|
722
|
+
|
|
723
|
+
if len(ctx_list) > 4:
|
|
724
|
+
param_constant_node = [self.visitExprComponent(ctx_list[4])]
|
|
725
|
+
if len(ctx_list) > 6:
|
|
726
|
+
param_constant_node.append(self.visitExprComponent(ctx_list[6]))
|
|
727
|
+
|
|
728
|
+
return ParamOp(op=op, children=children_node, params=param_constant_node)
|
|
729
|
+
|
|
656
730
|
"""
|
|
657
731
|
-----------------------------------
|
|
658
732
|
Conditional Functions
|
vtlengine/AST/ASTTemplate.py
CHANGED
|
@@ -314,6 +314,22 @@ class ASTTemplate(NodeVisitor):
|
|
|
314
314
|
self.visit(node.thenOp)
|
|
315
315
|
self.visit(node.elseOp)
|
|
316
316
|
|
|
317
|
+
def visit_Case(self, node: AST.Case) -> Any:
|
|
318
|
+
"""
|
|
319
|
+
Case: (conditions, thenOp, elseOp)
|
|
320
|
+
|
|
321
|
+
Basic usage:
|
|
322
|
+
|
|
323
|
+
for condition in node.conditions:
|
|
324
|
+
self.visit(condition)
|
|
325
|
+
self.visit(node.thenOp)
|
|
326
|
+
self.visit(node.elseOp)
|
|
327
|
+
"""
|
|
328
|
+
for case in node.cases:
|
|
329
|
+
self.visit(case.condition)
|
|
330
|
+
self.visit(case.thenOp)
|
|
331
|
+
self.visit(node.elseOp)
|
|
332
|
+
|
|
317
333
|
def visit_Validation(self, node: AST.Validation) -> Any:
|
|
318
334
|
"""
|
|
319
335
|
Validation: (op, validation, params, inbalance, invalid)
|
vtlengine/AST/Grammar/Vtl.g4
CHANGED
|
@@ -21,30 +21,33 @@ expr:
|
|
|
21
21
|
| op=(PLUS|MINUS|NOT) right=expr # unaryExpr
|
|
22
22
|
| left=expr op=(MUL|DIV) right=expr # arithmeticExpr
|
|
23
23
|
| left=expr op=(PLUS|MINUS|CONCAT) right=expr # arithmeticExprOrConcat
|
|
24
|
-
| left=expr op=comparisonOperand
|
|
24
|
+
| left=expr op=comparisonOperand right=expr # comparisonExpr
|
|
25
25
|
| left=expr op=(IN|NOT_IN)(lists|valueDomainID) # inNotInExpr
|
|
26
26
|
| left=expr op=AND right=expr # booleanExpr
|
|
27
27
|
| left=expr op=(OR|XOR) right=expr # booleanExpr
|
|
28
28
|
| IF conditionalExpr=expr THEN thenExpr=expr ELSE elseExpr=expr # ifExpr
|
|
29
|
+
| CASE (WHEN expr THEN expr)+ ELSE expr # caseExpr
|
|
29
30
|
| constant # constantExpr
|
|
30
31
|
| varID # varIdExpr
|
|
31
32
|
|
|
33
|
+
|
|
32
34
|
;
|
|
33
35
|
|
|
34
36
|
|
|
35
37
|
exprComponent:
|
|
36
|
-
LPAREN exprComponent RPAREN
|
|
37
|
-
| functionsComponents
|
|
38
|
-
| op=(PLUS|MINUS|NOT) right=exprComponent
|
|
39
|
-
| left=exprComponent op=(MUL|DIV) right=exprComponent
|
|
40
|
-
| left=exprComponent op=(PLUS|MINUS|CONCAT) right=exprComponent
|
|
41
|
-
| left=exprComponent comparisonOperand right=exprComponent
|
|
42
|
-
| left=exprComponent op=(IN|NOT_IN)(lists|valueDomainID)
|
|
43
|
-
| left=exprComponent op=AND right=exprComponent
|
|
44
|
-
| left=exprComponent op=(OR|XOR) right=exprComponent
|
|
45
|
-
| IF conditionalExpr=exprComponent THEN thenExpr=exprComponent ELSE elseExpr=exprComponent
|
|
46
|
-
|
|
|
47
|
-
|
|
|
38
|
+
LPAREN exprComponent RPAREN # parenthesisExprComp
|
|
39
|
+
| functionsComponents # functionsExpressionComp
|
|
40
|
+
| op=(PLUS|MINUS|NOT) right=exprComponent # unaryExprComp
|
|
41
|
+
| left=exprComponent op=(MUL|DIV) right=exprComponent # arithmeticExprComp
|
|
42
|
+
| left=exprComponent op=(PLUS|MINUS|CONCAT) right=exprComponent # arithmeticExprOrConcatComp
|
|
43
|
+
| left=exprComponent comparisonOperand right=exprComponent # comparisonExprComp
|
|
44
|
+
| left=exprComponent op=(IN|NOT_IN)(lists|valueDomainID) # inNotInExprComp
|
|
45
|
+
| left=exprComponent op=AND right=exprComponent # booleanExprComp
|
|
46
|
+
| left=exprComponent op=(OR|XOR) right=exprComponent # booleanExprComp
|
|
47
|
+
| IF conditionalExpr=exprComponent THEN thenExpr=exprComponent ELSE elseExpr=exprComponent # ifExprComp
|
|
48
|
+
| CASE (WHEN exprComponent THEN exprComponent)+ ELSE exprComponent # caseExprComp
|
|
49
|
+
| constant # constantExprComp
|
|
50
|
+
| componentID # compId
|
|
48
51
|
;
|
|
49
52
|
|
|
50
53
|
functionsComponents:
|
|
@@ -84,6 +87,7 @@ datasetClause:
|
|
|
84
87
|
| calcClause
|
|
85
88
|
| keepOrDropClause
|
|
86
89
|
| pivotOrUnpivotClause
|
|
90
|
+
/* | customPivotClause */
|
|
87
91
|
| subspaceClause
|
|
88
92
|
;
|
|
89
93
|
|
|
@@ -112,6 +116,10 @@ pivotOrUnpivotClause:
|
|
|
112
116
|
op=(PIVOT|UNPIVOT) id_=componentID COMMA mea=componentID
|
|
113
117
|
;
|
|
114
118
|
|
|
119
|
+
customPivotClause:
|
|
120
|
+
CUSTOMPIVOT id_=componentID COMMA mea=componentID IN constant (COMMA constant)*
|
|
121
|
+
;
|
|
122
|
+
|
|
115
123
|
subspaceClause:
|
|
116
124
|
SUBSPACE subspaceClauseItem (COMMA subspaceClauseItem)*
|
|
117
125
|
;
|
|
@@ -138,7 +146,7 @@ defOperators:
|
|
|
138
146
|
/*---------------------------------------------------FUNCTIONS-------------------------------------------------*/
|
|
139
147
|
genericOperators:
|
|
140
148
|
operatorID LPAREN (parameter (COMMA parameter)*)? RPAREN # callDataset
|
|
141
|
-
| EVAL LPAREN routineName LPAREN (varID|scalarItem)? (COMMA (varID|scalarItem))* RPAREN (LANGUAGE STRING_CONSTANT)? (RETURNS evalDatasetType)? RPAREN
|
|
149
|
+
| EVAL LPAREN routineName LPAREN (varID|scalarItem)? (COMMA (varID|scalarItem))* RPAREN (LANGUAGE STRING_CONSTANT)? (RETURNS evalDatasetType)? RPAREN # evalAtom
|
|
142
150
|
| CAST LPAREN expr COMMA (basicScalarType|valueDomainName) (COMMA STRING_CONSTANT)? RPAREN # castExprDataset
|
|
143
151
|
;
|
|
144
152
|
|
|
@@ -149,6 +157,7 @@ genericOperatorsComponent:
|
|
|
149
157
|
|
|
150
158
|
;
|
|
151
159
|
|
|
160
|
+
|
|
152
161
|
parameterComponent:
|
|
153
162
|
exprComponent
|
|
154
163
|
| OPTIONAL
|
|
@@ -176,13 +185,13 @@ stringOperatorsComponent:
|
|
|
176
185
|
numericOperators:
|
|
177
186
|
op=(CEIL | FLOOR | ABS | EXP | LN | SQRT) LPAREN expr RPAREN # unaryNumeric
|
|
178
187
|
| op=(ROUND | TRUNC) LPAREN expr (COMMA optionalExpr)? RPAREN # unaryWithOptionalNumeric
|
|
179
|
-
| op=(MOD | POWER|LOG) LPAREN left=expr COMMA right=expr RPAREN
|
|
188
|
+
| op=(MOD | POWER | LOG | RANDOM) LPAREN left=expr COMMA right=expr RPAREN # binaryNumeric
|
|
180
189
|
;
|
|
181
190
|
|
|
182
191
|
numericOperatorsComponent:
|
|
183
|
-
op=(CEIL | FLOOR | ABS | EXP | LN | SQRT) LPAREN exprComponent RPAREN
|
|
184
|
-
| op=(ROUND | TRUNC) LPAREN exprComponent (COMMA optionalExprComponent)? RPAREN
|
|
185
|
-
| op=(MOD | POWER | LOG) LPAREN left=exprComponent COMMA right=exprComponent RPAREN
|
|
192
|
+
op=(CEIL | FLOOR | ABS | EXP | LN | SQRT) LPAREN exprComponent RPAREN # unaryNumericComponent
|
|
193
|
+
| op=(ROUND | TRUNC) LPAREN exprComponent (COMMA optionalExprComponent)? RPAREN # unaryWithOptionalNumericComponent
|
|
194
|
+
| op=(MOD | POWER | LOG | RANDOM) LPAREN left=exprComponent COMMA right=exprComponent RPAREN # binaryNumericComponent
|
|
186
195
|
;
|
|
187
196
|
|
|
188
197
|
comparisonOperators:
|
|
@@ -205,6 +214,16 @@ timeOperators:
|
|
|
205
214
|
| TIMESHIFT LPAREN expr COMMA signedInteger RPAREN # timeShiftAtom
|
|
206
215
|
| TIME_AGG LPAREN periodIndTo=STRING_CONSTANT (COMMA periodIndFrom=(STRING_CONSTANT| OPTIONAL ))? (COMMA op=optionalExpr)? (COMMA (FIRST|LAST))? RPAREN # timeAggAtom
|
|
207
216
|
| CURRENT_DATE LPAREN RPAREN # currentDateAtom
|
|
217
|
+
| DATEDIFF LPAREN dateFrom=expr COMMA dateTo=expr RPAREN # dateDiffAtom
|
|
218
|
+
| DATEADD LPAREN op=expr COMMA shiftNumber=expr COMMA periodInd=expr RPAREN # dateAddAtom
|
|
219
|
+
| YEAR_OP LPAREN expr RPAREN # yearAtom
|
|
220
|
+
| MONTH_OP LPAREN expr RPAREN # monthAtom
|
|
221
|
+
| DAYOFMONTH LPAREN expr RPAREN # dayOfMonthAtom
|
|
222
|
+
| DAYOFYEAR LPAREN expr RPAREN # datOfYearAtom
|
|
223
|
+
| DAYTOYEAR LPAREN expr RPAREN # dayToYearAtom
|
|
224
|
+
| DAYTOMONTH LPAREN expr RPAREN # dayToMonthAtom
|
|
225
|
+
| YEARTODAY LPAREN expr RPAREN # yearTodayAtom
|
|
226
|
+
| MONTHTODAY LPAREN expr RPAREN # monthTodayAtom
|
|
208
227
|
;
|
|
209
228
|
|
|
210
229
|
timeOperatorsComponent:
|
|
@@ -213,7 +232,17 @@ timeOperatorsComponent:
|
|
|
213
232
|
| op=(FLOW_TO_STOCK | STOCK_TO_FLOW) LPAREN exprComponent RPAREN # flowAtomComponent
|
|
214
233
|
| TIMESHIFT LPAREN exprComponent COMMA signedInteger RPAREN # timeShiftAtomComponent
|
|
215
234
|
| TIME_AGG LPAREN periodIndTo=STRING_CONSTANT (COMMA periodIndFrom=(STRING_CONSTANT| OPTIONAL ))? (COMMA op=optionalExprComponent)? (COMMA (FIRST|LAST))? RPAREN # timeAggAtomComponent
|
|
216
|
-
| CURRENT_DATE LPAREN RPAREN
|
|
235
|
+
| CURRENT_DATE LPAREN RPAREN # currentDateAtomComponent
|
|
236
|
+
| DATEDIFF LPAREN dateFrom=exprComponent COMMA dateTo=exprComponent RPAREN # dateDiffAtomComponent
|
|
237
|
+
| DATEADD LPAREN op=exprComponent COMMA shiftNumber=exprComponent COMMA periodInd=exprComponent RPAREN # dateAddAtomComponent
|
|
238
|
+
| YEAR_OP LPAREN exprComponent RPAREN # yearAtomComponent
|
|
239
|
+
| MONTH_OP LPAREN exprComponent RPAREN # monthAtomComponent
|
|
240
|
+
| DAYOFMONTH LPAREN exprComponent RPAREN # dayOfMonthAtomComponent
|
|
241
|
+
| DAYOFYEAR LPAREN exprComponent RPAREN # datOfYearAtomComponent
|
|
242
|
+
| DAYTOYEAR LPAREN exprComponent RPAREN # dayToYearAtomComponent
|
|
243
|
+
| DAYTOMONTH LPAREN exprComponent RPAREN # dayToMonthAtomComponent
|
|
244
|
+
| YEARTODAY LPAREN exprComponent RPAREN # yearTodayAtomComponent
|
|
245
|
+
| MONTHTODAY LPAREN exprComponent RPAREN # monthTodayAtomComponent
|
|
217
246
|
;
|
|
218
247
|
|
|
219
248
|
setOperators:
|
|
@@ -284,7 +313,7 @@ aggrOperatorsGrouping:
|
|
|
284
313
|
| FIRST_VALUE
|
|
285
314
|
| LAST_VALUE)
|
|
286
315
|
LPAREN expr OVER LPAREN (partition=partitionByClause? orderBy=orderByClause? windowing=windowingClause?)RPAREN RPAREN #anSimpleFunction
|
|
287
|
-
| op=(LAG |LEAD) LPAREN expr (COMMA
|
|
316
|
+
| op=(LAG |LEAD) LPAREN expr (COMMA offset=signedInteger(COMMA defaultValue=scalarItem)?)? OVER LPAREN (partition=partitionByClause? orderBy=orderByClause) RPAREN RPAREN # lagOrLeadAn
|
|
288
317
|
| op=RATIO_TO_REPORT LPAREN expr OVER LPAREN (partition=partitionByClause) RPAREN RPAREN # ratioToReportAn
|
|
289
318
|
;
|
|
290
319
|
|
|
@@ -28,11 +28,22 @@ lexer grammar VtlTokens;
|
|
|
28
28
|
MEMBERSHIP : '#';
|
|
29
29
|
EVAL : 'eval';
|
|
30
30
|
IF : 'if';
|
|
31
|
+
CASE : 'case';
|
|
31
32
|
THEN : 'then';
|
|
32
33
|
ELSE : 'else';
|
|
33
34
|
USING : 'using';
|
|
34
35
|
WITH : 'with';
|
|
35
36
|
CURRENT_DATE : 'current_date';
|
|
37
|
+
DATEDIFF : 'datediff';
|
|
38
|
+
DATEADD : 'dateadd';
|
|
39
|
+
YEAR_OP : 'year';
|
|
40
|
+
MONTH_OP : 'month';
|
|
41
|
+
DAYOFMONTH : 'dayofmonth';
|
|
42
|
+
DAYOFYEAR : 'dayofyear';
|
|
43
|
+
DAYTOYEAR : 'daytoyear';
|
|
44
|
+
DAYTOMONTH : 'daytomonth';
|
|
45
|
+
YEARTODAY : 'yeartoday';
|
|
46
|
+
MONTHTODAY : 'monthtoday';
|
|
36
47
|
ON : 'on';
|
|
37
48
|
DROP : 'drop';
|
|
38
49
|
KEEP : 'keep';
|
|
@@ -54,6 +65,7 @@ lexer grammar VtlTokens;
|
|
|
54
65
|
DIFF : 'diff';
|
|
55
66
|
SYMDIFF : 'symdiff';
|
|
56
67
|
INTERSECT : 'intersect';
|
|
68
|
+
RANDOM : 'random';
|
|
57
69
|
KEYS : 'keys';
|
|
58
70
|
INTYEAR : 'intyear';
|
|
59
71
|
INTMONTH : 'intmonth';
|
|
@@ -394,4 +406,4 @@ FREQUENCY
|
|
|
394
406
|
| 'M'
|
|
395
407
|
| 'W'
|
|
396
408
|
| 'D'
|
|
397
|
-
;*/
|
|
409
|
+
;*/
|