vtlengine 1.4.0rc2__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.
Files changed (66) hide show
  1. vtlengine/API/_InternalApi.py +791 -0
  2. vtlengine/API/__init__.py +612 -0
  3. vtlengine/API/data/schema/external_routines_schema.json +34 -0
  4. vtlengine/API/data/schema/json_schema_2.1.json +116 -0
  5. vtlengine/API/data/schema/value_domain_schema.json +97 -0
  6. vtlengine/AST/ASTComment.py +57 -0
  7. vtlengine/AST/ASTConstructor.py +598 -0
  8. vtlengine/AST/ASTConstructorModules/Expr.py +1928 -0
  9. vtlengine/AST/ASTConstructorModules/ExprComponents.py +995 -0
  10. vtlengine/AST/ASTConstructorModules/Terminals.py +790 -0
  11. vtlengine/AST/ASTConstructorModules/__init__.py +50 -0
  12. vtlengine/AST/ASTDataExchange.py +10 -0
  13. vtlengine/AST/ASTEncoders.py +32 -0
  14. vtlengine/AST/ASTString.py +675 -0
  15. vtlengine/AST/ASTTemplate.py +558 -0
  16. vtlengine/AST/ASTVisitor.py +25 -0
  17. vtlengine/AST/DAG/__init__.py +479 -0
  18. vtlengine/AST/DAG/_words.py +10 -0
  19. vtlengine/AST/Grammar/Vtl.g4 +705 -0
  20. vtlengine/AST/Grammar/VtlTokens.g4 +409 -0
  21. vtlengine/AST/Grammar/__init__.py +0 -0
  22. vtlengine/AST/Grammar/lexer.py +2139 -0
  23. vtlengine/AST/Grammar/parser.py +16597 -0
  24. vtlengine/AST/Grammar/tokens.py +169 -0
  25. vtlengine/AST/VtlVisitor.py +824 -0
  26. vtlengine/AST/__init__.py +674 -0
  27. vtlengine/DataTypes/TimeHandling.py +562 -0
  28. vtlengine/DataTypes/__init__.py +863 -0
  29. vtlengine/DataTypes/_time_checking.py +135 -0
  30. vtlengine/Exceptions/__exception_file_generator.py +96 -0
  31. vtlengine/Exceptions/__init__.py +159 -0
  32. vtlengine/Exceptions/messages.py +1004 -0
  33. vtlengine/Interpreter/__init__.py +2048 -0
  34. vtlengine/Model/__init__.py +501 -0
  35. vtlengine/Operators/Aggregation.py +357 -0
  36. vtlengine/Operators/Analytic.py +455 -0
  37. vtlengine/Operators/Assignment.py +23 -0
  38. vtlengine/Operators/Boolean.py +106 -0
  39. vtlengine/Operators/CastOperator.py +451 -0
  40. vtlengine/Operators/Clause.py +366 -0
  41. vtlengine/Operators/Comparison.py +488 -0
  42. vtlengine/Operators/Conditional.py +495 -0
  43. vtlengine/Operators/General.py +191 -0
  44. vtlengine/Operators/HROperators.py +254 -0
  45. vtlengine/Operators/Join.py +447 -0
  46. vtlengine/Operators/Numeric.py +422 -0
  47. vtlengine/Operators/RoleSetter.py +77 -0
  48. vtlengine/Operators/Set.py +176 -0
  49. vtlengine/Operators/String.py +578 -0
  50. vtlengine/Operators/Time.py +1144 -0
  51. vtlengine/Operators/Validation.py +275 -0
  52. vtlengine/Operators/__init__.py +900 -0
  53. vtlengine/Utils/__Virtual_Assets.py +34 -0
  54. vtlengine/Utils/__init__.py +479 -0
  55. vtlengine/__extras_check.py +17 -0
  56. vtlengine/__init__.py +27 -0
  57. vtlengine/files/__init__.py +0 -0
  58. vtlengine/files/output/__init__.py +35 -0
  59. vtlengine/files/output/_time_period_representation.py +55 -0
  60. vtlengine/files/parser/__init__.py +240 -0
  61. vtlengine/files/parser/_rfc_dialect.py +22 -0
  62. vtlengine/py.typed +0 -0
  63. vtlengine-1.4.0rc2.dist-info/METADATA +89 -0
  64. vtlengine-1.4.0rc2.dist-info/RECORD +66 -0
  65. vtlengine-1.4.0rc2.dist-info/WHEEL +4 -0
  66. vtlengine-1.4.0rc2.dist-info/licenses/LICENSE.md +661 -0
