• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

localstack / localstack / 65ebfa7b-38ab-49bb-b71e-44800576a11c

14 Mar 2025 12:37AM UTC coverage: 86.954% (+0.02%) from 86.93%
65ebfa7b-38ab-49bb-b71e-44800576a11c

push

circleci

web-flow
Fix apigw input path formatting (#12379)

43 of 49 new or added lines in 2 files covered. (87.76%)

103 existing lines in 16 files now uncovered.

62313 of 71662 relevant lines covered (86.95%)

0.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.91
/localstack-core/localstack/services/stepfunctions/asl/parse/preprocessor.py
1
import json
1✔
2
import logging
1✔
3
from typing import Any, Optional
1✔
4

5
from antlr4 import ParserRuleContext
1✔
6
from antlr4.tree.Tree import ParseTree, TerminalNodeImpl
1✔
7

8
from localstack.services.stepfunctions.asl.antlr.runtime.ASLLexer import ASLLexer
1✔
9
from localstack.services.stepfunctions.asl.antlr.runtime.ASLParser import ASLParser
1✔
10
from localstack.services.stepfunctions.asl.antlr.runtime.ASLParserVisitor import ASLParserVisitor
1✔
11
from localstack.services.stepfunctions.asl.antlt4utils.antlr4utils import (
1✔
12
    from_string_literal,
13
    is_production,
14
    is_terminal,
15
)
16
from localstack.services.stepfunctions.asl.component.common.assign.assign_decl import AssignDecl
1✔
17
from localstack.services.stepfunctions.asl.component.common.assign.assign_decl_binding import (
1✔
18
    AssignDeclBinding,
19
)
20
from localstack.services.stepfunctions.asl.component.common.assign.assign_template_binding import (
1✔
21
    AssignTemplateBinding,
22
    AssignTemplateBindingStringExpressionSimple,
23
    AssignTemplateBindingValue,
24
)
25
from localstack.services.stepfunctions.asl.component.common.assign.assign_template_value import (
1✔
26
    AssignTemplateValue,
27
)
28
from localstack.services.stepfunctions.asl.component.common.assign.assign_template_value_array import (
1✔
29
    AssignTemplateValueArray,
30
)
31
from localstack.services.stepfunctions.asl.component.common.assign.assign_template_value_object import (
1✔
32
    AssignTemplateValueObject,
33
)
34
from localstack.services.stepfunctions.asl.component.common.assign.assign_template_value_terminal import (
1✔
35
    AssignTemplateValueTerminal,
36
    AssignTemplateValueTerminalLit,
37
    AssignTemplateValueTerminalStringJSONata,
38
)
39
from localstack.services.stepfunctions.asl.component.common.catch.catch_decl import CatchDecl
1✔
40
from localstack.services.stepfunctions.asl.component.common.catch.catcher_decl import CatcherDecl
1✔
41
from localstack.services.stepfunctions.asl.component.common.catch.catcher_props import CatcherProps
1✔
42
from localstack.services.stepfunctions.asl.component.common.comment import Comment
1✔
43
from localstack.services.stepfunctions.asl.component.common.error_name.custom_error_name import (
1✔
44
    CustomErrorName,
45
)
46
from localstack.services.stepfunctions.asl.component.common.error_name.error_equals_decl import (
1✔
47
    ErrorEqualsDecl,
48
)
49
from localstack.services.stepfunctions.asl.component.common.error_name.error_name import ErrorName
1✔
50
from localstack.services.stepfunctions.asl.component.common.error_name.states_error_name import (
1✔
51
    StatesErrorName,
52
)
53
from localstack.services.stepfunctions.asl.component.common.error_name.states_error_name_type import (
1✔
54
    StatesErrorNameType,
55
)
56
from localstack.services.stepfunctions.asl.component.common.flow.end import End
1✔
57
from localstack.services.stepfunctions.asl.component.common.flow.next import Next
1✔
58
from localstack.services.stepfunctions.asl.component.common.flow.start_at import StartAt
1✔
59
from localstack.services.stepfunctions.asl.component.common.jsonata.jsonata_template_binding import (
1✔
60
    JSONataTemplateBinding,
61
)
62
from localstack.services.stepfunctions.asl.component.common.jsonata.jsonata_template_value import (
1✔
63
    JSONataTemplateValue,
64
)
65
from localstack.services.stepfunctions.asl.component.common.jsonata.jsonata_template_value_array import (
1✔
66
    JSONataTemplateValueArray,
67
)
68
from localstack.services.stepfunctions.asl.component.common.jsonata.jsonata_template_value_object import (
1✔
69
    JSONataTemplateValueObject,
70
)
71
from localstack.services.stepfunctions.asl.component.common.jsonata.jsonata_template_value_terminal import (
1✔
72
    JSONataTemplateValueTerminalLit,
73
    JSONataTemplateValueTerminalStringJSONata,
74
)
75
from localstack.services.stepfunctions.asl.component.common.outputdecl import Output
1✔
76
from localstack.services.stepfunctions.asl.component.common.parargs import (
1✔
77
    ArgumentsJSONataTemplateValueObject,
78
    ArgumentsStringJSONata,
79
    Parameters,
80
    Parargs,
81
)
82
from localstack.services.stepfunctions.asl.component.common.path.input_path import InputPath
1✔
83
from localstack.services.stepfunctions.asl.component.common.path.items_path import ItemsPath
1✔
84
from localstack.services.stepfunctions.asl.component.common.path.output_path import OutputPath
1✔
85
from localstack.services.stepfunctions.asl.component.common.path.result_path import ResultPath
1✔
86
from localstack.services.stepfunctions.asl.component.common.payload.payloadvalue.payload_value import (
1✔
87
    PayloadValue,
88
)
89
from localstack.services.stepfunctions.asl.component.common.payload.payloadvalue.payloadarr.payload_arr import (
1✔
90
    PayloadArr,
91
)
92
from localstack.services.stepfunctions.asl.component.common.payload.payloadvalue.payloadbinding.payload_binding import (
1✔
93
    PayloadBinding,
94
    PayloadBindingStringExpressionSimple,
95
    PayloadBindingValue,
96
)
97
from localstack.services.stepfunctions.asl.component.common.payload.payloadvalue.payloadtmpl.payload_tmpl import (
1✔
98
    PayloadTmpl,
99
)
100
from localstack.services.stepfunctions.asl.component.common.payload.payloadvalue.payloadvaluelit.payload_value_bool import (
1✔
101
    PayloadValueBool,
102
)
103
from localstack.services.stepfunctions.asl.component.common.payload.payloadvalue.payloadvaluelit.payload_value_float import (
1✔
104
    PayloadValueFloat,
105
)
106
from localstack.services.stepfunctions.asl.component.common.payload.payloadvalue.payloadvaluelit.payload_value_int import (
1✔
107
    PayloadValueInt,
108
)
109
from localstack.services.stepfunctions.asl.component.common.payload.payloadvalue.payloadvaluelit.payload_value_null import (
1✔
110
    PayloadValueNull,
111
)
112
from localstack.services.stepfunctions.asl.component.common.payload.payloadvalue.payloadvaluelit.payload_value_str import (
1✔
113
    PayloadValueStr,
114
)
115
from localstack.services.stepfunctions.asl.component.common.query_language import (
1✔
116
    QueryLanguage,
117
    QueryLanguageMode,
118
)
119
from localstack.services.stepfunctions.asl.component.common.result_selector import ResultSelector
1✔
120
from localstack.services.stepfunctions.asl.component.common.retry.backoff_rate_decl import (
1✔
121
    BackoffRateDecl,
122
)
123
from localstack.services.stepfunctions.asl.component.common.retry.interval_seconds_decl import (
1✔
124
    IntervalSecondsDecl,
125
)
126
from localstack.services.stepfunctions.asl.component.common.retry.jitter_strategy_decl import (
1✔
127
    JitterStrategy,
128
    JitterStrategyDecl,
129
)
130
from localstack.services.stepfunctions.asl.component.common.retry.max_attempts_decl import (
1✔
131
    MaxAttemptsDecl,
132
)
133
from localstack.services.stepfunctions.asl.component.common.retry.max_delay_seconds_decl import (
1✔
134
    MaxDelaySecondsDecl,
135
)
136
from localstack.services.stepfunctions.asl.component.common.retry.retrier_decl import RetrierDecl
1✔
137
from localstack.services.stepfunctions.asl.component.common.retry.retrier_props import RetrierProps
1✔
138
from localstack.services.stepfunctions.asl.component.common.retry.retry_decl import RetryDecl
1✔
139
from localstack.services.stepfunctions.asl.component.common.string.string_expression import (
1✔
140
    StringContextPath,
141
    StringExpression,
142
    StringExpressionSimple,
143
    StringIntrinsicFunction,
144
    StringJSONata,
145
    StringJsonPath,
146
    StringLiteral,
147
    StringSampler,
148
    StringVariableSample,
149
)
150
from localstack.services.stepfunctions.asl.component.common.timeouts.heartbeat import (
1✔
151
    HeartbeatSeconds,
152
    HeartbeatSecondsJSONata,
153
    HeartbeatSecondsPath,
154
)
155
from localstack.services.stepfunctions.asl.component.common.timeouts.timeout import (
1✔
156
    TimeoutSeconds,
157
    TimeoutSecondsJSONata,
158
    TimeoutSecondsPath,
159
)
160
from localstack.services.stepfunctions.asl.component.component import Component
1✔
161
from localstack.services.stepfunctions.asl.component.program.program import Program
1✔
162
from localstack.services.stepfunctions.asl.component.program.states import States
1✔
163
from localstack.services.stepfunctions.asl.component.program.version import Version
1✔
164
from localstack.services.stepfunctions.asl.component.state.state import CommonStateField
1✔
165
from localstack.services.stepfunctions.asl.component.state.state_choice.choice_rule import (
1✔
166
    ChoiceRule,
167
)
168
from localstack.services.stepfunctions.asl.component.state.state_choice.choices_decl import (
1✔
169
    ChoicesDecl,
170
)
171
from localstack.services.stepfunctions.asl.component.state.state_choice.comparison.comparison import (
1✔
172
    ComparisonComposite,
173
    ComparisonCompositeAnd,
174
    ComparisonCompositeNot,
175
    ComparisonCompositeOr,
176
    ComparisonCompositeProps,
177
    ConditionJSONataLit,
178
    ConditionStringJSONata,
179
)
180
from localstack.services.stepfunctions.asl.component.state.state_choice.comparison.comparison_func import (
1✔
181
    ComparisonFunc,
182
    ComparisonFuncStringVariableSample,
183
    ComparisonFuncValue,
184
)
185
from localstack.services.stepfunctions.asl.component.state.state_choice.comparison.comparison_operator_type import (
1✔
186
    ComparisonOperatorType,
187
)
188
from localstack.services.stepfunctions.asl.component.state.state_choice.comparison.comparison_type import (
1✔
189
    Comparison,
190
)
191
from localstack.services.stepfunctions.asl.component.state.state_choice.comparison.comparison_variable import (
1✔
192
    ComparisonVariable,
193
)
194
from localstack.services.stepfunctions.asl.component.state.state_choice.comparison.variable import (
1✔
195
    Variable,
196
)
197
from localstack.services.stepfunctions.asl.component.state.state_choice.default_decl import (
1✔
198
    DefaultDecl,
199
)
200
from localstack.services.stepfunctions.asl.component.state.state_choice.state_choice import (
1✔
201
    StateChoice,
202
)
203
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.execution_type import (
1✔
204
    ExecutionType,
205
)
206
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.item_reader.item_reader_decl import (
1✔
207
    ItemReader,
208
)
209
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.item_reader.reader_config.csv_header_location import (
1✔
210
    CSVHeaderLocation,
211
)
212
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.item_reader.reader_config.csv_headers import (
1✔
213
    CSVHeaders,
214
)
215
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.item_reader.reader_config.input_type import (
1✔
216
    InputType,
217
)
218
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.item_reader.reader_config.max_items_decl import (
1✔
219
    MaxItemsDecl,
220
    MaxItemsInt,
221
    MaxItemsPath,
222
    MaxItemsStringJSONata,
223
)
224
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.item_reader.reader_config.reader_config_decl import (
1✔
225
    ReaderConfig,
226
)
227
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.item_reader.reader_config.reader_config_props import (
1✔
228
    ReaderConfigProps,
229
)
230
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.item_selector import (
1✔
231
    ItemSelector,
232
)
233
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.items.items import (
1✔
234
    ItemsArray,
235
    ItemsJSONata,
236
)
237
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.iteration.itemprocessor.item_processor_decl import (
1✔
238
    ItemProcessorDecl,
239
)
240
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.iteration.itemprocessor.processor_config import (
1✔
241
    ProcessorConfig,
242
)
243
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.iteration.iterator.iterator_decl import (
1✔
244
    IteratorDecl,
245
)
246
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.label import (
1✔
247
    Label,
248
)
249
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.max_concurrency import (
1✔
250
    MaxConcurrency,
251
    MaxConcurrencyJSONata,
252
    MaxConcurrencyPath,
253
)
254
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.mode import (
1✔
255
    Mode,
256
)
257
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.result_writer.result_writer_decl import (
1✔
258
    ResultWriter,
259
)
260
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.state_map import (
1✔
261
    StateMap,
262
)
263
from localstack.services.stepfunctions.asl.component.state.state_execution.state_map.tolerated_failure import (
1✔
264
    ToleratedFailureCountInt,
265
    ToleratedFailureCountPath,
266
    ToleratedFailurePercentage,
267
    ToleratedFailurePercentagePath,
268
    ToleratedFailurePercentageStringJSONata,
269
)
270
from localstack.services.stepfunctions.asl.component.state.state_execution.state_parallel.branches_decl import (
1✔
271
    BranchesDecl,
272
)
273
from localstack.services.stepfunctions.asl.component.state.state_execution.state_parallel.state_parallel import (
1✔
274
    StateParallel,
275
)
276
from localstack.services.stepfunctions.asl.component.state.state_execution.state_task.credentials import (
1✔
277
    Credentials,
278
    RoleArn,
279
)
280
from localstack.services.stepfunctions.asl.component.state.state_execution.state_task.service.resource import (
1✔
281
    Resource,
282
)
283
from localstack.services.stepfunctions.asl.component.state.state_execution.state_task.state_task_factory import (
1✔
284
    state_task_for,
285
)
286
from localstack.services.stepfunctions.asl.component.state.state_fail.cause_decl import (
1✔
287
    Cause,
288
    CausePath,
289
)
290
from localstack.services.stepfunctions.asl.component.state.state_fail.error_decl import (
1✔
291
    Error,
292
    ErrorPath,
293
)
294
from localstack.services.stepfunctions.asl.component.state.state_fail.state_fail import StateFail
1✔
295
from localstack.services.stepfunctions.asl.component.state.state_pass.result import Result
1✔
296
from localstack.services.stepfunctions.asl.component.state.state_pass.state_pass import StatePass
1✔
297
from localstack.services.stepfunctions.asl.component.state.state_props import StateProps
1✔
298
from localstack.services.stepfunctions.asl.component.state.state_succeed.state_succeed import (
1✔
299
    StateSucceed,
300
)
301
from localstack.services.stepfunctions.asl.component.state.state_type import StateType
1✔
302
from localstack.services.stepfunctions.asl.component.state.state_wait.state_wait import StateWait
1✔
303
from localstack.services.stepfunctions.asl.component.state.state_wait.wait_function.seconds import (
1✔
304
    Seconds,
305
    SecondsJSONata,
306
)
307
from localstack.services.stepfunctions.asl.component.state.state_wait.wait_function.seconds_path import (
1✔
308
    SecondsPath,
309
)
310
from localstack.services.stepfunctions.asl.component.state.state_wait.wait_function.timestamp import (
1✔
311
    Timestamp,
312
    TimestampPath,
313
)
314
from localstack.services.stepfunctions.asl.parse.intrinsic.intrinsic_parser import IntrinsicParser
1✔
315
from localstack.services.stepfunctions.asl.parse.typed_props import TypedProps
1✔
316

317
LOG = logging.getLogger(__name__)
1✔
318

319

320
class Preprocessor(ASLParserVisitor):
1✔
321
    _query_language_per_scope: list[QueryLanguage] = list()
1✔
322

323
    def _get_current_query_language(self) -> QueryLanguage:
1✔
324
        return self._query_language_per_scope[-1]
1✔
325

326
    def _open_query_language_scope(self, parse_tree: ParseTree) -> None:
1✔
327
        production = is_production(parse_tree)
1✔
328
        if production is None:
1✔
329
            raise RuntimeError(f"Cannot expect QueryLanguage definition at depth: {parse_tree}")
×
330

331
        # Extract the QueryLanguage declaration at this ParseTree level, if any.
332
        query_language = None
1✔
333
        for child in production.children:
1✔
334
            sub_production = is_production(child, ASLParser.RULE_top_layer_stmt) or is_production(
1✔
335
                child, ASLParser.RULE_state_stmt
336
            )
337
            if sub_production is not None:
1✔
338
                child = sub_production.children[0]
1✔
339
            sub_production = is_production(child, ASLParser.RULE_query_language_decl)
1✔
340
            if sub_production is not None:
1✔
341
                query_language = self.visit(sub_production)
1✔
342
                break
1✔
343

344
        # Check this is the initial scope, if so set the initial value to the declaration or the default.
345
        if not self._query_language_per_scope:
1✔
346
            if query_language is None:
1✔
347
                query_language = QueryLanguage()
1✔
348
        # Otherwise, check for logical conflicts and add the latest or inherited value to as the next scope.
349
        else:
350
            current_query_language = self._get_current_query_language()
1✔
351
            if query_language is None:
1✔
352
                query_language = current_query_language
1✔
353
            if (
1✔
354
                current_query_language.query_language_mode == QueryLanguageMode.JSONata
355
                and query_language.query_language_mode == QueryLanguageMode.JSONPath
356
            ):
357
                raise ValueError(
×
358
                    f"Cannot downgrade from JSONata context to a JSONPath context at: {parse_tree}"
359
                )
360

361
        self._query_language_per_scope.append(query_language)
1✔
362

363
    def _close_query_language_scope(self) -> None:
1✔
364
        self._query_language_per_scope.pop()
1✔
365

366
    def _is_query_language(self, query_language_mode: QueryLanguageMode) -> bool:
1✔
367
        current_query_language = self._get_current_query_language()
1✔
368
        return current_query_language.query_language_mode == query_language_mode
1✔
369

370
    def _raise_if_query_language_is_not(
1✔
371
        self, query_language_mode: QueryLanguageMode, ctx: ParserRuleContext
372
    ) -> None:
373
        if not self._is_query_language(query_language_mode=query_language_mode):
1✔
374
            raise ValueError(
1✔
375
                f"Unsupported declaration in QueryLanguage={query_language_mode} block: {ctx.getText()}"
376
            )
377

378
    @staticmethod
1✔
379
    def _inner_string_of(parser_rule_context: ParserRuleContext) -> Optional[str]:
1✔
380
        if is_terminal(parser_rule_context, ASLLexer.NULL):
1✔
381
            return None
1✔
382
        inner_str = parser_rule_context.getText()
1✔
383
        if inner_str.startswith('"') and inner_str.endswith('"'):
1✔
384
            inner_str = inner_str[1:-1]
1✔
385
        return inner_str
1✔
386

387
    def _inner_jsonata_expr(self, ctx: ParserRuleContext) -> str:
1✔
388
        self._raise_if_query_language_is_not(query_language_mode=QueryLanguageMode.JSONata, ctx=ctx)
1✔
389
        inner_string_value = from_string_literal(parser_rule_context=ctx)
1✔
390
        # Strip the start and end jsonata symbols {%<body>%}
391
        expression_body = inner_string_value[2:-2]
1✔
392
        # Often leading and trailing spaces are used around the body: remove.
393
        expression = expression_body.strip()
1✔
394
        return expression
1✔
395

396
    def visitComment_decl(self, ctx: ASLParser.Comment_declContext) -> Comment:
1✔
397
        inner_str = self._inner_string_of(parser_rule_context=ctx.string_literal())
1✔
398
        return Comment(comment=inner_str)
1✔
399

400
    def visitVersion_decl(self, ctx: ASLParser.Version_declContext) -> Version:
1✔
401
        version_str = self._inner_string_of(parser_rule_context=ctx.string_literal())
1✔
402
        return Version(version=version_str)
1✔
403

404
    def visitStartat_decl(self, ctx: ASLParser.Startat_declContext) -> StartAt:
1✔
405
        inner_str = self._inner_string_of(parser_rule_context=ctx.string_literal())
1✔
406
        return StartAt(start_at_name=inner_str)
1✔
407

408
    def visitStates_decl(self, ctx: ASLParser.States_declContext) -> States:
1✔
409
        states = States()
1✔
410
        for child in ctx.children:
1✔
411
            cmp: Optional[Component] = self.visit(child)
1✔
412
            if isinstance(cmp, CommonStateField):
1✔
413
                # TODO move check to setter or checker layer?
414
                if cmp.name in states.states:
1✔
415
                    raise ValueError(f"State redefinition {child.getText()}")
×
416
                states.states[cmp.name] = cmp
1✔
417
        return states
1✔
418

419
    def visitType_decl(self, ctx: ASLParser.Type_declContext) -> StateType:
1✔
420
        return self.visit(ctx.state_type())
1✔
421

422
    def visitState_type(self, ctx: ASLParser.State_typeContext) -> StateType:
1✔
423
        state_type: int = ctx.children[0].symbol.type
1✔
424
        return StateType(state_type)
1✔
425

426
    def visitResource_decl(self, ctx: ASLParser.Resource_declContext) -> Resource:
1✔
427
        inner_str = self._inner_string_of(parser_rule_context=ctx.string_literal())
1✔
428
        return Resource.from_resource_arn(inner_str)
1✔
429

430
    def visitEnd_decl(self, ctx: ASLParser.End_declContext) -> End:
1✔
431
        bool_child: ParseTree = ctx.children[-1]
1✔
432
        bool_term: Optional[TerminalNodeImpl] = is_terminal(bool_child)
1✔
433
        if bool_term is None:
1✔
434
            raise ValueError(f"Could not derive End from declaration context '{ctx.getText()}'")
×
435
        bool_term_rule: int = bool_term.getSymbol().type
1✔
436
        is_end = bool_term_rule == ASLLexer.TRUE
1✔
437
        return End(is_end=is_end)
1✔
438

439
    def visitNext_decl(self, ctx: ASLParser.Next_declContext) -> Next:
1✔
440
        inner_str = self._inner_string_of(parser_rule_context=ctx.string_literal())
1✔
441
        return Next(name=inner_str)
1✔
442

443
    def visitResult_path_decl(self, ctx: ASLParser.Result_path_declContext) -> ResultPath:
1✔
444
        self._raise_if_query_language_is_not(
1✔
445
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
446
        )
447
        inner_str = self._inner_string_of(parser_rule_context=ctx.children[-1])
1✔
448
        return ResultPath(result_path_src=inner_str)
1✔
449

450
    def visitInput_path_decl(self, ctx: ASLParser.Input_path_declContext) -> InputPath:
1✔
451
        string_sampler: Optional[StringSampler] = None
1✔
452
        if not is_terminal(pt=ctx.children[-1], token_type=ASLLexer.NULL):
1✔
453
            string_sampler: StringSampler = self.visitString_sampler(ctx.string_sampler())
1✔
454
        return InputPath(string_sampler=string_sampler)
1✔
455

456
    def visitOutput_path_decl(self, ctx: ASLParser.Output_path_declContext) -> OutputPath:
1✔
457
        self._raise_if_query_language_is_not(
1✔
458
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
459
        )
460
        string_sampler: Optional[StringSampler] = None
1✔
461
        if is_production(ctx.children[-1], ASLParser.RULE_string_sampler):
1✔
462
            string_sampler: StringSampler = self.visitString_sampler(ctx.children[-1])
1✔
463
        return OutputPath(string_sampler=string_sampler)
1✔
464

465
    def visitResult_decl(self, ctx: ASLParser.Result_declContext) -> Result:
1✔
466
        json_decl = ctx.json_value_decl()
1✔
467
        json_str: str = json_decl.getText()
1✔
468
        json_obj: json = json.loads(json_str)
1✔
469
        return Result(result_obj=json_obj)
1✔
470

471
    def visitParameters_decl(self, ctx: ASLParser.Parameters_declContext) -> Parameters:
1✔
472
        self._raise_if_query_language_is_not(
1✔
473
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
474
        )
475
        payload_tmpl: PayloadTmpl = self.visit(ctx.payload_tmpl_decl())
1✔
476
        return Parameters(payload_tmpl=payload_tmpl)
1✔
477

478
    def visitTimeout_seconds_int(self, ctx: ASLParser.Timeout_seconds_intContext) -> TimeoutSeconds:
1✔
479
        seconds = int(ctx.INT().getText())
1✔
480
        return TimeoutSeconds(timeout_seconds=seconds)
1✔
481

482
    def visitTimeout_seconds_jsonata(
1✔
483
        self, ctx: ASLParser.Timeout_seconds_jsonataContext
484
    ) -> TimeoutSecondsJSONata:
485
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx.string_jsonata())
×
486
        return TimeoutSecondsJSONata(string_jsonata=string_jsonata)
