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.

Files changed (53) hide show
  1. vtlengine/API/_InternalApi.py +288 -61
  2. vtlengine/API/__init__.py +269 -71
  3. vtlengine/API/data/schema/json_schema_2.1.json +116 -0
  4. vtlengine/AST/ASTComment.py +56 -0
  5. vtlengine/AST/ASTConstructor.py +76 -22
  6. vtlengine/AST/ASTConstructorModules/Expr.py +238 -120
  7. vtlengine/AST/ASTConstructorModules/ExprComponents.py +126 -61
  8. vtlengine/AST/ASTConstructorModules/Terminals.py +97 -42
  9. vtlengine/AST/ASTConstructorModules/__init__.py +50 -0
  10. vtlengine/AST/ASTEncoders.py +5 -1
  11. vtlengine/AST/ASTString.py +608 -0
  12. vtlengine/AST/ASTTemplate.py +28 -2
  13. vtlengine/AST/DAG/__init__.py +10 -4
  14. vtlengine/AST/Grammar/lexer.py +0 -1
  15. vtlengine/AST/Grammar/parser.py +185 -440
  16. vtlengine/AST/VtlVisitor.py +0 -1
  17. vtlengine/AST/__init__.py +127 -14
  18. vtlengine/DataTypes/TimeHandling.py +50 -15
  19. vtlengine/DataTypes/__init__.py +79 -7
  20. vtlengine/Exceptions/__init__.py +3 -5
  21. vtlengine/Exceptions/messages.py +74 -105
  22. vtlengine/Interpreter/__init__.py +136 -46
  23. vtlengine/Model/__init__.py +14 -11
  24. vtlengine/Operators/Aggregation.py +17 -9
  25. vtlengine/Operators/Analytic.py +64 -20
  26. vtlengine/Operators/Assignment.py +0 -1
  27. vtlengine/Operators/CastOperator.py +44 -44
  28. vtlengine/Operators/Clause.py +16 -10
  29. vtlengine/Operators/Comparison.py +20 -12
  30. vtlengine/Operators/Conditional.py +47 -15
  31. vtlengine/Operators/General.py +9 -4
  32. vtlengine/Operators/HROperators.py +4 -14
  33. vtlengine/Operators/Join.py +15 -14
  34. vtlengine/Operators/Numeric.py +32 -26
  35. vtlengine/Operators/RoleSetter.py +6 -2
  36. vtlengine/Operators/Set.py +12 -8
  37. vtlengine/Operators/String.py +9 -9
  38. vtlengine/Operators/Time.py +145 -124
  39. vtlengine/Operators/Validation.py +10 -4
  40. vtlengine/Operators/__init__.py +56 -69
  41. vtlengine/Utils/__init__.py +55 -1
  42. vtlengine/__extras_check.py +17 -0
  43. vtlengine/__init__.py +2 -2
  44. vtlengine/files/output/__init__.py +2 -1
  45. vtlengine/files/output/_time_period_representation.py +2 -1
  46. vtlengine/files/parser/__init__.py +52 -46
  47. vtlengine/files/parser/_time_checking.py +4 -4
  48. {vtlengine-1.0.3rc3.dist-info → vtlengine-1.1.dist-info}/METADATA +21 -17
  49. vtlengine-1.1.dist-info/RECORD +61 -0
  50. {vtlengine-1.0.3rc3.dist-info → vtlengine-1.1.dist-info}/WHEEL +1 -1
  51. vtlengine/DataTypes/NumericTypesHandling.py +0 -38
  52. vtlengine-1.0.3rc3.dist-info/RECORD +0 -58
  53. {vtlengine-1.0.3rc3.dist-info → vtlengine-1.1.dist-info}/LICENSE.md +0 -0