@@ -0,0 +1,790 @@
1
+ from antlr4.tree.Tree import TerminalNodeImpl
2
+
3
+ from vtlengine.AST import (
4
+ BinOp,
5
+ Collection,
6
+ Constant,
7
+ DPRIdentifier,
8
+ Identifier,
9
+ OrderBy,
10
+ ParamConstant,
11
+ ParamOp,
12
+ VarID,
13
+ Windowing,
14
+ )
15
+ from vtlengine.AST.ASTConstructorModules import extract_token_info
16
+ from vtlengine.AST.Grammar.parser import Parser
17
+ from vtlengine.AST.VtlVisitor import VtlVisitor
18
+ from vtlengine.DataTypes import (
19
+ Boolean,
20
+ Date,
21
+ Duration,
22
+ Integer,
23
+ Number,
24
+ String,
25
+ TimeInterval,
26
+ TimePeriod,
27
+ )
28
+ from vtlengine.Model import Component, Dataset, Role, Scalar
29
+
30
+
31
+ def _remove_scaped_characters(text):
32
+ has_scaped_char = text.find("'") != -1
33
+ if has_scaped_char:
34
+ text = str(text.replace("'", ""))
35
+ return text
36
+
37
+
38
+ class Terminals(VtlVisitor):
39
+ def visitConstant(self, ctx: Parser.ConstantContext):
40
+ token = ctx.children[0].getSymbol()
41
+ token_info = extract_token_info(token)
42
+
43
+ if token.type == Parser.INTEGER_CONSTANT:
44
+ constant_node = Constant(type_="INTEGER_CONSTANT", value=int(token.text), **token_info)
45
+
46
+ elif token.type == Parser.NUMBER_CONSTANT:
47
+ constant_node = Constant(type_="FLOAT_CONSTANT", value=float(token.text), **token_info)
48
+
49
+ elif token.type == Parser.BOOLEAN_CONSTANT:
50
+ if token.text == "true":
51
+ constant_node = Constant(type_="BOOLEAN_CONSTANT", value=True, **token_info)
52
+ elif token.text == "false":
53
+ constant_node = Constant(type_="BOOLEAN_CONSTANT", value=False, **token_info)
54
+ else:
55
+ raise NotImplementedError
56
+
57
+ elif token.type == Parser.STRING_CONSTANT:
58
+ constant_node = Constant(type_="STRING_CONSTANT", value=token.text[1:-1], **token_info)
59
+
60
+ elif token.type == Parser.NULL_CONSTANT:
61
+ constant_node = Constant(type_="NULL_CONSTANT", value=None, **token_info)
62
+
63
+ else:
64
+ raise NotImplementedError
65
+
66
+ return constant_node
67
+
68
+ def visitVarID(self, ctx: Parser.VarIDContext):
69
+ token = ctx.children[0].getSymbol()
70
+ token.text = _remove_scaped_characters(token.text)
71
+ token_info = extract_token_info(token)
72
+ var_id_node = VarID(value=token.text, **token_info)
73
+ return var_id_node
74
+
75
+ def visitVarIdExpr(self, ctx: Parser.VarIdExprContext):
76
+ if isinstance(ctx.children[0], Parser.VarIDContext):
77
+ return self.visitVarID(ctx.children[0])
78
+
79
+ token = ctx.children[0].getSymbol()
80
+ # check token text
81
+ token.text = _remove_scaped_characters(token.text)
82
+ token_info = extract_token_info(token)
83
+ var_id_node = VarID(value=token.text, **token_info)
84
+ return var_id_node
85
+
86
+ def visitSimpleComponentId(self, ctx: Parser.SimpleComponentIdContext):
87
+ """
88
+ componentID: IDENTIFIER ;
89
+ """
90
+ token = ctx.children[0].getSymbol()
91
+ # check token text
92
+ token.text = _remove_scaped_characters(token.text)
93
+
94
+ return Identifier(value=token.text, kind="ComponentID", **extract_token_info(ctx))
95
+
96
+ def visitComponentID(self, ctx: Parser.ComponentIDContext):
97
+ ctx_list = list(ctx.getChildren())
98
+
99
+ if len(ctx_list) == 1:
100
+ component_name = ctx_list[0].getSymbol().text
101
+ if component_name.startswith("'") and component_name.endswith(
102
+ "'"
103
+ ): # The component could be imbalance, errorcode or errorlevel
104
+ component_name = component_name[1:-1]
105
+ return Identifier(
106
+ value=component_name,
107
+ kind="ComponentID",
108
+ **extract_token_info(ctx_list[0].getSymbol()),
109
+ )
110
+ else:
111
+ component_name = ctx_list[2].getSymbol().text
112
+ if component_name.startswith("'") and component_name.endswith(
113
+ "'"
114
+ ): # The component could be imbalance, errorcode or errorlevel
115
+ component_name = component_name[1:-1]
116
+ op_node = ctx_list[1].getSymbol().text
117
+ return BinOp(
118
+ left=Identifier(
119
+ value=ctx_list[0].getSymbol().text,
120
+ kind="DatasetID",
121
+ **extract_token_info(ctx_list[0].getSymbol()),
122
+ ),
123
+ op=op_node,
124
+ right=Identifier(
125
+ value=component_name,
126
+ kind="ComponentID",
127
+ **extract_token_info(ctx_list[1].getSymbol()),
128
+ ),
129
+ **extract_token_info(ctx),
130
+ )
131
+
132
+ def visitOperatorID(self, ctx: Parser.OperatorIDContext):
133
+ """
134
+ operatorID: IDENTIFIER ;
135
+ """
136
+ ctx_list = list(ctx.getChildren())
137
+ c = ctx_list[0]
138
+ token = c.getSymbol()
139
+ return token.text
140
+
141
+ def visitValueDomainID(self, ctx: Parser.ValueDomainIDContext):
142
+ """
143
+ valueDomainID: IDENTIFIER ;
144
+ """
145
+ return Collection(
146
+ name=ctx.children[0].getSymbol().text,
147
+ children=[],
148
+ kind="ValueDomain",
149
+ type="",
150
+ **extract_token_info(ctx),
151
+ )
152
+
153
+ def visitRulesetID(self, ctx: Parser.RulesetIDContext):
154
+ """
155
+ rulesetID: IDENTIFIER ;
156
+ """
157
+ ctx_list = list(ctx.getChildren())
158
+ c = ctx_list[0]
159
+ token = c.getSymbol()
160
+ return token.text
161
+
162
+ def visitValueDomainName(self, ctx: Parser.ValueDomainNameContext):
163
+ """
164
+ valueDomainName: IDENTIFIER ;
165
+ """
166
+ ctx_list = list(ctx.getChildren())
167
+ # AST_ASTCONSTRUCTOR.48
168
+ raise NotImplementedError(
169
+ "Value Domain '{}' not available for cast operator or scalar type "
170
+ "representation or rulesets.".format(ctx_list[0].getSymbol().text)
171
+ )
172
+
173
+ def visitValueDomainValue(self, ctx: Parser.ValueDomainValueContext):
174
+ return _remove_scaped_characters(ctx.children[0].getSymbol().text)
175
+
176
+ def visitRoutineName(self, ctx: Parser.RoutineNameContext):
177
+ """
178
+ routineName: IDENTIFIER ;
179
+ """
180
+ ctx_list = list(ctx.getChildren())
181
+ c = ctx_list[0]
182
+ token = c.getSymbol()
183
+
184
+ return token.text
185
+
186
+ def visitBasicScalarType(self, ctx: Parser.BasicScalarTypeContext):
187
+ """
188
+ basicScalarType: STRING
189
+ | INTEGER
190
+ | NUMBER
191
+ | BOOLEAN
192
+ | DATE
193
+ | TIME_PERIOD
194
+ | DURATION
195
+ | SCALAR
196
+ | TIME
197
+ ;
198
+ """
199
+ ctx_list = list(ctx.getChildren())
200
+ c = ctx_list[0]
201
+ token = c.getSymbol()
202
+
203
+ if token.type == Parser.STRING:
204
+ return String
205
+ elif token.type == Parser.INTEGER:
206
+ return Integer
207
+ elif token.type == Parser.NUMBER:
208
+ return Number
209
+ elif token.type == Parser.BOOLEAN:
210
+ return Boolean
211
+ elif token.type == Parser.DATE:
212
+ return Date
213
+ elif token.type == Parser.TIME_PERIOD:
214
+ return TimePeriod
215
+ elif token.type == Parser.DURATION:
216
+ return Duration
217
+ elif token.type == Parser.SCALAR:
218
+ return "Scalar"
219
+ elif token.type == Parser.TIME:
220
+ return TimeInterval
221
+
222
+ def visitComponentRole(self, ctx: Parser.ComponentRoleContext):
223
+ """
224
+ componentRole: MEASURE
225
+ |COMPONENT
226
+ |DIMENSION
227
+ |ATTRIBUTE
228
+ |viralAttribute
229
+ ;
230
+ """
231
+ ctx_list = list(ctx.getChildren())
232
+ c = ctx_list[0]
233
+
234
+ if isinstance(c, Parser.ViralAttributeContext):
235
+ return self.visitViralAttribute(c)
236
+ else:
237
+ token = c.getSymbol()
238
+ text = token.text
239
+ if text == "component":
240
+ return None
241
+ # Use upper case on first letter
242
+ text = text[0].upper() + text[1:].lower()
243
+ return Role(text)
244
+
245
+ def visitViralAttribute(self, ctx: Parser.ViralAttributeContext):
246
+ """
247
+ viralAttribute: VIRAL ATTRIBUTE;
248
+ """
249
+ # ctx_list = list(ctx.getChildren())
250
+ # c = ctx_list[0]
251
+ # token = c.getSymbol()
252
+
253
+ raise NotImplementedError
254
+
255
+ def visitLists(self, ctx: Parser.ListsContext):
256
+ """
257
+ lists: GLPAREN scalarItem (COMMA scalarItem)* GRPAREN
258
+ """
259
+ ctx_list = list(ctx.getChildren())
260
+
261
+ scalar_nodes = []
262
+
263
+ scalars = [scalar for scalar in ctx_list if isinstance(scalar, Parser.SimpleScalarContext)]
264
+
265
+ scalars_with_cast = [
266
+ scalar for scalar in ctx_list if isinstance(scalar, Parser.ScalarWithCastContext)
267
+ ]
268
+
269
+ for scalar in scalars:
270
+ scalar_nodes.append(self.visitSimpleScalar(scalar))
271
+
272
+ for scalar_with_cast in scalars_with_cast:
273
+ scalar_nodes.append(self.visitScalarWithCast(scalar_with_cast))
274
+
275
+ return Collection(
276
+ name="List", type="Lists", children=scalar_nodes, **extract_token_info(ctx)
277
+ )
278
+
279
+ def visitMultModifier(self, ctx: Parser.MultModifierContext):
280
+ """
281
+ multModifier: OPTIONAL ( PLUS | MUL )?;
282
+ """
283
+ pass
284
+
285
+ def visitCompConstraint(self, ctx: Parser.CompConstraintContext):
286
+ """
287
+ compConstraint: componentType (componentID|multModifier) ;
288
+ """
289
+ ctx_list = list(ctx.getChildren())
290
+
291
+ component_node = [
292
+ self.visitComponentType(component)
293
+ for component in ctx_list
294
+ if isinstance(component, Parser.ComponentTypeContext)
295
+ ]
296
+ component_name = [
297
+ self.visitComponentID(component).value
298
+ for component in ctx_list
299
+ if isinstance(component, Parser.ComponentIDContext)
300
+ ]
301
+ component_mult = [
302
+ self.visitMultModifier(modifier)
303
+ for modifier in ctx_list
304
+ if isinstance(modifier, Parser.MultModifierContext)
305
+ ]
306
+
307
+ if len(component_mult) != 0:
308
+ # AST_ASTCONSTRUCTOR.51
309
+ raise NotImplementedError
310
+
311
+ component_node[0].name = component_name[0]
312
+ return component_node[0]
313
+
314
+ def visitSimpleScalar(self, ctx: Parser.SimpleScalarContext):
315
+ ctx_list = list(ctx.getChildren())
316
+ c = ctx_list[0]
317
+ if isinstance(c, Parser.ConstantContext):
318
+ return self.visitConstant(c)
319
+ else:
320
+ raise NotImplementedError
321
+
322
+ def visitScalarType(self, ctx: Parser.ScalarTypeContext):
323
+ """
324
+ scalarType: (basicScalarType|valueDomainName)scalarTypeConstraint?((NOT)? NULL_CONSTANT)? ;
325
+ """
326
+ ctx_list = list(ctx.getChildren())
327
+
328
+ types = (
329
+ Parser.BasicScalarTypeContext,
330
+ Parser.ValueDomainNameContext,
331
+ Parser.ScalarTypeConstraintContext,
332
+ )
333
+ scalartype = [scalartype for scalartype in ctx_list if isinstance(scalartype, types)][0]
334
+
335
+ scalartype_constraint = [
336
+ constraint
337
+ for constraint in ctx_list
338
+ if isinstance(constraint, Parser.ScalarTypeConstraintContext)
339
+ ]
340
+ not_ = [
341
+ not_.getSymbol().text
342
+ for not_ in ctx_list
343
+ if isinstance(not_, TerminalNodeImpl) and not_.getSymbol().type == Parser.NOT
344
+ ]
345
+ null_constant = [
346
+ null.getSymbol().text
347
+ for null in ctx_list
348
+ if isinstance(null, TerminalNodeImpl) and null.getSymbol().type == Parser.NULL_CONSTANT
349
+ ]
350
+
351
+ if isinstance(scalartype, Parser.BasicScalarTypeContext):
352
+ if scalartype.children[0].getSymbol().type == Parser.SCALAR:
353
+ return Scalar(name="", data_type=None, value=None)
354
+ type_node = self.visitBasicScalarType(scalartype)
355
+
356
+ else:
357
+ raise SyntaxError(
358
+ f"Invalid parameter type definition {scalartype.children[0]} at line "
359
+ f"{ctx.start.line}:{ctx.start.column}."
360
+ )
361
+
362
+ if len(scalartype_constraint) != 0:
363
+ # AST_ASTCONSTRUCTOR.45
364
+ raise NotImplementedError
365
+
366
+ if len(not_) != 0:
367
+ # AST_ASTCONSTRUCTOR.46
368
+ raise NotImplementedError
369
+
370
+ if len(null_constant) != 0:
371
+ # AST_ASTCONSTRUCTOR.47
372
+ raise NotImplementedError
373
+
374
+ return type_node
375
+
376
+ def visitDatasetType(self, ctx: Parser.DatasetTypeContext):
377
+ """
378
+ datasetType: DATASET ('{'compConstraint (',' compConstraint)* '}' )? ;
379
+ """
380
+ ctx_list = list(ctx.getChildren())
381
+
382
+ components = [
383
+ self.visitCompConstraint(constraint)
384
+ for constraint in ctx_list
385
+ if isinstance(constraint, Parser.CompConstraintContext)
386
+ ]
387
+ components = {component.name: component for component in components}
388
+
389
+ return Dataset(name="Dataset", components=components, data=None)
390
+
391
+ def visitRulesetType(self, ctx: Parser.RulesetTypeContext):
392
+ """
393
+ rulesetType: RULESET
394
+ | dpRuleset
395
+ | hrRuleset
396
+ ;
397
+ """
398
+ raise NotImplementedError
399
+
400
+ def visitDpRuleset(self, ctx: Parser.DpRulesetContext):
401
+ """
402
+ DATAPOINT # dataPoint
403
+ | DATAPOINT_ON_VD (GLPAREN valueDomainName (MUL valueDomainName)* GRPAREN )? # dataPointVd
404
+ | DATAPOINT_ON_VAR (GLPAREN varID (MUL varID)* GRPAREN )? # dataPointVar
405
+ ;
406
+ """ # noqa E501
407
+ # AST_ASTCONSTRUCTOR.54
408
+ raise NotImplementedError
409
+
410
+ def visitHrRuleset(self, ctx: Parser.HrRulesetContext):
411
+ """
412
+ hrRuleset: HIERARCHICAL # hrRulesetType
413
+ | HIERARCHICAL_ON_VD ( GLPAREN vdName=IDENTIFIER (LPAREN valueDomainName (MUL valueDomainName)* RPAREN)? GRPAREN )? # hrRulesetVdType
414
+ | HIERARCHICAL_ON_VAR ( GLPAREN varName=varID (LPAREN varID (MUL varID)* RPAREN)? GRPAREN )? # hrRulesetVarType
415
+ ;
416
+ """ # noqa E501
417
+ # AST_ASTCONSTRUCTOR.55
418
+ raise NotImplementedError
419
+
420
+ def visitComponentType(self, ctx: Parser.ComponentTypeContext):
421
+ """
422
+ componentType: componentRole ( LT scalarType MT )?
423
+ """
424
+ ctx_list = list(ctx.getChildren())
425
+
426
+ role_node = self.visitComponentRole(ctx_list[0])
427
+ data_type = [
428
+ self.visitScalarType(constraint)
429
+ for constraint in ctx_list
430
+ if isinstance(constraint, Parser.ScalarTypeContext)
431
+ ]
432
+ data_type = data_type[0] if len(data_type) > 0 else String()
433
+
434
+ nullable = role_node != Role.IDENTIFIER
435
+
436
+ return Component(name="Component", data_type=data_type, role=role_node, nullable=nullable)
437
+
438
+ def visitInputParameterType(self, ctx: Parser.InputParameterTypeContext):
439
+ """
440
+ inputParameterType:
441
+ scalarType
442
+ | datasetType
443
+ | scalarSetType
444
+ | rulesetType
445
+ | componentType
446
+ ;
447
+ """
448
+ ctx_list = list(ctx.getChildren())
449
+ c = ctx_list[0]
450
+
451
+ if isinstance(c, Parser.ScalarTypeContext):
452
+ return self.visitScalarType(c)
453
+
454
+ elif isinstance(c, Parser.DatasetTypeContext):
455
+ return self.visitDatasetType(c)
456
+
457
+ elif isinstance(c, Parser.ScalarSetTypeContext):
458
+ return self.visitScalarSetType(c)
459
+
460
+ elif isinstance(c, Parser.RulesetTypeContext):
461
+ return self.visitRulesetType(c)
462
+
463
+ elif isinstance(c, Parser.ComponentTypeContext):
464
+ return self.visitComponentType(c)
465
+ else:
466
+ raise NotImplementedError
467
+
468
+ def visitOutputParameterType(self, ctx: Parser.OutputParameterTypeContext):
469
+ """
470
+ outputParameterType: scalarType
471
+ | datasetType
472
+ | componentType
473
+ ;
474
+ """
475
+ ctx_list = list(ctx.getChildren())
476
+ c = ctx_list[0]
477
+
478
+ if isinstance(c, Parser.ScalarTypeContext):
479
+ # return self.visitScalarType(c).__class__.__name__
480
+ return "Scalar"
481
+
482
+ elif isinstance(c, Parser.DatasetTypeContext):
483
+ return "Dataset"
484
+
485
+ elif isinstance(c, Parser.ComponentTypeContext):
486
+ return "Component"
487
+ else:
488
+ raise NotImplementedError
489
+
490
+ def visitOutputParameterTypeComponent(self, ctx: Parser.OutputParameterTypeComponentContext):
491
+ """
492
+ outputParameterType: scalarType
493
+ | componentType
494
+ ;
495
+ """
496
+ ctx_list = list(ctx.getChildren())
497
+ c = ctx_list[0]
498
+
499
+ if isinstance(c, Parser.ScalarTypeContext):
500
+ return self.visitScalarType(c)
501
+
502
+ elif isinstance(c, Parser.ComponentTypeContext):
503
+ return self.visitComponentType(c)
504
+ else:
505
+ raise NotImplementedError
506
+
507
+ def visitScalarItem(self, ctx: Parser.ScalarItemContext):
508
+ ctx_list = list(ctx.getChildren())
509
+ c = ctx_list[0]
510
+
511
+ if isinstance(c, Parser.ConstantContext):
512
+ return self.visitConstant(c)
513
+ elif isinstance(c, Parser.ScalarWithCastContext):
514
+ return self.visitScalarWithCast(c)
515
+ else:
516
+ raise NotImplementedError
517
+
518
+ def visitScalarWithCast(self, ctx: Parser.ScalarWithCastContext):
519
+ """
520
+ | CAST LPAREN constant COMMA (basicScalarType) (COMMA STRING_CONSTANT)? RPAREN #scalarWithCast # noqa E501
521
+ """ # noqa E501
522
+ ctx_list = list(ctx.getChildren())
523
+ c = ctx_list[0]
524
+
525
+ token = c.getSymbol()
526
+
527
+ op = token.text
528
+ const_node = self.visitConstant(ctx_list[2])
529
+ basic_scalar_type = [self.visitBasicScalarType(ctx_list[4])]
530
+
531
+ param_node = (
532
+ [
533
+ ParamConstant(
534
+ type_="PARAM_CAST", value=ctx_list[6], **extract_token_info(ctx_list[6])
535
+ )
536
+ ]
537
+ if len(ctx_list) > 6
538
+ else []
539
+ )
540
+
541
+ if len(basic_scalar_type) == 1:
542
+ children_nodes = [const_node, basic_scalar_type[0]]
543
+
544
+ return ParamOp(
545
+ op=op, children=children_nodes, params=param_node, **extract_token_info(ctx)
546
+ )
547
+
548
+ else:
549
+ # AST_ASTCONSTRUCTOR.14
550
+ raise NotImplementedError
551
+
552
+ def visitScalarSetType(self, ctx: Parser.ScalarSetTypeContext):
553
+ """
554
+ scalarSetType: SET ('<' scalarType '>')? ;
555
+ """
556
+ # AST_ASTCONSTRUCTOR.60
557
+ raise NotImplementedError
558
+
559
+ def visitRetainType(self, ctx: Parser.RetainTypeContext):
560
+ """
561
+ retainType: BOOLEAN_CONSTANT
562
+ | ALL
563
+ ;
564
+ """
565
+ token = ctx.children[0].getSymbol()
566
+
567
+ if token.type == Parser.BOOLEAN_CONSTANT:
568
+ if token.text == "true":
569
+ param_constant_node = Constant(
570
+ type_="BOOLEAN_CONSTANT", value=True, **extract_token_info(token)
571
+ )
572
+ elif token.text == "false":
573
+ param_constant_node = Constant(
574
+ type_="BOOLEAN_CONSTANT", value=False, **extract_token_info(token)
575
+ )
576
+ else:
577
+ raise NotImplementedError
578
+
579
+ elif token.type == Parser.ALL:
580
+ param_constant_node = ParamConstant(
581
+ type_="PARAM_CONSTANT", value=token.text, **extract_token_info(token)
582
+ )
583
+
584
+ else:
585
+ raise NotImplementedError
586
+
587
+ return param_constant_node
588
+
589
+ def visitEvalDatasetType(self, ctx: Parser.EvalDatasetTypeContext):
590
+ ctx_list = list(ctx.getChildren())
591
+ c = ctx_list[0]
592
+
593
+ if isinstance(c, Parser.DatasetTypeContext):
594
+ return self.visitDatasetType(c)
595
+ elif isinstance(c, Parser.ScalarTypeContext):
596
+ return self.visitScalarType(c)
597
+ else:
598
+ raise NotImplementedError
599
+
600
+ def visitAlias(self, ctx: Parser.AliasContext):
601
+ return ctx.children[0].getSymbol().text
602
+
603
+ def visitSignedInteger(self, ctx: Parser.SignedIntegerContext):
604
+ return int(ctx.children[0].getSymbol().text)
605
+
606
+ def visitComparisonOperand(self, ctx: Parser.ComparisonOperandContext):
607
+ return ctx.children[0].getSymbol().text
608
+
609
+ def visitErCode(self, ctx: Parser.ErCodeContext):
610
+ """
611
+ erCode: ERRORCODE constant;
612
+ """
613
+ ctx_list = list(ctx.getChildren())
614
+
615
+ try:
616
+ return str(self.visitConstant(ctx_list[1]).value)
617
+ except Exception:
618
+ raise Exception(f"Error code must be a string, line {ctx_list[1].getSymbol().line}")
619
+
620
+ def visitErLevel(self, ctx: Parser.ErLevelContext):
621
+ """
622
+ erLevel: ERRORLEVEL constant;
623
+ """
624
+ ctx_list = list(ctx.getChildren())
625
+ return self.visitConstant(ctx_list[1]).value
626
+
627
+ def visitSignature(self, ctx: Parser.SignatureContext, kind="ComponentID"):
628
+ """
629
+ VarID (AS alias)?
630
+ """
631
+ token_info = extract_token_info(ctx)
632
+
633
+ ctx_list = list(ctx.getChildren())
634
+ c = ctx_list[0]
635
+
636
+ node_name = self.visitVarID(c).value
637
+
638
+ alias_name = None
639
+
640
+ if len(ctx_list) == 1:
641
+ return DPRIdentifier(value=node_name, kind=kind, alias=alias_name, **token_info)
642
+
643
+ alias_name = self.visitAlias(ctx_list[2])
644
+ return DPRIdentifier(value=node_name, kind=kind, alias=alias_name, **token_info)
645
+
646
+ """
647
+ From Hierarchical
648
+ """
649
+
650
+ def visitConditionClause(self, ctx: Parser.ConditionClauseContext):
651
+ ctx_list = list(ctx.getChildren())
652
+
653
+ components = [
654
+ self.visitComponentID(c) for c in ctx_list if isinstance(c, Parser.ComponentIDContext)
655
+ ]
656
+
657
+ return components
658
+
659
+ def visitValidationMode(self, ctx: Parser.ValidationModeContext):
660
+ return ctx.children[0].getSymbol().text
661
+
662
+ def visitValidationOutput(self, ctx: Parser.ValidationOutputContext):
663
+ return ctx.children[0].getSymbol().text
664
+
665
+ def visitInputMode(self, ctx: Parser.InputModeContext):
666
+ return ctx.children[0].getSymbol().text
667
+
668
+ def visitInputModeHierarchy(self, ctx: Parser.InputModeHierarchyContext):
669
+ return ctx.children[0].getSymbol().text
670
+
671
+ def visitOutputModeHierarchy(self, ctx: Parser.OutputModeHierarchyContext):
672
+ return ctx.children[0].getSymbol().text
673
+
674
+ """
675
+ From Analytic
676
+ """
677
+
678
+ def visitPartitionByClause(self, ctx: Parser.PartitionByClauseContext):
679
+ ctx_list = list(ctx.getChildren())
680
+
681
+ return [
682
+ self.visitComponentID(compID).value
683
+ for compID in ctx_list
684
+ if isinstance(compID, Parser.ComponentIDContext)
685
+ ]
686
+
687
+ def visitOrderByClause(self, ctx: Parser.OrderByClauseContext):
688
+ ctx_list = list(ctx.getChildren())
689
+
690
+ return [
691
+ self.visitOrderByItem(c) for c in ctx_list if isinstance(c, Parser.OrderByItemContext)
692
+ ]
693
+
694
+ def visitWindowingClause(self, ctx: Parser.WindowingClauseContext):
695
+ ctx_list = list(ctx.getChildren())
696
+
697
+ win_mode = ctx_list[0].getSymbol().text # Windowing mode (data points | range )
698
+
699
+ token_info = extract_token_info(ctx)
700
+
701
+ if win_mode == "data":
702
+ num_rows_1, mode_1 = self.visitLimitClauseItem(ctx_list[3])
703
+ num_rows_2, mode_2 = self.visitLimitClauseItem(ctx_list[5])
704
+ else:
705
+ num_rows_1, mode_1 = self.visitLimitClauseItem(ctx_list[2])
706
+ num_rows_2, mode_2 = self.visitLimitClauseItem(ctx_list[4])
707
+
708
+ first = num_rows_1 # unbounded (default value)
709
+ second = num_rows_2 # current data point (default value)
710
+
711
+ if (
712
+ mode_2 == "preceding"
713
+ and mode_1 == "preceding"
714
+ and num_rows_1 == -1
715
+ and num_rows_2 == -1
716
+ ): # preceding and preceding (error)
717
+ raise Exception(
718
+ f"Cannot have 2 preceding clauses with unbounded in analytic clause, "
719
+ f"line {ctx_list[3].start.line}"
720
+ )
721
+
722
+ if (
723
+ mode_1 == "following" and num_rows_1 == -1 and num_rows_2 == -1
724
+ ): # following and following (error)
725
+ raise Exception(
726
+ f"Cannot have 2 following clauses with unbounded in analytic clause, "
727
+ f"line {ctx_list[3].start.line}"
728
+ )
729
+
730
+ if mode_1 == mode_2:
731
+ if mode_1 == "preceding" and first != -1 and second > first: # 3 and 1: must be [-3:-1]
732
+ return create_windowing(win_mode, [second, first], [mode_2, mode_1], token_info)
733
+ if mode_1 == "preceding" and second == -1:
734
+ return create_windowing(win_mode, [second, first], [mode_2, mode_1], token_info)
735
+ if mode_1 == "following" and second != -1 and second < first: # 3 and 1: must be [1:3]
736
+ return create_windowing(win_mode, [second, first], [mode_2, mode_1], token_info)
737
+ if mode_1 == "following" and first == -1:
738
+ return create_windowing(win_mode, [second, first], [mode_2, mode_1], token_info)
739
+
740
+ return create_windowing(win_mode, [first, second], [mode_1, mode_2], token_info)
741
+
742
+ def visitOrderByItem(self, ctx: Parser.OrderByItemContext):
743
+ ctx_list = list(ctx.getChildren())
744
+
745
+ token_info = extract_token_info(ctx)
746
+
747
+ if len(ctx_list) == 1:
748
+ return OrderBy(
749
+ component=self.visitComponentID(ctx_list[0]).value, order="asc", **token_info
750
+ )
751
+
752
+ return OrderBy(
753
+ component=self.visitComponentID(ctx_list[0]).value,
754
+ order=ctx_list[1].getSymbol().text,
755
+ **token_info,
756
+ )
757
+
758
+ def visitLimitClauseItem(self, ctx: Parser.LimitClauseItemContext):
759
+ ctx_list = list(ctx.getChildren())
760
+ c = ctx_list[0]
761
+ if c.getSymbol().text.lower() == "unbounded":
762
+ result = -1
763
+ elif c.getSymbol().text == "current":
764
+ result = 0
765
+ return result, ctx_list[0].getSymbol().text
766
+ else:
767
+ result = int(c.getSymbol().text)
768
+ if result < 0:
769
+ raise Exception(
770
+ f"Cannot use negative numbers ({result}) on limitClause, line {c.symbol.line}"
771
+ )
772
+
773
+ return result, ctx_list[1].getSymbol().text
774
+
775
+
776
+ def create_windowing(win_mode, values, modes, token_info):
777
+ for e in range(0, 2):
778
+ if values[e] == -1:
779
+ values[e] = "unbounded"
780
+ elif values[e] == 0:
781
+ values[e] = "current row"
782
+
783
+ return Windowing(
784
+ type_=win_mode,
785
+ start=values[0],
786
+ stop=values[1],
787
+ start_mode=modes[0],
788
+ stop_mode=modes[1],
789
+ **token_info,
790
+ )