×
487

488
    def visitTimeout_seconds_path(
1✔
489
        self, ctx: ASLParser.Timeout_seconds_pathContext
490
    ) -> TimeoutSecondsPath:
491
        self._raise_if_query_language_is_not(
1✔
492
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
493
        )
494
        string_sampler: StringSampler = self.visitString_sampler(ctx.string_sampler())
1✔
495
        return TimeoutSecondsPath(string_sampler=string_sampler)
1✔
496

497
    def visitHeartbeat_seconds_int(
1✔
498
        self, ctx: ASLParser.Heartbeat_seconds_intContext
499
    ) -> HeartbeatSeconds:
500
        seconds = int(ctx.INT().getText())
1✔
501
        return HeartbeatSeconds(heartbeat_seconds=seconds)
1✔
502

503
    def visitHeartbeat_seconds_jsonata(
1✔
504
        self, ctx: ASLParser.Heartbeat_seconds_jsonataContext
505
    ) -> HeartbeatSecondsJSONata:
506
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx.string_jsonata())
1✔
507
        return HeartbeatSecondsJSONata(string_jsonata=string_jsonata)
1✔
508

509
    def visitHeartbeat_seconds_path(
1✔
510
        self, ctx: ASLParser.Heartbeat_seconds_pathContext
511
    ) -> HeartbeatSecondsPath:
