vtlengine 1.0__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 +159 -102
- vtlengine/API/__init__.py +110 -68
- vtlengine/AST/ASTConstructor.py +188 -98
- vtlengine/AST/ASTConstructorModules/Expr.py +402 -205
- vtlengine/AST/ASTConstructorModules/ExprComponents.py +248 -104
- vtlengine/AST/ASTConstructorModules/Terminals.py +158 -95
- vtlengine/AST/ASTEncoders.py +1 -1
- vtlengine/AST/ASTTemplate.py +24 -9
- vtlengine/AST/ASTVisitor.py +8 -12
- vtlengine/AST/DAG/__init__.py +43 -35
- vtlengine/AST/DAG/_words.py +4 -4
- vtlengine/AST/Grammar/Vtl.g4 +49 -20
- vtlengine/AST/Grammar/VtlTokens.g4 +13 -1
- vtlengine/AST/Grammar/lexer.py +2012 -1312
- vtlengine/AST/Grammar/parser.py +7524 -4343
- vtlengine/AST/Grammar/tokens.py +140 -128
- vtlengine/AST/VtlVisitor.py +16 -5
- vtlengine/AST/__init__.py +41 -11
- vtlengine/DataTypes/NumericTypesHandling.py +5 -4
- vtlengine/DataTypes/TimeHandling.py +196 -301
- vtlengine/DataTypes/__init__.py +304 -218
- vtlengine/Exceptions/__init__.py +96 -27
- vtlengine/Exceptions/messages.py +149 -69
- vtlengine/Interpreter/__init__.py +817 -497
- vtlengine/Model/__init__.py +172 -121
- vtlengine/Operators/Aggregation.py +156 -95
- vtlengine/Operators/Analytic.py +167 -79
- vtlengine/Operators/Assignment.py +7 -4
- vtlengine/Operators/Boolean.py +27 -32
- vtlengine/Operators/CastOperator.py +177 -131
- vtlengine/Operators/Clause.py +137 -99
- vtlengine/Operators/Comparison.py +148 -117
- vtlengine/Operators/Conditional.py +290 -98
- vtlengine/Operators/General.py +68 -47
- vtlengine/Operators/HROperators.py +91 -72
- vtlengine/Operators/Join.py +217 -118
- vtlengine/Operators/Numeric.py +129 -46
- vtlengine/Operators/RoleSetter.py +16 -15
- vtlengine/Operators/Set.py +61 -36
- vtlengine/Operators/String.py +213 -139
- vtlengine/Operators/Time.py +467 -215
- vtlengine/Operators/Validation.py +117 -76
- vtlengine/Operators/__init__.py +340 -213
- vtlengine/Utils/__init__.py +232 -41
- vtlengine/__init__.py +1 -1
- vtlengine/files/output/__init__.py +15 -6
- vtlengine/files/output/_time_period_representation.py +10 -9
- vtlengine/files/parser/__init__.py +79 -52
- vtlengine/files/parser/_rfc_dialect.py +6 -5
- vtlengine/files/parser/_time_checking.py +48 -37
- vtlengine-1.0.2.dist-info/METADATA +245 -0
- vtlengine-1.0.2.dist-info/RECORD +58 -0
- {vtlengine-1.0.dist-info → vtlengine-1.0.2.dist-info}/WHEEL +1 -1
- vtlengine-1.0.dist-info/METADATA +0 -104
- vtlengine-1.0.dist-info/RECORD +0 -58
- {vtlengine-1.0.dist-info → vtlengine-1.0.2.dist-info}/LICENSE.md +0 -0
|
@@ -1,14 +1,34 @@
|
|
|
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
|
-
from vtlengine.AST import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
from vtlengine.AST import (
|
|
8
|
+
If,
|
|
9
|
+
BinOp,
|
|
10
|
+
RenameNode,
|
|
11
|
+
UDOCall,
|
|
12
|
+
UnaryOp,
|
|
13
|
+
JoinOp,
|
|
14
|
+
Identifier,
|
|
15
|
+
ParamOp,
|
|
16
|
+
EvalOp,
|
|
17
|
+
ParamConstant,
|
|
18
|
+
MulOp,
|
|
19
|
+
RegularAggregation,
|
|
20
|
+
Assignment,
|
|
21
|
+
Aggregation,
|
|
22
|
+
ID,
|
|
23
|
+
TimeAggregation,
|
|
24
|
+
Constant,
|
|
25
|
+
Validation,
|
|
26
|
+
Analytic,
|
|
27
|
+
Windowing,
|
|
28
|
+
VarID,
|
|
29
|
+
Case,
|
|
30
|
+
CaseObj,
|
|
31
|
+
)
|
|
12
32
|
from vtlengine.AST.ASTConstructorModules.ExprComponents import ExprComp
|
|
13
33
|
from vtlengine.AST.ASTConstructorModules.Terminals import Terminals
|
|
14
34
|
from vtlengine.AST.ASTDataExchange import de_ruleset_elements
|
|
@@ -23,27 +43,28 @@ class Expr(VtlVisitor):
|
|
|
23
43
|
"""______________________________________________________________________________________
|
|
24
44
|
|
|
25
45
|
|
|
26
|
-
|
|
46
|
+
Expr Definition.
|
|
27
47
|
|
|
28
|
-
|
|
48
|
+
_______________________________________________________________________________________"""
|
|
29
49
|
|
|
30
50
|
def visitExpr(self, ctx: Parser.ExprContext):
|
|
31
51
|
"""
|
|
32
52
|
expr:
|
|
33
|
-
LPAREN expr RPAREN # parenthesisExpr
|
|
34
|
-
| functions # functionsExpression
|
|
35
|
-
| dataset=expr QLPAREN clause=datasetClause QRPAREN # clauseExpr
|
|
36
|
-
| expr MEMBERSHIP simpleComponentId # membershipExpr
|
|
37
|
-
| op=(PLUS|MINUS|NOT) right=expr # unaryExpr
|
|
38
|
-
| left=expr op=(MUL|DIV) right=expr # arithmeticExpr
|
|
39
|
-
| left=expr op=(PLUS|MINUS|CONCAT) right=expr # arithmeticExprOrConcat
|
|
40
|
-
| left=expr op=comparisonOperand right=expr # comparisonExpr
|
|
41
|
-
| left=expr op=(IN|NOT_IN)(lists|valueDomainID) # inNotInExpr
|
|
42
|
-
| left=expr op=AND right=expr # booleanExpr
|
|
43
|
-
| left=expr op=(OR|XOR) right=expr # booleanExpr
|
|
44
|
-
| IF conditionalExpr=expr THEN thenExpr=expr ELSE elseExpr=expr # ifExpr
|
|
45
|
-
|
|
|
46
|
-
|
|
|
53
|
+
LPAREN expr RPAREN # parenthesisExpr # noqa E501
|
|
54
|
+
| functions # functionsExpression # noqa E501
|
|
55
|
+
| dataset=expr QLPAREN clause=datasetClause QRPAREN # clauseExpr # noqa E501
|
|
56
|
+
| expr MEMBERSHIP simpleComponentId # membershipExpr # noqa E501
|
|
57
|
+
| op=(PLUS|MINUS|NOT) right=expr # unaryExpr # noqa E501
|
|
58
|
+
| left=expr op=(MUL|DIV) right=expr # arithmeticExpr # noqa E501
|
|
59
|
+
| left=expr op=(PLUS|MINUS|CONCAT) right=expr # arithmeticExprOrConcat # noqa E501
|
|
60
|
+
| left=expr op=comparisonOperand right=expr # comparisonExpr # noqa E501
|
|
61
|
+
| left=expr op=(IN|NOT_IN)(lists|valueDomainID) # inNotInExpr # noqa E501
|
|
62
|
+
| left=expr op=AND right=expr # booleanExpr # noqa E501
|
|
63
|
+
| left=expr op=(OR|XOR) right=expr # booleanExpr # noqa E501
|
|
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
|
|
66
|
+
| constant # constantExpr # noqa E501
|
|
67
|
+
| varID # varIdExpr # noqa E501
|
|
47
68
|
;
|
|
48
69
|
"""
|
|
49
70
|
ctx_list = list(ctx.getChildren())
|
|
@@ -98,6 +119,26 @@ class Expr(VtlVisitor):
|
|
|
98
119
|
|
|
99
120
|
return if_node
|
|
100
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
|
+
|
|
101
142
|
# constant
|
|
102
143
|
elif isinstance(ctx, Parser.ConstantExprContext):
|
|
103
144
|
return Terminals().visitConstant(c)
|
|
@@ -163,15 +204,19 @@ class Expr(VtlVisitor):
|
|
|
163
204
|
def visitMembershipExpr(self, ctx: Parser.MembershipExprContext):
|
|
164
205
|
ctx_list = list(ctx.getChildren())
|
|
165
206
|
c = ctx_list[0]
|
|
166
|
-
membership = [
|
|
167
|
-
|
|
207
|
+
membership = [
|
|
208
|
+
componentID
|
|
209
|
+
for componentID in ctx_list
|
|
210
|
+
if isinstance(componentID, Parser.SimpleComponentIdContext)
|
|
211
|
+
]
|
|
168
212
|
|
|
169
213
|
previous_node = self.visitExpr(c)
|
|
170
214
|
|
|
171
215
|
# It is only possible to put a membership at the end so go the last one.
|
|
172
216
|
if len(membership) != 0:
|
|
173
|
-
previous_node = BinOp(
|
|
174
|
-
|
|
217
|
+
previous_node = BinOp(
|
|
218
|
+
previous_node, "#", Terminals().visitSimpleComponentId(membership[0])
|
|
219
|
+
)
|
|
175
220
|
|
|
176
221
|
return previous_node
|
|
177
222
|
|
|
@@ -254,7 +299,7 @@ class Expr(VtlVisitor):
|
|
|
254
299
|
|
|
255
300
|
"""
|
|
256
301
|
-----------------------------------
|
|
257
|
-
Join Functions
|
|
302
|
+
Join Functions
|
|
258
303
|
-----------------------------------
|
|
259
304
|
"""
|
|
260
305
|
|
|
@@ -265,7 +310,7 @@ class Expr(VtlVisitor):
|
|
|
265
310
|
|
|
266
311
|
op_node = ctx_list[0].getSymbol().text
|
|
267
312
|
|
|
268
|
-
if op_node in [
|
|
313
|
+
if op_node in ["inner_join", "left_join"]:
|
|
269
314
|
clause_node, using_node = self.visitJoinClause(ctx_list[2])
|
|
270
315
|
else:
|
|
271
316
|
clause_node = self.visitJoinClauseWithoutUsing(ctx_list[2])
|
|
@@ -297,7 +342,7 @@ class Expr(VtlVisitor):
|
|
|
297
342
|
return left_node
|
|
298
343
|
|
|
299
344
|
intop_node = ctx_list[1].getSymbol().text
|
|
300
|
-
right_node = Identifier(Terminals().visitAlias(ctx_list[2]),
|
|
345
|
+
right_node = Identifier(Terminals().visitAlias(ctx_list[2]), "DatasetID")
|
|
301
346
|
return BinOp(left_node, intop_node, right_node)
|
|
302
347
|
|
|
303
348
|
def visitJoinClause(self, ctx: Parser.JoinClauseContext):
|
|
@@ -311,8 +356,9 @@ class Expr(VtlVisitor):
|
|
|
311
356
|
using = None
|
|
312
357
|
|
|
313
358
|
items = [item for item in ctx_list if isinstance(item, Parser.JoinClauseItemContext)]
|
|
314
|
-
components = [
|
|
315
|
-
|
|
359
|
+
components = [
|
|
360
|
+
component for component in ctx_list if isinstance(component, Parser.ComponentIDContext)
|
|
361
|
+
]
|
|
316
362
|
|
|
317
363
|
for item in items:
|
|
318
364
|
clause_nodes.append(self.visitJoinClauseItem(item))
|
|
@@ -326,7 +372,7 @@ class Expr(VtlVisitor):
|
|
|
326
372
|
|
|
327
373
|
def visitJoinClauseWithoutUsing(self, ctx: Parser.JoinClauseWithoutUsingContext):
|
|
328
374
|
"""
|
|
329
|
-
joinClause: joinClauseItem (COMMA joinClauseItem)* (USING componentID (COMMA componentID)*)? ;
|
|
375
|
+
joinClause: joinClauseItem (COMMA joinClauseItem)* (USING componentID (COMMA componentID)*)? ; # noqa E501
|
|
330
376
|
"""
|
|
331
377
|
ctx_list = list(ctx.getChildren())
|
|
332
378
|
|
|
@@ -341,7 +387,7 @@ class Expr(VtlVisitor):
|
|
|
341
387
|
|
|
342
388
|
def visitJoinBody(self, ctx: Parser.JoinBodyContext):
|
|
343
389
|
"""
|
|
344
|
-
joinBody: filterClause? (calcClause|joinApplyClause|aggrClause)? (keepOrDropClause)? renameClause?
|
|
390
|
+
joinBody: filterClause? (calcClause|joinApplyClause|aggrClause)? (keepOrDropClause)? renameClause? # noqa E501
|
|
345
391
|
"""
|
|
346
392
|
ctx_list = list(ctx.getChildren())
|
|
347
393
|
|
|
@@ -378,7 +424,7 @@ class Expr(VtlVisitor):
|
|
|
378
424
|
|
|
379
425
|
"""
|
|
380
426
|
-----------------------------------
|
|
381
|
-
Generic Functions
|
|
427
|
+
Generic Functions
|
|
382
428
|
-----------------------------------
|
|
383
429
|
"""
|
|
384
430
|
|
|
@@ -400,46 +446,65 @@ class Expr(VtlVisitor):
|
|
|
400
446
|
c = ctx_list[0]
|
|
401
447
|
|
|
402
448
|
op = Terminals().visitOperatorID(c)
|
|
403
|
-
param_nodes = [
|
|
404
|
-
|
|
449
|
+
param_nodes = [
|
|
450
|
+
self.visitParameter(element)
|
|
451
|
+
for element in ctx_list
|
|
452
|
+
if isinstance(element, Parser.ParameterContext)
|
|
453
|
+
]
|
|
405
454
|
|
|
406
455
|
return UDOCall(op=op, params=param_nodes)
|
|
407
456
|
|
|
408
457
|
def visitEvalAtom(self, ctx: Parser.EvalAtomContext):
|
|
409
458
|
"""
|
|
410
|
-
|
|
459
|
+
| EVAL LPAREN routineName LPAREN (varID|scalarItem)? (COMMA (varID|scalarItem))* RPAREN (LANGUAGE STRING_CONSTANT)? (RETURNS evalDatasetType)? RPAREN # noqa E501 # evalAtom
|
|
411
460
|
"""
|
|
412
461
|
ctx_list = list(ctx.getChildren())
|
|
413
462
|
|
|
414
463
|
routine_name = Terminals().visitRoutineName(ctx_list[2])
|
|
415
464
|
|
|
416
465
|
# Think of a way to maintain the order, for now its not necessary.
|
|
417
|
-
var_ids_nodes = [
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
466
|
+
var_ids_nodes = [
|
|
467
|
+
Terminals().visitVarID(varID)
|
|
468
|
+
for varID in ctx_list
|
|
469
|
+
if isinstance(varID, Parser.VarIDContext)
|
|
470
|
+
]
|
|
471
|
+
constant_nodes = [
|
|
472
|
+
Terminals().visitScalarItem(scalar)
|
|
473
|
+
for scalar in ctx_list
|
|
474
|
+
if isinstance(scalar, Parser.ScalarItemContext)
|
|
475
|
+
]
|
|
421
476
|
children_nodes = var_ids_nodes + constant_nodes
|
|
422
477
|
|
|
423
478
|
# Reference manual says it is mandatory.
|
|
424
|
-
language_name = [
|
|
425
|
-
|
|
426
|
-
|
|
479
|
+
language_name = [
|
|
480
|
+
language
|
|
481
|
+
for language in ctx_list
|
|
482
|
+
if isinstance(language, TerminalNodeImpl)
|
|
483
|
+
and language.getSymbol().type == Parser.STRING_CONSTANT
|
|
484
|
+
]
|
|
427
485
|
if len(language_name) == 0:
|
|
428
486
|
# AST_ASTCONSTRUCTOR.12
|
|
429
|
-
raise SemanticError("1-4-2-1", option=
|
|
487
|
+
raise SemanticError("1-4-2-1", option="language")
|
|
430
488
|
# Reference manual says it is mandatory.
|
|
431
|
-
output_node = [
|
|
432
|
-
|
|
489
|
+
output_node = [
|
|
490
|
+
Terminals().visitEvalDatasetType(output)
|
|
491
|
+
for output in ctx_list
|
|
492
|
+
if isinstance(output, Parser.EvalDatasetTypeContext)
|
|
493
|
+
]
|
|
433
494
|
if len(output_node) == 0:
|
|
434
495
|
# AST_ASTCONSTRUCTOR.13
|
|
435
|
-
raise SemanticError("1-4-2-1", option=
|
|
496
|
+
raise SemanticError("1-4-2-1", option="output")
|
|
436
497
|
|
|
437
|
-
return EvalOp(
|
|
438
|
-
|
|
498
|
+
return EvalOp(
|
|
499
|
+
name=routine_name,
|
|
500
|
+
operands=children_nodes,
|
|
501
|
+
output=output_node[0],
|
|
502
|
+
language=language_name[0].getSymbol().text,
|
|
503
|
+
)
|
|
439
504
|
|
|
440
505
|
def visitCastExprDataset(self, ctx: Parser.CastExprDatasetContext):
|
|
441
506
|
"""
|
|
442
|
-
|
|
507
|
+
| CAST LPAREN expr COMMA (basicScalarType|valueDomainName) (COMMA STRING_CONSTANT)? RPAREN # noqa E501 # castExprDataset
|
|
443
508
|
"""
|
|
444
509
|
ctx_list = list(ctx.getChildren())
|
|
445
510
|
c = ctx_list[0]
|
|
@@ -447,19 +512,28 @@ class Expr(VtlVisitor):
|
|
|
447
512
|
token = c.getSymbol()
|
|
448
513
|
|
|
449
514
|
op = token.text
|
|
450
|
-
expr_node = [
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
515
|
+
expr_node = [
|
|
516
|
+
self.visitExpr(expr) for expr in ctx_list if isinstance(expr, Parser.ExprContext)
|
|
517
|
+
]
|
|
518
|
+
basic_scalar_type = [
|
|
519
|
+
Terminals().visitBasicScalarType(type_)
|
|
520
|
+
for type_ in ctx_list
|
|
521
|
+
if isinstance(type_, Parser.BasicScalarTypeContext)
|
|
522
|
+
]
|
|
523
|
+
|
|
524
|
+
[
|
|
525
|
+
Terminals().visitValueDomainName(valueD)
|
|
526
|
+
for valueD in ctx_list
|
|
527
|
+
if isinstance(valueD, Parser.ValueDomainNameContext)
|
|
528
|
+
]
|
|
457
529
|
|
|
458
530
|
if len(ctx_list) > 6:
|
|
459
|
-
param_node = [
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
531
|
+
param_node = [
|
|
532
|
+
ParamConstant("PARAM_CAST", str_.symbol.text.strip('"'))
|
|
533
|
+
for str_ in ctx_list
|
|
534
|
+
if isinstance(str_, TerminalNodeImpl)
|
|
535
|
+
and str_.getSymbol().type == Parser.STRING_CONSTANT
|
|
536
|
+
]
|
|
463
537
|
else:
|
|
464
538
|
param_node = []
|
|
465
539
|
|
|
@@ -479,13 +553,13 @@ class Expr(VtlVisitor):
|
|
|
479
553
|
if isinstance(c, Parser.ExprContext):
|
|
480
554
|
return self.visitExpr(c)
|
|
481
555
|
elif isinstance(c, TerminalNodeImpl):
|
|
482
|
-
return ID(
|
|
556
|
+
return ID("OPTIONAL", c.getSymbol().text)
|
|
483
557
|
else:
|
|
484
558
|
raise NotImplementedError
|
|
485
559
|
|
|
486
560
|
"""
|
|
487
561
|
-----------------------------------
|
|
488
|
-
String Functions
|
|
562
|
+
String Functions
|
|
489
563
|
-----------------------------------
|
|
490
564
|
"""
|
|
491
565
|
|
|
@@ -536,10 +610,14 @@ class Expr(VtlVisitor):
|
|
|
536
610
|
c = ctx_list[0]
|
|
537
611
|
|
|
538
612
|
token = c.getSymbol()
|
|
539
|
-
expressions = [
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
613
|
+
expressions = [
|
|
614
|
+
self.visitExpr(expr) for expr in ctx_list if isinstance(expr, Parser.ExprContext)
|
|
615
|
+
]
|
|
616
|
+
params = [
|
|
617
|
+
self.visitOptionalExpr(param)
|
|
618
|
+
for param in ctx_list
|
|
619
|
+
if isinstance(param, Parser.OptionalExprContext)
|
|
620
|
+
]
|
|
543
621
|
|
|
544
622
|
op_node = token.text
|
|
545
623
|
|
|
@@ -553,10 +631,14 @@ class Expr(VtlVisitor):
|
|
|
553
631
|
c = ctx_list[0]
|
|
554
632
|
|
|
555
633
|
token = c.getSymbol()
|
|
556
|
-
expressions = [
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
634
|
+
expressions = [
|
|
635
|
+
self.visitExpr(expr) for expr in ctx_list if isinstance(expr, Parser.ExprContext)
|
|
636
|
+
]
|
|
637
|
+
params = [
|
|
638
|
+
self.visitOptionalExpr(param)
|
|
639
|
+
for param in ctx_list
|
|
640
|
+
if isinstance(param, Parser.OptionalExprContext)
|
|
641
|
+
]
|
|
560
642
|
|
|
561
643
|
op_node = token.text
|
|
562
644
|
|
|
@@ -567,7 +649,7 @@ class Expr(VtlVisitor):
|
|
|
567
649
|
|
|
568
650
|
"""
|
|
569
651
|
-----------------------------------
|
|
570
|
-
Numeric Functions
|
|
652
|
+
Numeric Functions
|
|
571
653
|
-----------------------------------
|
|
572
654
|
"""
|
|
573
655
|
|
|
@@ -624,7 +706,7 @@ class Expr(VtlVisitor):
|
|
|
624
706
|
|
|
625
707
|
"""
|
|
626
708
|
-----------------------------------
|
|
627
|
-
Comparison Functions
|
|
709
|
+
Comparison Functions
|
|
628
710
|
-----------------------------------
|
|
629
711
|
"""
|
|
630
712
|
|
|
@@ -678,22 +760,27 @@ class Expr(VtlVisitor):
|
|
|
678
760
|
token = ctx_list[0].getSymbol()
|
|
679
761
|
op = token.text
|
|
680
762
|
|
|
681
|
-
operand_nodes = [
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
763
|
+
operand_nodes = [
|
|
764
|
+
self.visitExpr(expr) for expr in ctx_list if isinstance(expr, Parser.ExprContext)
|
|
765
|
+
]
|
|
766
|
+
retain_nodes = [
|
|
767
|
+
Terminals().visitRetainType(retain)
|
|
768
|
+
for retain in ctx_list
|
|
769
|
+
if isinstance(retain, Parser.RetainTypeContext)
|
|
770
|
+
]
|
|
685
771
|
|
|
686
772
|
return MulOp(op=op, children=operand_nodes + retain_nodes)
|
|
687
773
|
|
|
688
774
|
"""
|
|
689
775
|
-----------------------------------
|
|
690
|
-
Time Functions
|
|
776
|
+
Time Functions
|
|
691
777
|
-----------------------------------
|
|
692
778
|
"""
|
|
693
779
|
|
|
694
780
|
def visitTimeFunctions(self, ctx: Parser.TimeFunctionsContext):
|
|
695
781
|
if isinstance(ctx, Parser.PeriodAtomContext):
|
|
696
|
-
return self.visitPeriodAtom(ctx)
|
|
782
|
+
# return self.visitPeriodAtom(ctx)
|
|
783
|
+
return self.visitTimeUnaryAtom(ctx)
|
|
697
784
|
elif isinstance(ctx, Parser.FillTimeAtomContext):
|
|
698
785
|
return self.visitFillTimeAtom(ctx)
|
|
699
786
|
elif isinstance(ctx, Parser.FlowAtomContext):
|
|
@@ -704,19 +791,39 @@ class Expr(VtlVisitor):
|
|
|
704
791
|
return self.visitTimeAggAtom(ctx)
|
|
705
792
|
elif isinstance(ctx, Parser.CurrentDateAtomContext):
|
|
706
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)
|
|
707
814
|
else:
|
|
708
815
|
raise NotImplementedError
|
|
709
816
|
|
|
710
|
-
def
|
|
711
|
-
"""
|
|
712
|
-
periodExpr: PERIOD_INDICATOR '(' expr? ')' ;
|
|
713
|
-
"""
|
|
817
|
+
def visitTimeUnaryAtom(self, ctx: Any):
|
|
714
818
|
ctx_list = list(ctx.getChildren())
|
|
715
819
|
c = ctx_list[0]
|
|
716
820
|
|
|
717
821
|
op = c.getSymbol().text
|
|
718
|
-
operand_node = [
|
|
719
|
-
|
|
822
|
+
operand_node = [
|
|
823
|
+
self.visitExpr(operand)
|
|
824
|
+
for operand in ctx_list
|
|
825
|
+
if isinstance(operand, Parser.ExprContext)
|
|
826
|
+
]
|
|
720
827
|
|
|
721
828
|
if len(operand_node) == 0:
|
|
722
829
|
# AST_ASTCONSTRUCTOR.15
|
|
@@ -724,6 +831,26 @@ class Expr(VtlVisitor):
|
|
|
724
831
|
|
|
725
832
|
return UnaryOp(op=op, operand=operand_node[0])
|
|
726
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
|
+
|
|
727
854
|
def visitTimeShiftAtom(self, ctx: Parser.TimeShiftAtomContext):
|
|
728
855
|
"""
|
|
729
856
|
timeShiftExpr: TIMESHIFT '(' expr ',' INTEGER_CONSTANT ')' ;
|
|
@@ -733,7 +860,7 @@ class Expr(VtlVisitor):
|
|
|
733
860
|
|
|
734
861
|
op = c.getSymbol().text
|
|
735
862
|
left_node = self.visitExpr(ctx_list[2])
|
|
736
|
-
right_node = Constant(
|
|
863
|
+
right_node = Constant("INTEGER_CONSTANT", Terminals().visitSignedInteger(ctx_list[4]))
|
|
737
864
|
|
|
738
865
|
return BinOp(left=left_node, op=op, right=right_node)
|
|
739
866
|
|
|
@@ -748,7 +875,7 @@ class Expr(VtlVisitor):
|
|
|
748
875
|
children_node = [self.visitExpr(ctx_list[2])]
|
|
749
876
|
|
|
750
877
|
if len(ctx_list) > 4:
|
|
751
|
-
param_constant_node = [ParamConstant(
|
|
878
|
+
param_constant_node = [ParamConstant("PARAM_TIMESERIES", ctx_list[4].getSymbol().text)]
|
|
752
879
|
else:
|
|
753
880
|
param_constant_node = []
|
|
754
881
|
|
|
@@ -756,7 +883,7 @@ class Expr(VtlVisitor):
|
|
|
756
883
|
|
|
757
884
|
def visitTimeAggAtom(self, ctx: Parser.TimeAggAtomContext):
|
|
758
885
|
"""
|
|
759
|
-
TIME_AGG LPAREN periodIndTo=STRING_CONSTANT (COMMA periodIndFrom=(STRING_CONSTANT| OPTIONAL ))? (COMMA op=optionalExpr)? (COMMA (FIRST|LAST))? RPAREN # timeAggAtom
|
|
886
|
+
TIME_AGG LPAREN periodIndTo=STRING_CONSTANT (COMMA periodIndFrom=(STRING_CONSTANT| OPTIONAL ))? (COMMA op=optionalExpr)? (COMMA (FIRST|LAST))? RPAREN # timeAggAtom # noqa E501
|
|
760
887
|
"""
|
|
761
888
|
ctx_list = list(ctx.getChildren())
|
|
762
889
|
c = ctx_list[0]
|
|
@@ -768,9 +895,12 @@ class Expr(VtlVisitor):
|
|
|
768
895
|
if ctx.periodIndFrom is not None and ctx.periodIndFrom.type != Parser.OPTIONAL:
|
|
769
896
|
period_from = str(ctx.periodIndFrom.text)[1:-1]
|
|
770
897
|
|
|
771
|
-
conf = [
|
|
772
|
-
|
|
773
|
-
|
|
898
|
+
conf = [
|
|
899
|
+
str_.getSymbol().text
|
|
900
|
+
for str_ in ctx_list
|
|
901
|
+
if isinstance(str_, TerminalNodeImpl)
|
|
902
|
+
and str_.getSymbol().type in [Parser.FIRST, Parser.LAST]
|
|
903
|
+
]
|
|
774
904
|
|
|
775
905
|
if len(conf) == 0:
|
|
776
906
|
conf = None
|
|
@@ -789,8 +919,9 @@ class Expr(VtlVisitor):
|
|
|
789
919
|
if operand_node is None:
|
|
790
920
|
# AST_ASTCONSTRUCTOR.17
|
|
791
921
|
raise Exception("Optional as expression node is not allowed in Time Aggregation")
|
|
792
|
-
return TimeAggregation(
|
|
793
|
-
|
|
922
|
+
return TimeAggregation(
|
|
923
|
+
op=op, operand=operand_node, period_to=period_to, period_from=period_from, conf=conf
|
|
924
|
+
)
|
|
794
925
|
|
|
795
926
|
def visitFlowAtom(self, ctx: Parser.FlowAtomContext):
|
|
796
927
|
ctx_list = list(ctx.getChildren())
|
|
@@ -803,9 +934,38 @@ class Expr(VtlVisitor):
|
|
|
803
934
|
c = list(ctx.getChildren())[0]
|
|
804
935
|
return MulOp(op=c.getSymbol().text, children=[])
|
|
805
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
|
+
|
|
806
966
|
"""
|
|
807
967
|
-----------------------------------
|
|
808
|
-
Conditional Functions
|
|
968
|
+
Conditional Functions
|
|
809
969
|
-----------------------------------
|
|
810
970
|
"""
|
|
811
971
|
|
|
@@ -828,15 +988,15 @@ class Expr(VtlVisitor):
|
|
|
828
988
|
|
|
829
989
|
"""
|
|
830
990
|
-----------------------------------
|
|
831
|
-
Set Functions
|
|
991
|
+
Set Functions
|
|
832
992
|
-----------------------------------
|
|
833
993
|
"""
|
|
834
994
|
|
|
835
995
|
def visitSetFunctions(self, ctx: Parser.SetFunctionsContext):
|
|
836
996
|
"""
|
|
837
|
-
setExpr: UNION LPAREN left=expr (COMMA expr)+ RPAREN # unionAtom
|
|
838
|
-
| INTERSECT LPAREN left=expr (COMMA expr)+ RPAREN # intersectAtom
|
|
839
|
-
| op=(SETDIFF|SYMDIFF) LPAREN left=expr COMMA right=expr RPAREN # setOrSYmDiffAtom
|
|
997
|
+
setExpr: UNION LPAREN left=expr (COMMA expr)+ RPAREN # unionAtom # noqa E501
|
|
998
|
+
| INTERSECT LPAREN left=expr (COMMA expr)+ RPAREN # intersectAtom # noqa E501
|
|
999
|
+
| op=(SETDIFF|SYMDIFF) LPAREN left=expr COMMA right=expr RPAREN # setOrSYmDiffAtom # noqa E501
|
|
840
1000
|
"""
|
|
841
1001
|
if isinstance(ctx, Parser.UnionAtomContext):
|
|
842
1002
|
return self.visitUnionAtom(ctx)
|
|
@@ -849,41 +1009,44 @@ class Expr(VtlVisitor):
|
|
|
849
1009
|
|
|
850
1010
|
def visitUnionAtom(self, ctx: Parser.UnionAtomContext):
|
|
851
1011
|
ctx_list = list(ctx.getChildren())
|
|
852
|
-
exprs_nodes = [
|
|
853
|
-
|
|
1012
|
+
exprs_nodes = [
|
|
1013
|
+
self.visitExpr(expr) for expr in ctx_list if isinstance(expr, Parser.ExprContext)
|
|
1014
|
+
]
|
|
854
1015
|
|
|
855
1016
|
return MulOp(ctx_list[0].getSymbol().text, exprs_nodes)
|
|
856
1017
|
|
|
857
1018
|
def visitIntersectAtom(self, ctx: Parser.IntersectAtomContext):
|
|
858
1019
|
ctx_list = list(ctx.getChildren())
|
|
859
|
-
exprs_nodes = [
|
|
860
|
-
|
|
1020
|
+
exprs_nodes = [
|
|
1021
|
+
self.visitExpr(expr) for expr in ctx_list if isinstance(expr, Parser.ExprContext)
|
|
1022
|
+
]
|
|
861
1023
|
|
|
862
1024
|
return MulOp(op=ctx_list[0].getSymbol().text, children=exprs_nodes)
|
|
863
1025
|
|
|
864
1026
|
def visitSetOrSYmDiffAtom(self, ctx: Parser.SetOrSYmDiffAtomContext):
|
|
865
1027
|
ctx_list = list(ctx.getChildren())
|
|
866
|
-
exprs_nodes = [
|
|
867
|
-
|
|
1028
|
+
exprs_nodes = [
|
|
1029
|
+
self.visitExpr(expr) for expr in ctx_list if isinstance(expr, Parser.ExprContext)
|
|
1030
|
+
]
|
|
868
1031
|
|
|
869
1032
|
return MulOp(op=ctx_list[0].getSymbol().text, children=exprs_nodes)
|
|
870
1033
|
|
|
871
1034
|
"""
|
|
872
1035
|
-----------------------------------
|
|
873
|
-
Hierarchy Functions
|
|
1036
|
+
Hierarchy Functions
|
|
874
1037
|
-----------------------------------
|
|
875
1038
|
"""
|
|
876
1039
|
|
|
877
1040
|
def visitHierarchyFunctions(self, ctx: Parser.HierarchyFunctionsContext):
|
|
878
1041
|
"""
|
|
879
|
-
|
|
1042
|
+
HIERARCHY LPAREN op=expr COMMA hrName=IDENTIFIER (conditionClause)? (RULE ruleComponent=componentID)? (validationMode)? (inputModeHierarchy)? outputModeHierarchy? RPAREN # noqa E501
|
|
880
1043
|
"""
|
|
881
1044
|
ctx_list = list(ctx.getChildren())
|
|
882
1045
|
c = ctx_list[0]
|
|
883
1046
|
|
|
884
1047
|
op = c.getSymbol().text
|
|
885
1048
|
dataset_node = self.visitExpr(ctx_list[2])
|
|
886
|
-
rule_name_node = Identifier(value=ctx_list[4].getSymbol().text, kind=
|
|
1049
|
+
rule_name_node = Identifier(value=ctx_list[4].getSymbol().text, kind="RuleID")
|
|
887
1050
|
|
|
888
1051
|
conditions = []
|
|
889
1052
|
modes = "non_null"
|
|
@@ -910,9 +1073,9 @@ class Expr(VtlVisitor):
|
|
|
910
1073
|
raise NotImplementedError("Dataset Priority input mode on HR is not implemented")
|
|
911
1074
|
param_constant_node = []
|
|
912
1075
|
|
|
913
|
-
param_constant_node.append(ParamConstant(
|
|
914
|
-
param_constant_node.append(ParamConstant(
|
|
915
|
-
param_constant_node.append(ParamConstant(
|
|
1076
|
+
param_constant_node.append(ParamConstant("PARAM_MODE", modes))
|
|
1077
|
+
param_constant_node.append(ParamConstant("PARAM_INPUT", inputs))
|
|
1078
|
+
param_constant_node.append(ParamConstant("PARAM_OUTPUT", retains))
|
|
916
1079
|
|
|
917
1080
|
if not rule_comp:
|
|
918
1081
|
if isinstance(de_ruleset_elements[rule_name_node.value], list):
|
|
@@ -921,16 +1084,19 @@ class Expr(VtlVisitor):
|
|
|
921
1084
|
rule_element = de_ruleset_elements[rule_name_node.value]
|
|
922
1085
|
if rule_element.kind == "DatasetID":
|
|
923
1086
|
check_hierarchy_rule = rule_element.value
|
|
924
|
-
rule_comp = Identifier(check_hierarchy_rule,
|
|
1087
|
+
rule_comp = Identifier(check_hierarchy_rule, "ComponentID")
|
|
925
1088
|
else: # ValuedomainID
|
|
926
1089
|
raise SemanticError("1-1-10-4", op=op)
|
|
927
1090
|
|
|
928
|
-
return ParamOp(
|
|
929
|
-
|
|
1091
|
+
return ParamOp(
|
|
1092
|
+
op=op,
|
|
1093
|
+
children=[dataset_node, rule_comp, rule_name_node, *conditions],
|
|
1094
|
+
params=param_constant_node,
|
|
1095
|
+
)
|
|
930
1096
|
|
|
931
1097
|
"""
|
|
932
1098
|
-----------------------------------
|
|
933
|
-
Validation Functions
|
|
1099
|
+
Validation Functions
|
|
934
1100
|
-----------------------------------
|
|
935
1101
|
"""
|
|
936
1102
|
|
|
@@ -944,7 +1110,7 @@ class Expr(VtlVisitor):
|
|
|
944
1110
|
|
|
945
1111
|
def visitValidateDPruleset(self, ctx: Parser.ValidateDPrulesetContext):
|
|
946
1112
|
"""
|
|
947
|
-
|
|
1113
|
+
validationDatapoint: CHECK_DATAPOINT '(' expr ',' IDENTIFIER (COMPONENTS componentID (',' componentID)*)? (INVALID|ALL_MEASURES|ALL)? ')' ; # noqa E501
|
|
948
1114
|
"""
|
|
949
1115
|
ctx_list = list(ctx.getChildren())
|
|
950
1116
|
c = ctx_list[0]
|
|
@@ -954,8 +1120,11 @@ class Expr(VtlVisitor):
|
|
|
954
1120
|
operand_node = self.visitExpr(ctx_list[2])
|
|
955
1121
|
rule_name = ctx_list[4].getSymbol().text
|
|
956
1122
|
|
|
957
|
-
components = [
|
|
958
|
-
|
|
1123
|
+
components = [
|
|
1124
|
+
Terminals().visitComponentID(comp)
|
|
1125
|
+
for comp in ctx_list
|
|
1126
|
+
if isinstance(comp, Parser.ComponentIDContext)
|
|
1127
|
+
]
|
|
959
1128
|
aux_components = []
|
|
960
1129
|
for x in components:
|
|
961
1130
|
if isinstance(x, BinOp):
|
|
@@ -966,18 +1135,17 @@ class Expr(VtlVisitor):
|
|
|
966
1135
|
components = aux_components
|
|
967
1136
|
|
|
968
1137
|
# Default value for output is invalid.
|
|
969
|
-
output =
|
|
1138
|
+
output = "invalid"
|
|
970
1139
|
|
|
971
1140
|
if isinstance(ctx_list[-2], Parser.ValidationOutputContext):
|
|
972
1141
|
output = Terminals().visitValidationOutput(ctx_list[-2])
|
|
973
1142
|
|
|
974
|
-
return ParamOp(op=op, children=[operand_node, rule_name, *components],
|
|
975
|
-
params=[output])
|
|
1143
|
+
return ParamOp(op=op, children=[operand_node, rule_name, *components], params=[output])
|
|
976
1144
|
|
|
977
1145
|
# TODO Not fully implemented only basic usage available.
|
|
978
1146
|
def visitValidateHRruleset(self, ctx: Parser.ValidateHRrulesetContext):
|
|
979
1147
|
"""
|
|
980
|
-
|
|
1148
|
+
CHECK_HIERARCHY LPAREN op=expr COMMA hrName=IDENTIFIER conditionClause? (RULE componentID)? validationMode? inputMode? validationOutput? RPAREN # noqa E501 # validateHRruleset
|
|
981
1149
|
"""
|
|
982
1150
|
|
|
983
1151
|
ctx_list = list(ctx.getChildren())
|
|
@@ -986,13 +1154,13 @@ class Expr(VtlVisitor):
|
|
|
986
1154
|
op = c.getSymbol().text
|
|
987
1155
|
|
|
988
1156
|
dataset_node = self.visitExpr(ctx_list[2])
|
|
989
|
-
rule_name_node = Identifier(value=ctx_list[4].getSymbol().text, kind=
|
|
1157
|
+
rule_name_node = Identifier(value=ctx_list[4].getSymbol().text, kind="RuleID")
|
|
990
1158
|
|
|
991
1159
|
conditions = []
|
|
992
1160
|
# Default values
|
|
993
|
-
modes =
|
|
994
|
-
inputs =
|
|
995
|
-
retains =
|
|
1161
|
+
modes = "non_null"
|
|
1162
|
+
inputs = "dataset"
|
|
1163
|
+
retains = "invalid"
|
|
996
1164
|
rule_comp = None
|
|
997
1165
|
for c in ctx_list:
|
|
998
1166
|
if isinstance(c, Parser.ConditionClauseContext):
|
|
@@ -1015,9 +1183,9 @@ class Expr(VtlVisitor):
|
|
|
1015
1183
|
if inputs == DATASET_PRIORITY:
|
|
1016
1184
|
raise NotImplementedError("Dataset Priority input mode on HR is not implemented")
|
|
1017
1185
|
|
|
1018
|
-
param_constant_node.append(ParamConstant(
|
|
1019
|
-
param_constant_node.append(ParamConstant(
|
|
1020
|
-
param_constant_node.append(ParamConstant(
|
|
1186
|
+
param_constant_node.append(ParamConstant("PARAM_MODE", modes))
|
|
1187
|
+
param_constant_node.append(ParamConstant("PARAM_INPUT", inputs))
|
|
1188
|
+
param_constant_node.append(ParamConstant("PARAM_OUTPUT", retains))
|
|
1021
1189
|
|
|
1022
1190
|
if not rule_comp:
|
|
1023
1191
|
if isinstance(de_ruleset_elements[rule_name_node.value], list):
|
|
@@ -1027,16 +1195,19 @@ class Expr(VtlVisitor):
|
|
|
1027
1195
|
|
|
1028
1196
|
if rule_element.kind == "DatasetID":
|
|
1029
1197
|
check_hierarchy_rule = rule_element.value
|
|
1030
|
-
rule_comp = Identifier(check_hierarchy_rule,
|
|
1198
|
+
rule_comp = Identifier(check_hierarchy_rule, "ComponentID")
|
|
1031
1199
|
else: # ValuedomainID
|
|
1032
1200
|
raise SemanticError("1-1-10-4", op=op)
|
|
1033
1201
|
|
|
1034
|
-
return ParamOp(
|
|
1035
|
-
|
|
1202
|
+
return ParamOp(
|
|
1203
|
+
op=op,
|
|
1204
|
+
children=[dataset_node, rule_comp, rule_name_node, *conditions],
|
|
1205
|
+
params=param_constant_node,
|
|
1206
|
+
)
|
|
1036
1207
|
|
|
1037
1208
|
def visitValidationSimple(self, ctx: Parser.ValidationSimpleContext):
|
|
1038
1209
|
"""
|
|
1039
|
-
|
|
1210
|
+
| CHECK LPAREN op=expr (codeErr=erCode)? (levelCode=erLevel)? imbalanceExpr? output=(INVALID|ALL)? RPAREN # noqa E501 # validationSimple
|
|
1040
1211
|
"""
|
|
1041
1212
|
ctx_list = list(ctx.getChildren())
|
|
1042
1213
|
c = ctx_list[0]
|
|
@@ -1060,13 +1231,16 @@ class Expr(VtlVisitor):
|
|
|
1060
1231
|
if invalid is None:
|
|
1061
1232
|
invalid_value = False
|
|
1062
1233
|
else:
|
|
1063
|
-
invalid_value = True if invalid.getSymbol().text ==
|
|
1234
|
+
invalid_value = True if invalid.getSymbol().text == "invalid" else False
|
|
1064
1235
|
|
|
1065
|
-
return Validation(
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1236
|
+
return Validation(
|
|
1237
|
+
op=token.text,
|
|
1238
|
+
validation=validation_node,
|
|
1239
|
+
error_code=error_code,
|
|
1240
|
+
error_level=error_level,
|
|
1241
|
+
imbalance=inbalance_node,
|
|
1242
|
+
invalid=invalid_value,
|
|
1243
|
+
)
|
|
1070
1244
|
|
|
1071
1245
|
def visitImbalanceExpr(self, ctx: Parser.ImbalanceExprContext):
|
|
1072
1246
|
ctx_list = list(ctx.getChildren())
|
|
@@ -1074,7 +1248,7 @@ class Expr(VtlVisitor):
|
|
|
1074
1248
|
|
|
1075
1249
|
"""
|
|
1076
1250
|
-----------------------------------
|
|
1077
|
-
Aggregate Functions
|
|
1251
|
+
Aggregate Functions
|
|
1078
1252
|
-----------------------------------
|
|
1079
1253
|
"""
|
|
1080
1254
|
|
|
@@ -1101,7 +1275,7 @@ class Expr(VtlVisitor):
|
|
|
1101
1275
|
|
|
1102
1276
|
def visitAggrDataset(self, ctx: Parser.AggrDatasetContext):
|
|
1103
1277
|
ctx_list = list(ctx.getChildren())
|
|
1104
|
-
c = ctx_list[0]
|
|
1278
|
+
# c = ctx_list[0]
|
|
1105
1279
|
|
|
1106
1280
|
grouping_op = None
|
|
1107
1281
|
group_node = None
|
|
@@ -1117,19 +1291,24 @@ class Expr(VtlVisitor):
|
|
|
1117
1291
|
grouping_op, group_node = self.visitGroupingClause(groups[0])
|
|
1118
1292
|
if len(haves) != 0:
|
|
1119
1293
|
have_node, expr = self.visitHavingClause(haves[0])
|
|
1120
|
-
setattr(have_node,
|
|
1294
|
+
setattr(have_node, "expr", expr)
|
|
1121
1295
|
|
|
1122
|
-
return Aggregation(
|
|
1123
|
-
|
|
1296
|
+
return Aggregation(
|
|
1297
|
+
op=op_node,
|
|
1298
|
+
operand=operand,
|
|
1299
|
+
grouping_op=grouping_op,
|
|
1300
|
+
grouping=group_node,
|
|
1301
|
+
having_clause=have_node,
|
|
1302
|
+
)
|
|
1124
1303
|
|
|
1125
1304
|
"""
|
|
1126
1305
|
-----------------------------------
|
|
1127
|
-
Analytic Functions
|
|
1306
|
+
Analytic Functions
|
|
1128
1307
|
-----------------------------------
|
|
1129
1308
|
"""
|
|
1130
1309
|
|
|
1131
1310
|
def visitAnalyticFunctions(self, ctx: Parser.AnalyticFunctionsContext):
|
|
1132
|
-
ctx_list = list(ctx.getChildren())
|
|
1311
|
+
# ctx_list = list(ctx.getChildren())
|
|
1133
1312
|
|
|
1134
1313
|
if isinstance(ctx, Parser.AnSimpleFunctionContext):
|
|
1135
1314
|
return self.visitAnSimpleFunction(ctx)
|
|
@@ -1165,15 +1344,12 @@ class Expr(VtlVisitor):
|
|
|
1165
1344
|
|
|
1166
1345
|
if window is None:
|
|
1167
1346
|
window = Windowing(
|
|
1168
|
-
type_=
|
|
1169
|
-
start=-1,
|
|
1170
|
-
stop=0,
|
|
1171
|
-
start_mode='preceding',
|
|
1172
|
-
stop_mode='current'
|
|
1347
|
+
type_="data", start=-1, stop=0, start_mode="preceding", stop_mode="current"
|
|
1173
1348
|
)
|
|
1174
1349
|
|
|
1175
|
-
return Analytic(
|
|
1176
|
-
|
|
1350
|
+
return Analytic(
|
|
1351
|
+
op=op_node, operand=operand, partition_by=partition_by, order_by=order_by, window=window
|
|
1352
|
+
)
|
|
1177
1353
|
|
|
1178
1354
|
def visitLagOrLeadAn(self, ctx: Parser.LagOrLeadAnContext):
|
|
1179
1355
|
ctx_list = list(ctx.getChildren())
|
|
@@ -1192,8 +1368,9 @@ class Expr(VtlVisitor):
|
|
|
1192
1368
|
elif isinstance(c, Parser.OrderByClauseContext):
|
|
1193
1369
|
order_by = Terminals().visitOrderByClause(c)
|
|
1194
1370
|
continue
|
|
1195
|
-
elif isinstance(c, Parser.SignedIntegerContext) or isinstance(
|
|
1196
|
-
|
|
1371
|
+
elif isinstance(c, Parser.SignedIntegerContext) or isinstance(
|
|
1372
|
+
c, Parser.ScalarItemContext
|
|
1373
|
+
):
|
|
1197
1374
|
if params is None:
|
|
1198
1375
|
params = []
|
|
1199
1376
|
if isinstance(c, Parser.SignedIntegerContext):
|
|
@@ -1206,13 +1383,14 @@ class Expr(VtlVisitor):
|
|
|
1206
1383
|
# AST_ASTCONSTRUCTOR.16
|
|
1207
1384
|
raise Exception(f"{op_node} requires an offset parameter.")
|
|
1208
1385
|
|
|
1209
|
-
return Analytic(
|
|
1210
|
-
|
|
1386
|
+
return Analytic(
|
|
1387
|
+
op=op_node, operand=operand, partition_by=partition_by, order_by=order_by, params=params
|
|
1388
|
+
)
|
|
1211
1389
|
|
|
1212
1390
|
def visitRatioToReportAn(self, ctx: Parser.RatioToReportAnContext):
|
|
1213
1391
|
ctx_list = list(ctx.getChildren())
|
|
1214
1392
|
|
|
1215
|
-
params = None
|
|
1393
|
+
# params = None
|
|
1216
1394
|
order_by = None
|
|
1217
1395
|
|
|
1218
1396
|
op_node = ctx_list[0].getSymbol().text
|
|
@@ -1276,7 +1454,7 @@ class Expr(VtlVisitor):
|
|
|
1276
1454
|
|
|
1277
1455
|
"""
|
|
1278
1456
|
-----------------------------------
|
|
1279
|
-
Rename Clause
|
|
1457
|
+
Rename Clause
|
|
1280
1458
|
-----------------------------------
|
|
1281
1459
|
"""
|
|
1282
1460
|
|
|
@@ -1286,8 +1464,11 @@ class Expr(VtlVisitor):
|
|
|
1286
1464
|
"""
|
|
1287
1465
|
ctx_list = list(ctx.getChildren())
|
|
1288
1466
|
|
|
1289
|
-
renames = [
|
|
1290
|
-
|
|
1467
|
+
renames = [
|
|
1468
|
+
ctx_child
|
|
1469
|
+
for ctx_child in ctx_list
|
|
1470
|
+
if isinstance(ctx_child, Parser.RenameClauseItemContext)
|
|
1471
|
+
]
|
|
1291
1472
|
rename_nodes = []
|
|
1292
1473
|
|
|
1293
1474
|
for ctx_rename in renames:
|
|
@@ -1297,13 +1478,13 @@ class Expr(VtlVisitor):
|
|
|
1297
1478
|
|
|
1298
1479
|
def visitRenameClauseItem(self, ctx: Parser.RenameClauseItemContext):
|
|
1299
1480
|
"""
|
|
1300
|
-
|
|
1481
|
+
renameClauseItem: fromName=componentID TO toName=componentID;
|
|
1301
1482
|
"""
|
|
1302
1483
|
ctx_list = list(ctx.getChildren())
|
|
1303
1484
|
|
|
1304
1485
|
left_node = Terminals().visitComponentID(ctx_list[0])
|
|
1305
1486
|
if isinstance(left_node, BinOp):
|
|
1306
|
-
left_node = f
|
|
1487
|
+
left_node = f"{left_node.left.value}{left_node.op}{left_node.right.value}"
|
|
1307
1488
|
else:
|
|
1308
1489
|
left_node = left_node.value
|
|
1309
1490
|
|
|
@@ -1313,7 +1494,7 @@ class Expr(VtlVisitor):
|
|
|
1313
1494
|
|
|
1314
1495
|
"""
|
|
1315
1496
|
-----------------------------------
|
|
1316
|
-
Aggregate Clause
|
|
1497
|
+
Aggregate Clause
|
|
1317
1498
|
-----------------------------------
|
|
1318
1499
|
"""
|
|
1319
1500
|
|
|
@@ -1325,8 +1506,11 @@ class Expr(VtlVisitor):
|
|
|
1325
1506
|
|
|
1326
1507
|
aggregates_nodes = []
|
|
1327
1508
|
|
|
1328
|
-
aggregates = [
|
|
1329
|
-
|
|
1509
|
+
aggregates = [
|
|
1510
|
+
aggregate
|
|
1511
|
+
for aggregate in ctx_list
|
|
1512
|
+
if isinstance(aggregate, Parser.AggrFunctionClauseContext)
|
|
1513
|
+
]
|
|
1330
1514
|
|
|
1331
1515
|
for agg in aggregates:
|
|
1332
1516
|
aggregates_nodes.append(self.visitAggrFunctionClause(agg))
|
|
@@ -1348,11 +1532,11 @@ class Expr(VtlVisitor):
|
|
|
1348
1532
|
role = Role.MEASURE
|
|
1349
1533
|
|
|
1350
1534
|
left_node = Terminals().visitSimpleComponentId(ctx_list[base_index])
|
|
1351
|
-
op_node =
|
|
1535
|
+
op_node = ":="
|
|
1352
1536
|
right_node = ExprComp().visitAggregateFunctionsComponents(ctx_list[base_index + 2])
|
|
1353
1537
|
# Encoding the role information inside the Assignment for easiness and simplicity.
|
|
1354
1538
|
# Cannot find another way with less lines of code
|
|
1355
|
-
setattr(left_node,
|
|
1539
|
+
setattr(left_node, "role", role)
|
|
1356
1540
|
|
|
1357
1541
|
return Assignment(left_node, op_node, right_node)
|
|
1358
1542
|
|
|
@@ -1379,21 +1563,25 @@ class Expr(VtlVisitor):
|
|
|
1379
1563
|
grouping_op, group_node = self.visitGroupingClause(groups[0])
|
|
1380
1564
|
if len(haves) > 0:
|
|
1381
1565
|
have_node, expr = self.visitHavingClause(haves[0])
|
|
1382
|
-
setattr(have_node,
|
|
1566
|
+
setattr(have_node, "expr", expr)
|
|
1383
1567
|
for element in aggregate_nodes:
|
|
1384
|
-
element.right = Aggregation(
|
|
1385
|
-
|
|
1386
|
-
|
|
1568
|
+
element.right = Aggregation(
|
|
1569
|
+
op=element.right.op,
|
|
1570
|
+
operand=element.right.operand,
|
|
1571
|
+
grouping_op=grouping_op,
|
|
1572
|
+
grouping=group_node,
|
|
1573
|
+
having_clause=have_node,
|
|
1574
|
+
)
|
|
1387
1575
|
children.append(copy(element))
|
|
1388
1576
|
|
|
1389
1577
|
return RegularAggregation(op=op_node, children=children)
|
|
1390
1578
|
|
|
1391
1579
|
def visitGroupingClause(self, ctx: Parser.GroupingClauseContext):
|
|
1392
1580
|
"""
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1581
|
+
groupingClause:
|
|
1582
|
+
GROUP op=(BY | EXCEPT) componentID (COMMA componentID)* # groupByOrExcept
|
|
1583
|
+
| GROUP ALL exprComponent # groupAll
|
|
1584
|
+
;
|
|
1397
1585
|
"""
|
|
1398
1586
|
if isinstance(ctx, Parser.GroupByOrExceptContext):
|
|
1399
1587
|
return self.visitGroupByOrExcept(ctx)
|
|
@@ -1410,24 +1598,24 @@ class Expr(VtlVisitor):
|
|
|
1410
1598
|
op_node = ctx_list[0].getSymbol().text
|
|
1411
1599
|
|
|
1412
1600
|
text = ctx_list[1].start.source[1].strdata
|
|
1413
|
-
expr = re.split(
|
|
1414
|
-
expr =
|
|
1601
|
+
expr = re.split("having", text)[1]
|
|
1602
|
+
expr = "having " + expr[:-2].strip()
|
|
1415
1603
|
|
|
1416
|
-
if
|
|
1417
|
-
index = expr.index(
|
|
1604
|
+
if "]" in expr:
|
|
1605
|
+
index = expr.index("]")
|
|
1418
1606
|
expr = expr[:index]
|
|
1419
|
-
if
|
|
1420
|
-
index = expr.index(
|
|
1607
|
+
if "end" in expr:
|
|
1608
|
+
index = expr.index("end")
|
|
1421
1609
|
expr = expr[:index]
|
|
1422
|
-
if expr.count(
|
|
1423
|
-
index = expr.rindex(
|
|
1610
|
+
if expr.count(")") > expr.count("("):
|
|
1611
|
+
index = expr.rindex(")")
|
|
1424
1612
|
expr = expr[:index]
|
|
1425
1613
|
|
|
1426
|
-
if
|
|
1427
|
-
expr = expr.replace(
|
|
1428
|
-
expr = expr.replace(
|
|
1429
|
-
if
|
|
1430
|
-
expr = expr.replace(
|
|
1614
|
+
if "{" in expr or "}" in expr:
|
|
1615
|
+
expr = expr.replace("{", "(")
|
|
1616
|
+
expr = expr.replace("}", ")")
|
|
1617
|
+
if "not_in" in expr:
|
|
1618
|
+
expr = expr.replace("not_in", "not in")
|
|
1431
1619
|
if '"' in expr:
|
|
1432
1620
|
expr = expr.replace('"', "'")
|
|
1433
1621
|
|
|
@@ -1448,10 +1636,13 @@ class Expr(VtlVisitor):
|
|
|
1448
1636
|
token_left = ctx_list[0].getSymbol().text
|
|
1449
1637
|
token_right = ctx_list[1].getSymbol().text
|
|
1450
1638
|
|
|
1451
|
-
op_node = token_left +
|
|
1639
|
+
op_node = token_left + " " + token_right
|
|
1452
1640
|
|
|
1453
|
-
children_nodes = [
|
|
1454
|
-
|
|
1641
|
+
children_nodes = [
|
|
1642
|
+
Terminals().visitComponentID(identifier)
|
|
1643
|
+
for identifier in ctx_list
|
|
1644
|
+
if isinstance(identifier, Parser.ComponentIDContext)
|
|
1645
|
+
]
|
|
1455
1646
|
|
|
1456
1647
|
return op_node, children_nodes
|
|
1457
1648
|
|
|
@@ -1461,7 +1652,7 @@ class Expr(VtlVisitor):
|
|
|
1461
1652
|
token_left = ctx_list[0].getSymbol().text
|
|
1462
1653
|
token_right = ctx_list[1].getSymbol().text
|
|
1463
1654
|
|
|
1464
|
-
op_node = token_left +
|
|
1655
|
+
op_node = token_left + " " + token_right
|
|
1465
1656
|
|
|
1466
1657
|
children_nodes = [ExprComp().visitExprComponent(ctx_list[2])]
|
|
1467
1658
|
|
|
@@ -1469,7 +1660,7 @@ class Expr(VtlVisitor):
|
|
|
1469
1660
|
|
|
1470
1661
|
"""
|
|
1471
1662
|
-----------------------------------
|
|
1472
|
-
Filter Clause
|
|
1663
|
+
Filter Clause
|
|
1473
1664
|
-----------------------------------
|
|
1474
1665
|
"""
|
|
1475
1666
|
|
|
@@ -1489,7 +1680,7 @@ class Expr(VtlVisitor):
|
|
|
1489
1680
|
|
|
1490
1681
|
"""
|
|
1491
1682
|
-----------------------------------
|
|
1492
|
-
Calc Clause
|
|
1683
|
+
Calc Clause
|
|
1493
1684
|
-----------------------------------
|
|
1494
1685
|
"""
|
|
1495
1686
|
|
|
@@ -1500,8 +1691,11 @@ class Expr(VtlVisitor):
|
|
|
1500
1691
|
ctx_list = list(ctx.getChildren())
|
|
1501
1692
|
c = ctx_list[0]
|
|
1502
1693
|
|
|
1503
|
-
calcClauseItems = [
|
|
1504
|
-
|
|
1694
|
+
calcClauseItems = [
|
|
1695
|
+
calcClauseItem
|
|
1696
|
+
for calcClauseItem in ctx_list
|
|
1697
|
+
if isinstance(calcClauseItem, Parser.CalcClauseItemContext)
|
|
1698
|
+
]
|
|
1505
1699
|
calcClauseItems_nodes = []
|
|
1506
1700
|
|
|
1507
1701
|
op_node = c.getSymbol().text
|
|
@@ -1522,7 +1716,7 @@ class Expr(VtlVisitor):
|
|
|
1522
1716
|
role = Terminals().visitComponentRole(c)
|
|
1523
1717
|
|
|
1524
1718
|
left_node = Terminals().visitComponentID(ctx_list[1])
|
|
1525
|
-
op_node =
|
|
1719
|
+
op_node = ":="
|
|
1526
1720
|
right_node = ExprComp().visitExprComponent(ctx_list[3])
|
|
1527
1721
|
operand_node = Assignment(left_node, op_node, right_node)
|
|
1528
1722
|
if role is None:
|
|
@@ -1530,7 +1724,7 @@ class Expr(VtlVisitor):
|
|
|
1530
1724
|
return UnaryOp(role.value.lower(), operand_node)
|
|
1531
1725
|
else:
|
|
1532
1726
|
left_node = Terminals().visitSimpleComponentId(c)
|
|
1533
|
-
op_node =
|
|
1727
|
+
op_node = ":="
|
|
1534
1728
|
right_node = ExprComp().visitExprComponent(ctx_list[2])
|
|
1535
1729
|
|
|
1536
1730
|
operand_node = Assignment(left_node, op_node, right_node)
|
|
@@ -1555,7 +1749,7 @@ class Expr(VtlVisitor):
|
|
|
1555
1749
|
|
|
1556
1750
|
"""
|
|
1557
1751
|
-----------------------------------
|
|
1558
|
-
Pivot/Unpivot Clause
|
|
1752
|
+
Pivot/Unpivot Clause
|
|
1559
1753
|
-----------------------------------
|
|
1560
1754
|
"""
|
|
1561
1755
|
|
|
@@ -1576,19 +1770,22 @@ class Expr(VtlVisitor):
|
|
|
1576
1770
|
|
|
1577
1771
|
"""
|
|
1578
1772
|
-----------------------------------
|
|
1579
|
-
Subspace Clause
|
|
1773
|
+
Subspace Clause
|
|
1580
1774
|
-----------------------------------
|
|
1581
1775
|
"""
|
|
1582
1776
|
|
|
1583
1777
|
def visitSubspaceClause(self, ctx: Parser.SubspaceClauseContext):
|
|
1584
1778
|
"""
|
|
1585
|
-
subspaceClause: SUBSPACE subspaceClauseItem (COMMA subspaceClauseItem)*;
|
|
1779
|
+
subspaceClause: SUBSPACE subspaceClauseItem (COMMA subspaceClauseItem)*;"""
|
|
1586
1780
|
ctx_list = list(ctx.getChildren())
|
|
1587
1781
|
c = ctx_list[0]
|
|
1588
1782
|
|
|
1589
1783
|
subspace_nodes = []
|
|
1590
|
-
subspaces = [
|
|
1591
|
-
|
|
1784
|
+
subspaces = [
|
|
1785
|
+
subspace
|
|
1786
|
+
for subspace in ctx_list
|
|
1787
|
+
if isinstance(subspace, Parser.SubspaceClauseItemContext)
|
|
1788
|
+
]
|
|
1592
1789
|
|
|
1593
1790
|
for subspace in subspaces:
|
|
1594
1791
|
subspace_nodes.append(self.visitSubspaceClauseItem(subspace))
|
|
@@ -1618,4 +1815,4 @@ class Expr(VtlVisitor):
|
|
|
1618
1815
|
elif isinstance(c, TerminalNodeImpl):
|
|
1619
1816
|
token = c.getSymbol()
|
|
1620
1817
|
opt = token.text
|
|
1621
|
-
return ID(
|
|
1818
|
+
return ID("OPTIONAL", opt)
|