@@ -20,6 +20,7 @@ from vtlengine.AST import (
20
20
  MulOp,
21
21
  ParamConstant,
22
22
  ParamOp,
23
+ ParFunction,
23
24
  RegularAggregation,
24
25
  RenameNode,
25
26
  TimeAggregation,
@@ -29,6 +30,7 @@ from vtlengine.AST import (
29
30
  VarID,
30
31
  Windowing,
31
32
  )
33
+ from vtlengine.AST.ASTConstructorModules import extract_token_info
32
34
  from vtlengine.AST.ASTConstructorModules.ExprComponents import ExprComp
33
35
  from vtlengine.AST.ASTConstructorModules.Terminals import Terminals
34
36
  from vtlengine.AST.ASTDataExchange import de_ruleset_elements
@@ -45,7 +47,8 @@ class Expr(VtlVisitor):
45
47
 
46
48
  Expr Definition.
47
49
 
48
- _______________________________________________________________________________________"""
50
+ _______________________________________________________________________________________
51
+ """
49
52
 
50
53
  def visitExpr(self, ctx: Parser.ExprContext):
51
54
  """
@@ -66,7 +69,7 @@ class Expr(VtlVisitor):
66
69
  | constant # constantExpr
67
70
  | varID # varIdExpr
68
71
  ;
69
- """ # noqa E501
72
+ """ # noqa E501
70
73
  ctx_list = list(ctx.getChildren())
71
74
  c = ctx_list[0]
72
75
 
@@ -115,13 +118,17 @@ class Expr(VtlVisitor):
115
118
  then_op_node = self.visitExpr(ctx_list[3])
116
119
  else_op_node = self.visitExpr(ctx_list[5])
117
120
 
118
- if_node = If(condition_node, then_op_node, else_op_node)
121
+ if_node = If(
122
+ condition=condition_node,
123
+ thenOp=then_op_node,
124
+ elseOp=else_op_node,
125
+ **extract_token_info(ctx),
126
+ )
119
127
 
120
128
  return if_node
121
129
 
122
130
  # CASE WHEN expr THEN expr ELSE expr END # caseExpr
123
131
  elif isinstance(c, TerminalNodeImpl) and (c.getSymbol().type == Parser.CASE):
124
-
125
132
  if len(ctx_list) % 4 != 3:
126
133
  raise ValueError("Syntax error.")
127
134
 
@@ -132,10 +139,12 @@ class Expr(VtlVisitor):
132
139
  for i in range(0, len(ctx_list), 4):
133
140
  condition = self.visitExpr(ctx_list[i + 1])
134
141
  thenOp = self.visitExpr(ctx_list[i + 3])
135
- case_obj = CaseObj(condition, thenOp)
142
+ case_obj = CaseObj(
143
+ condition=condition, thenOp=thenOp, **extract_token_info(ctx_list[i + 1])
144
+ )
136
145
  cases.append(case_obj)
137
146
 
138
- case_node = Case(cases, else_node)
147
+ case_node = Case(cases=cases, elseOp=else_node, **extract_token_info(ctx))
139
148
 
140
149
  return case_node
141
150
 
@@ -159,8 +168,8 @@ class Expr(VtlVisitor):
159
168
  else:
160
169
  op = ctx_list[1].getSymbol().text
161
170
  right_node = self.visitExpr(ctx_list[2])
162
-
163
- bin_op_node = BinOp(left_node, op, right_node)
171
+ token_info = extract_token_info(ctx)
172
+ bin_op_node = BinOp(left=left_node, op=op, right=right_node, **token_info)
164
173
 
165
174
  return bin_op_node
166
175
 
@@ -184,7 +193,7 @@ class Expr(VtlVisitor):
184
193
  right_node = Terminals().visitValueDomainID(ctx_list[2])
185
194
  else:
186
195
  raise NotImplementedError
187
- bin_op_node = BinOp(left_node, op, right_node)
196
+ bin_op_node = BinOp(left=left_node, op=op, right=right_node, **extract_token_info(ctx))
188
197
 
189
198
  return bin_op_node
190
199
 
@@ -192,14 +201,15 @@ class Expr(VtlVisitor):
192
201
  return self.bin_op_creator(ctx)
193
202
 
194
203
  def visitParenthesisExpr(self, ctx: Parser.ParenthesisExprContext):
195
- return self.visitExpr(list(ctx.getChildren())[1])
204
+ operand = self.visitExpr(list(ctx.getChildren())[1])
205
+ return ParFunction(operand=operand, **extract_token_info(ctx))
196
206
 
197
207
  def visitUnaryExpr(self, ctx: Parser.UnaryExprContext):
198
208
  c_list = list(ctx.getChildren())
199
209
  op = c_list[0].getSymbol().text
200
210
  right = self.visitExpr(c_list[1])
201
211
 
202
- return UnaryOp(op, right)
212
+ return UnaryOp(op=op, operand=right, **extract_token_info(ctx))
203
213
 
204
214
  def visitMembershipExpr(self, ctx: Parser.MembershipExprContext):
205
215
  ctx_list = list(ctx.getChildren())
@@ -215,13 +225,15 @@ class Expr(VtlVisitor):
215
225
  # It is only possible to put a membership at the end so go the last one.
216
226
  if len(membership) != 0:
217
227
  previous_node = BinOp(
218
- previous_node, "#", Terminals().visitSimpleComponentId(membership[0])
228
+ left=previous_node,
229
+ op="#",
230
+ right=Terminals().visitSimpleComponentId(membership[0]),
231
+ **extract_token_info(ctx),
219
232
  )
220
233
 
221
234
  return previous_node
222
235
 
223
236
  def visitClauseExpr(self, ctx: Parser.ClauseExprContext):
224
-
225
237
  ctx_list = list(ctx.getChildren())
226
238
 
227
239
  dataset = self.visitExpr(ctx_list[0])
@@ -317,8 +329,10 @@ class Expr(VtlVisitor):
317
329
 
318
330
  body_node = self.visitJoinBody(ctx_list[3])
319
331
 
332
+ token_info = extract_token_info(ctx)
333
+
320
334
  if len(body_node) != 0:
321
- previous_node = JoinOp(op_node, clause_node, using_node)
335
+ previous_node = JoinOp(op=op_node, clauses=clause_node, using=using_node, **token_info)
322
336
  regular_aggregation = None
323
337
  for body in body_node:
324
338
  regular_aggregation = body
@@ -331,7 +345,7 @@ class Expr(VtlVisitor):
331
345
  return regular_aggregation
332
346
 
333
347
  else:
334
- join_node = JoinOp(op_node, clause_node, using_node)
348
+ join_node = JoinOp(op=op_node, clauses=clause_node, using=using_node, **token_info)
335
349
  join_node.isLast = True
336
350
  return join_node
337
351
 
@@ -341,13 +355,18 @@ class Expr(VtlVisitor):
341
355
  if len(ctx_list) == 1:
342
356
  return left_node
343
357
 
358
+ token_info = extract_token_info(ctx)
344
359
  intop_node = ctx_list[1].getSymbol().text
345
- right_node = Identifier(Terminals().visitAlias(ctx_list[2]), "DatasetID")
346
- return BinOp(left_node, intop_node, right_node)
360
+ right_node = Identifier(
361
+ value=Terminals().visitAlias(ctx_list[2]),
362
+ kind="DatasetID",
363
+ **extract_token_info(ctx_list[1].getSymbol()),
364
+ )
365
+ return BinOp(left=left_node, op=intop_node, right=right_node, **token_info)
347
366
 
348
367
  def visitJoinClause(self, ctx: Parser.JoinClauseContext):
349
368
  """
350
- joinClauseItem (COMMA joinClauseItem)* (USING componentID (COMMA componentID)*)?
369
+ JoinClauseItem (COMMA joinClauseItem)* (USING componentID (COMMA componentID)*)?
351
370
  """
352
371
  ctx_list = list(ctx.getChildren())
353
372
 
@@ -373,7 +392,7 @@ class Expr(VtlVisitor):
373
392
  def visitJoinClauseWithoutUsing(self, ctx: Parser.JoinClauseWithoutUsingContext):
374
393
  """
375
394
  joinClause: joinClauseItem (COMMA joinClauseItem)* (USING componentID (COMMA componentID)*)? ;
376
- """ # noqa E501
395
+ """ # noqa E501
377
396
  ctx_list = list(ctx.getChildren())
378
397
 
379
398
  clause_nodes = []
@@ -388,7 +407,7 @@ class Expr(VtlVisitor):
388
407
  def visitJoinBody(self, ctx: Parser.JoinBodyContext):
389
408
  """
390
409
  joinBody: filterClause? (calcClause|joinApplyClause|aggrClause)? (keepOrDropClause)? renameClause?
391
- """ # noqa E501
410
+ """ # noqa E501
392
411
  ctx_list = list(ctx.getChildren())
393
412
 
394
413
  body_nodes = []
@@ -420,7 +439,7 @@ class Expr(VtlVisitor):
420
439
  op_node = ctx_list[0].getSymbol().text
421
440
  operand_nodes = [self.visitExpr(ctx_list[1])]
422
441
 
423
- return RegularAggregation(op_node, operand_nodes)
442
+ return RegularAggregation(op=op_node, children=operand_nodes, **extract_token_info(ctx))
424
443
 
425
444
  """
426
445
  -----------------------------------
@@ -452,12 +471,12 @@ class Expr(VtlVisitor):
452
471
  if isinstance(element, Parser.ParameterContext)
453
472
  ]
454
473
 
455
- return UDOCall(op=op, params=param_nodes)
474
+ return UDOCall(op=op, params=param_nodes, **extract_token_info(ctx))
456
475
 