512
        self._raise_if_query_language_is_not(
1✔
513
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
514
        )
515
        string_sampler: StringSampler = self.visitString_sampler(ctx.string_sampler())
1✔
516
        return HeartbeatSecondsPath(string_sampler=string_sampler)
1✔
517

518
    def visitResult_selector_decl(
1✔
519
        self, ctx: ASLParser.Result_selector_declContext
520
    ) -> ResultSelector:
521
        self._raise_if_query_language_is_not(
1✔
522
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
523
        )
524
        payload_tmpl: PayloadTmpl = self.visit(ctx.payload_tmpl_decl())
1✔
525
        return ResultSelector(payload_tmpl=payload_tmpl)
1✔
526

527
    def visitBranches_decl(self, ctx: ASLParser.Branches_declContext) -> BranchesDecl:
1✔
528
        programs: list[Program] = []
1✔
529
        for child in ctx.children:
1✔
530
            cmp: Optional[Component] = self.visit(child)
1✔
531
            if isinstance(cmp, Program):
1✔
532
                programs.append(cmp)
1✔
533
        return BranchesDecl(programs=programs)
1✔
534

535
    def visitState_decl_body(self, ctx: ASLParser.State_decl_bodyContext) -> StateProps:
1✔
536
        self._open_query_language_scope(ctx)
1✔
537
        state_props = StateProps()
1✔
538
        for child in ctx.children:
1✔
539
            cmp: Optional[Component] = self.visit(child)
1✔
540
            state_props.add(cmp)
1✔
541
        if state_props.get(QueryLanguage) is None:
1✔
542
            state_props.add(self._get_current_query_language())
1✔
543
        self._close_query_language_scope()
1✔
544
        return state_props
1✔
545

546
    def visitState_decl(self, ctx: ASLParser.State_declContext) -> CommonStateField:
1✔
547
        state_name = self._inner_string_of(parser_rule_context=ctx.string_literal())
1✔
548
        state_props: StateProps = self.visit(ctx.state_decl_body())
1✔
549
        state_props.name = state_name
1✔
550
        common_state_field = self._common_state_field_of(state_props=state_props)
1✔
551
        return common_state_field
1✔
552

553
    @staticmethod
1✔
554
    def _common_state_field_of(state_props: StateProps) -> CommonStateField:
1✔
555
        # TODO: use subtype loading strategy.
556
        match state_props.get(StateType):
1✔
557
            case StateType.Task:
1✔
558
                resource: Resource = state_props.get(Resource)
1✔
559
                state = state_task_for(resource)
1✔
560
            case StateType.Pass:
1✔
561
                state = StatePass()
1✔
562
            case StateType.Choice:
1✔
563
                state = StateChoice()
1✔
564
            case StateType.Fail:
1✔
565
                state = StateFail()
1✔
566
            case StateType.Succeed:
1✔
567
                state = StateSucceed()
1✔
568
            case StateType.Wait:
1✔
569
                state = StateWait()
1✔
570
            case StateType.Map:
1✔
571
                state = StateMap()
1✔
572
            case StateType.Parallel:
1✔
573
                state = StateParallel()
1✔
574
            case None:
×
575
                raise TypeError("No Type declaration for State in context.")
×
576
            case unknown:
×
577
                raise TypeError(
×
578
                    f"Unknown StateType value '{unknown}' in StateProps object in context."  # noqa
579
                )
580
        state.from_state_props(state_props)
1✔
581
        return state
1✔
582

583
    def visitCondition_lit(self, ctx: ASLParser.Condition_litContext) -> ConditionJSONataLit:
1✔
584
        self._raise_if_query_language_is_not(query_language_mode=QueryLanguageMode.JSONata, ctx=ctx)
1✔
585
        bool_child: ParseTree = ctx.children[-1]
1✔
586
        bool_term: Optional[TerminalNodeImpl] = is_terminal(bool_child)
1✔
587
        if bool_term is None:
1✔
588
            raise ValueError(
×
589
                f"Could not derive boolean literal from declaration context '{ctx.getText()}'."
590
            )
591
        bool_term_rule: int = bool_term.getSymbol().type
1✔
592
        bool_val: bool = bool_term_rule == ASLLexer.TRUE
1✔
593
        return ConditionJSONataLit(literal=bool_val)
