vtlengine 1.0.1__py3-none-any.whl → 1.0.3__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 +19 -8
- vtlengine/API/__init__.py +9 -9
- vtlengine/AST/ASTConstructor.py +23 -43
- vtlengine/AST/ASTConstructorModules/Expr.py +147 -71
- vtlengine/AST/ASTConstructorModules/ExprComponents.py +104 -40
- vtlengine/AST/ASTConstructorModules/Terminals.py +28 -39
- vtlengine/AST/ASTTemplate.py +16 -1
- vtlengine/AST/DAG/__init__.py +12 -15
- 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 -2
- vtlengine/AST/__init__.py +21 -3
- vtlengine/DataTypes/TimeHandling.py +12 -7
- vtlengine/DataTypes/__init__.py +17 -24
- vtlengine/Exceptions/__init__.py +43 -1
- vtlengine/Exceptions/messages.py +82 -62
- vtlengine/Interpreter/__init__.py +125 -120
- vtlengine/Model/__init__.py +17 -12
- vtlengine/Operators/Aggregation.py +14 -14
- vtlengine/Operators/Analytic.py +56 -31
- vtlengine/Operators/Assignment.py +2 -3
- vtlengine/Operators/Boolean.py +5 -7
- vtlengine/Operators/CastOperator.py +12 -13
- vtlengine/Operators/Clause.py +11 -13
- vtlengine/Operators/Comparison.py +31 -17
- vtlengine/Operators/Conditional.py +157 -17
- vtlengine/Operators/General.py +4 -4
- vtlengine/Operators/HROperators.py +41 -34
- vtlengine/Operators/Join.py +18 -22
- vtlengine/Operators/Numeric.py +76 -39
- vtlengine/Operators/RoleSetter.py +6 -8
- vtlengine/Operators/Set.py +7 -12
- vtlengine/Operators/String.py +19 -27
- vtlengine/Operators/Time.py +366 -43
- vtlengine/Operators/Validation.py +4 -7
- vtlengine/Operators/__init__.py +38 -41
- vtlengine/Utils/__init__.py +149 -94
- vtlengine/__init__.py +1 -1
- vtlengine/files/output/__init__.py +2 -2
- vtlengine/files/output/_time_period_representation.py +0 -1
- vtlengine/files/parser/__init__.py +18 -18
- vtlengine/files/parser/_time_checking.py +3 -2
- {vtlengine-1.0.1.dist-info → vtlengine-1.0.3.dist-info}/METADATA +17 -5
- vtlengine-1.0.3.dist-info/RECORD +58 -0
- vtlengine-1.0.1.dist-info/RECORD +0 -58
- {vtlengine-1.0.1.dist-info → vtlengine-1.0.3.dist-info}/LICENSE.md +0 -0
- {vtlengine-1.0.1.dist-info → vtlengine-1.0.3.dist-info}/WHEEL +0 -0
vtlengine/API/_InternalApi.py
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import os
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import Any, Dict, List, Optional, Union
|
|
5
5
|
|
|
6
6
|
import pandas as pd
|
|
7
7
|
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.
|
|
12
|
-
from vtlengine.files.parser import
|
|
11
|
+
from vtlengine.Exceptions import check_key
|
|
12
|
+
from vtlengine.files.parser import _fill_dataset_empty_data, _validate_pandas
|
|
13
|
+
from vtlengine.Model import (
|
|
14
|
+
Component,
|
|
15
|
+
Dataset,
|
|
16
|
+
ExternalRoutine,
|
|
17
|
+
Role,
|
|
18
|
+
Role_keys,
|
|
19
|
+
Scalar,
|
|
20
|
+
ValueDomain,
|
|
21
|
+
)
|
|
13
22
|
|
|
14
23
|
base_path = Path(__file__).parent
|
|
15
24
|
filepath_VTL = base_path / "data" / "vtl"
|
|
@@ -30,15 +39,17 @@ def _load_dataset_from_structure(structures: Dict[str, Any]) -> Dict[str, Any]:
|
|
|
30
39
|
if "datasets" in structures:
|
|
31
40
|
for dataset_json in structures["datasets"]:
|
|
32
41
|
dataset_name = dataset_json["name"]
|
|
33
|
-
components = {
|
|
34
|
-
|
|
42
|
+
components = {}
|
|
43
|
+
|
|
44
|
+
for component in dataset_json["DataStructure"]:
|
|
45
|
+
check_key("data_type", SCALAR_TYPES.keys(), component["type"])
|
|
46
|
+
check_key("role", Role_keys, component["role"])
|
|
47
|
+
components[component["name"]] = Component(
|
|
35
48
|
name=component["name"],
|
|
36
49
|
data_type=SCALAR_TYPES[component["type"]],
|
|
37
50
|
role=Role(component["role"]),
|
|
38
51
|
nullable=component["nullable"],
|
|
39
52
|
)
|
|
40
|
-
for component in dataset_json["DataStructure"]
|
|
41
|
-
}
|
|
42
53
|
|
|
43
54
|
datasets[dataset_name] = Dataset(name=dataset_name, components=components, data=None)
|
|
44
55
|
if "scalars" in structures:
|
|
@@ -208,7 +219,7 @@ def load_datasets_with_data(data_structures: Any, datapoints: Optional[Any] = No
|
|
|
208
219
|
return datasets, None
|
|
209
220
|
# Handling dictionary of paths
|
|
210
221
|
dict_datapoints = _load_datapoints_path(datapoints)
|
|
211
|
-
for dataset_name,
|
|
222
|
+
for dataset_name, _ in dict_datapoints.items():
|
|
212
223
|
if dataset_name not in datasets:
|
|
213
224
|
raise Exception(f"Not found dataset {dataset_name}")
|
|
214
225
|
|
vtlengine/API/__init__.py
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
from typing import Any,
|
|
2
|
+
from typing import Any, Dict, List, Optional, Union
|
|
3
3
|
|
|
4
4
|
import pandas as pd
|
|
5
5
|
from antlr4 import CommonTokenStream, InputStream # type: ignore[import-untyped]
|
|
6
6
|
from antlr4.error.ErrorListener import ErrorListener # type: ignore[import-untyped]
|
|
7
7
|
|
|
8
8
|
from vtlengine.API._InternalApi import (
|
|
9
|
-
|
|
9
|
+
_check_output_folder,
|
|
10
|
+
_return_only_persistent_datasets,
|
|
10
11
|
load_datasets,
|
|
11
|
-
load_value_domains,
|
|
12
|
-
load_external_routines,
|
|
13
12
|
load_datasets_with_data,
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
load_external_routines,
|
|
14
|
+
load_value_domains,
|
|
15
|
+
load_vtl,
|
|
16
16
|
)
|
|
17
17
|
from vtlengine.AST import Start
|
|
18
18
|
from vtlengine.AST.ASTConstructor import ASTVisitor
|
|
19
19
|
from vtlengine.AST.DAG import DAGAnalyzer
|
|
20
20
|
from vtlengine.AST.Grammar.lexer import Lexer
|
|
21
21
|
from vtlengine.AST.Grammar.parser import Parser
|
|
22
|
-
from vtlengine.Interpreter import InterpreterAnalyzer
|
|
23
22
|
from vtlengine.files.output._time_period_representation import (
|
|
24
|
-
format_time_period_external_representation,
|
|
25
23
|
TimePeriodRepresentation,
|
|
24
|
+
format_time_period_external_representation,
|
|
26
25
|
)
|
|
26
|
+
from vtlengine.Interpreter import InterpreterAnalyzer
|
|
27
27
|
|
|
28
28
|
pd.options.mode.chained_assignment = None
|
|
29
29
|
|
|
@@ -78,7 +78,7 @@ def create_ast(text: str) -> Start:
|
|
|
78
78
|
stream = _lexer(text)
|
|
79
79
|
cst = _parser(stream)
|
|
80
80
|
visitor = ASTVisitor()
|
|
81
|
-
ast = visitor.
|
|
81
|
+
ast = visitor.visitStart(cst)
|
|
82
82
|
DAGAnalyzer.createDAG(ast)
|
|
83
83
|
return ast
|
|
84
84
|
|
vtlengine/AST/ASTConstructor.py
CHANGED
|
@@ -10,18 +10,18 @@ Node Creator.
|
|
|
10
10
|
from antlr4.tree.Tree import TerminalNodeImpl
|
|
11
11
|
|
|
12
12
|
from vtlengine.AST import (
|
|
13
|
-
Start,
|
|
14
|
-
Assignment,
|
|
15
|
-
PersistentAssignment,
|
|
16
|
-
Operator,
|
|
17
13
|
Argument,
|
|
14
|
+
Assignment,
|
|
15
|
+
DefIdentifier,
|
|
16
|
+
DPRule,
|
|
18
17
|
DPRuleset,
|
|
19
18
|
HRBinOp,
|
|
20
|
-
DPRule,
|
|
21
|
-
HRuleset,
|
|
22
|
-
DefIdentifier,
|
|
23
19
|
HRule,
|
|
20
|
+
HRuleset,
|
|
24
21
|
HRUnOp,
|
|
22
|
+
Operator,
|
|
23
|
+
PersistentAssignment,
|
|
24
|
+
Start,
|
|
25
25
|
)
|
|
26
26
|
from vtlengine.AST.ASTConstructorModules.Expr import Expr
|
|
27
27
|
from vtlengine.AST.ASTConstructorModules.ExprComponents import ExprComp
|
|
@@ -30,8 +30,7 @@ from vtlengine.AST.ASTDataExchange import de_ruleset_elements
|
|
|
30
30
|
from vtlengine.AST.Grammar.parser import Parser
|
|
31
31
|
from vtlengine.AST.VtlVisitor import VtlVisitor
|
|
32
32
|
from vtlengine.Exceptions import SemanticError
|
|
33
|
-
from vtlengine.Model import
|
|
34
|
-
|
|
33
|
+
from vtlengine.Model import Component, Dataset, Scalar
|
|
35
34
|
|
|
36
35
|
# pylint: disable=unreachable,expression-not-assigned
|
|
37
36
|
# pylint: disable=assignment-from-no-return
|
|
@@ -280,19 +279,13 @@ class ASTVisitor(VtlVisitor):
|
|
|
280
279
|
for erCode_name in ctx_list
|
|
281
280
|
if isinstance(erCode_name, Parser.ErCodeContext)
|
|
282
281
|
]
|
|
283
|
-
if len(er_code) == 0
|
|
284
|
-
er_code = None
|
|
285
|
-
else:
|
|
286
|
-
er_code = er_code[0]
|
|
282
|
+
er_code = None if len(er_code) == 0 else er_code[0]
|
|
287
283
|
er_level = [
|
|
288
284
|
Terminals().visitErLevel(erLevel_name)
|
|
289
285
|
for erLevel_name in ctx_list
|
|
290
286
|
if isinstance(erLevel_name, Parser.ErLevelContext)
|
|
291
287
|
]
|
|
292
|
-
if len(er_level) == 0
|
|
293
|
-
er_level = None
|
|
294
|
-
else:
|
|
295
|
-
er_level = er_level[0]
|
|
288
|
+
er_level = None if len(er_level) == 0 else er_level[0]
|
|
296
289
|
|
|
297
290
|
return DPRule(name=rule_name, rule=rule_node, erCode=er_code, erLevel=er_level)
|
|
298
291
|
|
|
@@ -317,11 +310,7 @@ class ASTVisitor(VtlVisitor):
|
|
|
317
310
|
for element in ctx_list
|
|
318
311
|
if isinstance(element, Parser.ScalarItemContext)
|
|
319
312
|
]
|
|
320
|
-
|
|
321
|
-
if len(argument_default) == 0:
|
|
322
|
-
argument_default = None
|
|
323
|
-
else:
|
|
324
|
-
argument_default = argument_default[0]
|
|
313
|
+
argument_default = None if len(argument_default) == 0 else argument_default[0]
|
|
325
314
|
|
|
326
315
|
if isinstance(argument_type, (Dataset, Component, Scalar)):
|
|
327
316
|
argument_type.name = argument_name.value
|
|
@@ -375,10 +364,7 @@ class ASTVisitor(VtlVisitor):
|
|
|
375
364
|
if isinstance(valueDomain, TerminalNodeImpl)
|
|
376
365
|
and valueDomain.getSymbol().type == Parser.VALUE_DOMAIN
|
|
377
366
|
]
|
|
378
|
-
if len(value_domain) != 0
|
|
379
|
-
kind = "ValuedomainID"
|
|
380
|
-
else:
|
|
381
|
-
kind = "DatasetID"
|
|
367
|
+
kind = "ValuedomainID" if len(value_domain) != 0 else "DatasetID"
|
|
382
368
|
|
|
383
369
|
conditions = [
|
|
384
370
|
self.visitValueDomainSignature(vtlsig)
|
|
@@ -408,8 +394,8 @@ class ASTVisitor(VtlVisitor):
|
|
|
408
394
|
# TODO Support for valueDomainSignature.
|
|
409
395
|
def visitValueDomainSignature(self, ctx: Parser.ValueDomainSignatureContext):
|
|
410
396
|
"""
|
|
411
|
-
valueDomainSignature: CONDITION IDENTIFIER (AS IDENTIFIER)? (',' IDENTIFIER (AS IDENTIFIER)?)* ;
|
|
412
|
-
"""
|
|
397
|
+
valueDomainSignature: CONDITION IDENTIFIER (AS IDENTIFIER)? (',' IDENTIFIER (AS IDENTIFIER)?)* ;
|
|
398
|
+
""" # noqa E501
|
|
413
399
|
# AST_ASTCONSTRUCTOR.7
|
|
414
400
|
ctx_list = list(ctx.getChildren())
|
|
415
401
|
component_nodes = [
|
|
@@ -458,28 +444,22 @@ class ASTVisitor(VtlVisitor):
|
|
|
458
444
|
for erCode_name in ctx_list
|
|
459
445
|
if isinstance(erCode_name, Parser.ErCodeContext)
|
|
460
446
|
]
|
|
461
|
-
if len(er_code) == 0
|
|
462
|
-
er_code = None
|
|
463
|
-
else:
|
|
464
|
-
er_code = er_code[0]
|
|
447
|
+
er_code = None if len(er_code) == 0 else er_code[0]
|
|
465
448
|
er_level = [
|
|
466
449
|
Terminals().visitErLevel(erLevel_name)
|
|
467
450
|
for erLevel_name in ctx_list
|
|
468
451
|
if isinstance(erLevel_name, Parser.ErLevelContext)
|
|
469
452
|
]
|
|
470
|
-
if len(er_level) == 0
|
|
471
|
-
er_level = None
|
|
472
|
-
else:
|
|
473
|
-
er_level = er_level[0]
|
|
453
|
+
er_level = None if len(er_level) == 0 else er_level[0]
|
|
474
454
|
|
|
475
455
|
return HRule(name=rule_name, rule=rule_node, erCode=er_code, erLevel=er_level)
|
|
476
456
|
|
|
477
457
|
def visitCodeItemRelation(self, ctx: Parser.CodeItemRelationContext):
|
|
478
458
|
"""
|
|
479
|
-
codeItemRelation: ( WHEN expr THEN )? codeItemRef codeItemRelationClause (codeItemRelationClause)* ;
|
|
480
|
-
( WHEN exprComponent THEN )? codetemRef=valueDomainValue comparisonOperand? codeItemRelationClause (codeItemRelationClause)*
|
|
459
|
+
codeItemRelation: ( WHEN expr THEN )? codeItemRef codeItemRelationClause (codeItemRelationClause)* ;
|
|
460
|
+
( WHEN exprComponent THEN )? codetemRef=valueDomainValue comparisonOperand? codeItemRelationClause (codeItemRelationClause)*
|
|
481
461
|
|
|
482
|
-
"""
|
|
462
|
+
""" # noqa E501
|
|
483
463
|
|
|
484
464
|
ctx_list = list(ctx.getChildren())
|
|
485
465
|
|
|
@@ -531,8 +511,8 @@ class ASTVisitor(VtlVisitor):
|
|
|
531
511
|
|
|
532
512
|
def visitCodeItemRelationClause(self, ctx: Parser.CodeItemRelationClauseContext):
|
|
533
513
|
"""
|
|
534
|
-
(opAdd=( PLUS | MINUS ))? rightCodeItem=valueDomainValue ( QLPAREN rightCondition=exprComponent QRPAREN )?
|
|
535
|
-
"""
|
|
514
|
+
(opAdd=( PLUS | MINUS ))? rightCodeItem=valueDomainValue ( QLPAREN rightCondition=exprComponent QRPAREN )?
|
|
515
|
+
""" # noqa E501
|
|
536
516
|
ctx_list = list(ctx.getChildren())
|
|
537
517
|
|
|
538
518
|
expr = [expr for expr in ctx_list if isinstance(expr, Parser.ExprContext)]
|
|
@@ -552,13 +532,13 @@ class ASTVisitor(VtlVisitor):
|
|
|
552
532
|
|
|
553
533
|
code_item = DefIdentifier(value=value, kind="CodeItemID")
|
|
554
534
|
if right_condition:
|
|
555
|
-
|
|
535
|
+
code_item._right_condition = right_condition[0]
|
|
556
536
|
|
|
557
537
|
return HRBinOp(left=None, op=op, right=code_item)
|
|
558
538
|
else:
|
|
559
539
|
value = Terminals().visitValueDomainValue(ctx_list[0])
|
|
560
540
|
code_item = DefIdentifier(value=value, kind="CodeItemID")
|
|
561
541
|
if right_condition:
|
|
562
|
-
|
|
542
|
+
code_item._right_condition = right_condition[0]
|
|
563
543
|
|
|
564
544
|
return code_item
|
|
@@ -1,30 +1,33 @@
|
|
|
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
|
|
|
6
7
|
from vtlengine.AST import (
|
|
7
|
-
|
|
8
|
+
ID,
|
|
9
|
+
Aggregation,
|
|
10
|
+
Analytic,
|
|
11
|
+
Assignment,
|
|
8
12
|
BinOp,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
JoinOp,
|
|
13
|
-
Identifier,
|
|
14
|
-
ParamOp,
|
|
13
|
+
Case,
|
|
14
|
+
CaseObj,
|
|
15
|
+
Constant,
|
|
15
16
|
EvalOp,
|
|
16
|
-
|
|
17
|
+
Identifier,
|
|
18
|
+
If,
|
|
19
|
+
JoinOp,
|
|
17
20
|
MulOp,
|
|
21
|
+
ParamConstant,
|
|
22
|
+
ParamOp,
|
|
18
23
|
RegularAggregation,
|
|
19
|
-
|
|
20
|
-
Aggregation,
|
|
21
|
-
ID,
|
|
24
|
+
RenameNode,
|
|
22
25
|
TimeAggregation,
|
|
23
|
-
|
|
26
|
+
UDOCall,
|
|
27
|
+
UnaryOp,
|
|
24
28
|
Validation,
|
|
25
|
-
Analytic,
|
|
26
|
-
Windowing,
|
|
27
29
|
VarID,
|
|
30
|
+
Windowing,
|
|
28
31
|
)
|
|
29
32
|
from vtlengine.AST.ASTConstructorModules.ExprComponents import ExprComp
|
|
30
33
|
from vtlengine.AST.ASTConstructorModules.Terminals import Terminals
|
|
@@ -47,22 +50,23 @@ class Expr(VtlVisitor):
|
|
|
47
50
|
def visitExpr(self, ctx: Parser.ExprContext):
|
|
48
51
|
"""
|
|
49
52
|
expr:
|
|
50
|
-
LPAREN expr RPAREN # parenthesisExpr
|
|
51
|
-
| functions # functionsExpression
|
|
52
|
-
| dataset=expr QLPAREN clause=datasetClause QRPAREN # clauseExpr
|
|
53
|
-
| expr MEMBERSHIP simpleComponentId # membershipExpr
|
|
54
|
-
| op=(PLUS|MINUS|NOT) right=expr # unaryExpr
|
|
55
|
-
| left=expr op=(MUL|DIV) right=expr # arithmeticExpr
|
|
56
|
-
| left=expr op=(PLUS|MINUS|CONCAT) right=expr # arithmeticExprOrConcat
|
|
57
|
-
| left=expr op=comparisonOperand right=expr # comparisonExpr
|
|
58
|
-
| left=expr op=(IN|NOT_IN)(lists|valueDomainID) # inNotInExpr
|
|
59
|
-
| left=expr op=AND right=expr # booleanExpr
|
|
60
|
-
| left=expr op=(OR|XOR) right=expr # booleanExpr
|
|
61
|
-
| IF conditionalExpr=expr THEN thenExpr=expr ELSE elseExpr=expr # ifExpr
|
|
62
|
-
|
|
|
63
|
-
|
|
|
53
|
+
LPAREN expr RPAREN # parenthesisExpr
|
|
54
|
+
| functions # functionsExpression
|
|
55
|
+
| dataset=expr QLPAREN clause=datasetClause QRPAREN # clauseExpr
|
|
56
|
+
| expr MEMBERSHIP simpleComponentId # membershipExpr
|
|
57
|
+
| op=(PLUS|MINUS|NOT) right=expr # unaryExpr
|
|
58
|
+
| left=expr op=(MUL|DIV) right=expr # arithmeticExpr
|
|
59
|
+
| left=expr op=(PLUS|MINUS|CONCAT) right=expr # arithmeticExprOrConcat
|
|
60
|
+
| left=expr op=comparisonOperand right=expr # comparisonExpr
|
|
61
|
+
| left=expr op=(IN|NOT_IN)(lists|valueDomainID) # inNotInExpr
|
|
62
|
+
| left=expr op=AND right=expr # booleanExpr
|
|
63
|
+
| left=expr op=(OR|XOR) right=expr # booleanExpr
|
|
64
|
+
| IF conditionalExpr=expr THEN thenExpr=expr ELSE elseExpr=expr # ifExpr
|
|
65
|
+
| CASE WHEN expr THEN expr ELSE expr END # caseExpr
|
|
66
|
+
| constant # constantExpr
|
|
67
|
+
| varID # varIdExpr
|
|
64
68
|
;
|
|
65
|
-
"""
|
|
69
|
+
""" # noqa E501
|
|
66
70
|
ctx_list = list(ctx.getChildren())
|
|
67
71
|
c = ctx_list[0]
|
|
68
72
|
|
|
@@ -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)
|
|
@@ -348,8 +372,8 @@ class Expr(VtlVisitor):
|
|
|
348
372
|
|
|
349
373
|
def visitJoinClauseWithoutUsing(self, ctx: Parser.JoinClauseWithoutUsingContext):
|
|
350
374
|
"""
|
|
351
|
-
joinClause: joinClauseItem (COMMA joinClauseItem)* (USING componentID (COMMA componentID)*)? ;
|
|
352
|
-
"""
|
|
375
|
+
joinClause: joinClauseItem (COMMA joinClauseItem)* (USING componentID (COMMA componentID)*)? ;
|
|
376
|
+
""" # noqa E501
|
|
353
377
|
ctx_list = list(ctx.getChildren())
|
|
354
378
|
|
|
355
379
|
clause_nodes = []
|
|
@@ -363,8 +387,8 @@ class Expr(VtlVisitor):
|
|
|
363
387
|
|
|
364
388
|
def visitJoinBody(self, ctx: Parser.JoinBodyContext):
|
|
365
389
|
"""
|
|
366
|
-
joinBody: filterClause? (calcClause|joinApplyClause|aggrClause)? (keepOrDropClause)? renameClause?
|
|
367
|
-
"""
|
|
390
|
+
joinBody: filterClause? (calcClause|joinApplyClause|aggrClause)? (keepOrDropClause)? renameClause?
|
|
391
|
+
""" # noqa E501
|
|
368
392
|
ctx_list = list(ctx.getChildren())
|
|
369
393
|
|
|
370
394
|
body_nodes = []
|
|
@@ -432,8 +456,8 @@ class Expr(VtlVisitor):
|
|
|
432
456
|
|
|
433
457
|
def visitEvalAtom(self, ctx: Parser.EvalAtomContext):
|
|
434
458
|
"""
|
|
435
|
-
| EVAL LPAREN routineName LPAREN (varID|scalarItem)? (COMMA (varID|scalarItem))* RPAREN (LANGUAGE STRING_CONSTANT)? (RETURNS evalDatasetType)? RPAREN
|
|
436
|
-
"""
|
|
459
|
+
| EVAL LPAREN routineName LPAREN (varID|scalarItem)? (COMMA (varID|scalarItem))* RPAREN (LANGUAGE STRING_CONSTANT)? (RETURNS evalDatasetType)? RPAREN # evalAtom
|
|
460
|
+
""" # noqa E501
|
|
437
461
|
ctx_list = list(ctx.getChildren())
|
|
438
462
|
|
|
439
463
|
routine_name = Terminals().visitRoutineName(ctx_list[2])
|
|
@@ -480,8 +504,8 @@ class Expr(VtlVisitor):
|
|
|
480
504
|
|
|
481
505
|
def visitCastExprDataset(self, ctx: Parser.CastExprDatasetContext):
|
|
482
506
|
"""
|
|
483
|
-
| CAST LPAREN expr COMMA (basicScalarType|valueDomainName) (COMMA STRING_CONSTANT)? RPAREN
|
|
484
|
-
"""
|
|
507
|
+
| CAST LPAREN expr COMMA (basicScalarType|valueDomainName) (COMMA STRING_CONSTANT)? RPAREN # castExprDataset
|
|
508
|
+
""" # noqa E501
|
|
485
509
|
ctx_list = list(ctx.getChildren())
|
|
486
510
|
c = ctx_list[0]
|
|
487
511
|
|
|
@@ -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,24 @@ 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
|
+
Parser.MonthAtomContext,
|
|
800
|
+
Parser.DayOfMonthAtomContext,
|
|
801
|
+
Parser.DayOfYearAtomContext,
|
|
802
|
+
Parser.DayToYearAtomContext,
|
|
803
|
+
Parser.DayToMonthAtomContext,
|
|
804
|
+
Parser.YearTodayAtomContext,
|
|
805
|
+
Parser.MonthTodayAtomContext)):
|
|
806
|
+
|
|
807
|
+
return self.visitTimeUnaryAtom(ctx)
|
|
769
808
|
else:
|
|
770
809
|
raise NotImplementedError
|
|
771
810
|
|
|
772
|
-
def
|
|
773
|
-
"""
|
|
774
|
-
periodExpr: PERIOD_INDICATOR '(' expr? ')' ;
|
|
775
|
-
"""
|
|
811
|
+
def visitTimeUnaryAtom(self, ctx: Any):
|
|
776
812
|
ctx_list = list(ctx.getChildren())
|
|
777
813
|
c = ctx_list[0]
|
|
778
814
|
|
|
@@ -789,6 +825,26 @@ class Expr(VtlVisitor):
|
|
|
789
825
|
|
|
790
826
|
return UnaryOp(op=op, operand=operand_node[0])
|
|
791
827
|
|
|
828
|
+
# def visitPeriodAtom(self, ctx: Parser.PeriodAtomContext):
|
|
829
|
+
# """
|
|
830
|
+
# periodExpr: PERIOD_INDICATOR '(' expr? ')' ;
|
|
831
|
+
# """
|
|
832
|
+
# ctx_list = list(ctx.getChildren())
|
|
833
|
+
# c = ctx_list[0]
|
|
834
|
+
#
|
|
835
|
+
# op = c.getSymbol().text
|
|
836
|
+
# operand_node = [
|
|
837
|
+
# self.visitExpr(operand)
|
|
838
|
+
# for operand in ctx_list
|
|
839
|
+
# if isinstance(operand, Parser.ExprContext)
|
|
840
|
+
# ]
|
|
841
|
+
#
|
|
842
|
+
# if len(operand_node) == 0:
|
|
843
|
+
# # AST_ASTCONSTRUCTOR.15
|
|
844
|
+
# raise NotImplementedError
|
|
845
|
+
#
|
|
846
|
+
# return UnaryOp(op=op, operand=operand_node[0])
|
|
847
|
+
|
|
792
848
|
def visitTimeShiftAtom(self, ctx: Parser.TimeShiftAtomContext):
|
|
793
849
|
"""
|
|
794
850
|
timeShiftExpr: TIMESHIFT '(' expr ',' INTEGER_CONSTANT ')' ;
|
|
@@ -821,8 +877,8 @@ class Expr(VtlVisitor):
|
|
|
821
877
|
|
|
822
878
|
def visitTimeAggAtom(self, ctx: Parser.TimeAggAtomContext):
|
|
823
879
|
"""
|
|
824
|
-
TIME_AGG LPAREN periodIndTo=STRING_CONSTANT (COMMA periodIndFrom=(STRING_CONSTANT| OPTIONAL ))? (COMMA op=optionalExpr)? (COMMA (FIRST|LAST))? RPAREN # timeAggAtom
|
|
825
|
-
"""
|
|
880
|
+
TIME_AGG LPAREN periodIndTo=STRING_CONSTANT (COMMA periodIndFrom=(STRING_CONSTANT| OPTIONAL ))? (COMMA op=optionalExpr)? (COMMA (FIRST|LAST))? RPAREN # timeAggAtom
|
|
881
|
+
""" # noqa E501
|
|
826
882
|
ctx_list = list(ctx.getChildren())
|
|
827
883
|
c = ctx_list[0]
|
|
828
884
|
|
|
@@ -840,10 +896,7 @@ class Expr(VtlVisitor):
|
|
|
840
896
|
and str_.getSymbol().type in [Parser.FIRST, Parser.LAST]
|
|
841
897
|
]
|
|
842
898
|
|
|
843
|
-
if len(conf) == 0
|
|
844
|
-
conf = None
|
|
845
|
-
else:
|
|
846
|
-
conf = conf[0]
|
|
899
|
+
conf = None if len(conf) == 0 else conf[0]
|
|
847
900
|
|
|
848
901
|
if ctx.op is not None:
|
|
849
902
|
operand_node = self.visitOptionalExpr(ctx.op)
|
|
@@ -872,6 +925,35 @@ class Expr(VtlVisitor):
|
|
|
872
925
|
c = list(ctx.getChildren())[0]
|
|
873
926
|
return MulOp(op=c.getSymbol().text, children=[])
|
|
874
927
|
|
|
928
|
+
def visitTimeDiffAtom(self, ctx: Parser.TimeShiftAtomContext):
|
|
929
|
+
""" """
|
|
930
|
+
ctx_list = list(ctx.getChildren())
|
|
931
|
+
c = ctx_list[0]
|
|
932
|
+
|
|
933
|
+
op = c.getSymbol().text
|
|
934
|
+
left_node = self.visitExpr(ctx_list[2])
|
|
935
|
+
right_node = self.visitExpr(ctx_list[4])
|
|
936
|
+
|
|
937
|
+
return BinOp(left=left_node, op=op, right=right_node)
|
|
938
|
+
|
|
939
|
+
def visitTimeAddAtom(self, ctx: Parser.TimeShiftAtomContext):
|
|
940
|
+
""" """
|
|
941
|
+
|
|
942
|
+
ctx_list = list(ctx.getChildren())
|
|
943
|
+
c = ctx_list[0]
|
|
944
|
+
|
|
945
|
+
op = c.getSymbol().text
|
|
946
|
+
children_node = [self.visitExpr(ctx_list[2])]
|
|
947
|
+
|
|
948
|
+
param_constant_node = []
|
|
949
|
+
|
|
950
|
+
if len(ctx_list) > 4:
|
|
951
|
+
param_constant_node = [self.visitExpr(ctx_list[4])]
|
|
952
|
+
if len(ctx_list) > 6:
|
|
953
|
+
param_constant_node.append(self.visitExpr(ctx_list[6]))
|
|
954
|
+
|
|
955
|
+
return ParamOp(op=op, children=children_node, params=param_constant_node)
|
|
956
|
+
|
|
875
957
|
"""
|
|
876
958
|
-----------------------------------
|
|
877
959
|
Conditional Functions
|
|
@@ -903,10 +985,10 @@ class Expr(VtlVisitor):
|
|
|
903
985
|
|
|
904
986
|
def visitSetFunctions(self, ctx: Parser.SetFunctionsContext):
|
|
905
987
|
"""
|
|
906
|
-
setExpr: UNION LPAREN left=expr (COMMA expr)+ RPAREN # unionAtom
|
|
907
|
-
| INTERSECT LPAREN left=expr (COMMA expr)+ RPAREN # intersectAtom
|
|
908
|
-
| op=(SETDIFF|SYMDIFF) LPAREN left=expr COMMA right=expr RPAREN # setOrSYmDiffAtom
|
|
909
|
-
"""
|
|
988
|
+
setExpr: UNION LPAREN left=expr (COMMA expr)+ RPAREN # unionAtom
|
|
989
|
+
| INTERSECT LPAREN left=expr (COMMA expr)+ RPAREN # intersectAtom
|
|
990
|
+
| op=(SETDIFF|SYMDIFF) LPAREN left=expr COMMA right=expr RPAREN # setOrSYmDiffAtom
|
|
991
|
+
""" # noqa E501
|
|
910
992
|
if isinstance(ctx, Parser.UnionAtomContext):
|
|
911
993
|
return self.visitUnionAtom(ctx)
|
|
912
994
|
elif isinstance(ctx, Parser.IntersectAtomContext):
|
|
@@ -948,8 +1030,8 @@ class Expr(VtlVisitor):
|
|
|
948
1030
|
|
|
949
1031
|
def visitHierarchyFunctions(self, ctx: Parser.HierarchyFunctionsContext):
|
|
950
1032
|
"""
|
|
951
|
-
HIERARCHY LPAREN op=expr COMMA hrName=IDENTIFIER (conditionClause)? (RULE ruleComponent=componentID)? (validationMode)? (inputModeHierarchy)? outputModeHierarchy? RPAREN
|
|
952
|
-
"""
|
|
1033
|
+
HIERARCHY LPAREN op=expr COMMA hrName=IDENTIFIER (conditionClause)? (RULE ruleComponent=componentID)? (validationMode)? (inputModeHierarchy)? outputModeHierarchy? RPAREN
|
|
1034
|
+
""" # noqa E501
|
|
953
1035
|
ctx_list = list(ctx.getChildren())
|
|
954
1036
|
c = ctx_list[0]
|
|
955
1037
|
|
|
@@ -1019,8 +1101,8 @@ class Expr(VtlVisitor):
|
|
|
1019
1101
|
|
|
1020
1102
|
def visitValidateDPruleset(self, ctx: Parser.ValidateDPrulesetContext):
|
|
1021
1103
|
"""
|
|
1022
|
-
validationDatapoint: CHECK_DATAPOINT '(' expr ',' IDENTIFIER (COMPONENTS componentID (',' componentID)*)? (INVALID|ALL_MEASURES|ALL)? ')' ;
|
|
1023
|
-
"""
|
|
1104
|
+
validationDatapoint: CHECK_DATAPOINT '(' expr ',' IDENTIFIER (COMPONENTS componentID (',' componentID)*)? (INVALID|ALL_MEASURES|ALL)? ')' ;
|
|
1105
|
+
""" # noqa E501
|
|
1024
1106
|
ctx_list = list(ctx.getChildren())
|
|
1025
1107
|
c = ctx_list[0]
|
|
1026
1108
|
|
|
@@ -1054,8 +1136,8 @@ class Expr(VtlVisitor):
|
|
|
1054
1136
|
# TODO Not fully implemented only basic usage available.
|
|
1055
1137
|
def visitValidateHRruleset(self, ctx: Parser.ValidateHRrulesetContext):
|
|
1056
1138
|
"""
|
|
1057
|
-
CHECK_HIERARCHY LPAREN op=expr COMMA hrName=IDENTIFIER conditionClause? (RULE componentID)? validationMode? inputMode? validationOutput? RPAREN
|
|
1058
|
-
"""
|
|
1139
|
+
CHECK_HIERARCHY LPAREN op=expr COMMA hrName=IDENTIFIER conditionClause? (RULE componentID)? validationMode? inputMode? validationOutput? RPAREN # validateHRruleset
|
|
1140
|
+
""" # noqa E501
|
|
1059
1141
|
|
|
1060
1142
|
ctx_list = list(ctx.getChildren())
|
|
1061
1143
|
c = ctx_list[0]
|
|
@@ -1116,8 +1198,8 @@ class Expr(VtlVisitor):
|
|
|
1116
1198
|
|
|
1117
1199
|
def visitValidationSimple(self, ctx: Parser.ValidationSimpleContext):
|
|
1118
1200
|
"""
|
|
1119
|
-
| CHECK LPAREN op=expr (codeErr=erCode)? (levelCode=erLevel)? imbalanceExpr? output=(INVALID|ALL)? RPAREN
|
|
1120
|
-
"""
|
|
1201
|
+
| CHECK LPAREN op=expr (codeErr=erCode)? (levelCode=erLevel)? imbalanceExpr? output=(INVALID|ALL)? RPAREN # validationSimple
|
|
1202
|
+
""" # noqa E501
|
|
1121
1203
|
ctx_list = list(ctx.getChildren())
|
|
1122
1204
|
c = ctx_list[0]
|
|
1123
1205
|
token = c.getSymbol()
|
|
@@ -1136,11 +1218,7 @@ class Expr(VtlVisitor):
|
|
|
1136
1218
|
inbalance_node = self.visitImbalanceExpr(param)
|
|
1137
1219
|
|
|
1138
1220
|
invalid = ctx_list[-2] if isinstance(ctx_list[-2], TerminalNodeImpl) else None
|
|
1139
|
-
|
|
1140
|
-
if invalid is None:
|
|
1141
|
-
invalid_value = False
|
|
1142
|
-
else:
|
|
1143
|
-
invalid_value = True if invalid.getSymbol().text == "invalid" else False
|
|
1221
|
+
invalid_value = False if invalid is None else invalid.getSymbol().text == "invalid"
|
|
1144
1222
|
|
|
1145
1223
|
return Validation(
|
|
1146
1224
|
op=token.text,
|
|
@@ -1200,7 +1278,7 @@ class Expr(VtlVisitor):
|
|
|
1200
1278
|
grouping_op, group_node = self.visitGroupingClause(groups[0])
|
|
1201
1279
|
if len(haves) != 0:
|
|
1202
1280
|
have_node, expr = self.visitHavingClause(haves[0])
|
|
1203
|
-
|
|
1281
|
+
have_node.expr = expr
|
|
1204
1282
|
|
|
1205
1283
|
return Aggregation(
|
|
1206
1284
|
op=op_node,
|
|
@@ -1277,9 +1355,7 @@ class Expr(VtlVisitor):
|
|
|
1277
1355
|
elif isinstance(c, Parser.OrderByClauseContext):
|
|
1278
1356
|
order_by = Terminals().visitOrderByClause(c)
|
|
1279
1357
|
continue
|
|
1280
|
-
elif isinstance(c, Parser.SignedIntegerContext)
|
|
1281
|
-
c, Parser.ScalarItemContext
|
|
1282
|
-
):
|
|
1358
|
+
elif isinstance(c, (Parser.SignedIntegerContext, Parser.ScalarItemContext)):
|
|
1283
1359
|
if params is None:
|
|
1284
1360
|
params = []
|
|
1285
1361
|
if isinstance(c, Parser.SignedIntegerContext):
|
|
@@ -1445,7 +1521,7 @@ class Expr(VtlVisitor):
|
|
|
1445
1521
|
right_node = ExprComp().visitAggregateFunctionsComponents(ctx_list[base_index + 2])
|
|
1446
1522
|
# Encoding the role information inside the Assignment for easiness and simplicity.
|
|
1447
1523
|
# Cannot find another way with less lines of code
|
|
1448
|
-
|
|
1524
|
+
left_node.role = role
|
|
1449
1525
|
|
|
1450
1526
|
return Assignment(left_node, op_node, right_node)
|
|
1451
1527
|
|
|
@@ -1472,7 +1548,7 @@ class Expr(VtlVisitor):
|
|
|
1472
1548
|
grouping_op, group_node = self.visitGroupingClause(groups[0])
|
|
1473
1549
|
if len(haves) > 0:
|
|
1474
1550
|
have_node, expr = self.visitHavingClause(haves[0])
|
|
1475
|
-
|
|
1551
|
+
have_node.expr = expr
|
|
1476
1552
|
for element in aggregate_nodes:
|
|
1477
1553
|
element.right = Aggregation(
|
|
1478
1554
|
op=element.right.op,
|