vtlengine 1.0.3rc3__py3-none-any.whl → 1.1__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 +288 -61
- vtlengine/API/__init__.py +269 -71
- vtlengine/API/data/schema/json_schema_2.1.json +116 -0
- vtlengine/AST/ASTComment.py +56 -0
- vtlengine/AST/ASTConstructor.py +76 -22
- vtlengine/AST/ASTConstructorModules/Expr.py +238 -120
- vtlengine/AST/ASTConstructorModules/ExprComponents.py +126 -61
- vtlengine/AST/ASTConstructorModules/Terminals.py +97 -42
- vtlengine/AST/ASTConstructorModules/__init__.py +50 -0
- vtlengine/AST/ASTEncoders.py +5 -1
- vtlengine/AST/ASTString.py +608 -0
- vtlengine/AST/ASTTemplate.py +28 -2
- vtlengine/AST/DAG/__init__.py +10 -4
- vtlengine/AST/Grammar/lexer.py +0 -1
- vtlengine/AST/Grammar/parser.py +185 -440
- vtlengine/AST/VtlVisitor.py +0 -1
- vtlengine/AST/__init__.py +127 -14
- vtlengine/DataTypes/TimeHandling.py +50 -15
- vtlengine/DataTypes/__init__.py +79 -7
- vtlengine/Exceptions/__init__.py +3 -5
- vtlengine/Exceptions/messages.py +74 -105
- vtlengine/Interpreter/__init__.py +136 -46
- vtlengine/Model/__init__.py +14 -11
- vtlengine/Operators/Aggregation.py +17 -9
- vtlengine/Operators/Analytic.py +64 -20
- vtlengine/Operators/Assignment.py +0 -1
- vtlengine/Operators/CastOperator.py +44 -44
- vtlengine/Operators/Clause.py +16 -10
- vtlengine/Operators/Comparison.py +20 -12
- vtlengine/Operators/Conditional.py +47 -15
- vtlengine/Operators/General.py +9 -4
- vtlengine/Operators/HROperators.py +4 -14
- vtlengine/Operators/Join.py +15 -14
- vtlengine/Operators/Numeric.py +32 -26
- vtlengine/Operators/RoleSetter.py +6 -2
- vtlengine/Operators/Set.py +12 -8
- vtlengine/Operators/String.py +9 -9
- vtlengine/Operators/Time.py +145 -124
- vtlengine/Operators/Validation.py +10 -4
- vtlengine/Operators/__init__.py +56 -69
- vtlengine/Utils/__init__.py +55 -1
- vtlengine/__extras_check.py +17 -0
- vtlengine/__init__.py +2 -2
- vtlengine/files/output/__init__.py +2 -1
- vtlengine/files/output/_time_period_representation.py +2 -1
- vtlengine/files/parser/__init__.py +52 -46
- vtlengine/files/parser/_time_checking.py +4 -4
- {vtlengine-1.0.3rc3.dist-info → vtlengine-1.1.dist-info}/METADATA +21 -17
- vtlengine-1.1.dist-info/RECORD +61 -0
- {vtlengine-1.0.3rc3.dist-info → vtlengine-1.1.dist-info}/WHEEL +1 -1
- vtlengine/DataTypes/NumericTypesHandling.py +0 -38
- vtlengine-1.0.3rc3.dist-info/RECORD +0 -58
- {vtlengine-1.0.3rc3.dist-info → vtlengine-1.1.dist-info}/LICENSE.md +0 -0
|
@@ -12,6 +12,7 @@ from vtlengine.AST import (
|
|
|
12
12
|
VarID,
|
|
13
13
|
Windowing,
|
|
14
14
|
)
|
|
15
|
+
from vtlengine.AST.ASTConstructorModules import extract_token_info
|
|
15
16
|
from vtlengine.AST.Grammar.parser import Parser
|
|
16
17
|
from vtlengine.AST.VtlVisitor import VtlVisitor
|
|
17
18
|
from vtlengine.DataTypes import (
|
|
@@ -37,26 +38,27 @@ def _remove_scaped_characters(text):
|
|
|
37
38
|
class Terminals(VtlVisitor):
|
|
38
39
|
def visitConstant(self, ctx: Parser.ConstantContext):
|
|
39
40
|
token = ctx.children[0].getSymbol()
|
|
41
|
+
token_info = extract_token_info(token)
|
|
40
42
|
|
|
41
43
|
if token.type == Parser.INTEGER_CONSTANT:
|
|
42
|
-
constant_node = Constant("INTEGER_CONSTANT", int(token.text))
|
|
44
|
+
constant_node = Constant(type_="INTEGER_CONSTANT", value=int(token.text), **token_info)
|
|
43
45
|
|
|
44
46
|
elif token.type == Parser.NUMBER_CONSTANT:
|
|
45
|
-
constant_node = Constant("FLOAT_CONSTANT", float(token.text))
|
|
47
|
+
constant_node = Constant(type_="FLOAT_CONSTANT", value=float(token.text), **token_info)
|
|
46
48
|
|
|
47
49
|
elif token.type == Parser.BOOLEAN_CONSTANT:
|
|
48
50
|
if token.text == "true":
|
|
49
|
-
constant_node = Constant("BOOLEAN_CONSTANT", True)
|
|
51
|
+
constant_node = Constant(type_="BOOLEAN_CONSTANT", value=True, **token_info)
|
|
50
52
|
elif token.text == "false":
|
|
51
|
-
constant_node = Constant("BOOLEAN_CONSTANT", False)
|
|
53
|
+
constant_node = Constant(type_="BOOLEAN_CONSTANT", value=False, **token_info)
|
|
52
54
|
else:
|
|
53
55
|
raise NotImplementedError
|
|
54
56
|
|
|
55
57
|
elif token.type == Parser.STRING_CONSTANT:
|
|
56
|
-
constant_node = Constant("STRING_CONSTANT", token.text[1:-1])
|
|
58
|
+
constant_node = Constant(type_="STRING_CONSTANT", value=token.text[1:-1], **token_info)
|
|
57
59
|
|
|
58
60
|
elif token.type == Parser.NULL_CONSTANT:
|
|
59
|
-
constant_node = Constant("NULL_CONSTANT", None)
|
|
61
|
+
constant_node = Constant(type_="NULL_CONSTANT", value=None, **token_info)
|
|
60
62
|
|
|
61
63
|
else:
|
|
62
64
|
raise NotImplementedError
|
|
@@ -66,18 +68,19 @@ class Terminals(VtlVisitor):
|
|
|
66
68
|
def visitVarID(self, ctx: Parser.VarIDContext):
|
|
67
69
|
token = ctx.children[0].getSymbol()
|
|
68
70
|
token.text = _remove_scaped_characters(token.text)
|
|
69
|
-
|
|
71
|
+
token_info = extract_token_info(token)
|
|
72
|
+
var_id_node = VarID(value=token.text, **token_info)
|
|
70
73
|
return var_id_node
|
|
71
74
|
|
|
72
75
|
def visitVarIdExpr(self, ctx: Parser.VarIdExprContext):
|
|
73
|
-
|
|
74
76
|
if isinstance(ctx.children[0], Parser.VarIDContext):
|
|
75
77
|
return self.visitVarID(ctx.children[0])
|
|
76
78
|
|
|
77
79
|
token = ctx.children[0].getSymbol()
|
|
78
80
|
# check token text
|
|
79
81
|
token.text = _remove_scaped_characters(token.text)
|
|
80
|
-
|
|
82
|
+
token_info = extract_token_info(token)
|
|
83
|
+
var_id_node = VarID(value=token.text, **token_info)
|
|
81
84
|
return var_id_node
|
|
82
85
|
|
|
83
86
|
def visitSimpleComponentId(self, ctx: Parser.SimpleComponentIdContext):
|
|
@@ -88,7 +91,7 @@ class Terminals(VtlVisitor):
|
|
|
88
91
|
# check token text
|
|
89
92
|
token.text = _remove_scaped_characters(token.text)
|
|
90
93
|
|
|
91
|
-
return Identifier(token.text, "ComponentID")
|
|
94
|
+
return Identifier(value=token.text, kind="ComponentID", **extract_token_info(ctx))
|
|
92
95
|
|
|
93
96
|
def visitComponentID(self, ctx: Parser.ComponentIDContext):
|
|
94
97
|
ctx_list = list(ctx.getChildren())
|
|
@@ -99,7 +102,11 @@ class Terminals(VtlVisitor):
|
|
|
99
102
|
"'"
|
|
100
103
|
): # The component could be imbalance, errorcode or errorlevel
|
|
101
104
|
component_name = component_name[1:-1]
|
|
102
|
-
return Identifier(
|
|
105
|
+
return Identifier(
|
|
106
|
+
value=component_name,
|
|
107
|
+
kind="ComponentID",
|
|
108
|
+
**extract_token_info(ctx_list[0].getSymbol()),
|
|
109
|
+
)
|
|
103
110
|
else:
|
|
104
111
|
component_name = ctx_list[2].getSymbol().text
|
|
105
112
|
if component_name.startswith("'") and component_name.endswith(
|
|
@@ -108,9 +115,18 @@ class Terminals(VtlVisitor):
|
|
|
108
115
|
component_name = component_name[1:-1]
|
|
109
116
|
op_node = ctx_list[1].getSymbol().text
|
|
110
117
|
return BinOp(
|
|
111
|
-
left=Identifier(
|
|
118
|
+
left=Identifier(
|
|
119
|
+
value=ctx_list[0].getSymbol().text,
|
|
120
|
+
kind="DatasetID",
|
|
121
|
+
**extract_token_info(ctx_list[0].getSymbol()),
|
|
122
|
+
),
|
|
112
123
|
op=op_node,
|
|
113
|
-
right=Identifier(
|
|
124
|
+
right=Identifier(
|
|
125
|
+
value=component_name,
|
|
126
|
+
kind="ComponentID",
|
|
127
|
+
**extract_token_info(ctx_list[1].getSymbol()),
|
|
128
|
+
),
|
|
129
|
+
**extract_token_info(ctx),
|
|
114
130
|
)
|
|
115
131
|
|
|
116
132
|
def visitOperatorID(self, ctx: Parser.OperatorIDContext):
|
|
@@ -127,7 +143,11 @@ class Terminals(VtlVisitor):
|
|
|
127
143
|
valueDomainID: IDENTIFIER ;
|
|
128
144
|
"""
|
|
129
145
|
return Collection(
|
|
130
|
-
name=ctx.children[0].getSymbol().text,
|
|
146
|
+
name=ctx.children[0].getSymbol().text,
|
|
147
|
+
children=[],
|
|
148
|
+
kind="ValueDomain",
|
|
149
|
+
type="",
|
|
150
|
+
**extract_token_info(ctx),
|
|
131
151
|
)
|
|
132
152
|
|
|
133
153
|
def visitRulesetID(self, ctx: Parser.RulesetIDContext):
|
|
@@ -252,7 +272,9 @@ class Terminals(VtlVisitor):
|
|
|
252
272
|
for scalar_with_cast in scalars_with_cast:
|
|
253
273
|
scalar_nodes.append(self.visitScalarWithCast(scalar_with_cast))
|
|
254
274
|
|
|
255
|
-
return Collection(
|
|
275
|
+
return Collection(
|
|
276
|
+
name="List", type="Lists", children=scalar_nodes, **extract_token_info(ctx)
|
|
277
|
+
)
|
|
256
278
|
|
|
257
279
|
def visitMultModifier(self, ctx: Parser.MultModifierContext):
|
|
258
280
|
"""
|
|
@@ -381,7 +403,7 @@ class Terminals(VtlVisitor):
|
|
|
381
403
|
| DATAPOINT_ON_VD (GLPAREN valueDomainName (MUL valueDomainName)* GRPAREN )? # dataPointVd
|
|
382
404
|
| DATAPOINT_ON_VAR (GLPAREN varID (MUL varID)* GRPAREN )? # dataPointVar
|
|
383
405
|
;
|
|
384
|
-
"""
|
|
406
|
+
""" # noqa E501
|
|
385
407
|
# AST_ASTCONSTRUCTOR.54
|
|
386
408
|
raise NotImplementedError
|
|
387
409
|
|
|
@@ -391,7 +413,7 @@ class Terminals(VtlVisitor):
|
|
|
391
413
|
| HIERARCHICAL_ON_VD ( GLPAREN vdName=IDENTIFIER (LPAREN valueDomainName (MUL valueDomainName)* RPAREN)? GRPAREN )? # hrRulesetVdType
|
|
392
414
|
| HIERARCHICAL_ON_VAR ( GLPAREN varName=varID (LPAREN varID (MUL varID)* RPAREN)? GRPAREN )? # hrRulesetVarType
|
|
393
415
|
;
|
|
394
|
-
"""
|
|
416
|
+
""" # noqa E501
|
|
395
417
|
# AST_ASTCONSTRUCTOR.55
|
|
396
418
|
raise NotImplementedError
|
|
397
419
|
|
|
@@ -483,7 +505,6 @@ class Terminals(VtlVisitor):
|
|
|
483
505
|
raise NotImplementedError
|
|
484
506
|
|
|
485
507
|
def visitScalarItem(self, ctx: Parser.ScalarItemContext):
|
|
486
|
-
|
|
487
508
|
ctx_list = list(ctx.getChildren())
|
|
488
509
|
c = ctx_list[0]
|
|
489
510
|
|
|
@@ -497,7 +518,7 @@ class Terminals(VtlVisitor):
|
|
|
497
518
|
def visitScalarWithCast(self, ctx: Parser.ScalarWithCastContext):
|
|
498
519
|
"""
|
|
499
520
|
| CAST LPAREN constant COMMA (basicScalarType) (COMMA STRING_CONSTANT)? RPAREN #scalarWithCast # noqa E501
|
|
500
|
-
"""
|
|
521
|
+
""" # noqa E501
|
|
501
522
|
ctx_list = list(ctx.getChildren())
|
|
502
523
|
c = ctx_list[0]
|
|
503
524
|
|
|
@@ -507,12 +528,22 @@ class Terminals(VtlVisitor):
|
|
|
507
528
|
const_node = self.visitConstant(ctx_list[2])
|
|
508
529
|
basic_scalar_type = [self.visitBasicScalarType(ctx_list[4])]
|
|
509
530
|
|
|
510
|
-
param_node =
|
|
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
|
+
)
|
|
511
540
|
|
|
512
541
|
if len(basic_scalar_type) == 1:
|
|
513
542
|
children_nodes = [const_node, basic_scalar_type[0]]
|
|
514
543
|
|
|
515
|
-
return ParamOp(
|
|
544
|
+
return ParamOp(
|
|
545
|
+
op=op, children=children_nodes, params=param_node, **extract_token_info(ctx)
|
|
546
|
+
)
|
|
516
547
|
|
|
517
548
|
else:
|
|
518
549
|
# AST_ASTCONSTRUCTOR.14
|
|
@@ -535,14 +566,20 @@ class Terminals(VtlVisitor):
|
|
|
535
566
|
|
|
536
567
|
if token.type == Parser.BOOLEAN_CONSTANT:
|
|
537
568
|
if token.text == "true":
|
|
538
|
-
param_constant_node = Constant(
|
|
569
|
+
param_constant_node = Constant(
|
|
570
|
+
type_="BOOLEAN_CONSTANT", value=True, **extract_token_info(token)
|
|
571
|
+
)
|
|
539
572
|
elif token.text == "false":
|
|
540
|
-
param_constant_node = Constant(
|
|
573
|
+
param_constant_node = Constant(
|
|
574
|
+
type_="BOOLEAN_CONSTANT", value=False, **extract_token_info(token)
|
|
575
|
+
)
|
|
541
576
|
else:
|
|
542
577
|
raise NotImplementedError
|
|
543
578
|
|
|
544
579
|
elif token.type == Parser.ALL:
|
|
545
|
-
param_constant_node = ParamConstant(
|
|
580
|
+
param_constant_node = ParamConstant(
|
|
581
|
+
type_="PARAM_CONSTANT", value=token.text, **extract_token_info(token)
|
|
582
|
+
)
|
|
546
583
|
|
|
547
584
|
else:
|
|
548
585
|
raise NotImplementedError
|
|
@@ -564,7 +601,7 @@ class Terminals(VtlVisitor):
|
|
|
564
601
|
return ctx.children[0].getSymbol().text
|
|
565
602
|
|
|
566
603
|
def visitSignedInteger(self, ctx: Parser.SignedIntegerContext):
|
|
567
|
-
return ctx.children[0].getSymbol().text
|
|
604
|
+
return int(ctx.children[0].getSymbol().text)
|
|
568
605
|
|
|
569
606
|
def visitComparisonOperand(self, ctx: Parser.ComparisonOperandContext):
|
|
570
607
|
return ctx.children[0].getSymbol().text
|
|
@@ -593,8 +630,9 @@ class Terminals(VtlVisitor):
|
|
|
593
630
|
|
|
594
631
|
def visitSignature(self, ctx: Parser.SignatureContext, kind="ComponentID"):
|
|
595
632
|
"""
|
|
596
|
-
|
|
633
|
+
VarID (AS alias)?
|
|
597
634
|
"""
|
|
635
|
+
token_info = extract_token_info(ctx)
|
|
598
636
|
|
|
599
637
|
ctx_list = list(ctx.getChildren())
|
|
600
638
|
c = ctx_list[0]
|
|
@@ -604,10 +642,10 @@ class Terminals(VtlVisitor):
|
|
|
604
642
|
alias_name = None
|
|
605
643
|
|
|
606
644
|
if len(ctx_list) == 1:
|
|
607
|
-
return DPRIdentifier(value=node_name, kind=kind, alias=alias_name)
|
|
645
|
+
return DPRIdentifier(value=node_name, kind=kind, alias=alias_name, **token_info)
|
|
608
646
|
|
|
609
647
|
alias_name = self.visitAlias(ctx_list[2])
|
|
610
|
-
return DPRIdentifier(value=node_name, kind=kind, alias=alias_name)
|
|
648
|
+
return DPRIdentifier(value=node_name, kind=kind, alias=alias_name, **token_info)
|
|
611
649
|
|
|
612
650
|
"""
|
|
613
651
|
From Hierarchical
|
|
@@ -662,6 +700,8 @@ class Terminals(VtlVisitor):
|
|
|
662
700
|
|
|
663
701
|
win_mode = ctx_list[0].getSymbol().text # Windowing mode (data points | range )
|
|
664
702
|
|
|
703
|
+
token_info = extract_token_info(ctx)
|
|
704
|
+
|
|
665
705
|
if win_mode == "data":
|
|
666
706
|
num_rows_1, mode_1 = self.visitLimitClauseItem(ctx_list[3])
|
|
667
707
|
num_rows_2, mode_2 = self.visitLimitClauseItem(ctx_list[5])
|
|
@@ -672,8 +712,12 @@ class Terminals(VtlVisitor):
|
|
|
672
712
|
first = num_rows_1 # unbounded (default value)
|
|
673
713
|
second = num_rows_2 # current data point (default value)
|
|
674
714
|
|
|
675
|
-
if (
|
|
676
|
-
|
|
715
|
+
if (
|
|
716
|
+
mode_2 == "preceding"
|
|
717
|
+
and mode_1 == "preceding"
|
|
718
|
+
and num_rows_1 == -1
|
|
719
|
+
and num_rows_2 == -1
|
|
720
|
+
): # preceding and preceding (error)
|
|
677
721
|
raise Exception(
|
|
678
722
|
f"Cannot have 2 preceding clauses with unbounded in analytic clause, "
|
|
679
723
|
f"line {ctx_list[3].start.line}"
|
|
@@ -689,30 +733,36 @@ class Terminals(VtlVisitor):
|
|
|
689
733
|
|
|
690
734
|
if mode_1 == mode_2:
|
|
691
735
|
if mode_1 == "preceding" and first != -1 and second > first: # 3 and 1: must be [-3:-1]
|
|
692
|
-
return create_windowing(win_mode, [second, first], [mode_2, mode_1])
|
|
736
|
+
return create_windowing(win_mode, [second, first], [mode_2, mode_1], token_info)
|
|
693
737
|
if mode_1 == "preceding" and second == -1:
|
|
694
|
-
return create_windowing(win_mode, [second, first], [mode_2, mode_1])
|
|
738
|
+
return create_windowing(win_mode, [second, first], [mode_2, mode_1], token_info)
|
|
695
739
|
if mode_1 == "following" and second != -1 and second < first: # 3 and 1: must be [1:3]
|
|
696
|
-
return create_windowing(win_mode, [second, first], [mode_2, mode_1])
|
|
740
|
+
return create_windowing(win_mode, [second, first], [mode_2, mode_1], token_info)
|
|
697
741
|
if mode_1 == "following" and first == -1:
|
|
698
|
-
return create_windowing(win_mode, [second, first], [mode_2, mode_1])
|
|
742
|
+
return create_windowing(win_mode, [second, first], [mode_2, mode_1], token_info)
|
|
699
743
|
|
|
700
|
-
return create_windowing(win_mode, [first, second], [mode_1, mode_2])
|
|
744
|
+
return create_windowing(win_mode, [first, second], [mode_1, mode_2], token_info)
|
|
701
745
|
|
|
702
746
|
def visitOrderByItem(self, ctx: Parser.OrderByItemContext):
|
|
703
747
|
ctx_list = list(ctx.getChildren())
|
|
704
748
|
|
|
749
|
+
token_info = extract_token_info(ctx)
|
|
750
|
+
|
|
705
751
|
if len(ctx_list) == 1:
|
|
706
|
-
return OrderBy(
|
|
752
|
+
return OrderBy(
|
|
753
|
+
component=self.visitComponentID(ctx_list[0]).value, order="asc", **token_info
|
|
754
|
+
)
|
|
707
755
|
|
|
708
756
|
return OrderBy(
|
|
709
|
-
component=self.visitComponentID(ctx_list[0]).value,
|
|
757
|
+
component=self.visitComponentID(ctx_list[0]).value,
|
|
758
|
+
order=ctx_list[1].getSymbol().text,
|
|
759
|
+
**token_info,
|
|
710
760
|
)
|
|
711
761
|
|
|
712
762
|
def visitLimitClauseItem(self, ctx: Parser.LimitClauseItemContext):
|
|
713
763
|
ctx_list = list(ctx.getChildren())
|
|
714
764
|
c = ctx_list[0]
|
|
715
|
-
if c.getSymbol().text == "unbounded":
|
|
765
|
+
if c.getSymbol().text.lower() == "unbounded":
|
|
716
766
|
result = -1
|
|
717
767
|
elif c.getSymbol().text == "current":
|
|
718
768
|
result = 0
|
|
@@ -727,13 +777,18 @@ class Terminals(VtlVisitor):
|
|
|
727
777
|
return result, ctx_list[1].getSymbol().text
|
|
728
778
|
|
|
729
779
|
|
|
730
|
-
def create_windowing(win_mode, values, modes):
|
|
780
|
+
def create_windowing(win_mode, values, modes, token_info):
|
|
731
781
|
for e in range(0, 2):
|
|
732
782
|
if values[e] == -1:
|
|
733
|
-
values[e] = "
|
|
783
|
+
values[e] = "unbounded"
|
|
734
784
|
elif values[e] == 0:
|
|
735
|
-
values[e] = "
|
|
785
|
+
values[e] = "current row"
|
|
736
786
|
|
|
737
787
|
return Windowing(
|
|
738
|
-
type_=win_mode,
|
|
788
|
+
type_=win_mode,
|
|
789
|
+
start=values[0],
|
|
790
|
+
stop=values[1],
|
|
791
|
+
start_mode=modes[0],
|
|
792
|
+
stop_mode=modes[1],
|
|
793
|
+
**token_info,
|
|
739
794
|
)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from typing import Dict, Union
|
|
2
|
+
|
|
3
|
+
from antlr4.ParserRuleContext import ParserRuleContext
|
|
4
|
+
from antlr4.Token import CommonToken
|
|
5
|
+
|
|
6
|
+
from vtlengine.AST.Grammar.lexer import Lexer
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def extract_token_info(token: Union[CommonToken, ParserRuleContext]) -> Dict[str, int]:
|
|
10
|
+
"""
|
|
11
|
+
Extracts the token information from a token or ParserRuleContext.
|
|
12
|
+
|
|
13
|
+
The Token information includes:
|
|
14
|
+
- column_start: The starting column of the token.
|
|
15
|
+
- column_stop: The stopping column of the token.
|
|
16
|
+
- line_start: The starting line number of the token.
|
|
17
|
+
- line_stop: The stopping line number of the token.
|
|
18
|
+
|
|
19
|
+
The overall idea is to provide the information from which line and column,
|
|
20
|
+
and to which line and column, the text is referenced by the AST object, including children.
|
|
21
|
+
|
|
22
|
+
Important Note: the keys of the dict are the same as the class attributes of the AST Object.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
token (Union[CommonToken, ParserRuleContext]): The token or ParserRuleContext to extract
|
|
26
|
+
information from.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
Dict[str, int]: A dictionary containing the token information.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
if isinstance(token, ParserRuleContext):
|
|
33
|
+
return {
|
|
34
|
+
"column_start": token.start.column,
|
|
35
|
+
"column_stop": token.stop.column + len(token.stop.text),
|
|
36
|
+
"line_start": token.start.line,
|
|
37
|
+
"line_stop": token.stop.line,
|
|
38
|
+
}
|
|
39
|
+
line_start = token.line
|
|
40
|
+
line_stop = token.line
|
|
41
|
+
# For block comments, we need to add the lines inside the block, marked by \n, to the stop line.
|
|
42
|
+
# The ML_COMMENT does not take into account the final \n in its grammar.
|
|
43
|
+
if token.type == Lexer.ML_COMMENT:
|
|
44
|
+
line_stop = token.line + token.text.count("\n")
|
|
45
|
+
return {
|
|
46
|
+
"column_start": token.column,
|
|
47
|
+
"column_stop": token.column + len(token.text),
|
|
48
|
+
"line_start": line_start,
|
|
49
|
+
"line_stop": line_stop,
|
|
50
|
+
}
|
vtlengine/AST/ASTEncoders.py
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import json
|
|
2
2
|
|
|
3
|
-
import AST
|
|
3
|
+
from vtlengine import AST
|
|
4
|
+
from vtlengine.Model import Dataset
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class ComplexEncoder(json.JSONEncoder):
|
|
7
8
|
def default(self, obj):
|
|
8
9
|
if hasattr(obj, "toJSON"):
|
|
9
10
|
return obj.toJSON()
|
|
11
|
+
# Makes a circular reference error if we do not check for this
|
|
12
|
+
elif isinstance(obj, Dataset):
|
|
13
|
+
return "dataset"
|
|
10
14
|
else:
|
|
11
15
|
return json.__dict__
|
|
12
16
|
|