1✔
594

595
    def visitCondition_string_jsonata(
1✔
596
        self, ctx: ASLParser.Condition_string_jsonataContext
597
    ) -> ConditionStringJSONata:
598
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx=ctx.string_jsonata())
1✔
599
        return ConditionStringJSONata(string_jsonata=string_jsonata)
1✔
600

601
    def visitVariable_decl(self, ctx: ASLParser.Variable_declContext) -> Variable:
1✔
602
        self._raise_if_query_language_is_not(
1✔
603
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
604
        )
605
        string_sampler: StringSampler = self.visitString_sampler(ctx=ctx.string_sampler())
1✔
606
        return Variable(string_sampler=string_sampler)
1✔
607

608
    def visitComparison_op(self, ctx: ASLParser.Comparison_opContext) -> ComparisonOperatorType:
1✔
609
        self._raise_if_query_language_is_not(
1✔
610
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
611
        )
612
        try:
1✔
613
            operator_type: int = ctx.children[0].symbol.type
1✔
614
            return ComparisonOperatorType(operator_type)
1✔
615
        except Exception:
×
616
            raise ValueError(f"Could not derive ComparisonOperator from context '{ctx.getText()}'.")
×
617

618
    def visitComparison_func_value(
1✔
619
        self, ctx: ASLParser.Comparison_func_valueContext
620
    ) -> ComparisonFuncValue:
621
        self._raise_if_query_language_is_not(
1✔
622
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
623
        )
624
        comparison_op: ComparisonOperatorType = self.visit(ctx.comparison_op())
1✔
625
        json_decl = ctx.json_value_decl()
1✔
626
        json_str: str = json_decl.getText()
1✔
627
        json_obj: Any = json.loads(json_str)
1✔
628
        return ComparisonFuncValue(operator_type=comparison_op, value=json_obj)
1✔
629

630
    def visitComparison_func_string_variable_sample(
1✔
631
        self, ctx: ASLParser.Comparison_func_string_variable_sampleContext
632
    ) -> ComparisonFuncStringVariableSample:
633
        self._raise_if_query_language_is_not(
1✔
634
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
635
        )
636
        comparison_op: ComparisonOperatorType = self.visit(ctx.comparison_op())
1✔
637
        string_variable_sample: StringVariableSample = self.visitString_variable_sample(
1✔
638
            ctx.string_variable_sample()
639
        )
640
        return ComparisonFuncStringVariableSample(
1✔
641
            operator_type=comparison_op, string_variable_sample=string_variable_sample
642
        )
643

644
    def visitDefault_decl(self, ctx: ASLParser.Default_declContext) -> DefaultDecl:
1✔
645
        state_name = self._inner_string_of(parser_rule_context=ctx.string_literal())
1✔
646
        return DefaultDecl(state_name=state_name)
1✔
647

648
    def visitChoice_operator(
1✔
649
        self, ctx: ASLParser.Choice_operatorContext
650
    ) -> ComparisonComposite.ChoiceOp:
651
        self._raise_if_query_language_is_not(
1✔
652
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
653
        )
654
        pt: Optional[TerminalNodeImpl] = is_terminal(ctx.children[0])
1✔
655
        if not pt:
1✔
656
            raise ValueError(f"Could not derive ChoiceOperator in block '{ctx.getText()}'.")
×
657
        return ComparisonComposite.ChoiceOp(pt.symbol.type)
1✔
658

659
    def visitComparison_composite(
1✔
660
        self, ctx: ASLParser.Comparison_compositeContext
661
    ) -> ComparisonComposite:
662
        choice_op: ComparisonComposite.ChoiceOp = self.visit(ctx.choice_operator())
1✔
663
        rules: list[ChoiceRule] = list()
1✔
664
        for child in ctx.children[1:]:
1✔
665
            cmp: Optional[Component] = self.visit(child)
1✔
666
            if not cmp:
1✔
667
                continue
1✔
668
            elif isinstance(cmp, ChoiceRule):
1✔
669
                rules.append(cmp)
1✔
670

671
        match choice_op:
1✔
672
            case ComparisonComposite.ChoiceOp.Not:
1✔
673
                if len(rules) != 1:
1✔
674
                    raise ValueError(
×
675
                        f"ComparisonCompositeNot must carry only one ComparisonCompositeStmt in: '{ctx.getText()}'."
676
                    )
677
                return ComparisonCompositeNot(rule=rules[0])
1✔
678
            case ComparisonComposite.ChoiceOp.And:
1✔
679
                return ComparisonCompositeAnd(rules=rules)
1✔
680
            case ComparisonComposite.ChoiceOp.Or:
×
681
                return ComparisonCompositeOr(rules=rules)
×
682

683
    def visitChoice_rule_comparison_composite(
1✔
684
        self, ctx: ASLParser.Choice_rule_comparison_compositeContext
685
    ) -> ChoiceRule:
686
        composite_stmts = ComparisonCompositeProps()
1✔
687
        for child in ctx.children:
1✔
688
            cmp: Optional[Component] = self.visit(child)
1✔
689
            composite_stmts.add(cmp)
1✔
690
        return ChoiceRule(
1✔
691
            comparison=composite_stmts.get(
692
                typ=ComparisonComposite,
693
                raise_on_missing=ValueError(
694
                    f"Expecting a 'ComparisonComposite' definition at '{ctx.getText()}'."
695
                ),
696
            ),
697
            next_stmt=composite_stmts.get(Next),
698
            comment=composite_stmts.get(Comment),
699
            assign=composite_stmts.get(AssignDecl),
700
            output=composite_stmts.get(Output),
701
        )
702

703
    def visitChoice_rule_comparison_variable(
1✔
704
        self, ctx: ASLParser.Choice_rule_comparison_variableContext
705
    ) -> ChoiceRule:
706
        comparison_stmts = StateProps()
1✔
707
        for child in ctx.children:
1✔
708
            cmp: Optional[Component] = self.visit(child)
1✔
709
            comparison_stmts.add(cmp)
1✔
710
        if self._is_query_language(query_language_mode=QueryLanguageMode.JSONPath):
1✔
711
            variable: Variable = comparison_stmts.get(
1✔
712
                typ=Variable,
713
                raise_on_missing=ValueError(
714
                    f"Expected a Variable declaration in '{ctx.getText()}'."
715
                ),
716
            )
717
            comparison_func: Comparison = comparison_stmts.get(
1✔
718
                typ=Comparison,
719
                raise_on_missing=ValueError(
720
                    f"Expected a ComparisonFunction declaration in '{ctx.getText()}'."
721
                ),
722
            )
723
            if not isinstance(comparison_func, ComparisonFunc):
1✔
724
                raise ValueError(f"Expected a ComparisonFunction declaration in '{ctx.getText()}'")
×
725
            comparison_variable = ComparisonVariable(variable=variable, func=comparison_func)
1✔
726
            return ChoiceRule(
1✔
727
                comparison=comparison_variable,
728
                next_stmt=comparison_stmts.get(Next),
729
                comment=comparison_stmts.get(Comment),
730
                assign=None,
731
                output=None,
732
            )
733
        else:
734
            condition: Comparison = comparison_stmts.get(
1✔
735
                typ=Comparison,
736
                raise_on_missing=ValueError(
737
                    f"Expected a Condition declaration in '{ctx.getText()}'"
738
                ),
739
            )
740
            return ChoiceRule(
1✔
741
                comparison=condition,
742
                next_stmt=comparison_stmts.get(Next),
743
                comment=comparison_stmts.get(Comment),
744
                assign=comparison_stmts.get(AssignDecl),
745
                output=comparison_stmts.get(Output),
746
            )
747

748
    def visitChoices_decl(self, ctx: ASLParser.Choices_declContext) -> ChoicesDecl:
1✔
749
        rules: list[ChoiceRule] = list()
1✔
750
        for child in ctx.children:
1✔
751
            cmp: Optional[Component] = self.visit(child)
1✔
752
            if not cmp:
1✔
753
                continue
1✔
754
            elif isinstance(cmp, ChoiceRule):
1✔
755
                rules.append(cmp)
1✔
756
        return ChoicesDecl(rules=rules)
1✔
757

758
    def visitError(self, ctx: ASLParser.ErrorContext) -> Error:
1✔
759
        string_expression: StringExpression = self.visit(ctx.children[-1])
1✔
760
        return Error(string_expression=string_expression)
1✔
761

762
    def visitError_path(self, ctx: ASLParser.Error_pathContext) -> ErrorPath:
1✔
763
        self._raise_if_query_language_is_not(
1✔
764
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
765
        )
766
        string_expression: StringExpression = self.visit(ctx.children[-1])
1✔
767
        return ErrorPath(string_expression=string_expression)
1✔
768

769
    def visitCause(self, ctx: ASLParser.CauseContext) -> Cause:
1✔
770
        string_expression: StringExpression = self.visit(ctx.children[-1])
1✔
771
        return Cause(string_expression=string_expression)
1✔
772

773
    def visitCause_path(self, ctx: ASLParser.Cause_pathContext) -> CausePath:
1✔
774
        self._raise_if_query_language_is_not(
1✔
775
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
776
        )
777
        string_expression: StringExpression = self.visit(ctx.children[-1])
1✔
778
        return CausePath(string_expression=string_expression)
1✔
779

780
    def visitRole_arn(self, ctx: ASLParser.Role_arnContext) -> RoleArn:
1✔
781
        string_expression: StringExpression = self.visit(ctx.children[-1])
1✔
782
        return RoleArn(string_expression=string_expression)
1✔
783

784
    def visitRole_path(self, ctx: ASLParser.Role_pathContext) -> RoleArn:
1✔
785
        self._raise_if_query_language_is_not(
1✔
786
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
787
        )
788
        string_expression_simple: StringExpressionSimple = self.visitString_expression_simple(
1✔
789
            ctx=ctx.string_expression_simple()
790
        )
791
        return RoleArn(string_expression=string_expression_simple)
1✔
792

793
    def visitCredentials_decl(self, ctx: ASLParser.Credentials_declContext) -> Credentials:
1✔
794
        role_arn: RoleArn = self.visit(ctx.role_arn_decl())
1✔
795
        return Credentials(role_arn=role_arn)
1✔
796

797
    def visitSeconds_int(self, ctx: ASLParser.Seconds_intContext) -> Seconds:
1✔
798
        return Seconds(seconds=int(ctx.INT().getText()))