457
476
  def visitEvalAtom(self, ctx: Parser.EvalAtomContext):
458
477
  """
459
478
  | EVAL LPAREN routineName LPAREN (varID|scalarItem)? (COMMA (varID|scalarItem))* RPAREN (LANGUAGE STRING_CONSTANT)? (RETURNS evalDatasetType)? RPAREN # evalAtom
460
- """ # noqa E501
479
+ """ # noqa E501
461
480
  ctx_list = list(ctx.getChildren())
462
481
 
463
482
  routine_name = Terminals().visitRoutineName(ctx_list[2])
@@ -500,12 +519,13 @@ class Expr(VtlVisitor):
500
519
  operands=children_nodes,
501
520
  output=output_node[0],
502
521
  language=language_name[0].getSymbol().text,
522
+ **extract_token_info(ctx),
503
523
  )
504
524
 
505
525
  def visitCastExprDataset(self, ctx: Parser.CastExprDatasetContext):
506
526
  """
507
527
  | CAST LPAREN expr COMMA (basicScalarType|valueDomainName) (COMMA STRING_CONSTANT)? RPAREN # castExprDataset
508
- """ # noqa E501
528
+ """ # noqa E501
509
529
  ctx_list = list(ctx.getChildren())
510
530
  c = ctx_list[0]
511
531
 
@@ -529,7 +549,11 @@ class Expr(VtlVisitor):
529
549
 
530
550
  if len(ctx_list) > 6:
531
551
  param_node = [
532
- ParamConstant("PARAM_CAST", str_.symbol.text.strip('"'))
552
+ ParamConstant(
553
+ type_="PARAM_CAST",
554
+ value=str_.symbol.text.strip('"'),
555
+ **extract_token_info(str_.getSymbol()),
556
+ )
533
557
  for str_ in ctx_list
534
558
  if isinstance(str_, TerminalNodeImpl)
535
559
  and str_.getSymbol().type == Parser.STRING_CONSTANT
@@ -540,7 +564,9 @@ class Expr(VtlVisitor):
540
564
  if len(basic_scalar_type) == 1:
541
565
  children_nodes = expr_node + basic_scalar_type
542
566
 
543
- return ParamOp(op=op, children=children_nodes, params=param_node)
567
+ return ParamOp(
568
+ op=op, children=children_nodes, params=param_node, **extract_token_info(ctx)
569
+ )
544
570
 
545
571
  else:
546
572
  # AST_ASTCONSTRUCTOR.14
@@ -553,7 +579,9 @@ class Expr(VtlVisitor):
553
579
  if isinstance(c, Parser.ExprContext):
554
580
  return self.visitExpr(c)
555
581
  elif isinstance(c, TerminalNodeImpl):
556
- return ID("OPTIONAL", c.getSymbol().text)
582
+ return ID(
583
+ type_="OPTIONAL", value=c.getSymbol().text, **extract_token_info(c.getSymbol())
584
+ )
557
585
  else:
558
586
  raise NotImplementedError
559
587
 
@@ -582,7 +610,7 @@ class Expr(VtlVisitor):
582
610
  token = c.getSymbol()
583
611
  op_node = token.text
584
612
  operand_node = self.visitExpr(ctx_list[2])
585
- return UnaryOp(op_node, operand_node)
613
+ return UnaryOp(op=op_node, operand=operand_node, **extract_token_info(ctx))
586
614
 
587
615
  def visitSubstrAtom(self, ctx: Parser.SubstrAtomContext):
588
616
  ctx_list = list(ctx.getChildren())
@@ -603,7 +631,9 @@ class Expr(VtlVisitor):
603
631
  for param in params:
604
632
  params_nodes.append(self.visitOptionalExpr(param))
605
633
 
606
- return ParamOp(op_node, children_nodes, params_nodes)
634
+ return ParamOp(
635
+ op=op_node, children=children_nodes, params=params_nodes, **extract_token_info(ctx)
636
+ )
607
637
 
608
638
  def visitReplaceAtom(self, ctx: Parser.ReplaceAtomContext):
609
639
  ctx_list = list(ctx.getChildren())
@@ -624,7 +654,9 @@ class Expr(VtlVisitor):
624
654
  children_nodes = [expressions[0]]
625
655
  params_nodes = [expressions[1]] + params
626
656
 
627
- return ParamOp(op_node, children_nodes, params_nodes)
657
+ return ParamOp(
658
+ op=op_node, children=children_nodes, params=params_nodes, **extract_token_info(ctx)
659
+ )
628
660
 
629
661
  def visitInstrAtom(self, ctx: Parser.InstrAtomContext):
630
662
  ctx_list = list(ctx.getChildren())
@@ -645,7 +677,9 @@ class Expr(VtlVisitor):
645
677
  children_nodes = [expressions[0]]
646
678
  params_nodes = [expressions[1]] + params
647
679
 
648
- return ParamOp(op_node, children_nodes, params_nodes)
680
+ return ParamOp(
681
+ op=op_node, children=children_nodes, params=params_nodes, **extract_token_info(ctx)
682
+ )
649
683
 
650
684
  """
651
685
  -----------------------------------
@@ -670,7 +704,7 @@ class Expr(VtlVisitor):
670
704
  token = c.getSymbol()
671
705
  op_node = token.text
672
706
  operand_node = self.visitExpr(ctx_list[2])
673
- return UnaryOp(op_node, operand_node)
707
+ return UnaryOp(op=op_node, operand=operand_node, **extract_token_info(ctx))
674
708
 
675
709
  def visitUnaryWithOptionalNumeric(self, ctx: Parser.UnaryWithOptionalNumericContext):
676
710
  ctx_list = list(ctx.getChildren())
@@ -691,7 +725,9 @@ class Expr(VtlVisitor):
691
725
  for param in params:
692
726
  params_nodes.append(self.visitOptionalExpr(param))
693
727
 
694
- return ParamOp(op_node, children_nodes, params_nodes)
728
+ return ParamOp(
729
+ op=op_node, children=children_nodes, params=params_nodes, **extract_token_info(ctx)
730
+ )
695
731
 
696
732
  def visitBinaryNumeric(self, ctx: Parser.BinaryNumericContext):
697
733
  ctx_list = list(ctx.getChildren())
@@ -702,7 +738,7 @@ class Expr(VtlVisitor):
702
738
  left_node = self.visitExpr(ctx_list[2])
703
739
  op_node = token.text
704
740
  right_node = self.visitExpr(ctx_list[4])
705
- return BinOp(left_node, op_node, right_node)
741
+ return BinOp(left=left_node, op=op_node, right=right_node, **extract_token_info(ctx))
706
742
 
707
743
  """
708
744
  -----------------------------------
@@ -735,7 +771,7 @@ class Expr(VtlVisitor):
735
771
  for children in childrens:
736
772
  children_nodes.append(self.visitExpr(children))
737
773
 
738
- return MulOp(op_node, children_nodes)
774
+ return MulOp(op=op_node, children=children_nodes, **extract_token_info(ctx))
739
775
 
740
776
  def visitCharsetMatchAtom(self, ctx: Parser.CharsetMatchAtomContext):
741
777
  ctx_list = list(ctx.getChildren())
@@ -745,7 +781,7 @@ class Expr(VtlVisitor):
745
781
  left_node = self.visitExpr(ctx_list[2])
746
782
  op_node = token.text
747
783
  right_node = self.visitExpr(ctx_list[4])
748
- return BinOp(left_node, op_node, right_node)
784
+ return BinOp(left=left_node, op=op_node, right=right_node, **extract_token_info(ctx))
749
785
 
750
786
  def visitIsNullAtom(self, ctx: Parser.IsNullAtomContext):
751
787
  ctx_list = list(ctx.getChildren())
@@ -753,7 +789,7 @@ class Expr(VtlVisitor):
753
789
  token = c.getSymbol()
754
790
  op_node = token.text
755
791
  operand_node = self.visitExpr(ctx_list[2])
756
- return UnaryOp(op_node, operand_node)
792
+ return UnaryOp(op=op_node, operand=operand_node, **extract_token_info(ctx))
757
793
 
758
794
  def visitExistInAtom(self, ctx: Parser.ExistInAtomContext):
759
795
  ctx_list = list(ctx.getChildren())
@@ -769,7 +805,7 @@ class Expr(VtlVisitor):
769
805
  if isinstance(retain, Parser.RetainTypeContext)
770
806
  ]
