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.
- vtlengine/API/_InternalApi.py +791 -0
- vtlengine/API/__init__.py +612 -0
- vtlengine/API/data/schema/external_routines_schema.json +34 -0
- vtlengine/API/data/schema/json_schema_2.1.json +116 -0
- vtlengine/API/data/schema/value_domain_schema.json +97 -0
- vtlengine/AST/ASTComment.py +57 -0
- vtlengine/AST/ASTConstructor.py +598 -0
- vtlengine/AST/ASTConstructorModules/Expr.py +1928 -0
- vtlengine/AST/ASTConstructorModules/ExprComponents.py +995 -0
- vtlengine/AST/ASTConstructorModules/Terminals.py +790 -0
- vtlengine/AST/ASTConstructorModules/__init__.py +50 -0
- vtlengine/AST/ASTDataExchange.py +10 -0
- vtlengine/AST/ASTEncoders.py +32 -0
- vtlengine/AST/ASTString.py +675 -0
- vtlengine/AST/ASTTemplate.py +558 -0
- vtlengine/AST/ASTVisitor.py +25 -0
- vtlengine/AST/DAG/__init__.py +479 -0
- vtlengine/AST/DAG/_words.py +10 -0
- vtlengine/AST/Grammar/Vtl.g4 +705 -0
- vtlengine/AST/Grammar/VtlTokens.g4 +409 -0
- vtlengine/AST/Grammar/__init__.py +0 -0
- vtlengine/AST/Grammar/lexer.py +2139 -0
- vtlengine/AST/Grammar/parser.py +16597 -0
- vtlengine/AST/Grammar/tokens.py +169 -0
- vtlengine/AST/VtlVisitor.py +824 -0
- vtlengine/AST/__init__.py +674 -0
- vtlengine/DataTypes/TimeHandling.py +562 -0
- vtlengine/DataTypes/__init__.py +863 -0
- vtlengine/DataTypes/_time_checking.py +135 -0
- vtlengine/Exceptions/__exception_file_generator.py +96 -0
- vtlengine/Exceptions/__init__.py +159 -0
- vtlengine/Exceptions/messages.py +1004 -0
- vtlengine/Interpreter/__init__.py +2048 -0
- vtlengine/Model/__init__.py +501 -0
- vtlengine/Operators/Aggregation.py +357 -0
- vtlengine/Operators/Analytic.py +455 -0
- vtlengine/Operators/Assignment.py +23 -0
- vtlengine/Operators/Boolean.py +106 -0
- vtlengine/Operators/CastOperator.py +451 -0
- vtlengine/Operators/Clause.py +366 -0
- vtlengine/Operators/Comparison.py +488 -0
- vtlengine/Operators/Conditional.py +495 -0
- vtlengine/Operators/General.py +191 -0
- vtlengine/Operators/HROperators.py +254 -0
- vtlengine/Operators/Join.py +447 -0
- vtlengine/Operators/Numeric.py +422 -0
- vtlengine/Operators/RoleSetter.py +77 -0
- vtlengine/Operators/Set.py +176 -0
- vtlengine/Operators/String.py +578 -0
- vtlengine/Operators/Time.py +1144 -0
- vtlengine/Operators/Validation.py +275 -0
- vtlengine/Operators/__init__.py +900 -0
- vtlengine/Utils/__Virtual_Assets.py +34 -0
- vtlengine/Utils/__init__.py +479 -0
- vtlengine/__extras_check.py +17 -0
- vtlengine/__init__.py +27 -0
- vtlengine/files/__init__.py +0 -0
- vtlengine/files/output/__init__.py +35 -0
- vtlengine/files/output/_time_period_representation.py +55 -0
- vtlengine/files/parser/__init__.py +240 -0
- vtlengine/files/parser/_rfc_dialect.py +22 -0
- vtlengine/py.typed +0 -0
- vtlengine-1.4.0rc2.dist-info/METADATA +89 -0
- vtlengine-1.4.0rc2.dist-info/RECORD +66 -0
- vtlengine-1.4.0rc2.dist-info/WHEEL +4 -0
- 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
|
+
)
|