1✔
799

800
    def visitSeconds_jsonata(self, ctx: ASLParser.Seconds_jsonataContext) -> SecondsJSONata:
1✔
801
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx.string_jsonata())
1✔
802
        return SecondsJSONata(string_jsonata=string_jsonata)
1✔
803

804
    def visitSeconds_path(self, ctx: ASLParser.Seconds_pathContext) -> SecondsPath:
1✔
805
        self._raise_if_query_language_is_not(
1✔
806
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
807
        )
808
        string_sampler: StringSampler = self.visitString_sampler(ctx=ctx.string_sampler())
1✔
809
        return SecondsPath(string_sampler=string_sampler)
1✔
810

811
    def visitItems_path_decl(self, ctx: ASLParser.Items_path_declContext) -> ItemsPath:
1✔
812
        self._raise_if_query_language_is_not(
1✔
813
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
814
        )
815
        string_sampler: StringSampler = self.visitString_sampler(ctx.string_sampler())
1✔
816
        return ItemsPath(string_sampler=string_sampler)
1✔
817

818
    def visitMax_concurrency_int(self, ctx: ASLParser.Max_concurrency_intContext) -> MaxConcurrency:
1✔
819
        return MaxConcurrency(num=int(ctx.INT().getText()))
1✔
820

821
    def visitMax_concurrency_jsonata(
1✔
822
        self, ctx: ASLParser.Max_concurrency_jsonataContext
823
    ) -> MaxConcurrencyJSONata:
824
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx.string_jsonata())
1✔
825
        return MaxConcurrencyJSONata(string_jsonata=string_jsonata)
1✔
826

827
    def visitMax_concurrency_path(
1✔
828
        self, ctx: ASLParser.Max_concurrency_pathContext
829
    ) -> MaxConcurrencyPath:
830
        self._raise_if_query_language_is_not(
1✔
831
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
832
        )
833
        string_sampler: StringSampler = self.visitString_sampler(ctx.string_sampler())
1✔
834
        return MaxConcurrencyPath(string_sampler=string_sampler)
1✔
835

836
    def visitMode_decl(self, ctx: ASLParser.Mode_declContext) -> Mode:
1✔
837
        mode_type: int = self.visit(ctx.mode_type())
1✔
838
        return Mode(mode_type)
1✔
839

840
    def visitMode_type(self, ctx: ASLParser.Mode_typeContext) -> int:
1✔
841
        return ctx.children[0].symbol.type
1✔
842

843
    def visitExecution_decl(self, ctx: ASLParser.Execution_declContext) -> ExecutionType:
1✔
844
        execution_type: int = self.visit(ctx.execution_type())
1✔
845
        return ExecutionType(execution_type)
1✔
846

847
    def visitExecution_type(self, ctx: ASLParser.Execution_typeContext) -> int:
1✔
848
        return ctx.children[0].symbol.type
1✔
849

850
    def visitTimestamp(self, ctx: ASLParser.TimestampContext) -> Timestamp:
1✔
851
        string: StringExpression = self.visit(ctx.children[-1])
1✔
852
        return Timestamp(string=string)
1✔
853

854
    def visitTimestamp_path(self, ctx: ASLParser.Timestamp_pathContext) -> TimestampPath:
1✔
855
        self._raise_if_query_language_is_not(
1✔
856
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
857
        )
858
        string_sampler: StringSampler = self.visitString_sampler(ctx.string_sampler())
1✔
859
        return TimestampPath(string=string_sampler)
1✔
860

861
    def visitProcessor_config_decl(
1✔
862
        self, ctx: ASLParser.Processor_config_declContext
863
    ) -> ProcessorConfig:
864
        props = TypedProps()
1✔
865
        for child in ctx.children:
1✔
866
            cmp = self.visit(child)
1✔
867
            props.add(cmp)
1✔
868
        return ProcessorConfig(
1✔
869
            mode=props.get(typ=Mode) or ProcessorConfig.DEFAULT_MODE,
870
            execution_type=props.get(typ=ExecutionType) or ProcessorConfig.DEFAULT_EXECUTION_TYPE,
871
        )
872

873
    def visitItem_processor_item(self, ctx: ASLParser.Item_processor_itemContext) -> Component:
1✔
874
        return self.visit(ctx.children[0])
1✔
875

876
    def visitItem_processor_decl(
1✔
877
        self, ctx: ASLParser.Item_processor_declContext
878
    ) -> ItemProcessorDecl:
879
        props = TypedProps()
1✔
880
        for child in ctx.children:
1✔
881
            cmp = self.visit(child)
1✔
882
            props.add(cmp)
1✔
883
        return ItemProcessorDecl(
1✔
884
            query_language=props.get(QueryLanguage) or QueryLanguage(),
885
            start_at=props.get(
886
                typ=StartAt,
887
                raise_on_missing=ValueError(
888
                    f"Expected a StartAt declaration at '{ctx.getText()}'."
889
                ),
890
            ),
891
            states=props.get(
892
                typ=States,
893
                raise_on_missing=ValueError(f"Expected a States declaration at '{ctx.getText()}'."),
894
            ),
895
            comment=props.get(typ=Comment),
896
            processor_config=props.get(typ=ProcessorConfig) or ProcessorConfig(),
897
        )
898

899
    def visitIterator_decl(self, ctx: ASLParser.Iterator_declContext) -> IteratorDecl:
1✔
900
        props = TypedProps()
1✔
901
        for child in ctx.children:
1✔
902
            cmp = self.visit(child)
1✔
903
            props.add(cmp)
1✔
904
        return IteratorDecl(
1✔
905
            comment=props.get(typ=Comment),
906
            query_language=self._get_current_query_language(),
907
            start_at=props.get(
908
                typ=StartAt,
909
                raise_on_missing=ValueError(
910
                    f"Expected a StartAt declaration at '{ctx.getText()}'."
911
                ),
912
            ),
913
            states=props.get(
914
                typ=States,
915
                raise_on_missing=ValueError(f"Expected a States declaration at '{ctx.getText()}'."),
916
            ),
917
            processor_config=props.get(typ=ProcessorConfig) or ProcessorConfig(),
918
        )
919

920
    def visitItem_selector_decl(self, ctx: ASLParser.Item_selector_declContext) -> ItemSelector:
1✔
921
        template_value_object = self.visitAssign_template_value_object(
1✔
922
            ctx=ctx.assign_template_value_object()
923
        )
924
        return ItemSelector(template_value_object=template_value_object)
1✔
925

926
    def visitItem_reader_decl(self, ctx: ASLParser.Item_reader_declContext) -> ItemReader:
1✔
927
        props = StateProps()
1✔
928
        for child in ctx.children[3:-1]:
1✔
929
            cmp = self.visit(child)
1✔
930
            props.add(cmp)
1✔
931
        resource: Resource = props.get(
1✔
932
            typ=Resource,
933
            raise_on_missing=ValueError(f"Expected a Resource declaration at '{ctx.getText()}'."),
934
        )
935
        return ItemReader(
1✔
936
            resource=resource,
937
            parargs=props.get(Parargs),
938
            reader_config=props.get(ReaderConfig),
939
        )
940

941
    def visitReader_config_decl(self, ctx: ASLParser.Reader_config_declContext) -> ReaderConfig:
1✔
942
        props = ReaderConfigProps()
1✔
943
        for child in ctx.children:
1✔
944
            cmp = self.visit(child)
1✔
945
            props.add(cmp)
1✔
946
        return ReaderConfig(
1✔
947
            input_type=props.get(
948
                typ=InputType,
949
                raise_on_missing=ValueError(
950
                    f"Expected a InputType declaration at '{ctx.getText()}'."
951
                ),
952
            ),
953
            max_items_decl=props.get(typ=MaxItemsDecl),
954
            csv_header_location=props.get(CSVHeaderLocation),
955
            csv_headers=props.get(CSVHeaders),
956
        )
957

958
    def visitInput_type_decl(self, ctx: ASLParser.Input_type_declContext) -> InputType:
1✔
959
        input_type = self._inner_string_of(ctx.string_literal())
1✔
960
        return InputType(input_type=input_type)
1✔
961

962
    def visitCsv_header_location_decl(
1✔
963
        self, ctx: ASLParser.Csv_header_location_declContext
964
    ) -> CSVHeaderLocation:
965
        value = self._inner_string_of(ctx.string_literal())
1✔
966
        return CSVHeaderLocation(csv_header_location_value=value)
1✔
967

968
    def visitCsv_headers_decl(self, ctx: ASLParser.Csv_headers_declContext) -> CSVHeaders:
1✔
969
        csv_headers: list[str] = list()
1✔
970
        for child in ctx.children[3:-1]:
1✔
971
            maybe_str = is_production(pt=child, rule_index=ASLParser.RULE_string_literal)
1✔
972
            if maybe_str is not None:
1✔
973
                csv_headers.append(self._inner_string_of(maybe_str))
1✔
974
        # TODO: check for empty headers behaviour.
975
        return CSVHeaders(header_names=csv_headers)
1✔
976

977
    def visitMax_items_path(self, ctx: ASLParser.Max_items_pathContext) -> MaxItemsPath:
1✔
978
        self._raise_if_query_language_is_not(
1✔
979
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
980
        )
981
        string_sampler: StringSampler = self.visitString_sampler(ctx=ctx.string_sampler())
1✔
982
        return MaxItemsPath(string_sampler=string_sampler)
1✔
983

984
    def visitMax_items_int(self, ctx: ASLParser.Max_items_intContext) -> MaxItemsInt:
1✔
985
        return MaxItemsInt(max_items=int(ctx.INT().getText()))
1✔
986

987
    def visitMax_items_string_jsonata(
1✔
988
        self, ctx: ASLParser.Max_items_string_jsonataContext
989
    ) -> MaxItemsStringJSONata:
990
        self._raise_if_query_language_is_not(query_language_mode=QueryLanguageMode.JSONata, ctx=ctx)
1✔
991
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx.string_jsonata())
1✔
992
        return MaxItemsStringJSONata(string_jsonata=string_jsonata)
1✔
993

994
    def visitTolerated_failure_count_int(
1✔
995
        self, ctx: ASLParser.Tolerated_failure_count_intContext
996
    ) -> ToleratedFailureCountInt:
997
        LOG.warning(
1✔
998
            "ToleratedFailureCount declarations currently have no effect on the program evaluation."
999
        )