771
807
 
772
- return MulOp(op=op, children=operand_nodes + retain_nodes)
808
+ return MulOp(op=op, children=operand_nodes + retain_nodes, **extract_token_info(ctx))
773
809
 
774
810
  """
775
811
  -----------------------------------
@@ -795,15 +831,19 @@ class Expr(VtlVisitor):
795
831
  return self.visitTimeDiffAtom(ctx)
796
832
  elif isinstance(ctx, Parser.DateAddAtomContext):
797
833
  return self.visitTimeAddAtom(ctx)
798
- elif isinstance(ctx, (Parser.YearAtomContext,
799
- Parser.MonthAtomContext,
800
- Parser.DayOfMonthAtomContext,
801
- Parser.DayOfYearAtomContext,
802
- Parser.DayToYearAtomContext,
803
- Parser.DayToMonthAtomContext,
804
- Parser.YearTodayAtomContext,
805
- Parser.MonthTodayAtomContext)):
806
-
834
+ elif isinstance(
835
+ ctx,
836
+ (
837
+ Parser.YearAtomContext,
838
+ Parser.MonthAtomContext,
839
+ Parser.DayOfMonthAtomContext,
840
+ Parser.DayOfYearAtomContext,
841
+ Parser.DayToYearAtomContext,
842
+ Parser.DayToMonthAtomContext,
843
+ Parser.YearTodayAtomContext,
844
+ Parser.MonthTodayAtomContext,
845
+ ),
846
+ ):
807
847
  return self.visitTimeUnaryAtom(ctx)
808
848
  else:
809
849
  raise NotImplementedError
@@ -823,27 +863,7 @@ class Expr(VtlVisitor):
823
863
  # AST_ASTCONSTRUCTOR.15
824
864
  raise NotImplementedError
825
865
 
826
- return UnaryOp(op=op, operand=operand_node[0])
827
-
828
- # def visitPeriodAtom(self, ctx: Parser.PeriodAtomContext):
829
- # """
830
- # periodExpr: PERIOD_INDICATOR '(' expr? ')' ;
831
- # """
832
- # ctx_list = list(ctx.getChildren())
833
- # c = ctx_list[0]
834
- #
835
- # op = c.getSymbol().text
836
- # operand_node = [
837
- # self.visitExpr(operand)
838
- # for operand in ctx_list
839
- # if isinstance(operand, Parser.ExprContext)
840
- # ]
841
- #
842
- # if len(operand_node) == 0:
843
- # # AST_ASTCONSTRUCTOR.15
844
- # raise NotImplementedError
845
- #
846
- # return UnaryOp(op=op, operand=operand_node[0])
866
+ return UnaryOp(op=op, operand=operand_node[0], **extract_token_info(ctx))
847
867
 
848
868
  def visitTimeShiftAtom(self, ctx: Parser.TimeShiftAtomContext):
849
869
  """
@@ -854,9 +874,13 @@ class Expr(VtlVisitor):
854
874
 
855
875
  op = c.getSymbol().text
856
876
  left_node = self.visitExpr(ctx_list[2])
857
- right_node = Constant("INTEGER_CONSTANT", Terminals().visitSignedInteger(ctx_list[4]))
877
+ right_node = Constant(
878
+ type_="INTEGER_CONSTANT",
879
+ value=Terminals().visitSignedInteger(ctx_list[4]),
880
+ **extract_token_info(ctx_list[4]),
881
+ )
858
882
 
859
- return BinOp(left=left_node, op=op, right=right_node)
883
+ return BinOp(left=left_node, op=op, right=right_node, **extract_token_info(ctx))
860
884
 
861
885
  def visitFillTimeAtom(self, ctx: Parser.FillTimeAtomContext):
862
886
  """
@@ -869,16 +893,24 @@ class Expr(VtlVisitor):
869
893
  children_node = [self.visitExpr(ctx_list[2])]
870
894
 
871
895
  if len(ctx_list) > 4:
872
- param_constant_node = [ParamConstant("PARAM_TIMESERIES", ctx_list[4].getSymbol().text)]
896
+ param_constant_node = [
897
+ ParamConstant(
898
+ type_="PARAM_TIMESERIES",
899
+ value=ctx_list[4].getSymbol().text,
900
+ **extract_token_info(ctx_list[4].getSymbol()),
901
+ )
902
+ ]
873
903
  else:
874
904
  param_constant_node = []
875
905
 
876
- return ParamOp(op=op, children=children_node, params=param_constant_node)
906
+ return ParamOp(
907
+ op=op, children=children_node, params=param_constant_node, **extract_token_info(ctx)
908
+ )
877
909
 
878
910
  def visitTimeAggAtom(self, ctx: Parser.TimeAggAtomContext):
879
911
  """
880
912
  TIME_AGG LPAREN periodIndTo=STRING_CONSTANT (COMMA periodIndFrom=(STRING_CONSTANT| OPTIONAL ))? (COMMA op=optionalExpr)? (COMMA (FIRST|LAST))? RPAREN # timeAggAtom
881
- """ # noqa E501
913
+ """ # noqa E501
882
914
  ctx_list = list(ctx.getChildren())
883
915
  c = ctx_list[0]
884
916
 
@@ -903,7 +935,7 @@ class Expr(VtlVisitor):
903
935
  if isinstance(operand_node, ID):
904
936
  operand_node = None
905
937
  elif isinstance(operand_node, Identifier):
906
- operand_node = VarID(operand_node.value)
938
+ operand_node = VarID(value=operand_node.value, **extract_token_info(ctx))
907
939
  else:
908
940
  operand_node = None
909
941
 
@@ -911,7 +943,12 @@ class Expr(VtlVisitor):
911
943
  # AST_ASTCONSTRUCTOR.17
912
944
  raise Exception("Optional as expression node is not allowed in Time Aggregation")
913
945
  return TimeAggregation(
914
- op=op, operand=operand_node, period_to=period_to, period_from=period_from, conf=conf
946
+ op=op,
947
+ operand=operand_node,
948
+ period_to=period_to,
949
+ period_from=period_from,
950
+ conf=conf,
951
+ **extract_token_info(ctx),
915
952
  )
916
953
 
917
954
  def visitFlowAtom(self, ctx: Parser.FlowAtomContext):
@@ -919,11 +956,11 @@ class Expr(VtlVisitor):
919
956
 
920
957
  op_node = ctx_list[0].getSymbol().text
921
958
  operand_node = self.visitExpr(ctx_list[2])
922
- return UnaryOp(op_node, operand_node)
959
+ return UnaryOp(op=op_node, operand=operand_node, **extract_token_info(ctx))
923
960
 
924
961
  def visitCurrentDateAtom(self, ctx: Parser.CurrentDateAtomContext):
925
962
  c = list(ctx.getChildren())[0]
926
- return MulOp(op=c.getSymbol().text, children=[])
963
+ return MulOp(op=c.getSymbol().text, children=[], **extract_token_info(ctx))
927
964
 
928
965
  def visitTimeDiffAtom(self, ctx: Parser.TimeShiftAtomContext):
929
966
  """ """
@@ -934,7 +971,7 @@ class Expr(VtlVisitor):
934
971
  left_node = self.visitExpr(ctx_list[2])
935
972
  right_node = self.visitExpr(ctx_list[4])
936
973
 
937
- return BinOp(left=left_node, op=op, right=right_node)
974
+ return BinOp(left=left_node, op=op, right=right_node, **extract_token_info(ctx))
938
975
 
939
976
  def visitTimeAddAtom(self, ctx: Parser.TimeShiftAtomContext):
940
977
  """ """
@@ -952,7 +989,9 @@ class Expr(VtlVisitor):
952
989
  if len(ctx_list) > 6:
953
990
  param_constant_node.append(self.visitExpr(ctx_list[6]))
954
991
 
955
- return ParamOp(op=op, children=children_node, params=param_constant_node)
992
+ return ParamOp(
993
+ op=op, children=children_node, params=param_constant_node, **extract_token_info(ctx)
994
+ )
956
995
 
957
996
  """
958
997
  -----------------------------------
@@ -975,7 +1014,7 @@ class Expr(VtlVisitor):
975
1014
  left_node = self.visitExpr(ctx_list[2])
976
1015
  op_node = token.text
977
1016
  right_node = self.visitExpr(ctx_list[4])
978
- return BinOp(left_node, op_node, right_node)
1017
+ return BinOp(left=left_node, op=op_node, right=right_node, **extract_token_info(ctx))
979
1018
 
980
1019
  """
981
1020
  -----------------------------------
@@ -988,7 +1027,7 @@ class Expr(VtlVisitor):
988
1027
  setExpr: UNION LPAREN left=expr (COMMA expr)+ RPAREN # unionAtom
989
1028
  | INTERSECT LPAREN left=expr (COMMA expr)+ RPAREN # intersectAtom
990
1029
  | op=(SETDIFF|SYMDIFF) LPAREN left=expr COMMA right=expr RPAREN # setOrSYmDiffAtom
991
- """ # noqa E501
1030
+ """ # noqa E501
992
1031
  if isinstance(ctx, Parser.UnionAtomContext):
993
1032
  return self.visitUnionAtom(ctx)
994
1033
  elif isinstance(ctx, Parser.IntersectAtomContext):
@@ -1004,7 +1043,9 @@ class Expr(VtlVisitor):
1004
1043
  self.visitExpr(expr) for expr in ctx_list if isinstance(expr, Parser.ExprContext)
1005
1044
  ]
1006
1045
 
1007
- return MulOp(ctx_list[0].getSymbol().text, exprs_nodes)
1046
+ return MulOp(
1047
+ op=ctx_list[0].getSymbol().text, children=exprs_nodes, **extract_token_info(ctx)
1048
+ )
1008
1049
 
1009
1050
  def visitIntersectAtom(self, ctx: Parser.IntersectAtomContext):
1010
1051
  ctx_list = list(ctx.getChildren())
@@ -1012,7 +1053,9 @@ class Expr(VtlVisitor):
1012
1053
  self.visitExpr(expr) for expr in ctx_list if isinstance(expr, Parser.ExprContext)
1013
1054
  ]
1014
1055
 
1015
- return MulOp(op=ctx_list[0].getSymbol().text, children=exprs_nodes)
1056
+ return MulOp(
1057
+ op=ctx_list[0].getSymbol().text, children=exprs_nodes, **extract_token_info(ctx)
1058
+ )
1016
1059
 
1017
1060
  def visitSetOrSYmDiffAtom(self, ctx: Parser.SetOrSYmDiffAtomContext):
1018
1061
  ctx_list = list(ctx.getChildren())
@@ -1020,7 +1063,9 @@ class Expr(VtlVisitor):
1020
1063
  self.visitExpr(expr) for expr in ctx_list if isinstance(expr, Parser.ExprContext)
1021
1064
  ]
1022
1065
 
1023
- return MulOp(op=ctx_list[0].getSymbol().text, children=exprs_nodes)
1066
+ return MulOp(
1067
+ op=ctx_list[0].getSymbol().text, children=exprs_nodes, **extract_token_info(ctx)
1068
+ )
1024
1069
 
1025
1070
  """
1026
1071
  -----------------------------------
@@ -1031,19 +1076,24 @@ class Expr(VtlVisitor):
1031
1076
  def visitHierarchyFunctions(self, ctx: Parser.HierarchyFunctionsContext):