1000
        count = int(ctx.INT().getText())
1✔
1001
        return ToleratedFailureCountInt(tolerated_failure_count=count)
1✔
1002

1003
    def visitTolerated_failure_count_string_jsonata(
1✔
1004
        self, ctx: ASLParser.Tolerated_failure_count_string_jsonataContext
1005
    ) -> ToleratedFailurePercentageStringJSONata:
1006
        LOG.warning(
1✔
1007
            "ToleratedFailureCount declarations currently have no effect on the program evaluation."
1008
        )
1009
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx=ctx.string_jsonata())
1✔
1010
        return ToleratedFailurePercentageStringJSONata(string_jsonata=string_jsonata)
1✔
1011

1012
    def visitTolerated_failure_count_path(
1✔
1013
        self, ctx: ASLParser.Tolerated_failure_count_pathContext
1014
    ) -> ToleratedFailureCountPath:
1015
        self._raise_if_query_language_is_not(
1✔
1016
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
1017
        )
1018
        LOG.warning(
1✔
1019
            "ToleratedFailureCountPath declarations currently have no effect on the program evaluation."
1020
        )
1021
        string_sampler: StringSampler = self.visitString_sampler(ctx.string_sampler())
1✔
1022
        return ToleratedFailureCountPath(string_sampler=string_sampler)
1✔
1023

1024
    def visitTolerated_failure_percentage_number(
1✔
1025
        self, ctx: ASLParser.Tolerated_failure_percentage_numberContext
1026
    ) -> ToleratedFailurePercentage:
1027
        LOG.warning(
1✔
1028
            "ToleratedFailurePercentage declarations currently have no effect on the program evaluation."
1029
        )
1030
        percentage = float(ctx.NUMBER().getText())
1✔
1031
        return ToleratedFailurePercentage(tolerated_failure_percentage=percentage)
1✔
1032

1033
    def visitTolerated_failure_percentage_string_jsonata(
1✔
1034
        self, ctx: ASLParser.Tolerated_failure_percentage_string_jsonataContext
1035
    ) -> ToleratedFailurePercentageStringJSONata:
1036
        LOG.warning(
1✔
1037
            "ToleratedFailurePercentage declarations currently have no effect on the program evaluation."
1038
        )
1039
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx=ctx.string_jsonata())
1✔
1040
        return ToleratedFailurePercentageStringJSONata(string_jsonata=string_jsonata)
1✔
1041

1042
    def visitTolerated_failure_percentage_path(
1✔
1043
        self, ctx: ASLParser.Tolerated_failure_percentage_pathContext
1044
    ) -> ToleratedFailurePercentagePath:
1045
        self._raise_if_query_language_is_not(
1✔
1046
            query_language_mode=QueryLanguageMode.JSONPath, ctx=ctx
1047
        )
1048
        LOG.warning(
1✔
1049
            "ToleratedFailurePercentagePath declarations currently have no effect on the program evaluation."
1050
        )
1051
        string_sampler: StringSampler = self.visitString_sampler(ctx.string_sampler())
1✔
1052
        return ToleratedFailurePercentagePath(string_sampler=string_sampler)
1✔
1053

1054
    def visitLabel_decl(self, ctx: ASLParser.Label_declContext) -> Label:
1✔
1055
        label = self._inner_string_of(parser_rule_context=ctx.string_literal())
1✔
1056
        return Label(label=label)
1✔
1057

1058
    def visitResult_writer_decl(self, ctx: ASLParser.Result_writer_declContext) -> ResultWriter:
1✔
1059
        props = StateProps()
1✔
1060
        for child in ctx.children[3:-1]:
1✔
1061
            cmp = self.visit(child)
1✔
1062
            props.add(cmp)
1✔
1063
        resource: Resource = props.get(
1✔
1064
            typ=Resource,
1065
            raise_on_missing=ValueError(f"Expected a Resource declaration at '{ctx.getText()}'."),
1066
        )
1067
        # TODO: add tests for arguments in jsonata blocks using result writer
1068
        parargs: Parargs = props.get(
1✔
1069
            typ=Parargs,
1070
            raise_on_missing=ValueError(
1071
                f"Expected a Parameters/Arguments declaration at '{ctx.getText()}'."
1072
            ),
1073
        )
1074
        return ResultWriter(resource=resource, parargs=parargs)
1✔
1075

1076
    def visitRetry_decl(self, ctx: ASLParser.Retry_declContext) -> RetryDecl:
1✔
1077
        retriers: list[RetrierDecl] = list()
1✔
1078
        for child in ctx.children:
1✔
1079
            cmp: Optional[Component] = self.visit(child)
1✔
1080
            if isinstance(cmp, RetrierDecl):
1✔
1081
                retriers.append(cmp)
1✔
1082
        return RetryDecl(retriers=retriers)
1✔
1083

1084
    def visitRetrier_decl(self, ctx: ASLParser.Retrier_declContext) -> RetrierDecl:
1✔
1085
        props = RetrierProps()
1✔
1086
        for child in ctx.children:
1✔
1087
            cmp: Optional[Component] = self.visit(child)
1✔
1088
            props.add(cmp)
1✔
1089
        return RetrierDecl.from_retrier_props(props=props)
1✔
1090

1091
    def visitRetrier_stmt(self, ctx: ASLParser.Retrier_stmtContext):
1✔
1092
        return self.visit(ctx.children[0])
1✔
1093

1094
    def visitError_equals_decl(self, ctx: ASLParser.Error_equals_declContext) -> ErrorEqualsDecl:
1✔
1095
        error_names: list[ErrorName] = list()
1✔
1096
        for child in ctx.children:
1✔
1097
            cmp = self.visit(child)
1✔
1098
            if isinstance(cmp, ErrorName):
1✔
1099
                error_names.append(cmp)
1✔
1100
        return ErrorEqualsDecl(error_names=error_names)
1✔
1101

1102
    def visitError_name(self, ctx: ASLParser.Error_nameContext) -> ErrorName:
1✔
1103
        pt = ctx.children[0]
1✔
1104

1105
        # Case: StatesErrorName.
1106
        prc: Optional[ParserRuleContext] = is_production(
1✔
1107
            pt=pt, rule_index=ASLParser.RULE_states_error_name
1108
        )
1109
        if prc:
1✔
1110
            return self.visit(prc)
1✔
1111

1112
        # Case CustomErrorName.
1113
        error_name = self._inner_string_of(parser_rule_context=ctx.string_literal())
1✔
1114
        return CustomErrorName(error_name=error_name)
1✔
1115

1116
    def visitStates_error_name(self, ctx: ASLParser.States_error_nameContext) -> StatesErrorName:
1✔
1117
        pt: Optional[TerminalNodeImpl] = is_terminal(ctx.children[0])
1✔
1118
        if not pt:
1✔
UNCOV
1119
            raise ValueError(f"Could not derive ErrorName in block '{ctx.getText()}'.")
×
1120
        states_error_name_type = StatesErrorNameType(pt.symbol.type)
1✔
1121
        return StatesErrorName(states_error_name_type)
1✔
1122

1123
    def visitInterval_seconds_decl(
1✔
1124
        self, ctx: ASLParser.Interval_seconds_declContext
1125
    ) -> IntervalSecondsDecl:
1126
        return IntervalSecondsDecl(seconds=int(ctx.INT().getText()))
1✔
1127

1128
    def visitMax_attempts_decl(self, ctx: ASLParser.Max_attempts_declContext) -> MaxAttemptsDecl:
1✔
1129
        return MaxAttemptsDecl(attempts=int(ctx.INT().getText()))
1✔
1130

1131
    def visitBackoff_rate_decl(self, ctx: ASLParser.Backoff_rate_declContext) -> BackoffRateDecl:
1✔
1132
        return BackoffRateDecl(rate=float(ctx.children[-1].getText()))
1✔
1133

1134
    def visitMax_delay_seconds_decl(
1✔
1135
        self, ctx: ASLParser.Max_delay_seconds_declContext
1136
    ) -> MaxDelaySecondsDecl:
1137
        return MaxDelaySecondsDecl(max_delays_seconds=int(ctx.INT().getText()))
1✔
1138

1139
    def visitJitter_strategy_decl(
1✔
1140
        self, ctx: ASLParser.Jitter_strategy_declContext
1141
    ) -> JitterStrategyDecl:
1142
        last_child: ParseTree = ctx.children[-1]
1✔
1143
        strategy_child: Optional[TerminalNodeImpl] = is_terminal(last_child)
1✔
1144
        strategy_value = strategy_child.getSymbol().type
1✔
1145
        jitter_strategy = JitterStrategy(strategy_value)
1✔
1146
        return JitterStrategyDecl(jitter_strategy=jitter_strategy)
1✔
1147

1148
    def visitCatch_decl(self, ctx: ASLParser.Catch_declContext) -> CatchDecl:
1✔
1149
        catchers: list[CatcherDecl] = list()
1✔
1150
        for child in ctx.children:
1✔
1151
            cmp: Optional[Component] = self.visit(child)
1✔
1152
            if isinstance(cmp, CatcherDecl):
1✔
1153
                catchers.append(cmp)
1✔
1154
        return CatchDecl(catchers=catchers)
1✔
1155

1156
    def visitCatcher_decl(self, ctx: ASLParser.Catcher_declContext) -> CatcherDecl:
1✔
1157
        props = CatcherProps()
1✔
1158
        for child in ctx.children:
1✔
1159
            cmp: Optional[Component] = self.visit(child)
1✔
1160
            props.add(cmp)
1✔
1161
        if self._is_query_language(QueryLanguageMode.JSONPath) and not props.get(ResultPath):
1✔
1162
            props.add(CatcherDecl.DEFAULT_RESULT_PATH)
1✔
1163
        return CatcherDecl.from_catcher_props(props=props)
1✔
1164

1165
    def visitPayload_value_float(
1✔
1166
        self, ctx: ASLParser.Payload_value_floatContext
1167
    ) -> PayloadValueFloat:
UNCOV
1168
        return PayloadValueFloat(val=float(ctx.NUMBER().getText()))
×
1169

1170
    def visitPayload_value_int(self, ctx: ASLParser.Payload_value_intContext) -> PayloadValueInt:
1✔
1171
        return PayloadValueInt(val=int(ctx.INT().getText()))
1✔
1172

1173
    def visitPayload_value_bool(self, ctx: ASLParser.Payload_value_boolContext) -> PayloadValueBool:
1✔
1174
        bool_child: ParseTree = ctx.children[0]
1✔
1175
        bool_term: Optional[TerminalNodeImpl] = is_terminal(bool_child)
1✔
1176
        if bool_term is None:
1✔
UNCOV
1177
            raise ValueError(
×
1178
                f"Could not derive PayloadValueBool from declaration context '{ctx.getText()}'."
1179
            )
1180
        bool_term_rule: int = bool_term.getSymbol().type
1✔
1181
        bool_val: bool = bool_term_rule == ASLLexer.TRUE
1✔
1182
        return PayloadValueBool(val=bool_val)
1✔
1183

1184
    def visitPayload_value_null(self, ctx: ASLParser.Payload_value_nullContext) -> PayloadValueNull:
1✔
UNCOV
1185
        return PayloadValueNull()
×
1186

1187
    def visitPayload_value_str(self, ctx: ASLParser.Payload_value_strContext) -> PayloadValueStr:
1✔
1188
        string_literal: StringLiteral = self.visitString_literal(ctx=ctx.string_literal())
1✔
1189
        return PayloadValueStr(val=string_literal.literal_value)
1✔
1190

1191
    def visitPayload_binding_sample(
1✔
1192
        self, ctx: ASLParser.Payload_binding_sampleContext
1193
    ) -> PayloadBindingStringExpressionSimple:
1194
        string_dollar: str = self._inner_string_of(parser_rule_context=ctx.STRINGDOLLAR())
1✔
1195
        field = string_dollar[:-2]
1✔
1196
        string_expression_simple: StringExpressionSimple = self.visitString_expression_simple(
1✔
1197
            ctx.string_expression_simple()
1198
        )
1199
        return PayloadBindingStringExpressionSimple(
1✔
1200
            field=field, string_expression_simple=string_expression_simple
1201
        )
1202

1203
    def visitPayload_binding_value(
1✔
1204
        self, ctx: ASLParser.Payload_binding_valueContext
1205
    ) -> PayloadBindingValue:
1206
        string_literal: StringLiteral = self.visitString_literal(ctx=ctx.string_literal())
1✔
1207
        payload_value: PayloadValue = self.visit(ctx.payload_value_decl())
1✔
1208
        return PayloadBindingValue(field=string_literal.literal_value, payload_value=payload_value)
1✔
1209

1210
    def visitPayload_arr_decl(self, ctx: ASLParser.Payload_arr_declContext) -> PayloadArr:
1✔
1211
        payload_values: list[PayloadValue] = list()
1✔
1212
        for child in ctx.children:
1✔
1213
            cmp: Optional[Component] = self.visit(child)
1✔
1214
            if isinstance(cmp, PayloadValue):
1✔
1215
                payload_values.append(cmp)
1✔
1216
        return PayloadArr(payload_values=payload_values)
1✔
1217

1218
    def visitPayload_tmpl_decl(self, ctx: ASLParser.Payload_tmpl_declContext) -> PayloadTmpl:
1✔
1219
        payload_bindings: list[PayloadBinding] = list()
1✔
1220
        for child in ctx.children:
1✔
1221
            cmp: Optional[Component] = self.visit(child)
1✔
1222
            if isinstance(cmp, PayloadBinding):
1✔
1223
                payload_bindings.append(cmp)
1✔
1224
        return PayloadTmpl(payload_bindings=payload_bindings)
1✔
1225

1226
    def visitPayload_value_decl(self, ctx: ASLParser.Payload_value_declContext) -> PayloadValue:
1✔
1227
        value = ctx.children[0]
1✔
1228
        return self.visit(value)
1✔
1229

1230
    def visitProgram_decl(self, ctx: ASLParser.Program_declContext) -> Program:
1✔
1231
        self._open_query_language_scope(ctx)
1✔
1232
        props = TypedProps()
1✔
1233
        for child in ctx.children:
1✔
1234
            cmp: Optional[Component] = self.visit(child)
1✔
1235
            props.add(cmp)
1✔
1236
        if props.get(QueryLanguage) is None:
1✔
1237
            props.add(self._get_current_query_language())
1✔
1238
        program = Program(
1✔
1239
            query_language=props.get(typ=QueryLanguage) or QueryLanguage(),
1240
            start_at=props.get(
1241
                typ=StartAt,
1242
                raise_on_missing=ValueError(
1243
                    f"No '{StartAt}' definition for Program in context: '{ctx.getText()}'."
1244
                ),
1245
            ),
1246
            states=props.get(
1247
                typ=States,
1248
                raise_on_missing=ValueError(
1249
                    f"No '{States}' definition for Program in context: '{ctx.getText()}'."
1250
                ),
1251
            ),
1252
            timeout_seconds=props.get(TimeoutSeconds),
1253
            comment=props.get(typ=Comment),
1254
            version=props.get(typ=Version),
1255
        )
1256
        self._close_query_language_scope()
1✔
1257
        return program
1✔
1258

1259
    def visitState_machine(self, ctx: ASLParser.State_machineContext) -> Program:
1✔
1260
        return self.visit(ctx.program_decl())
1✔
1261

1262
    def visitQuery_language_decl(self, ctx: ASLParser.Query_language_declContext) -> QueryLanguage:
1✔
1263
        query_language_mode_int = ctx.children[-1].getSymbol().type
1✔
1264
        query_language_mode = QueryLanguageMode(value=query_language_mode_int)
1✔
1265
        return QueryLanguage(query_language_mode=query_language_mode)
1✔
1266

1267
    def visitAssign_template_value_terminal_float(
1✔
1268
        self, ctx: ASLParser.Assign_template_value_terminal_floatContext
1269
    ) -> AssignTemplateValueTerminalLit:
1270
        float_value = float(ctx.NUMBER().getText())
1✔
1271
        return AssignTemplateValueTerminalLit(value=float_value)
1✔
1272

1273
    def visitAssign_template_value_terminal_int(
1✔
1274
        self, ctx: ASLParser.Assign_template_value_terminal_intContext
1275
    ) -> AssignTemplateValueTerminalLit:
1276
        int_value = int(ctx.INT().getText())
1✔
1277
        return AssignTemplateValueTerminalLit(value=int_value)
1✔
1278

1279
    def visitAssign_template_value_terminal_bool(
1✔
1280
        self, ctx: ASLParser.Assign_template_value_terminal_boolContext
1281
    ) -> AssignTemplateValueTerminalLit:
1282
        bool_term_rule: int = ctx.children[0].getSymbol().type
1✔
1283
        bool_value: bool = bool_term_rule == ASLLexer.TRUE
1✔
1284
        return AssignTemplateValueTerminalLit(value=bool_value)
1✔
1285

1286
    def visitAssign_template_value_terminal_null(
1✔
1287
        self, ctx: ASLParser.Assign_template_value_terminal_nullContext
1288
    ) -> AssignTemplateValueTerminalLit:
1289
        return AssignTemplateValueTerminalLit(value=None)
1✔
1290

1291
    def visitAssign_template_value_terminal_string_jsonata(
1✔
1292
        self, ctx: ASLParser.Assign_template_value_terminal_string_jsonataContext
1293
    ) -> AssignTemplateValueTerminal:
1294
        # Return a JSONata expression resolver or a suppressed depending on the current language mode.
1295
        current_query_language = self._get_current_query_language()
1✔
1296
        if current_query_language.query_language_mode == QueryLanguageMode.JSONata:
1✔
1297
            string_jsonata: StringJSONata = self.visitString_jsonata(ctx.string_jsonata())
1✔
1298
            return AssignTemplateValueTerminalStringJSONata(string_jsonata=string_jsonata)
1✔
1299
        else:
1300
            inner_string_value = self._inner_string_of(parser_rule_context=ctx.string_jsonata())
1✔
1301
            return AssignTemplateValueTerminalLit(value=inner_string_value)
1✔
1302

1303
    def visitAssign_template_value_terminal_string_literal(
1✔
1304
        self, ctx: ASLParser.Assign_template_value_terminal_string_literalContext
1305
    ) -> AssignTemplateValueTerminal:
1306
        string_literal = self._inner_string_of(ctx.string_literal())
1✔
1307
        return AssignTemplateValueTerminalLit(value=string_literal)
1✔
1308

1309
    def visitAssign_template_value(self, ctx: ASLParser.Assign_template_valueContext):
1✔
1310
        return self.visit(ctx.children[0])
1✔
1311

1312
    def visitAssign_template_value_array(
1✔
1313
        self, ctx: ASLParser.Assign_template_value_arrayContext
1314
    ) -> AssignTemplateValueArray:
1315
        values: list[AssignTemplateValue] = list()
1✔
1316
        for child in ctx.children:
1✔
1317
            cmp: Optional[Component] = self.visit(child)
1✔
1318
            if isinstance(cmp, AssignTemplateValue):
1✔
1319
                values.append(cmp)
1✔
1320
        return AssignTemplateValueArray(values=values)
1✔
1321

1322
    def visitAssign_template_value_object(
1✔
1323
        self, ctx: ASLParser.Assign_template_value_objectContext
1324
    ) -> AssignTemplateValueObject:
1325
        bindings: list[AssignTemplateBinding] = list()
1✔
1326
        for child in ctx.children:
1✔
1327
            cmp: Optional[Component] = self.visit(child)
1✔
1328
            if isinstance(cmp, AssignTemplateBinding):
1✔
1329
                bindings.append(cmp)
1✔
1330
        return AssignTemplateValueObject(bindings=bindings)
1✔
1331

1332
    def visitAssign_template_binding_value(
1✔
1333
        self, ctx: ASLParser.Assign_template_binding_valueContext
1334
    ) -> AssignTemplateBindingValue:
1335
        string_literal: StringLiteral = self.visitString_literal(ctx=ctx.string_literal())
1✔
1336
        assign_value: AssignTemplateValue = self.visit(ctx.assign_template_value())
1✔
1337
        return AssignTemplateBindingValue(
1✔
1338
            identifier=string_literal.literal_value, assign_value=assign_value
1339
        )
1340

1341
    def visitAssign_template_binding_string_expression_simple(
1✔
1342
        self, ctx: ASLParser.Assign_template_binding_string_expression_simpleContext
1343
    ) -> AssignTemplateBindingStringExpressionSimple:
1344
        identifier: str = self._inner_string_of(ctx.STRINGDOLLAR())