1032
1077
  """
1033
1078
  HIERARCHY LPAREN op=expr COMMA hrName=IDENTIFIER (conditionClause)? (RULE ruleComponent=componentID)? (validationMode)? (inputModeHierarchy)? outputModeHierarchy? RPAREN
1034
- """ # noqa E501
1079
+ """ # noqa E501
1035
1080
  ctx_list = list(ctx.getChildren())
1036
1081
  c = ctx_list[0]
1037
1082
 
1038
1083
  op = c.getSymbol().text
1039
1084
  dataset_node = self.visitExpr(ctx_list[2])
1040
- rule_name_node = Identifier(value=ctx_list[4].getSymbol().text, kind="RuleID")
1085
+ rule_name_node = Identifier(
1086
+ value=ctx_list[4].getSymbol().text,
1087
+ kind="RuleID",
1088
+ **extract_token_info(ctx_list[4].getSymbol()),
1089
+ )
1041
1090
 
1042
1091
  conditions = []
1043
1092
  modes = "non_null"
1044
1093
  inputs = "rule"
1045
1094
  retains = "computed"
1046
1095
  rule_comp = None
1096
+
1047
1097
  for c in ctx_list:
1048
1098
  if isinstance(c, Parser.ConditionClauseContext):
1049
1099
  conditions.append(Terminals().visitConditionClause(c))
@@ -1064,9 +1114,15 @@ class Expr(VtlVisitor):
1064
1114
  raise NotImplementedError("Dataset Priority input mode on HR is not implemented")
1065
1115
  param_constant_node = []
1066
1116
 
1067
- param_constant_node.append(ParamConstant("PARAM_MODE", modes))
1068
- param_constant_node.append(ParamConstant("PARAM_INPUT", inputs))
1069
- param_constant_node.append(ParamConstant("PARAM_OUTPUT", retains))
1117
+ param_constant_node.append(
1118
+ ParamConstant(type_="PARAM_MODE", value=modes, **extract_token_info(ctx))
1119
+ )
1120
+ param_constant_node.append(
1121
+ ParamConstant(type_="PARAM_INPUT", value=inputs, **extract_token_info(ctx))
1122
+ )
1123
+ param_constant_node.append(
1124
+ ParamConstant(type_="PARAM_OUTPUT", value=retains, **extract_token_info(ctx))
1125
+ )
1070
1126
 
1071
1127
  if not rule_comp:
1072
1128
  if isinstance(de_ruleset_elements[rule_name_node.value], list):
@@ -1075,7 +1131,9 @@ class Expr(VtlVisitor):
1075
1131
  rule_element = de_ruleset_elements[rule_name_node.value]
1076
1132
  if rule_element.kind == "DatasetID":
1077
1133
  check_hierarchy_rule = rule_element.value
1078
- rule_comp = Identifier(check_hierarchy_rule, "ComponentID")
1134
+ rule_comp = Identifier(
1135
+ value=check_hierarchy_rule, kind="ComponentID", **extract_token_info(ctx)
1136
+ )
1079
1137
  else: # ValuedomainID
1080
1138
  raise SemanticError("1-1-10-4", op=op)
1081
1139
 
@@ -1083,6 +1141,7 @@ class Expr(VtlVisitor):
1083
1141
  op=op,
1084
1142
  children=[dataset_node, rule_comp, rule_name_node, *conditions],
1085
1143
  params=param_constant_node,
1144
+ **extract_token_info(ctx),
1086
1145
  )
1087
1146
 
1088
1147
  """
@@ -1102,7 +1161,7 @@ class Expr(VtlVisitor):
1102
1161
  def visitValidateDPruleset(self, ctx: Parser.ValidateDPrulesetContext):
1103
1162
  """
1104
1163
  validationDatapoint: CHECK_DATAPOINT '(' expr ',' IDENTIFIER (COMPONENTS componentID (',' componentID)*)? (INVALID|ALL_MEASURES|ALL)? ')' ;
1105
- """ # noqa E501
1164
+ """ # noqa E501
1106
1165
  ctx_list = list(ctx.getChildren())
1107
1166
  c = ctx_list[0]
1108
1167
 
@@ -1131,13 +1190,18 @@ class Expr(VtlVisitor):
1131
1190
  if isinstance(ctx_list[-2], Parser.ValidationOutputContext):
1132
1191
  output = Terminals().visitValidationOutput(ctx_list[-2])
1133
1192
 
1134
- return ParamOp(op=op, children=[operand_node, rule_name, *components], params=[output])
1193
+ return ParamOp(
1194
+ op=op,
1195
+ children=[operand_node, rule_name, *components],
1196
+ params=[output],
1197
+ **extract_token_info(ctx),
1198
+ )
1135
1199
 
1136
1200
  # TODO Not fully implemented only basic usage available.
1137
1201
  def visitValidateHRruleset(self, ctx: Parser.ValidateHRrulesetContext):
1138
1202
  """
1139
1203
  CHECK_HIERARCHY LPAREN op=expr COMMA hrName=IDENTIFIER conditionClause? (RULE componentID)? validationMode? inputMode? validationOutput? RPAREN # validateHRruleset
1140
- """ # noqa E501
1204
+ """ # noqa E501
1141
1205
 
1142
1206
  ctx_list = list(ctx.getChildren())
1143
1207
  c = ctx_list[0]
@@ -1145,7 +1209,11 @@ class Expr(VtlVisitor):
1145
1209
  op = c.getSymbol().text
1146
1210
 
1147
1211
  dataset_node = self.visitExpr(ctx_list[2])
1148
- rule_name_node = Identifier(value=ctx_list[4].getSymbol().text, kind="RuleID")
1212
+ rule_name_node = Identifier(
1213
+ value=ctx_list[4].getSymbol().text,
1214
+ kind="RuleID",
1215
+ **extract_token_info(ctx_list[4].getSymbol()),
1216
+ )
1149
1217
 
1150
1218
  conditions = []
1151
1219
  # Default values
@@ -1153,6 +1221,7 @@ class Expr(VtlVisitor):
1153
1221
  inputs = "dataset"
1154
1222
  retains = "invalid"
1155
1223
  rule_comp = None
1224
+
1156
1225
  for c in ctx_list:
1157
1226
  if isinstance(c, Parser.ConditionClauseContext):
1158
1227
  conditions.append(Terminals().visitConditionClause(c))
@@ -1174,9 +1243,15 @@ class Expr(VtlVisitor):
1174
1243
  if inputs == DATASET_PRIORITY:
1175
1244
  raise NotImplementedError("Dataset Priority input mode on HR is not implemented")
1176
1245
 
1177
- param_constant_node.append(ParamConstant("PARAM_MODE", modes))
1178
- param_constant_node.append(ParamConstant("PARAM_INPUT", inputs))
1179
- param_constant_node.append(ParamConstant("PARAM_OUTPUT", retains))
1246
+ param_constant_node.append(
1247
+ ParamConstant(type_="PARAM_MODE", value=modes, **extract_token_info(ctx))
1248
+ )
1249
+ param_constant_node.append(
1250
+ ParamConstant(type_="PARAM_INPUT", value=inputs, **extract_token_info(ctx))
1251
+ )
1252
+ param_constant_node.append(
1253
+ ParamConstant(type_="PARAM_OUTPUT", value=retains, **extract_token_info(ctx))
1254
+ )
1180
1255
 
1181
1256
  if not rule_comp:
1182
1257
  if isinstance(de_ruleset_elements[rule_name_node.value], list):
@@ -1186,7 +1261,11 @@ class Expr(VtlVisitor):
1186
1261
 
1187
1262
  if rule_element.kind == "DatasetID":
1188
1263
  check_hierarchy_rule = rule_element.value
1189
- rule_comp = Identifier(check_hierarchy_rule, "ComponentID")
1264
+ rule_comp = Identifier(
1265
+ value=check_hierarchy_rule,
1266
+ kind="ComponentID",
1267
+ **extract_token_info(ctx),
1268
+ )
1190
1269
  else: # ValuedomainID
1191
1270
  raise SemanticError("1-1-10-4", op=op)
1192
1271
 
@@ -1194,12 +1273,13 @@ class Expr(VtlVisitor):
1194
1273
  op=op,
1195
1274
  children=[dataset_node, rule_comp, rule_name_node, *conditions],
1196
1275
  params=param_constant_node,
1276
+ **extract_token_info(ctx),
1197
1277
  )
1198
1278
 
1199
1279
  def visitValidationSimple(self, ctx: Parser.ValidationSimpleContext):
1200
1280
  """
1201
1281
  | CHECK LPAREN op=expr (codeErr=erCode)? (levelCode=erLevel)? imbalanceExpr? output=(INVALID|ALL)? RPAREN # validationSimple
1202
- """ # noqa E501
1282
+ """ # noqa E501
1203
1283
  ctx_list = list(ctx.getChildren())
1204
1284
  c = ctx_list[0]
1205
1285
  token = c.getSymbol()
@@ -1227,6 +1307,7 @@ class Expr(VtlVisitor):
1227
1307
  error_level=error_level,
1228
1308
  imbalance=inbalance_node,
1229
1309
  invalid=invalid_value,
1310
+ **extract_token_info(ctx),
1230
1311
  )
1231
1312
 
1232
1313
  def visitImbalanceExpr(self, ctx: Parser.ImbalanceExprContext):
@@ -1286,6 +1367,7 @@ class Expr(VtlVisitor):
1286
1367
  grouping_op=grouping_op,
1287
1368
  grouping=group_node,
1288
1369
  having_clause=have_node,
1370
+ **extract_token_info(ctx),
1289
1371
  )
1290
1372
 
1291
1373
  """
@@ -1331,11 +1413,21 @@ class Expr(VtlVisitor):
1331
1413
 
1332
1414
  if window is None:
1333
1415
  window = Windowing(
1334
- type_="data", start=-1, stop=0, start_mode="preceding", stop_mode="current"
1416
+ type_="data",
1417
+ start=-1,
1418
+ stop=0,
1419
+ start_mode="preceding",
1420
+ stop_mode="current",
1421
+ **extract_token_info(ctx),
1335
1422
  )
1336
1423
 
1337
1424
  return Analytic(
1338
- op=op_node, operand=operand, partition_by=partition_by, order_by=order_by, window=window
1425
+ op=op_node,
1426
+ operand=operand,
1427
+ partition_by=partition_by,
1428
+ order_by=order_by,
1429
+ window=window,
1430
+ **extract_token_info(ctx),
1339
1431
  )
1340
1432
 
1341
1433
  def visitLagOrLeadAn(self, ctx: Parser.LagOrLeadAnContext):
@@ -1369,7 +1461,12 @@ class Expr(VtlVisitor):
1369
1461
  raise Exception(f"{op_node} requires an offset parameter.")
1370
1462
 
1371
1463
  return Analytic(
1372
- op=op_node, operand=operand, partition_by=partition_by, order_by=order_by, params=params
1464
+ op=op_node,
1465
+ operand=operand,
1466
+ partition_by=partition_by,
1467
+ order_by=order_by,
1468
+ params=params,
1469
+ **extract_token_info(ctx),
1373
1470
  )
1374
1471
 
1375
1472
  def visitRatioToReportAn(self, ctx: Parser.RatioToReportAnContext):
@@ -1383,7 +1480,13 @@ class Expr(VtlVisitor):
1383
1480
 
1384
1481
  partition_by = Terminals().visitPartitionByClause(ctx_list[5])
1385
1482
 
1386
- return Analytic(op=op_node, operand=operand, partition_by=partition_by, order_by=order_by)
1483
+ return Analytic(
1484
+ op=op_node,
1485
+ operand=operand,
1486
+ partition_by=partition_by,
1487
+ order_by=order_by,
1488
+ **extract_token_info(ctx),
1489
+ )
1387
1490
 
1388
1491
  """______________________________________________________________________________________
1389
1492
 
@@ -1459,7 +1562,9 @@ class Expr(VtlVisitor):
1459
1562
  for ctx_rename in renames:
1460
1563
  rename_nodes.append(self.visitRenameClauseItem(ctx_rename))
1461
1564
 
1462
- return RegularAggregation(op=ctx_list[0].getSymbol().text, children=rename_nodes)
1565
+ return RegularAggregation(
1566
+ op=ctx_list[0].getSymbol().text, children=rename_nodes, **extract_token_info(ctx)
1567
+ )
1463
1568
 
1464
1569
  def visitRenameClauseItem(self, ctx: Parser.RenameClauseItemContext):
1465
1570
  """
@@ -1475,7 +1580,7 @@ class Expr(VtlVisitor):
1475
1580
 
1476
1581
  right_node = Terminals().visitVarID(ctx_list[2]).value
1477
1582
 
1478
- return RenameNode(left_node, right_node)
1583
+ return RenameNode(old_name=left_node, new_name=right_node, **extract_token_info(ctx))
1479
1584
 
1480
1585
  """
1481
1586
  -----------------------------------
@@ -1523,7 +1628,7 @@ class Expr(VtlVisitor):
1523
1628
  # Cannot find another way with less lines of code
1524
1629
  left_node.role = role
1525
1630
 
1526
- return Assignment(left_node, op_node, right_node)
1631
+ return Assignment(left=left_node, op=op_node, right=right_node, **extract_token_info(ctx))
1527
1632
 
1528
1633
  def visitAggrClause(self, ctx: Parser.AggrClauseContext):
1529
1634
  """
@@ -1556,10 +1661,11 @@ class Expr(VtlVisitor):
1556
1661
  grouping_op=grouping_op,
1557
1662
  grouping=group_node,
1558
1663
  having_clause=have_node,
1664
+ **extract_token_info(ctx_list[1]),
1559
1665
  )
1560
1666
  children.append(copy(element))
1561
1667
 
1562
- return RegularAggregation(op=op_node, children=children)
1668
+ return RegularAggregation(op=op_node, children=children, **extract_token_info(ctx))
1563
1669
 
1564
1670
  def visitGroupingClause(self, ctx: Parser.GroupingClauseContext):
1565
1671
  """
@@ -1613,7 +1719,9 @@ class Expr(VtlVisitor):
1613
1719
  else:
1614
1720
  raise NotImplementedError
1615
1721
 
1616
- return ParamOp(op=op_node, children=None, params=param_nodes), expr
1722
+ return ParamOp(
1723
+ op=op_node, children=None, params=param_nodes, **extract_token_info(ctx)
1724
+ ), expr
1617
1725
 
1618
1726
  def visitGroupByOrExcept(self, ctx: Parser.GroupByOrExceptContext):
1619
1727
  ctx_list = list(ctx.getChildren())
@@ -1661,7 +1769,7 @@ class Expr(VtlVisitor):
1661
1769
  operand_nodes = []
1662
1770
  operand_nodes.append(ExprComp().visitExprComponent(ctx_list[1]))
1663
1771
 
1664
- return RegularAggregation(op_node, operand_nodes)
1772
+ return RegularAggregation(op=op_node, children=operand_nodes, **extract_token_info(ctx))
1665
1773
 
1666
1774
  """
1667
1775
  -----------------------------------
@@ -1688,7 +1796,9 @@ class Expr(VtlVisitor):
1688
1796
  result = self.visitCalcClauseItem(calcClauseItem)
1689
1797
  calcClauseItems_nodes.append(result)
1690
1798
 
1691
- return RegularAggregation(op_node, calcClauseItems_nodes)
1799
+ return RegularAggregation(
1800
+ op=op_node, children=calcClauseItems_nodes, **extract_token_info(ctx)
1801
+ )
1692
1802
 
1693
1803
  def visitCalcClauseItem(self, ctx: Parser.CalcClauseItemContext):
1694
1804
  """
@@ -1703,17 +1813,25 @@ class Expr(VtlVisitor):
1703
1813
  left_node = Terminals().visitComponentID(ctx_list[1])
1704
1814
  op_node = ":="
1705
1815
  right_node = ExprComp().visitExprComponent(ctx_list[3])
1706
- operand_node = Assignment(left_node, op_node, right_node)
1816
+ operand_node = Assignment(
1817
+ left=left_node, op=op_node, right=right_node, **extract_token_info(ctx)
1818
+ )
1707
1819
  if role is None:
1708
- return UnaryOp(Role.MEASURE.value.lower(), operand_node)
1709
- return UnaryOp(role.value.lower(), operand_node)
1820
+ return UnaryOp(
1821
+ op=Role.MEASURE.value.lower(), operand=operand_node, **extract_token_info(c)
1822
+ )
1823
+ return UnaryOp(op=role.value.lower(), operand=operand_node, **extract_token_info(c))
1710
1824
  else:
1711
1825
  left_node = Terminals().visitSimpleComponentId(c)
1712
1826
  op_node = ":="
1713
1827
  right_node = ExprComp().visitExprComponent(ctx_list[2])
1714
1828
 
1715
- operand_node = Assignment(left_node, op_node, right_node)
1716
- return UnaryOp(Role.MEASURE.value.lower(), operand_node)
1829
+ operand_node = Assignment(
1830
+ left=left_node, op=op_node, right=right_node, **extract_token_info(ctx)
1831
+ )
1832
+ return UnaryOp(
1833
+ op=Role.MEASURE.value.lower(), operand=operand_node, **extract_token_info(ctx)
1834
+ )
1717
1835
 
1718
1836
  def visitKeepOrDropClause(self, ctx: Parser.KeepOrDropClauseContext):
1719
1837
  """
@@ -1730,7 +1848,7 @@ class Expr(VtlVisitor):
1730
1848
  for item in items:
1731
1849
  nodes.append(Terminals().visitComponentID(item))
1732
1850
 
1733
- return RegularAggregation(op_node, nodes)
1851
+ return RegularAggregation(op=op_node, children=nodes, **extract_token_info(ctx))
1734
1852
 
1735
1853
  """
1736
1854
  -----------------------------------
@@ -1751,7 +1869,7 @@ class Expr(VtlVisitor):
1751
1869
  children_nodes.append(Terminals().visitComponentID(ctx_list[1]))
1752
1870
  children_nodes.append(Terminals().visitComponentID(ctx_list[3]))
1753
1871
 
1754
- return RegularAggregation(op_node, children_nodes)
1872
+ return RegularAggregation(op=op_node, children=children_nodes, **extract_token_info(ctx))
1755
1873
 
1756
1874
  """
1757
1875
  -----------------------------------
@@ -1776,7 +1894,7 @@ class Expr(VtlVisitor):
1776
1894
  subspace_nodes.append(self.visitSubspaceClauseItem(subspace))
1777
1895
 
1778
1896
  op_node = c.getSymbol().text
1779
- return RegularAggregation(op_node, subspace_nodes)
1897
+ return RegularAggregation(op=op_node, children=subspace_nodes, **extract_token_info(ctx))
1780
1898
 
1781
1899
  def visitSubspaceClauseItem(self, ctx: Parser.SubspaceClauseItemContext):
1782
1900
  ctx_list = list(ctx.getChildren())
@@ -1784,7 +1902,7 @@ class Expr(VtlVisitor):
1784
1902
  left_node = Terminals().visitVarID(ctx_list[0])
1785
1903
  op_node = ctx_list[1].getSymbol().text
1786
1904
  right_node = Terminals().visitScalarItem(ctx_list[2])
1787
- return BinOp(left_node, op_node, right_node)
1905
+ return BinOp(left=left_node, op=op_node, right=right_node, **extract_token_info(ctx))
1788
1906
 
1789
1907
  def visitOptionalExpr(self, ctx: Parser.OptionalExprContext):
1790
1908
  """
@@ -1800,4 +1918,4 @@ class Expr(VtlVisitor):
1800
1918
  elif isinstance(c, TerminalNodeImpl):
1801
1919
  token = c.getSymbol()
1802
1920
  opt = token.text
1803
- return ID("OPTIONAL", opt)
1921
+ return ID(type_="OPTIONAL", value=opt, **extract_token_info(ctx))