1✔
1345
        identifier = identifier[:-2]
1✔
1346
        string_expression_simple: StringExpressionSimple = self.visitString_expression_simple(
1✔
1347
            ctx.string_expression_simple()
1348
        )
1349
        return AssignTemplateBindingStringExpressionSimple(
1✔
1350
            identifier=identifier, string_expression_simple=string_expression_simple
1351
        )
1352

1353
    def visitAssign_decl_binding(
1✔
1354
        self, ctx: ASLParser.Assign_decl_bindingContext
1355
    ) -> AssignDeclBinding:
1356
        binding: AssignTemplateBinding = self.visit(ctx.assign_template_binding())
1✔
1357
        return AssignDeclBinding(binding=binding)
1✔
1358

1359
    def visitAssign_decl_body(
1✔
1360
        self, ctx: ASLParser.Assign_decl_bodyContext
1361
    ) -> list[AssignDeclBinding]:
1362
        bindings: list[AssignDeclBinding] = list()
1✔
1363
        for child in ctx.children:
1✔
1364
            cmp: Optional[Component] = self.visit(child)
1✔
1365
            if isinstance(cmp, AssignDeclBinding):
1✔
1366
                bindings.append(cmp)
1✔
1367
        return bindings
1✔
1368

1369
    def visitAssign_decl(self, ctx: ASLParser.Assign_declContext) -> AssignDecl:
1✔
1370
        declaration_bindings: list[AssignDeclBinding] = self.visit(ctx.assign_decl_body())
1✔
1371
        return AssignDecl(declaration_bindings=declaration_bindings)
1✔
1372

1373
    def visitJsonata_template_value_terminal_float(
1✔
1374
        self, ctx: ASLParser.Jsonata_template_value_terminal_floatContext
1375
    ) -> JSONataTemplateValueTerminalLit:
1376
        float_value = float(ctx.NUMBER().getText())
1✔
1377
        return JSONataTemplateValueTerminalLit(value=float_value)
1✔
1378

1379
    def visitJsonata_template_value_terminal_int(
1✔
1380
        self, ctx: ASLParser.Jsonata_template_value_terminal_intContext
1381
    ) -> JSONataTemplateValueTerminalLit:
1382
        int_value = int(ctx.INT().getText())
1✔
1383
        return JSONataTemplateValueTerminalLit(value=int_value)
1✔
1384

1385
    def visitJsonata_template_value_terminal_bool(
1✔
1386
        self, ctx: ASLParser.Jsonata_template_value_terminal_boolContext
1387
    ) -> JSONataTemplateValueTerminalLit:
1388
        bool_term_rule: int = ctx.children[0].getSymbol().type
1✔
1389
        bool_value: bool = bool_term_rule == ASLLexer.TRUE
1✔
1390
        return JSONataTemplateValueTerminalLit(value=bool_value)
1✔
1391

1392
    def visitJsonata_template_value_terminal_null(
1✔
1393
        self, ctx: ASLParser.Jsonata_template_value_terminal_nullContext
1394
    ) -> JSONataTemplateValueTerminalLit:
1395
        return JSONataTemplateValueTerminalLit(value=None)
1✔
1396

1397
    def visitJsonata_template_value_terminal_string_jsonata(
1✔
1398
        self, ctx: ASLParser.Jsonata_template_value_terminal_string_jsonataContext
1399
    ) -> JSONataTemplateValueTerminalStringJSONata:
1400
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx.string_jsonata())
1✔
1401
        return JSONataTemplateValueTerminalStringJSONata(string_jsonata=string_jsonata)
1✔
1402

1403
    def visitJsonata_template_value_terminal_string_literal(
1✔
1404
        self, ctx: ASLParser.Jsonata_template_value_terminal_string_literalContext
1405
    ) -> JSONataTemplateValueTerminalLit:
1406
        string = from_string_literal(ctx.string_literal())
1✔
1407
        return JSONataTemplateValueTerminalLit(value=string)
1✔
1408

1409
    def visitJsonata_template_value(
1✔
1410
        self, ctx: ASLParser.Jsonata_template_valueContext
1411
    ) -> JSONataTemplateValue:
1412
        return self.visit(ctx.children[0])
1✔
1413

1414
    def visitJsonata_template_value_array(
1✔
1415
        self, ctx: ASLParser.Jsonata_template_value_arrayContext
1416
    ) -> JSONataTemplateValueArray:
1417
        values: list[JSONataTemplateValue] = list()
1✔
1418
        for child in ctx.children:
1✔
1419
            cmp: Optional[Component] = self.visit(child)
1✔
1420
            if isinstance(cmp, JSONataTemplateValue):
1✔
1421
                values.append(cmp)
1✔
1422
        return JSONataTemplateValueArray(values=values)
1✔
1423

1424
    def visitJsonata_template_value_object(
1✔
1425
        self, ctx: ASLParser.Jsonata_template_value_objectContext
1426
    ) -> JSONataTemplateValueObject:
1427
        bindings: list[JSONataTemplateBinding] = list()
1✔
1428
        for child in ctx.children:
1✔
1429
            cmp: Optional[Component] = self.visit(child)
1✔
1430
            if isinstance(cmp, JSONataTemplateBinding):
1✔
1431
                bindings.append(cmp)
1✔
1432
        return JSONataTemplateValueObject(bindings=bindings)
1✔
1433

1434
    def visitJsonata_template_binding(
1✔
1435
        self, ctx: ASLParser.Jsonata_template_bindingContext
1436
    ) -> JSONataTemplateBinding:
1437
        identifier: str = self._inner_string_of(ctx.string_literal())
1✔
1438
        value: JSONataTemplateValue = self.visit(ctx.jsonata_template_value())
1✔
1439
        return JSONataTemplateBinding(identifier=identifier, value=value)
1✔
1440

1441
    def visitArguments_string_jsonata(
1✔
1442
        self, ctx: ASLParser.Arguments_string_jsonataContext
1443
    ) -> ArgumentsStringJSONata:
1444
        self._raise_if_query_language_is_not(query_language_mode=QueryLanguageMode.JSONata, ctx=ctx)
×
UNCOV
1445
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx.string_jsonata())
×
UNCOV
1446
        return ArgumentsStringJSONata(string_jsonata=string_jsonata)
×
1447

1448
    def visitArguments_jsonata_template_value_object(
1✔
1449
        self, ctx: ASLParser.Arguments_jsonata_template_value_objectContext
1450
    ) -> ArgumentsJSONataTemplateValueObject:
1451
        self._raise_if_query_language_is_not(query_language_mode=QueryLanguageMode.JSONata, ctx=ctx)
1✔
1452
        jsonata_template_value_object: JSONataTemplateValueObject = self.visit(
1✔
1453
            ctx.jsonata_template_value_object()
1454
        )
1455
        return ArgumentsJSONataTemplateValueObject(
1✔
1456
            jsonata_template_value_object=jsonata_template_value_object
1457
        )
1458

1459
    def visitOutput_decl(self, ctx: ASLParser.Output_declContext) -> Output:
1✔
1460
        jsonata_template_value: JSONataTemplateValue = self.visit(ctx.jsonata_template_value())
1✔
1461
        return Output(jsonata_template_value=jsonata_template_value)
1✔
1462

1463
    def visitItems_array(self, ctx: ASLParser.Items_arrayContext) -> ItemsArray:
1✔
1464
        jsonata_template_value_array: JSONataTemplateValueArray = self.visit(
1✔
1465
            ctx.jsonata_template_value_array()
1466
        )
1467
        return ItemsArray(jsonata_template_value_array=jsonata_template_value_array)
1✔
1468

1469
    def visitItems_jsonata(self, ctx: ASLParser.Items_jsonataContext) -> ItemsJSONata:
1✔
1470
        string_jsonata: StringJSONata = self.visitString_jsonata(ctx.string_jsonata())
1✔
1471
        return ItemsJSONata(string_jsonata=string_jsonata)
1✔
1472

1473
    def visitString_sampler(self, ctx: ASLParser.String_samplerContext) -> StringSampler:
1✔
1474
        return self.visit(ctx.children[0])
1✔
1475

1476
    def visitString_literal(self, ctx: ASLParser.String_literalContext) -> StringLiteral:
1✔
1477
        string_literal = from_string_literal(parser_rule_context=ctx)
1✔
1478
        return StringLiteral(literal_value=string_literal)
1✔
1479

1480
    def visitString_jsonpath(self, ctx: ASLParser.String_jsonpathContext) -> StringJsonPath:
1✔
1481
        json_path: str = self._inner_string_of(parser_rule_context=ctx)
1✔
1482
        return StringJsonPath(json_path=json_path)
1✔
1483

1484
    def visitString_context_path(
1✔
1485
        self, ctx: ASLParser.String_context_pathContext
1486
    ) -> StringContextPath:
1487
        context_object_path: str = self._inner_string_of(parser_rule_context=ctx)
1✔
1488
        return StringContextPath(context_object_path=context_object_path)
1✔
1489

1490
    def visitString_variable_sample(
1✔
1491
        self, ctx: ASLParser.String_variable_sampleContext
1492
    ) -> StringVariableSample:
1493
        query_language_mode: QueryLanguageMode = (
1✔
1494
            self._get_current_query_language().query_language_mode
1495
        )
1496
        expression: str = self._inner_string_of(parser_rule_context=ctx)
1✔
1497
        return StringVariableSample(query_language_mode=query_language_mode, expression=expression)
1✔
1498

1499
    def visitString_jsonata(self, ctx: ASLParser.String_jsonataContext) -> StringJSONata:
1✔
1500
        self._raise_if_query_language_is_not(query_language_mode=QueryLanguageMode.JSONata, ctx=ctx)
1✔
1501
        expression = self._inner_jsonata_expr(ctx=ctx)
1✔
1502
        return StringJSONata(expression=expression)
1✔
1503

1504
    def visitString_intrinsic_function(
1✔
1505
        self, ctx: ASLParser.String_intrinsic_functionContext
1506
    ) -> StringIntrinsicFunction:
1507
        intrinsic_function_derivation = ctx.STRINGINTRINSICFUNC().getText()[1:-1]
1✔
1508
        function, _ = IntrinsicParser.parse(intrinsic_function_derivation)
1✔
1509
        return StringIntrinsicFunction(
1✔
1510
            intrinsic_function_derivation=intrinsic_function_derivation, function=function
1511
        )
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc